df-ae-forms-package 1.0.22 → 1.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../node_modules/react/jsx-runtime.js","../node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../src/services/conditionalLogicService.ts","../src/services/toast.service.ts","../src/df-form-controls/df-form-error-msg/DfFormErrorMsg.tsx","../src/components/RaiseIssueModal.tsx","../src/ThresholdAlert.tsx","../src/df-form-controls/df-form-input/DfFormInput.tsx","../src/df-form-controls/df-form-textarea/DfFormTextarea.tsx","../src/df-form-controls/df-form-select/DfFormSelect.tsx","../src/df-form-controls/df-form-checkbox/DfFormCheckbox.tsx","../src/df-form-controls/df-form-radio/DfFormRadio.tsx","../src/df-form-controls/df-form-segment/DfFormSegment.tsx","../src/df-form-controls/df-form-date-time/DfFormDateTime.tsx","../src/df-form-controls/df-form-signature/DfFormSignature.tsx","../src/df-form-controls/df-form-file-upload/DfFormFileUpload.tsx","../src/df-form-controls/df-form-location/DfFormLocation.tsx","../src/df-form-controls/df-form-heading/DfFormHeading.tsx","../src/df-form-controls/df-form-instruction/DfFormInstruction.tsx","../src/ComponentActionFeatures.tsx","../src/components/ComponentSubmissionActions.tsx","../src/df-form-controls/df-form-section/df-form-section.tsx","../src/df-form-controls/df-form-grid/df-form-grid.tsx","../src/DfFormPreview.tsx","../src/df-form-controls/df-form-comments/DfFormComments.tsx","../src/df-form-controls/df-form-table/df-form-table.tsx","../src/types/form-builder-schema.model.ts"],"sourcesContent":["'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","/**\n * @license React\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var f=require(\"react\"),k=Symbol.for(\"react.element\"),l=Symbol.for(\"react.fragment\"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=\"\"+g);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}exports.Fragment=l;exports.jsx=q;exports.jsxs=q;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types.\nvar REACT_ELEMENT_TYPE = Symbol.for('react.element');\nvar REACT_PORTAL_TYPE = Symbol.for('react.portal');\nvar REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');\nvar REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');\nvar REACT_PROFILER_TYPE = Symbol.for('react.profiler');\nvar REACT_PROVIDER_TYPE = Symbol.for('react.provider');\nvar REACT_CONTEXT_TYPE = Symbol.for('react.context');\nvar REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');\nvar REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');\nvar REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');\nvar REACT_MEMO_TYPE = Symbol.for('react.memo');\nvar REACT_LAZY_TYPE = Symbol.for('react.lazy');\nvar REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n if (maybeIterable === null || typeof maybeIterable !== 'object') {\n return null;\n }\n\n var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n if (typeof maybeIterator === 'function') {\n return maybeIterator;\n }\n\n return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n {\n {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n printWarning('error', format, args);\n }\n }\n}\n\nfunction printWarning(level, format, args) {\n // When changing this logic, you might want to also\n // update consoleWithStackDev.www.js as well.\n {\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n if (stack !== '') {\n format += '%s';\n args = args.concat([stack]);\n } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n var argsWithFormat = args.map(function (item) {\n return String(item);\n }); // Careful: RN currently depends on this prefix\n\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n // breaks IE9: https://github.com/facebook/react/issues/13610\n // eslint-disable-next-line react-internal/no-production-logging\n\n Function.prototype.apply.call(console[level], console, argsWithFormat);\n }\n}\n\n// -----------------------------------------------------------------------------\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\nvar enableCacheElement = false;\nvar enableTransitionTracing = false; // No known bugs, but needs performance testing\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n// stuff. Intended to enable React core members to more easily debug scheduling\n// issues in DEV builds.\n\nvar enableDebugTracing = false; // Track which Fiber(s) schedule render work.\n\nvar REACT_MODULE_REFERENCE;\n\n{\n REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');\n}\n\nfunction isValidElementType(type) {\n if (typeof type === 'string' || typeof type === 'function') {\n return true;\n } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {\n return true;\n }\n\n if (typeof type === 'object' && type !== null) {\n if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object\n // types supported by any Flight configuration anywhere since\n // we don't know which Flight build this will end up being used\n // with.\n type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n var displayName = outerType.displayName;\n\n if (displayName) {\n return displayName;\n }\n\n var functionName = innerType.displayName || innerType.name || '';\n return functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName;\n} // Keep in sync with react-reconciler/getComponentNameFromFiber\n\n\nfunction getContextName(type) {\n return type.displayName || 'Context';\n} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.\n\n\nfunction getComponentNameFromType(type) {\n if (type == null) {\n // Host root, text node or just invalid type.\n return null;\n }\n\n {\n if (typeof type.tag === 'number') {\n error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');\n }\n }\n\n if (typeof type === 'function') {\n return type.displayName || type.name || null;\n }\n\n if (typeof type === 'string') {\n return type;\n }\n\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return 'Fragment';\n\n case REACT_PORTAL_TYPE:\n return 'Portal';\n\n case REACT_PROFILER_TYPE:\n return 'Profiler';\n\n case REACT_STRICT_MODE_TYPE:\n return 'StrictMode';\n\n case REACT_SUSPENSE_TYPE:\n return 'Suspense';\n\n case REACT_SUSPENSE_LIST_TYPE:\n return 'SuspenseList';\n\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_CONTEXT_TYPE:\n var context = type;\n return getContextName(context) + '.Consumer';\n\n case REACT_PROVIDER_TYPE:\n var provider = type;\n return getContextName(provider._context) + '.Provider';\n\n case REACT_FORWARD_REF_TYPE:\n return getWrappedName(type, type.render, 'ForwardRef');\n\n case REACT_MEMO_TYPE:\n var outerName = type.displayName || null;\n\n if (outerName !== null) {\n return outerName;\n }\n\n return getComponentNameFromType(type.type) || 'Memo';\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n return getComponentNameFromType(init(payload));\n } catch (x) {\n return null;\n }\n }\n\n // eslint-disable-next-line no-fallthrough\n }\n }\n\n return null;\n}\n\nvar assign = Object.assign;\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n {\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n prevLog = console.log;\n prevInfo = console.info;\n prevWarn = console.warn;\n prevError = console.error;\n prevGroup = console.group;\n prevGroupCollapsed = console.groupCollapsed;\n prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n var props = {\n configurable: true,\n enumerable: true,\n value: disabledLog,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n info: props,\n log: props,\n warn: props,\n error: props,\n group: props,\n groupCollapsed: props,\n groupEnd: props\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n disabledDepth++;\n }\n}\nfunction reenableLogs() {\n {\n disabledDepth--;\n\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n var props = {\n configurable: true,\n enumerable: true,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n log: assign({}, props, {\n value: prevLog\n }),\n info: assign({}, props, {\n value: prevInfo\n }),\n warn: assign({}, props, {\n value: prevWarn\n }),\n error: assign({}, props, {\n value: prevError\n }),\n group: assign({}, props, {\n value: prevGroup\n }),\n groupCollapsed: assign({}, props, {\n value: prevGroupCollapsed\n }),\n groupEnd: assign({}, props, {\n value: prevGroupEnd\n })\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n if (disabledDepth < 0) {\n error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n }\n }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n {\n if (prefix === undefined) {\n // Extract the VM specific prefix used by each line.\n try {\n throw Error();\n } catch (x) {\n var match = x.stack.trim().match(/\\n( *(at )?)/);\n prefix = match && match[1] || '';\n }\n } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n return '\\n' + prefix + name;\n }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n // If something asked for a stack inside a fake render, it should get ignored.\n if ( !fn || reentry) {\n return '';\n }\n\n {\n var frame = componentFrameCache.get(fn);\n\n if (frame !== undefined) {\n return frame;\n }\n }\n\n var control;\n reentry = true;\n var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n Error.prepareStackTrace = undefined;\n var previousDispatcher;\n\n {\n previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n // for warnings.\n\n ReactCurrentDispatcher.current = null;\n disableLogs();\n }\n\n try {\n // This should throw.\n if (construct) {\n // Something should be setting the props in the constructor.\n var Fake = function () {\n throw Error();\n }; // $FlowFixMe\n\n\n Object.defineProperty(Fake.prototype, 'props', {\n set: function () {\n // We use a throwing setter instead of frozen or non-writable props\n // because that won't throw in a non-strict mode function.\n throw Error();\n }\n });\n\n if (typeof Reflect === 'object' && Reflect.construct) {\n // We construct a different control for this case to include any extra\n // frames added by the construct call.\n try {\n Reflect.construct(Fake, []);\n } catch (x) {\n control = x;\n }\n\n Reflect.construct(fn, [], Fake);\n } else {\n try {\n Fake.call();\n } catch (x) {\n control = x;\n }\n\n fn.call(Fake.prototype);\n }\n } else {\n try {\n throw Error();\n } catch (x) {\n control = x;\n }\n\n fn();\n }\n } catch (sample) {\n // This is inlined manually because closure doesn't do it for us.\n if (sample && control && typeof sample.stack === 'string') {\n // This extracts the first frame from the sample that isn't also in the control.\n // Skipping one frame that we assume is the frame that calls the two.\n var sampleLines = sample.stack.split('\\n');\n var controlLines = control.stack.split('\\n');\n var s = sampleLines.length - 1;\n var c = controlLines.length - 1;\n\n while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n // We expect at least one stack frame to be shared.\n // Typically this will be the root most one. However, stack frames may be\n // cut off due to maximum stack limits. In this case, one maybe cut off\n // earlier than the other. We assume that the sample is longer or the same\n // and there for cut off earlier. So we should find the root most frame in\n // the sample somewhere in the control.\n c--;\n }\n\n for (; s >= 1 && c >= 0; s--, c--) {\n // Next we find the first one that isn't the same which should be the\n // frame that called our sample function and the control.\n if (sampleLines[s] !== controlLines[c]) {\n // In V8, the first line is describing the message but other VMs don't.\n // If we're about to return the first line, and the control is also on the same\n // line, that's a pretty good indicator that our sample threw at same line as\n // the control. I.e. before we entered the sample frame. So we ignore this result.\n // This can happen if you passed a class to function component, or non-function.\n if (s !== 1 || c !== 1) {\n do {\n s--;\n c--; // We may still have similar intermediate frames from the construct call.\n // The next one that isn't the same should be our match though.\n\n if (c < 0 || sampleLines[s] !== controlLines[c]) {\n // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n var _frame = '\\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled \"<anonymous>\"\n // but we have a user-provided \"displayName\"\n // splice it in to make the stack more readable.\n\n\n if (fn.displayName && _frame.includes('<anonymous>')) {\n _frame = _frame.replace('<anonymous>', fn.displayName);\n }\n\n {\n if (typeof fn === 'function') {\n componentFrameCache.set(fn, _frame);\n }\n } // Return the line we found.\n\n\n return _frame;\n }\n } while (s >= 1 && c >= 0);\n }\n\n break;\n }\n }\n }\n } finally {\n reentry = false;\n\n {\n ReactCurrentDispatcher.current = previousDispatcher;\n reenableLogs();\n }\n\n Error.prepareStackTrace = previousPrepareStackTrace;\n } // Fallback to just using the name if we couldn't make it throw.\n\n\n var name = fn ? fn.displayName || fn.name : '';\n var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n\n {\n if (typeof fn === 'function') {\n componentFrameCache.set(fn, syntheticFrame);\n }\n }\n\n return syntheticFrame;\n}\nfunction describeFunctionComponentFrame(fn, source, ownerFn) {\n {\n return describeNativeComponentFrame(fn, false);\n }\n}\n\nfunction shouldConstruct(Component) {\n var prototype = Component.prototype;\n return !!(prototype && prototype.isReactComponent);\n}\n\nfunction describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {\n\n if (type == null) {\n return '';\n }\n\n if (typeof type === 'function') {\n {\n return describeNativeComponentFrame(type, shouldConstruct(type));\n }\n }\n\n if (typeof type === 'string') {\n return describeBuiltInComponentFrame(type);\n }\n\n switch (type) {\n case REACT_SUSPENSE_TYPE:\n return describeBuiltInComponentFrame('Suspense');\n\n case REACT_SUSPENSE_LIST_TYPE:\n return describeBuiltInComponentFrame('SuspenseList');\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_FORWARD_REF_TYPE:\n return describeFunctionComponentFrame(type.render);\n\n case REACT_MEMO_TYPE:\n // Memo may contain any component type so we recursively resolve it.\n return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n // Lazy may contain any component type so we recursively resolve it.\n return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);\n } catch (x) {}\n }\n }\n }\n\n return '';\n}\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement(element) {\n {\n if (element) {\n var owner = element._owner;\n var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n ReactDebugCurrentFrame.setExtraStackFrame(stack);\n } else {\n ReactDebugCurrentFrame.setExtraStackFrame(null);\n }\n }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n {\n // $FlowFixMe This is okay but Flow doesn't know it.\n var has = Function.call.bind(hasOwnProperty);\n\n for (var typeSpecName in typeSpecs) {\n if (has(typeSpecs, typeSpecName)) {\n var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n // fail the render phase where it didn't fail before. So we log it.\n // After these have been cleaned up, we'll let them throw.\n\n try {\n // This is intentionally an invariant that gets caught. It's the same\n // behavior as without this statement except with a better message.\n if (typeof typeSpecs[typeSpecName] !== 'function') {\n // eslint-disable-next-line react-internal/prod-error-codes\n var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n err.name = 'Invariant Violation';\n throw err;\n }\n\n error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n } catch (ex) {\n error$1 = ex;\n }\n\n if (error$1 && !(error$1 instanceof Error)) {\n setCurrentlyValidatingElement(element);\n\n error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n setCurrentlyValidatingElement(null);\n }\n\n if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n // Only monitor this failure once because there tends to be a lot of the\n // same error.\n loggedTypeFailures[error$1.message] = true;\n setCurrentlyValidatingElement(element);\n\n error('Failed %s type: %s', location, error$1.message);\n\n setCurrentlyValidatingElement(null);\n }\n }\n }\n }\n}\n\nvar isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare\n\nfunction isArray(a) {\n return isArrayImpl(a);\n}\n\n/*\n * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol\n * and Temporal.* types. See https://github.com/facebook/react/pull/22064.\n *\n * The functions in this module will throw an easier-to-understand,\n * easier-to-debug exception with a clear errors message message explaining the\n * problem. (Instead of a confusing exception thrown inside the implementation\n * of the `value` object).\n */\n// $FlowFixMe only called in DEV, so void return is not possible.\nfunction typeName(value) {\n {\n // toStringTag is needed for namespaced types like Temporal.Instant\n var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;\n var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object';\n return type;\n }\n} // $FlowFixMe only called in DEV, so void return is not possible.\n\n\nfunction willCoercionThrow(value) {\n {\n try {\n testStringCoercion(value);\n return false;\n } catch (e) {\n return true;\n }\n }\n}\n\nfunction testStringCoercion(value) {\n // If you ended up here by following an exception call stack, here's what's\n // happened: you supplied an object or symbol value to React (as a prop, key,\n // DOM attribute, CSS property, string ref, etc.) and when React tried to\n // coerce it to a string using `'' + value`, an exception was thrown.\n //\n // The most common types that will cause this exception are `Symbol` instances\n // and Temporal objects like `Temporal.Instant`. But any object that has a\n // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this\n // exception. (Library authors do this to prevent users from using built-in\n // numeric operators like `+` or comparison operators like `>=` because custom\n // methods are needed to perform accurate arithmetic or comparison.)\n //\n // To fix the problem, coerce this object or symbol value to a string before\n // passing it to React. The most reliable way is usually `String(value)`.\n //\n // To find which value is throwing, check the browser or debugger console.\n // Before this exception was thrown, there should be `console.error` output\n // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the\n // problem and how that type was used: key, atrribute, input value prop, etc.\n // In most cases, this console output also shows the component and its\n // ancestor components where the exception happened.\n //\n // eslint-disable-next-line react-internal/safe-string-coercion\n return '' + value;\n}\nfunction checkKeyStringCoercion(value) {\n {\n if (willCoercionThrow(value)) {\n error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));\n\n return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n }\n }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar RESERVED_PROPS = {\n key: true,\n ref: true,\n __self: true,\n __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n {\n if (hasOwnProperty.call(config, 'ref')) {\n var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n if (getter && getter.isReactWarning) {\n return false;\n }\n }\n }\n\n return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n {\n if (hasOwnProperty.call(config, 'key')) {\n var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n if (getter && getter.isReactWarning) {\n return false;\n }\n }\n }\n\n return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n {\n if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n var componentName = getComponentNameFromType(ReactCurrentOwner.current.type);\n\n if (!didWarnAboutStringRefs[componentName]) {\n error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentNameFromType(ReactCurrentOwner.current.type), config.ref);\n\n didWarnAboutStringRefs[componentName] = true;\n }\n }\n }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n {\n var warnAboutAccessingKey = function () {\n if (!specialPropKeyWarningShown) {\n specialPropKeyWarningShown = true;\n\n error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n }\n };\n\n warnAboutAccessingKey.isReactWarning = true;\n Object.defineProperty(props, 'key', {\n get: warnAboutAccessingKey,\n configurable: true\n });\n }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n {\n var warnAboutAccessingRef = function () {\n if (!specialPropRefWarningShown) {\n specialPropRefWarningShown = true;\n\n error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n }\n };\n\n warnAboutAccessingRef.isReactWarning = true;\n Object.defineProperty(props, 'ref', {\n get: warnAboutAccessingRef,\n configurable: true\n });\n }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n var element = {\n // This tag allows us to uniquely identify this as a React Element\n $$typeof: REACT_ELEMENT_TYPE,\n // Built-in properties that belong on the element\n type: type,\n key: key,\n ref: ref,\n props: props,\n // Record the component responsible for creating this element.\n _owner: owner\n };\n\n {\n // The validation flag is currently mutative. We put it on\n // an external backing store so that we can freeze the whole object.\n // This can be replaced with a WeakMap once they are implemented in\n // commonly used development environments.\n element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n // the validation flag non-enumerable (where possible, which should\n // include every environment we run tests in), so the test framework\n // ignores it.\n\n Object.defineProperty(element._store, 'validated', {\n configurable: false,\n enumerable: false,\n writable: true,\n value: false\n }); // self and source are DEV only properties.\n\n Object.defineProperty(element, '_self', {\n configurable: false,\n enumerable: false,\n writable: false,\n value: self\n }); // Two elements created in two different places should be considered\n // equal for testing purposes and therefore we hide it from enumeration.\n\n Object.defineProperty(element, '_source', {\n configurable: false,\n enumerable: false,\n writable: false,\n value: source\n });\n\n if (Object.freeze) {\n Object.freeze(element.props);\n Object.freeze(element);\n }\n }\n\n return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n {\n var propName; // Reserved names are extracted\n\n var props = {};\n var key = null;\n var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n // but as an intermediary step, we will use jsxDEV for everything except\n // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n // key is explicitly declared to be undefined or not.\n\n if (maybeKey !== undefined) {\n {\n checkKeyStringCoercion(maybeKey);\n }\n\n key = '' + maybeKey;\n }\n\n if (hasValidKey(config)) {\n {\n checkKeyStringCoercion(config.key);\n }\n\n key = '' + config.key;\n }\n\n if (hasValidRef(config)) {\n ref = config.ref;\n warnIfStringRefCannotBeAutoConverted(config, self);\n } // Remaining properties are added to a new props object\n\n\n for (propName in config) {\n if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n props[propName] = config[propName];\n }\n } // Resolve default props\n\n\n if (type && type.defaultProps) {\n var defaultProps = type.defaultProps;\n\n for (propName in defaultProps) {\n if (props[propName] === undefined) {\n props[propName] = defaultProps[propName];\n }\n }\n }\n\n if (key || ref) {\n var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n if (key) {\n defineKeyPropWarningGetter(props, displayName);\n }\n\n if (ref) {\n defineRefPropWarningGetter(props, displayName);\n }\n }\n\n return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n {\n if (element) {\n var owner = element._owner;\n var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n ReactDebugCurrentFrame$1.setExtraStackFrame(stack);\n } else {\n ReactDebugCurrentFrame$1.setExtraStackFrame(null);\n }\n }\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\n\nfunction isValidElement(object) {\n {\n return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n }\n}\n\nfunction getDeclarationErrorAddendum() {\n {\n if (ReactCurrentOwner$1.current) {\n var name = getComponentNameFromType(ReactCurrentOwner$1.current.type);\n\n if (name) {\n return '\\n\\nCheck the render method of `' + name + '`.';\n }\n }\n\n return '';\n }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n {\n if (source !== undefined) {\n var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n var lineNumber = source.lineNumber;\n return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n }\n\n return '';\n }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n {\n var info = getDeclarationErrorAddendum();\n\n if (!info) {\n var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n if (parentName) {\n info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n }\n }\n\n return info;\n }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n {\n if (!element._store || element._store.validated || element.key != null) {\n return;\n }\n\n element._store.validated = true;\n var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n return;\n }\n\n ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n // property, it may be the creator of the child that's responsible for\n // assigning it a key.\n\n var childOwner = '';\n\n if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n // Give the component that originally created this child.\n childOwner = \" It was passed a child from \" + getComponentNameFromType(element._owner.type) + \".\";\n }\n\n setCurrentlyValidatingElement$1(element);\n\n error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n setCurrentlyValidatingElement$1(null);\n }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n {\n if (typeof node !== 'object') {\n return;\n }\n\n if (isArray(node)) {\n for (var i = 0; i < node.length; i++) {\n var child = node[i];\n\n if (isValidElement(child)) {\n validateExplicitKey(child, parentType);\n }\n }\n } else if (isValidElement(node)) {\n // This element was passed in a valid location.\n if (node._store) {\n node._store.validated = true;\n }\n } else if (node) {\n var iteratorFn = getIteratorFn(node);\n\n if (typeof iteratorFn === 'function') {\n // Entry iterators used to provide implicit keys,\n // but now we print a separate warning for them later.\n if (iteratorFn !== node.entries) {\n var iterator = iteratorFn.call(node);\n var step;\n\n while (!(step = iterator.next()).done) {\n if (isValidElement(step.value)) {\n validateExplicitKey(step.value, parentType);\n }\n }\n }\n }\n }\n }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n {\n var type = element.type;\n\n if (type === null || type === undefined || typeof type === 'string') {\n return;\n }\n\n var propTypes;\n\n if (typeof type === 'function') {\n propTypes = type.propTypes;\n } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n // Inner props are checked in the reconciler.\n type.$$typeof === REACT_MEMO_TYPE)) {\n propTypes = type.propTypes;\n } else {\n return;\n }\n\n if (propTypes) {\n // Intentionally inside to avoid triggering lazy initializers:\n var name = getComponentNameFromType(type);\n checkPropTypes(propTypes, element.props, 'prop', name, element);\n } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n var _name = getComponentNameFromType(type);\n\n error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n }\n\n if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n }\n }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n {\n var keys = Object.keys(fragment.props);\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n\n if (key !== 'children' && key !== 'key') {\n setCurrentlyValidatingElement$1(fragment);\n\n error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n setCurrentlyValidatingElement$1(null);\n break;\n }\n }\n\n if (fragment.ref !== null) {\n setCurrentlyValidatingElement$1(fragment);\n\n error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n setCurrentlyValidatingElement$1(null);\n }\n }\n}\n\nvar didWarnAboutKeySpread = {};\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n {\n var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n // succeed and there will likely be errors in render.\n\n if (!validType) {\n var info = '';\n\n if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n }\n\n var sourceInfo = getSourceInfoErrorAddendum(source);\n\n if (sourceInfo) {\n info += sourceInfo;\n } else {\n info += getDeclarationErrorAddendum();\n }\n\n var typeString;\n\n if (type === null) {\n typeString = 'null';\n } else if (isArray(type)) {\n typeString = 'array';\n } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n typeString = \"<\" + (getComponentNameFromType(type.type) || 'Unknown') + \" />\";\n info = ' Did you accidentally export a JSX literal instead of a component?';\n } else {\n typeString = typeof type;\n }\n\n error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n }\n\n var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n // TODO: Drop this when these are no longer allowed as the type argument.\n\n if (element == null) {\n return element;\n } // Skip key warning if the type isn't valid since our key validation logic\n // doesn't expect a non-string/function type and can throw confusing errors.\n // We don't want exception behavior to differ between dev and prod.\n // (Rendering will throw with a helpful message and as soon as the type is\n // fixed, the key warnings will appear.)\n\n\n if (validType) {\n var children = props.children;\n\n if (children !== undefined) {\n if (isStaticChildren) {\n if (isArray(children)) {\n for (var i = 0; i < children.length; i++) {\n validateChildKeys(children[i], type);\n }\n\n if (Object.freeze) {\n Object.freeze(children);\n }\n } else {\n error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n }\n } else {\n validateChildKeys(children, type);\n }\n }\n }\n\n {\n if (hasOwnProperty.call(props, 'key')) {\n var componentName = getComponentNameFromType(type);\n var keys = Object.keys(props).filter(function (k) {\n return k !== 'key';\n });\n var beforeExample = keys.length > 0 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}' : '{key: someKey}';\n\n if (!didWarnAboutKeySpread[componentName + beforeExample]) {\n var afterExample = keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';\n\n error('A props object containing a \"key\" prop is being spread into JSX:\\n' + ' let props = %s;\\n' + ' <%s {...props} />\\n' + 'React keys must be passed directly to JSX without using spread:\\n' + ' let props = %s;\\n' + ' <%s key={someKey} {...props} />', beforeExample, componentName, afterExample, componentName);\n\n didWarnAboutKeySpread[componentName + beforeExample] = true;\n }\n }\n }\n\n if (type === REACT_FRAGMENT_TYPE) {\n validateFragmentProps(element);\n } else {\n validatePropTypes(element);\n }\n\n return element;\n }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n {\n return jsxWithValidation(type, props, key, true);\n }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n {\n return jsxWithValidation(type, props, key, false);\n }\n}\n\nvar jsx = jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs = jsxWithValidationStatic ;\n\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n })();\n}\n","import { FormComponentType, ICondition, IConditionalLogic } from '../df-form-controls/df-form-preview-interfaces';\r\n\r\nexport interface IAvailableComponent {\r\n id: string;\r\n label: string;\r\n type: string;\r\n key: string;\r\n}\r\n\r\nexport interface IConditionalEvaluationResult {\r\n shouldShow: boolean;\r\n evaluatedConditions: Array<{\r\n condition: ICondition;\r\n result: boolean;\r\n componentValue: any;\r\n }>;\r\n}\r\n\r\nexport class ConditionalLogicService {\r\n private static instance: ConditionalLogicService;\r\n\r\n private constructor() {}\r\n\r\n public static getInstance(): ConditionalLogicService {\r\n if (!ConditionalLogicService.instance) {\r\n ConditionalLogicService.instance = new ConditionalLogicService();\r\n }\r\n return ConditionalLogicService.instance;\r\n }\r\n\r\n getAvailableComponentsForConditional(\r\n formSchema: FormComponentType[], \r\n excludeComponentId?: string\r\n ): IAvailableComponent[] {\r\n \r\n if (!formSchema || !Array.isArray(formSchema)) {\r\n return [];\r\n }\r\n\r\n const availableComponents = formSchema\r\n .filter(component => !excludeComponentId || component.id !== excludeComponentId)\r\n .map(component => {\r\n const mappedComponent = {\r\n id: component.id,\r\n label: component.basic?.label || component.id,\r\n type: component.name,\r\n key: component.id\r\n };\r\n return mappedComponent;\r\n })\r\n .sort((a, b) => a.label.localeCompare(b.label));\r\n \r\n return availableComponents;\r\n }\r\n\r\n public getApplicableOperators(componentType: string): string[] {\r\n switch (componentType) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'textarea':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'contains',\r\n 'notContains',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'number-input':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'greaterThan',\r\n 'lessThan',\r\n 'greaterThanOrEqual',\r\n 'lessThanOrEqual',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'select':\r\n case 'radio':\r\n case 'segment':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'checkbox':\r\n return [\r\n 'contains',\r\n 'notContains',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'date-picker':\r\n case 'datetime-picker':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'greaterThan',\r\n 'lessThan',\r\n 'greaterThanOrEqual',\r\n 'lessThanOrEqual',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n default:\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n }\r\n }\r\n\r\n public validateConditionalLogic(\r\n conditional: IConditionalLogic,\r\n formSchema: FormComponentType[]\r\n ): { isValid: boolean; errors: string[] } {\r\n const errors: string[] = [];\r\n\r\n if (!conditional) {\r\n return { isValid: true, errors: [] };\r\n }\r\n\r\n if (!['show', 'hide', 'always'].includes(conditional.action)) {\r\n errors.push('Invalid conditional action');\r\n }\r\n\r\n if (!['all', 'any'].includes(conditional.when)) {\r\n errors.push('Invalid when condition');\r\n }\r\n\r\n if (!conditional.conditions || conditional.conditions.length === 0) {\r\n errors.push('At least one condition is required');\r\n } else {\r\n conditional.conditions.forEach((condition, index) => {\r\n const component = formSchema.find(comp => comp.id === condition.when);\r\n if (!component) {\r\n errors.push(`Condition ${index + 1}: Component not found`);\r\n return;\r\n }\r\n\r\n const applicableOperators = this.getApplicableOperators(component.name);\r\n if (!applicableOperators.includes(condition.operator)) {\r\n errors.push(`Condition ${index + 1}: Operator not applicable for component type`);\r\n }\r\n\r\n if (!this.isValidConditionValue(condition.value, component.name, condition.operator)) {\r\n errors.push(`Condition ${index + 1}: Invalid condition value`);\r\n }\r\n });\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n }\r\n\r\n evaluateConditionalLogic(\r\n conditional: IConditionalLogic,\r\n formSchema: FormComponentType[],\r\n formValues: Record<string, any>\r\n ): IConditionalEvaluationResult {\r\n\r\n if (conditional.action === 'always') {\r\n return {\r\n shouldShow: true,\r\n evaluatedConditions: []\r\n };\r\n }\r\n\r\n if (!conditional || !conditional.conditions || conditional.conditions.length === 0) {\r\n return {\r\n shouldShow: true,\r\n evaluatedConditions: []\r\n };\r\n }\r\n\r\n const evaluatedConditions = conditional.conditions.map(condition => {\r\n const componentValue = this.getComponentValue(condition.when, formSchema, formValues);\r\n const result = this.evaluateCondition(condition, componentValue);\r\n \r\n return {\r\n condition,\r\n result,\r\n componentValue\r\n };\r\n });\r\n\r\n const shouldShow = this.determineFinalResult(conditional, evaluatedConditions);\r\n\r\n return {\r\n shouldShow,\r\n evaluatedConditions\r\n };\r\n }\r\n\r\n private getComponentValue(\r\n componentId: string, \r\n formSchema: FormComponentType[], \r\n formValues: Record<string, any>\r\n ): any {\r\n\r\n if (formValues && formValues[componentId] !== undefined) {\r\n return formValues[componentId];\r\n }\r\n\r\n const component = formSchema.find(comp => comp.id === componentId);\r\n if (component && 'defaultValue' in component.basic) {\r\n return component.basic.defaultValue;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private evaluateCondition(condition: ICondition, componentValue: any): boolean {\r\n const { operator, value } = condition;\r\n\r\n if (value === 'checked' || value === 'notChecked') {\r\n return this.evaluateCheckboxCondition(componentValue, value);\r\n }\r\n\r\n switch (operator) {\r\n case 'equals':\r\n return this.isEqual(componentValue, value);\r\n \r\n case 'notEquals':\r\n return !this.isEqual(componentValue, value);\r\n \r\n case 'isEmpty':\r\n return this.isEmpty(componentValue);\r\n \r\n case 'isNotEmpty':\r\n return !this.isEmpty(componentValue);\r\n \r\n case 'contains':\r\n return this.contains(componentValue, value);\r\n \r\n case 'notContains':\r\n return !this.contains(componentValue, value);\r\n \r\n case 'greaterThan':\r\n return this.isGreaterThan(componentValue, value);\r\n \r\n case 'lessThan':\r\n return this.isLessThan(componentValue, value);\r\n \r\n case 'greaterThanOrEqual':\r\n return this.isGreaterThanOrEqual(componentValue, value);\r\n \r\n case 'lessThanOrEqual':\r\n return this.isLessThanOrEqual(componentValue, value);\r\n \r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n private evaluateCheckboxCondition(componentValue: any, expectedValue: string): boolean {\r\n const isChecked = this.isCheckboxChecked(componentValue);\r\n \r\n if (expectedValue === 'checked') {\r\n return isChecked;\r\n } else if (expectedValue === 'notChecked') {\r\n return !isChecked;\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private isCheckboxChecked(componentValue: any): boolean {\r\n if (componentValue === null || componentValue === undefined) {\r\n return false;\r\n }\r\n \r\n if (typeof componentValue === 'boolean') {\r\n return componentValue;\r\n }\r\n \r\n if (typeof componentValue === 'string') {\r\n return componentValue.toLowerCase() === 'true' || componentValue === '1';\r\n }\r\n \r\n if (Array.isArray(componentValue)) {\r\n return componentValue.length > 0;\r\n }\r\n \r\n if (typeof componentValue === 'number') {\r\n return componentValue > 0;\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private determineFinalResult(\r\n conditional: IConditionalLogic, \r\n evaluatedConditions: Array<{ result: boolean }>\r\n ): boolean {\r\n let conditionsMet: boolean;\r\n if (conditional.when === 'all') {\r\n conditionsMet = evaluatedConditions.every(condition => condition.result);\r\n } else if (conditional.when === 'any') {\r\n conditionsMet = evaluatedConditions.some(condition => condition.result);\r\n } else {\r\n conditionsMet = false;\r\n }\r\n \r\n let finalResult: boolean;\r\n if (conditional.action === 'show') {\r\n finalResult = conditionsMet;\r\n } else if (conditional.action === 'hide') {\r\n finalResult = !conditionsMet;\r\n } else if (conditional.action === 'always') {\r\n finalResult = true;\r\n } else {\r\n finalResult = true;\r\n }\r\n \r\n return finalResult;\r\n }\r\n\r\n private isEqual(a: any, b: any): boolean {\r\n if (a === b) return true;\r\n if (a == null || b == null) return false;\r\n \r\n if (Array.isArray(a) && Array.isArray(b)) {\r\n if (a.length !== b.length) return false;\r\n return a.every((val, index) => this.isEqual(val, b[index]));\r\n }\r\n \r\n if (typeof a === 'object' && typeof b === 'object') {\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n return keysA.every(key => this.isEqual(a[key], b[key]));\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private isEmpty(value: any): boolean {\r\n if (value == null || value === undefined) return true;\r\n if (typeof value === 'string') return value.trim() === '';\r\n if (Array.isArray(value)) return value.length === 0;\r\n if (typeof value === 'object') return Object.keys(value).length === 0;\r\n return false;\r\n }\r\n\r\n private contains(container: any, searchValue: any): boolean {\r\n if (container == null || searchValue == null) return false;\r\n \r\n if (typeof container === 'string') {\r\n return container.toLowerCase().includes(String(searchValue).toLowerCase());\r\n }\r\n \r\n if (Array.isArray(container)) {\r\n return container.some(item => this.isEqual(item, searchValue));\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private isGreaterThan(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA > numB;\r\n }\r\n\r\n private isLessThan(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA < numB;\r\n }\r\n\r\n private isGreaterThanOrEqual(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA >= numB;\r\n }\r\n\r\n private isLessThanOrEqual(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA <= numB;\r\n }\r\n\r\n private isValidConditionValue(value: any, componentType: string, operator: string): boolean {\r\n if (value === null || value === undefined) {\r\n return ['isEmpty', 'isNotEmpty'].includes(operator);\r\n }\r\n\r\n switch (componentType) {\r\n case 'number-input':\r\n return !isNaN(Number(value)) || ['isEmpty', 'isNotEmpty'].includes(operator);\r\n\r\n case 'date-picker':\r\n case 'datetime-picker':\r\n return !isNaN(Date.parse(value)) || ['isEmpty', 'isNotEmpty'].includes(operator);\r\n\r\n case 'checkbox':\r\n return Array.isArray(value) || typeof value === 'string' || typeof value === 'number';\r\n\r\n default:\r\n return true;\r\n }\r\n }\r\n\r\n public createDefaultConditionalLogic(): IConditionalLogic {\r\n return {\r\n action: 'show',\r\n when: 'all',\r\n conditions: []\r\n };\r\n }\r\n\r\n public getOperatorDisplayText(operator: string): string {\r\n const operatorTexts: Record<string, string> = {\r\n 'equals': 'Is Equal To',\r\n 'notEquals': 'Is Not Equal To',\r\n 'contains': 'Contains',\r\n 'notContains': 'Does Not Contain',\r\n 'isEmpty': 'Is Empty',\r\n 'isNotEmpty': 'Is Not Empty',\r\n 'greaterThan': 'Is Greater Than',\r\n 'lessThan': 'Is Less Than',\r\n 'greaterThanOrEqual': 'Is Greater Than Or Equal To',\r\n 'lessThanOrEqual': 'Is Less Than Or Equal To'\r\n };\r\n\r\n return operatorTexts[operator] || operator;\r\n }\r\n\r\n public getActionDisplayText(action: string): string {\r\n const actionTexts: Record<string, string> = {\r\n show: 'Show this field when',\r\n hide: 'Hide this field when',\r\n always: 'Always show this field'\r\n };\r\n\r\n return actionTexts[action] || action;\r\n }\r\n\r\n public getConditionalLogicSummary(conditional: IConditionalLogic, formSchema: FormComponentType[]): string {\r\n if (!conditional || conditional.conditions.length === 0) {\r\n return 'No conditions';\r\n }\r\n\r\n if (conditional.action === 'always') {\r\n return 'Always show';\r\n }\r\n\r\n const actionText = this.getActionDisplayText(conditional.action);\r\n const conditionTexts = conditional.conditions.map(condition => {\r\n const component = formSchema.find(comp => comp.id === condition.when);\r\n const componentLabel = component?.basic.label || 'Unknown component';\r\n const operatorText = this.getOperatorDisplayText(condition.operator);\r\n const valueText = this.formatConditionValue(condition.value);\r\n \r\n return `${componentLabel} ${operatorText} ${valueText}`;\r\n });\r\n\r\n const operatorText = conditional.when === 'all' ? ' and ' : ' or ';\r\n return `${actionText} ${conditionTexts.join(operatorText)}`;\r\n }\r\n\r\n private formatConditionValue(value: any): string {\r\n if (value === null || value === undefined) {\r\n return 'empty';\r\n }\r\n \r\n if (Array.isArray(value)) {\r\n return `[${value.join(', ')}]`;\r\n }\r\n \r\n if (typeof value === 'string') {\r\n return `\"${value}\"`;\r\n }\r\n \r\n return String(value);\r\n }\r\n}\r\n\r\nexport const conditionalLogicService = ConditionalLogicService.getInstance();\r\n\r\n","export interface IToast {\r\n id: string;\r\n message: string;\r\n type: 'success' | 'danger' | 'warning' | 'info';\r\n duration?: number;\r\n}\r\n\r\nclass ToastService {\r\n private toasts: IToast[] = [];\r\n private listeners: Array<(toasts: IToast[]) => void> = [];\r\n private defaultDuration = 3000;\r\n private timeouts: Record<string, NodeJS.Timeout> = {};\r\n\r\n private generateId(): string {\r\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\r\n }\r\n\r\n private notifyListeners(): void {\r\n this.listeners.forEach(listener => listener([...this.toasts]));\r\n }\r\n\r\n private addToast(toast: IToast): void {\r\n try {\r\n this.toasts.push(toast);\r\n this.notifyListeners();\r\n\r\n this.timeouts[toast.id] = setTimeout(() => {\r\n this.removeToast(toast.id);\r\n }, toast.duration || this.defaultDuration);\r\n } catch (error) {\r\n console.error('Error displaying toast message:', error);\r\n }\r\n }\r\n\r\n removeToast(id: string): void {\r\n if (this.timeouts[id]) {\r\n clearTimeout(this.timeouts[id]);\r\n delete this.timeouts[id];\r\n }\r\n\r\n this.toasts = this.toasts.filter((toast) => toast.id !== id);\r\n this.notifyListeners();\r\n }\r\n\r\n showSuccess(message: string, duration = 3000): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'success',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n showError(message: string, duration = 5000): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'danger',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n showWarning(message: string, duration?: number): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'warning',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n showInfo(message: string, duration?: number): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'info',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n show(\r\n message: string,\r\n type: 'success' | 'danger' | 'warning' | 'info' = 'success',\r\n duration?: number,\r\n ): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type,\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n clearAll(): void {\r\n Object.values(this.timeouts).forEach((timeout) => clearTimeout(timeout));\r\n this.timeouts = {};\r\n this.toasts = [];\r\n this.notifyListeners();\r\n }\r\n\r\n subscribe(listener: (toasts: IToast[]) => void): () => void {\r\n this.listeners.push(listener);\r\n return () => {\r\n this.listeners = this.listeners.filter(l => l !== listener);\r\n };\r\n }\r\n\r\n getToasts(): IToast[] {\r\n return [...this.toasts];\r\n }\r\n}\r\n\r\nexport const toastService = new ToastService();\r\n\r\n","import React from 'react';\r\nimport { ErrorMessageProps } from '../df-form-preview-interfaces';\r\n\r\nexport const DfFormErrorMsg: React.FC<ErrorMessageProps> = ({\r\n validationErrors,\r\n fieldId,\r\n touchedFields,\r\n formSubmitted,\r\n properties,\r\n localValidation,\r\n isTouched: localIsTouched,\r\n mode,\r\n}) => {\r\n const getErrorMessage = (): string => {\r\n // Only show error messages in test mode\r\n if (mode !== 'test') {\r\n return '';\r\n }\r\n \r\n // Check if field is touched or form is submitted\r\n const isTouched = localIsTouched || touchedFields[fieldId] || formSubmitted;\r\n \r\n if (!isTouched) {\r\n return '';\r\n }\r\n\r\n // Prioritize local validation - if local validation is valid, don't show any errors\r\n if (localValidation && localValidation.isValid) {\r\n return '';\r\n }\r\n\r\n // Show local validation errors if validation failed\r\n // CRITICAL: Only show errors if validation is actually invalid AND there are error keys\r\n if (localValidation && !localValidation.isValid && Object.keys(localValidation.errors).length > 0) {\r\n const errorKeys = Object.keys(localValidation.errors);\r\n // CRITICAL: Only show error if there's actually an error condition met\r\n // Filter out false/undefined error keys\r\n const actualErrors = errorKeys.filter(key => localValidation.errors[key] === true);\r\n if (actualErrors.length > 0) {\r\n const firstError = actualErrors[0];\r\n return getDefaultErrorMessage(firstError);\r\n }\r\n }\r\n\r\n // Only check external validation errors if local validation doesn't exist or is not valid\r\n const fieldErrors = validationErrors[fieldId];\r\n if (fieldErrors && typeof fieldErrors === 'string' && fieldErrors.trim() !== '') {\r\n // For date/time components, check if we should use mode-specific message\r\n const componentName = (properties as any).name || '';\r\n const isDateTimeComponent = componentName === 'date-picker' || componentName === 'datetime-picker';\r\n if (isDateTimeComponent && fieldErrors.includes('valid date')) {\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n if (dateTimeMode === 'time') {\r\n return 'Please select a valid time';\r\n } else if (dateTimeMode === 'datetime') {\r\n return 'Please select a valid date and time';\r\n }\r\n }\r\n return fieldErrors;\r\n }\r\n\r\n return '';\r\n };\r\n\r\n const getDefaultErrorMessage = (errorType: string): string => {\r\n const fieldLabel = properties.basic.label || 'This field';\r\n \r\n // CRITICAL: Only use custom validation message if there's actually an error\r\n // Don't show custom message for valid fields\r\n const customMessage = properties.validation?.customValidationMessage;\r\n // Only use custom message if it exists and we have an actual error\r\n if (customMessage && customMessage.trim() !== '') {\r\n return customMessage;\r\n }\r\n \r\n // For date/time components, check dateTimeMode for appropriate error messages\r\n const componentName = (properties as any).name || '';\r\n const isDateTimeComponent = componentName === 'date-picker' || componentName === 'datetime-picker';\r\n const dateTimeMode = isDateTimeComponent ? ((properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date')) : null;\r\n \r\n switch (errorType) {\r\n case 'required':\r\n return `${fieldLabel} is required`;\r\n case 'invalidDate':\r\n // Show mode-specific error messages for date/time components\r\n if (dateTimeMode === 'time') {\r\n return 'Please select a valid time';\r\n } else if (dateTimeMode === 'datetime') {\r\n return 'Please select a valid date and time';\r\n } else if (dateTimeMode === 'date') {\r\n return 'Please select a valid date';\r\n }\r\n return `${fieldLabel} is invalid`;\r\n case 'minLength':\r\n const minLength = properties.validation.minLength;\r\n return `${fieldLabel} must be at least ${minLength} characters long`;\r\n case 'maxLength':\r\n const maxLength = properties.validation.maxLength;\r\n return `${fieldLabel} must be no more than ${maxLength} characters long`;\r\n case 'min':\r\n const min = properties.validation.min;\r\n return `${fieldLabel} must be at least ${min}`;\r\n case 'max':\r\n const max = properties.validation.max;\r\n return `${fieldLabel} must be no more than ${max}`;\r\n case 'lowerLimit':\r\n const numberValidation = properties.validation as any;\r\n const lowerLimit = numberValidation?.lowerLimit;\r\n return `You are under the limit. ${fieldLabel} must be at least ${lowerLimit}`;\r\n case 'upperLimit':\r\n const numberValidationUpper = properties.validation as any;\r\n const upperLimit = numberValidationUpper?.upperLimit;\r\n return `You crossed the limit. ${fieldLabel} must be no more than ${upperLimit}`;\r\n case 'pattern':\r\n return `${fieldLabel} format is invalid`;\r\n case 'email':\r\n return `${fieldLabel} must be a valid email address`;\r\n default:\r\n return `${fieldLabel} is invalid`;\r\n }\r\n };\r\n\r\n const errorMessage = getErrorMessage();\r\n\r\n if (!errorMessage) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"form-error-msg\">\r\n {errorMessage}\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormErrorMsg;\r\n","import React, { useState, useEffect } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { X, AlertTriangle, User, Calendar, MessageSquare } from 'lucide-react';\r\nimport { FormComponentType } from '../df-form-controls/df-form-preview-interfaces';\r\nimport { toastService } from '../services/toast.service';\r\nimport './RaiseIssueModal.scss';\r\n\r\n// Issue status enum\r\nenum EIssueStatus {\r\n OPEN = 'Open',\r\n IN_PROGRESS = 'In-Progress',\r\n REJECTED = 'Rejected',\r\n RESOLVE = 'Resolve'\r\n}\r\n\r\n// Issue interface\r\ninterface IIssue {\r\n _id?: string;\r\n issueNumber?: string;\r\n title?: string;\r\n description?: string;\r\n workOrderNumber?: string;\r\n assetNumber?: string;\r\n formTemplateId?: string;\r\n component?: FormComponentType;\r\n priority?: 'High' | 'Medium' | 'Low';\r\n status?: string;\r\n assignee?: string;\r\n comments?: string;\r\n createdAt?: string;\r\n}\r\n\r\ninterface IRaiseIssueModalProps {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onSuccess?: (createdIssue?: IIssue) => void;\r\n component?: FormComponentType;\r\n formTemplateId?: string;\r\n notes?: string;\r\n attachments?: File[] | null;\r\n issue?: IIssue | null;\r\n // Optional API callbacks - if not provided, modal will just call onSuccess\r\n onCreateIssue?: (issueData: any, attachments: File[]) => Promise<IIssue>;\r\n onUpdateIssue?: (issueId: string, updateData: any) => Promise<void>;\r\n // Optional user info\r\n user?: {\r\n firstName?: string;\r\n lastName?: string;\r\n };\r\n // Optional available users list\r\n availableUsers?: string[];\r\n}\r\n\r\nexport const RaiseIssueModal: React.FC<IRaiseIssueModalProps> = ({\r\n isOpen,\r\n onClose,\r\n onSuccess,\r\n component,\r\n formTemplateId,\r\n notes = '',\r\n attachments = null,\r\n issue = null,\r\n onCreateIssue,\r\n onUpdateIssue,\r\n user,\r\n availableUsers = [\r\n 'Priya Das',\r\n 'Maria Garcia',\r\n 'John Smith',\r\n 'Sarah Johnson'\r\n ]\r\n}) => {\r\n const [title, setTitle] = useState<string>('');\r\n const [description, setDescription] = useState<string>('');\r\n const [workOrderNumber, setWorkOrderNumber] = useState<string>('');\r\n const [assetNumber, setAssetNumber] = useState<string>('');\r\n const [priority, setPriority] = useState<'High' | 'Medium' | 'Low'>('Medium');\r\n const [status, setStatus] = useState<string>(EIssueStatus.OPEN);\r\n const [assignee, setAssignee] = useState<string>('');\r\n const [comments, setComments] = useState<string>('');\r\n const [isSubmitting, setIsSubmitting] = useState<boolean>(false);\r\n\r\n const isEditMode = !!issue;\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n if (issue) {\r\n // Edit mode: populate with issue data\r\n setTitle(issue.title || '');\r\n setDescription(issue.description || '');\r\n setWorkOrderNumber(issue.workOrderNumber || '');\r\n setAssetNumber(issue.assetNumber || '');\r\n setPriority(issue.priority || 'Medium');\r\n // Use enum value or default to OPEN\r\n const issueStatus = issue.status || EIssueStatus.OPEN;\r\n // Normalize to enum values if needed (handle legacy values)\r\n const normalizedStatus = \r\n issueStatus === EIssueStatus.OPEN || issueStatus === EIssueStatus.IN_PROGRESS || issueStatus === EIssueStatus.REJECTED || issueStatus === EIssueStatus.RESOLVE\r\n ? issueStatus\r\n : EIssueStatus.OPEN;\r\n setStatus(normalizedStatus);\r\n setAssignee(issue.assignee || '');\r\n setComments(issue.comments || '');\r\n } else if (component) {\r\n // Create mode: initialize form with component data\r\n const componentLabel = component.basic?.label || 'Component';\r\n setTitle(`${componentLabel} - Issue`);\r\n \r\n // Build description from component value and notes\r\n let desc = `Issue raised for component: ${componentLabel}`;\r\n if (component.basic && 'value' in component.basic && component.basic.value) {\r\n desc += `\\nComponent Value: ${component.basic.value}`;\r\n }\r\n if (notes) {\r\n desc += `\\nNotes: ${notes}`;\r\n }\r\n setDescription(desc);\r\n setComments(notes || '');\r\n }\r\n }\r\n }, [isOpen, component, notes, issue]);\r\n\r\n const updateIssueStatus = async (newStatus: string) => {\r\n if (!issue) return;\r\n\r\n setIsSubmitting(true);\r\n\r\n try {\r\n const updateData = {\r\n title: String(title || '').trim(),\r\n description: String(description || '').trim(),\r\n workOrderNumber: String(workOrderNumber || '').trim() || '',\r\n assetNumber: String(assetNumber || '').trim() || '',\r\n formTemplateId: issue.formTemplateId || '',\r\n component: issue.component || {},\r\n priority,\r\n assignee: String(assignee || '').trim() || undefined,\r\n status: newStatus,\r\n comments: String(comments || '').trim() || ''\r\n };\r\n\r\n if (onUpdateIssue && issue._id) {\r\n await onUpdateIssue(issue._id, updateData);\r\n }\r\n setStatus(newStatus);\r\n \r\n const statusMessages: Record<string, string> = {\r\n [EIssueStatus.IN_PROGRESS]: 'Issue accepted and moved to In-Progress',\r\n [EIssueStatus.RESOLVE]: 'Issue resolved successfully',\r\n [EIssueStatus.REJECTED]: 'Issue rejected'\r\n };\r\n \r\n toastService.showSuccess(statusMessages[newStatus] || 'Issue status updated successfully');\r\n \r\n if (onSuccess) {\r\n onSuccess();\r\n }\r\n onClose();\r\n } catch (error: any) {\r\n const errorMessage = error?.message || error?.error?.message || 'Failed to update issue status. Please try again.';\r\n toastService.showError(errorMessage);\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleAccept = async () => {\r\n await updateIssueStatus(EIssueStatus.IN_PROGRESS);\r\n };\r\n\r\n const handleResolve = async () => {\r\n await updateIssueStatus(EIssueStatus.RESOLVE);\r\n };\r\n\r\n const handleReject = async () => {\r\n await updateIssueStatus(EIssueStatus.REJECTED);\r\n };\r\n\r\n const handleSubmit = async () => {\r\n if (!String(title || '').trim()) {\r\n toastService.showError('Title is required');\r\n return;\r\n }\r\n\r\n if (!String(description || '').trim()) {\r\n toastService.showError('Description is required');\r\n return;\r\n }\r\n\r\n setIsSubmitting(true);\r\n\r\n try {\r\n if (isEditMode && issue) {\r\n // Update existing issue\r\n const updateData = {\r\n title: String(title || '').trim(),\r\n description: String(description || '').trim(),\r\n workOrderNumber: String(workOrderNumber || '').trim() || '',\r\n assetNumber: String(assetNumber || '').trim() || undefined,\r\n formTemplateId: issue.formTemplateId || '',\r\n component: issue.component || {},\r\n priority,\r\n assignee: String(assignee || '').trim() || undefined,\r\n status: status,\r\n comments: String(comments || '').trim() || ''\r\n };\r\n\r\n if (onUpdateIssue && issue._id) {\r\n await onUpdateIssue(issue._id, updateData);\r\n }\r\n toastService.showSuccess('Issue updated successfully');\r\n \r\n if (onSuccess) {\r\n onSuccess();\r\n }\r\n onClose();\r\n } else {\r\n // Create new issue\r\n if (!component) {\r\n toastService.showError('Component is required');\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n \r\n if (!formTemplateId || String(formTemplateId || '').trim() === '') {\r\n toastService.showError('Form template is required');\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n\r\n // Prepare component data for API - include all component properties\r\n const componentData = {\r\n ...component,\r\n basic: {\r\n ...component.basic,\r\n comments: String(notes || '')\r\n }\r\n };\r\n\r\n const issueData = {\r\n title: String(title || '').trim(),\r\n workOrderNumber: String(workOrderNumber || '').trim() || undefined,\r\n assetNumber: String(assetNumber || '').trim() || undefined,\r\n component: componentData,\r\n description: String(description || '').trim(),\r\n formTemplateId,\r\n assignee: String(assignee || '').trim() || undefined,\r\n priority,\r\n status: status,\r\n comments: String(comments || '').trim() || ''\r\n };\r\n\r\n let createdIssue: IIssue | undefined;\r\n if (onCreateIssue) {\r\n createdIssue = await onCreateIssue(issueData, attachments || []);\r\n }\r\n toastService.showSuccess('Issue raised successfully');\r\n \r\n if (onSuccess) {\r\n onSuccess(createdIssue);\r\n }\r\n onClose();\r\n }\r\n } catch (error: any) {\r\n const errorMessage = error?.message || error?.error?.message || (isEditMode ? 'Failed to update issue. Please try again.' : 'Failed to raise issue. Please try again.');\r\n toastService.showError(errorMessage);\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n if (!isOpen) {\r\n return null;\r\n }\r\n\r\n const modalContent = (\r\n <div className=\"raise-issue-modal-overlay\" onClick={onClose}>\r\n <div className=\"raise-issue-modal\" onClick={(e) => e.stopPropagation()}>\r\n {/* Header */}\r\n <div className=\"raise-issue-modal-header\">\r\n <div className=\"raise-issue-modal-header-left\">\r\n <AlertTriangle className=\"raise-issue-modal-icon\" size={20} />\r\n <div className=\"raise-issue-modal-header-text\">\r\n <div className=\"raise-issue-modal-title-main\">Issue Details</div>\r\n </div>\r\n </div>\r\n <button\r\n className=\"raise-issue-modal-close\"\r\n onClick={onClose}\r\n aria-label=\"Close\"\r\n >\r\n <X size={18} />\r\n </button>\r\n </div>\r\n\r\n {/* Content */}\r\n <div className=\"raise-issue-modal-content\">\r\n <div className=\"raise-issue-fields-grid\">\r\n {/* Issue Number - Show only in edit mode */}\r\n {isEditMode && issue?.issueNumber && (\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Issue ID</label>\r\n <input\r\n type=\"text\"\r\n className=\"raise-issue-field-input raise-issue-field-readonly\"\r\n value={issue.issueNumber}\r\n readOnly\r\n />\r\n </div>\r\n )}\r\n\r\n {/* Title */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Title <span className=\"raise-issue-required\">*</span></label>\r\n <input\r\n type=\"text\"\r\n className={`raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n placeholder=\"Enter issue title\"\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Work Order */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Work Order <span className=\"raise-issue-required\">*</span></label>\r\n <input\r\n type=\"text\"\r\n className={`raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={workOrderNumber}\r\n onChange={(e) => setWorkOrderNumber(e.target.value)}\r\n placeholder=\"N/A\"\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Asset Number */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Asset Number <span className=\"raise-issue-required\">*</span></label>\r\n <input\r\n type=\"text\"\r\n className={`raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={assetNumber}\r\n onChange={(e) => setAssetNumber(e.target.value)}\r\n placeholder=\"Enter asset number\"\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Raised By */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Raised By</label>\r\n <div className=\"raise-issue-field-value-with-icon\">\r\n <User size={16} />\r\n <span>{user ? `${user.firstName || ''} ${user.lastName || ''}`.trim() || 'User' : 'User'}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Created On */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Created On</label>\r\n <div className=\"raise-issue-field-value-with-icon\">\r\n <Calendar size={16} />\r\n <span>\r\n {isEditMode && issue?.createdAt\r\n ? new Date(issue.createdAt).toLocaleString('en-US', {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n })\r\n : new Date().toLocaleString('en-US', {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n })}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Description - Full Width */}\r\n <div className=\"raise-issue-field raise-issue-field-full-width\">\r\n <label className=\"raise-issue-field-label\">Description <span className=\"raise-issue-required\">*</span></label>\r\n <textarea\r\n className={`raise-issue-field-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n placeholder=\"Enter issue description\"\r\n rows={4}\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Status */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Status <span className=\"raise-issue-required\">*</span></label>\r\n <select\r\n className={`raise-issue-field-select ${!isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={status}\r\n onChange={(e) => setStatus(e.target.value)}\r\n disabled={!isEditMode}\r\n >\r\n <option value={EIssueStatus.OPEN}>{EIssueStatus.OPEN}</option>\r\n <option value={EIssueStatus.IN_PROGRESS}>{EIssueStatus.IN_PROGRESS}</option>\r\n <option value={EIssueStatus.REJECTED}>{EIssueStatus.REJECTED}</option>\r\n <option value={EIssueStatus.RESOLVE}>{EIssueStatus.RESOLVE}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Assignee */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Assignee <span className=\"raise-issue-required\">*</span></label>\r\n <select\r\n className=\"raise-issue-field-select\"\r\n value={assignee}\r\n onChange={(e) => setAssignee(e.target.value)}\r\n >\r\n <option value=\"\">Unassigned</option>\r\n {availableUsers.map(userName => (\r\n <option key={userName} value={userName}>\r\n {userName}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Priority */}\r\n <div className=\"raise-issue-field raise-issue-field-full-width\">\r\n <label className=\"raise-issue-field-label\">Priority <span className=\"raise-issue-required\">*</span></label>\r\n <div className=\"raise-issue-priority-buttons\">\r\n <button\r\n type=\"button\"\r\n className={`priority-button priority-low ${priority === 'Low' ? 'active' : ''}`}\r\n onClick={() => setPriority('Low')}\r\n >\r\n Low\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`priority-button priority-medium ${priority === 'Medium' ? 'active' : ''}`}\r\n onClick={() => setPriority('Medium')}\r\n >\r\n Medium\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`priority-button priority-high ${priority === 'High' ? 'active' : ''}`}\r\n onClick={() => setPriority('High')}\r\n >\r\n High\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Comments - Full Width */}\r\n <div className=\"raise-issue-field raise-issue-field-full-width\">\r\n <label className=\"raise-issue-field-label-with-icon\">\r\n <MessageSquare size={16} />\r\n <span>Comments</span>\r\n </label>\r\n {!comments && (\r\n <div className=\"raise-issue-no-comments\">No comments yet</div>\r\n )}\r\n <textarea\r\n className={`raise-issue-field-textarea raise-issue-comments-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={comments}\r\n onChange={(e) => setComments(e.target.value)}\r\n placeholder=\"Add a comment...\"\r\n rows={4}\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Actions */}\r\n <div className=\"raise-issue-modal-actions\">\r\n <div className=\"raise-issue-modal-actions-buttons\">\r\n {/* Action buttons - only show in edit mode and when status allows actions */}\r\n {isEditMode && issue && (\r\n <>\r\n {status === EIssueStatus.OPEN && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-accept\"\r\n onClick={handleAccept}\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? 'Processing...' : 'Accept'}\r\n </button>\r\n )}\r\n {status === EIssueStatus.IN_PROGRESS && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-resolve\"\r\n onClick={handleResolve}\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? 'Processing...' : 'Resolve'}\r\n </button>\r\n )}\r\n {status === EIssueStatus.OPEN && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-reject\"\r\n onClick={handleReject}\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? 'Processing...' : 'Reject'}\r\n </button>\r\n )}\r\n </>\r\n )}\r\n {!isEditMode && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-save\"\r\n onClick={handleSubmit}\r\n disabled={isSubmitting || !String(title || '').trim() || !String(description || '').trim()}\r\n >\r\n {isSubmitting ? 'Saving...' : 'Save Changes'}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n\r\n // Render modal using portal to document body for full-page overlay\r\n return createPortal(modalContent, document.body);\r\n};\r\n","import React, { useState, useCallback, useEffect } from 'react';\r\nimport { AlertTriangle, CheckCircle2 } from 'lucide-react';\r\nimport { RaiseIssueModal } from './components/RaiseIssueModal';\r\nimport { toastService } from './services/toast.service';\r\n\r\n// Stub interface for issue (replace with your own)\r\ninterface IIssue {\r\n _id: string;\r\n id?: string;\r\n issueNumber?: string;\r\n title?: string;\r\n description?: string;\r\n status?: string;\r\n createdAt?: string;\r\n component?: any;\r\n formTemplateId?: string;\r\n}\r\nimport './ThresholdAlert.scss';\r\n\r\ninterface IThresholdAlertProps {\r\n component: any;\r\n condition: any;\r\n currentValue: string | number;\r\n thresholdValue: string | number;\r\n formTemplateId?: string;\r\n onDismiss?: () => void;\r\n onIssueRaised?: (conditionId: string) => void;\r\n isIssueRaised?: boolean; // Track if issue has been raised for this condition\r\n compact?: boolean; // Show compact one-liner version for small screens/tables\r\n}\r\n\r\nexport const ThresholdAlert: React.FC<IThresholdAlertProps> = ({\r\n component,\r\n condition,\r\n currentValue,\r\n thresholdValue,\r\n formTemplateId,\r\n onIssueRaised,\r\n isIssueRaised = false,\r\n compact = false\r\n}) => {\r\n const [showRaiseIssueModal, setShowRaiseIssueModal] = useState(false);\r\n const [issue, setIssue] = useState<IIssue | null>(null);\r\n const [isLoadingIssue, setIsLoadingIssue] = useState(false);\r\n const [localIssueRaised, setLocalIssueRaised] = useState(false);\r\n\r\n // Sync local state with prop - if parent says issue is raised, update local state\r\n useEffect(() => {\r\n if (isIssueRaised) {\r\n setLocalIssueRaised(true);\r\n }\r\n }, [isIssueRaised]);\r\n\r\n // Reset local state when condition changes (new condition = new alert)\r\n useEffect(() => {\r\n setLocalIssueRaised(false);\r\n }, [condition?.id]);\r\n\r\n const getOperatorSymbol = (operator: string): string => {\r\n const symbols: Record<string, string> = {\r\n 'greaterThan': '>',\r\n 'lessThan': '<',\r\n 'greaterThanOrEqual': '≥',\r\n 'lessThanOrEqual': '≤',\r\n 'equals': '=',\r\n 'notEquals': '≠'\r\n };\r\n return symbols[operator] || operator;\r\n };\r\n\r\n const getConditionMessage = (): string => {\r\n const operatorSymbol = getOperatorSymbol(condition.operator);\r\n return `${component.basic?.label || 'Value'}: Value ${currentValue} exceeds threshold ${operatorSymbol} ${thresholdValue}`;\r\n };\r\n\r\n const getCompactMessage = (): string => {\r\n const operatorSymbol = getOperatorSymbol(condition.operator);\r\n return `Threshold ${operatorSymbol} ${thresholdValue}`;\r\n };\r\n\r\n const handleRaiseIssueClick = useCallback(async () => {\r\n if (isIssueRaised || localIssueRaised) {\r\n // If we already have the issue stored (from recent creation), use it\r\n if (issue) {\r\n setShowRaiseIssueModal(true);\r\n return;\r\n }\r\n \r\n // Otherwise, fetch the issue data before opening modal\r\n setIsLoadingIssue(true);\r\n try {\r\n // Stub implementation - in a real app, this would fetch from your API\r\n // For now, we'll just open the modal without fetching\r\n // You can replace this with your own issue fetching logic\r\n setIssue(null);\r\n setShowRaiseIssueModal(true);\r\n } catch (error: any) {\r\n console.error('Error fetching issue:', error);\r\n toastService.showError('Failed to load issue details');\r\n } finally {\r\n setIsLoadingIssue(false);\r\n }\r\n } else {\r\n // For new issues, just open the modal\r\n setIssue(null);\r\n setShowRaiseIssueModal(true);\r\n }\r\n }, [isIssueRaised, localIssueRaised, formTemplateId, component, issue]);\r\n\r\n const handleRaiseIssueClose = useCallback(() => {\r\n setShowRaiseIssueModal(false);\r\n // Don't clear issue if it was just created - keep it for viewing\r\n // Only clear if we're not in \"issue raised\" state\r\n if (!isIssueRaised && !localIssueRaised) {\r\n setIssue(null);\r\n }\r\n }, [isIssueRaised, localIssueRaised]);\r\n\r\n const handleRaiseIssueSuccess = useCallback((createdIssue?: IIssue) => {\r\n setShowRaiseIssueModal(false);\r\n // Store the created issue if provided, so we can show it immediately when viewing\r\n if (createdIssue) {\r\n setIssue(createdIssue);\r\n } else {\r\n setIssue(null); // Clear issue state so next view will fetch the new issue\r\n }\r\n // Immediately set local state to hide the alert\r\n setLocalIssueRaised(true);\r\n // Notify parent that issue has been raised for this condition\r\n // Call immediately to ensure state updates\r\n if (onIssueRaised && condition?.id) {\r\n onIssueRaised(condition.id);\r\n }\r\n }, [onIssueRaised, condition]);\r\n\r\n // If issue is raised (either from prop or local state), show only an icon with primary color (like other components)\r\n if (isIssueRaised || localIssueRaised) {\r\n return (\r\n <>\r\n <div className=\"threshold-issue-icon-only\">\r\n <button\r\n type=\"button\"\r\n onClick={handleRaiseIssueClick}\r\n className=\"threshold-issue-icon-button\"\r\n disabled={isLoadingIssue}\r\n title=\"View Raised Issue\"\r\n >\r\n <AlertTriangle className=\"threshold-issue-icon\" size={16} fill=\"currentColor\" />\r\n </button>\r\n </div>\r\n\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={component}\r\n formTemplateId={formTemplateId}\r\n notes=\"\"\r\n attachments={null}\r\n issue={issue}\r\n />\r\n )}\r\n </>\r\n );\r\n }\r\n\r\n // Show compact version for small screens/tables\r\n if (compact) {\r\n return (\r\n <>\r\n <div className=\"threshold-alert threshold-alert-unresolved threshold-alert-compact\">\r\n <div className=\"threshold-alert-border\" />\r\n <div className=\"threshold-alert-content-compact\">\r\n <AlertTriangle className=\"threshold-alert-icon-compact\" size={14} />\r\n <span className=\"threshold-alert-message-compact\">\r\n {getCompactMessage()}\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={handleRaiseIssueClick}\r\n className=\"threshold-alert-raise-issue-btn-compact\"\r\n title=\"Raise Issue\"\r\n >\r\n Raise Issue\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={component}\r\n formTemplateId={formTemplateId}\r\n notes=\"\"\r\n attachments={null}\r\n issue={issue}\r\n />\r\n )}\r\n </>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n <div className=\"threshold-alert threshold-alert-unresolved\">\r\n <div className=\"threshold-alert-border\" />\r\n <div className=\"threshold-alert-content\">\r\n <div className=\"threshold-alert-header\">\r\n <div className=\"threshold-alert-title-group\">\r\n <AlertTriangle className=\"threshold-alert-icon\" size={20} />\r\n <span className=\"threshold-alert-title\">\r\n Threshold Condition Met - Action Required\r\n </span>\r\n </div>\r\n </div>\r\n \r\n <div className=\"threshold-alert-message\">\r\n {getConditionMessage()}\r\n <span className=\"threshold-alert-warning\"> You must raise an issue before submitting the form.</span>\r\n </div>\r\n\r\n <div className=\"threshold-alert-buttons\">\r\n <button\r\n type=\"button\"\r\n onClick={handleRaiseIssueClick}\r\n className=\"threshold-alert-raise-issue-btn\"\r\n >\r\n Raise Issue Now\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={component}\r\n formTemplateId={formTemplateId}\r\n notes=\"\"\r\n attachments={null}\r\n issue={issue}\r\n />\r\n )}\r\n </>\r\n );\r\n};\r\n\r\n","import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';\r\nimport { \r\n ITextInputComponent, \r\n INumberInputComponent, \r\n IEmailInputComponent, \r\n TInputComponentType,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\nimport { ThresholdAlert } from '../../ThresholdAlert';\r\n\r\ninterface DfFormInputProps {\r\n id: string;\r\n properties: ITextInputComponent | INumberInputComponent | IEmailInputComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n inputType?: TInputComponentType;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n formTemplateId?: string;\r\n onThresholdIssueRaised?: (conditionId: string) => void;\r\n raisedThresholdIssues?: Set<string>; // Track which threshold issues have been raised\r\n}\r\n\r\nexport const DfFormInput: React.FC<DfFormInputProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n inputType = 'text',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'test',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false,\r\n formTemplateId,\r\n onThresholdIssueRaised,\r\n raisedThresholdIssues = new Set()\r\n}) => {\r\n // Ensure formValue is always a string to prevent [object Object] errors\r\n const getStringValue = (val: any): string => {\r\n if (val === null || val === undefined) return '';\r\n if (typeof val === 'string') return val;\r\n if (typeof val === 'number') return String(val);\r\n if (typeof val === 'boolean') return String(val);\r\n // If it's an object, try to extract a meaningful value or return empty string\r\n if (typeof val === 'object') {\r\n if (Array.isArray(val)) return '';\r\n // Try common object properties\r\n if ('value' in val) return getStringValue(val.value);\r\n if ('label' in val) return getStringValue(val.label);\r\n return '';\r\n }\r\n return String(val || '');\r\n };\r\n\r\n // CRITICAL: Use a ref to track the component's unique ID to prevent value sharing\r\n const componentIdRef = useRef<string>(id);\r\n const inputWrapperRef = useRef<HTMLDivElement>(null);\r\n \r\n // Update ref if ID changes (shouldn't happen, but safety check)\r\n useEffect(() => {\r\n if (id !== componentIdRef.current) {\r\n console.warn(`[DfFormInput] Component ID changed from ${componentIdRef.current} to ${id}`);\r\n componentIdRef.current = id;\r\n }\r\n }, [id]);\r\n \r\n const initialValue = getStringValue(formValue || properties?.basic?.defaultValue || '');\r\n const [value, setValue] = useState<string>(initialValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [isFocused, setIsFocused] = useState<boolean>(false);\r\n const [dismissedAlerts, setDismissedAlerts] = useState<Set<string>>(new Set());\r\n const [previousValue, setPreviousValue] = useState<string>(initialValue);\r\n\r\n // Determine input type based on component name\r\n const getInputType = (): TInputComponentType => {\r\n if (inputType) return inputType;\r\n \r\n const name = properties?.name;\r\n if (name === 'text-input') return 'text';\r\n if (name === 'number-input') return 'number';\r\n if (name === 'email-input') return 'email';\r\n \r\n return 'text';\r\n };\r\n\r\n // Build validation rules\r\n const buildValidationRules = () => {\r\n const rules: any = {};\r\n \r\n if (properties?.validation?.required) {\r\n rules.required = true;\r\n }\r\n \r\n if (getInputType() === 'email') {\r\n rules.email = true;\r\n }\r\n \r\n if (getInputType() === 'text') {\r\n const textValidation = properties.validation as ITextInputComponent['validation'];\r\n if (textValidation?.minLength) rules.minLength = textValidation.minLength;\r\n if (textValidation?.maxLength) rules.maxLength = textValidation.maxLength;\r\n }\r\n \r\n if (getInputType() === 'number') {\r\n const numberValidation = properties.validation as INumberInputComponent['validation'];\r\n if (numberValidation?.min) rules.min = numberValidation.min;\r\n if (numberValidation?.max) rules.max = numberValidation.max;\r\n if (numberValidation?.lowerLimit !== undefined) rules.lowerLimit = numberValidation.lowerLimit;\r\n if (numberValidation?.upperLimit !== undefined) rules.upperLimit = numberValidation.upperLimit;\r\n }\r\n \r\n return rules;\r\n };\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const rules = buildValidationRules();\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (rules.required && (!val || val.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n // Email validation\r\n if (rules.email && val && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/.test(val)) {\r\n errors.email = true;\r\n isValid = false;\r\n }\r\n\r\n // Length validations\r\n if (rules.minLength && val && val.length < rules.minLength) {\r\n errors.minLength = true;\r\n isValid = false;\r\n }\r\n\r\n if (rules.maxLength && val && val.length > rules.maxLength) {\r\n errors.maxLength = true;\r\n isValid = false;\r\n }\r\n\r\n // Number validations\r\n // CRITICAL: Only validate if value is not empty and is a valid number\r\n if (getInputType() === 'number' && val && val.trim() !== '') {\r\n // Remove any whitespace and check if it's a valid number string\r\n const trimmedVal = val.trim();\r\n // CRITICAL FIX: Updated regex to properly accept integers, decimals, and scientific notation\r\n // Pattern: optional minus, digits (required), optional decimal point with digits, optional scientific notation\r\n // This allows: \"33\", \"33.5\", \"-33\", \"33.5e2\", etc.\r\n const isValidNumberFormat = /^-?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(trimmedVal);\r\n \r\n if (!isValidNumberFormat) {\r\n // Invalid number format - only set pattern error if it's clearly not a number\r\n // Don't set pattern error for partial input during typing (e.g., \"-\", \".\", \"3.\", \"-3.\")\r\n const isPartialInput = /^-?\\.?$/.test(trimmedVal) || /^-?\\d+\\.?$/.test(trimmedVal);\r\n if (trimmedVal.length > 0 && !isPartialInput) {\r\n errors.pattern = true;\r\n isValid = false;\r\n }\r\n } else {\r\n // Valid number format - parse and check min/max/limits\r\n const numValue = parseFloat(trimmedVal);\r\n if (isNaN(numValue)) {\r\n // This shouldn't happen if format is valid, but check anyway\r\n // Only set error if it's not a partial input\r\n const isPartialInput = /^-?\\.?$/.test(trimmedVal) || /^-?\\d+\\.?$/.test(trimmedVal);\r\n if (!isPartialInput) {\r\n errors.pattern = true;\r\n isValid = false;\r\n }\r\n } else {\r\n // Valid number - check min/max/limits only if they are defined\r\n if (rules.min !== undefined && numValue < rules.min) {\r\n errors.min = true;\r\n isValid = false;\r\n }\r\n if (rules.max !== undefined && numValue > rules.max) {\r\n errors.max = true;\r\n isValid = false;\r\n }\r\n if (rules.lowerLimit !== undefined && numValue < rules.lowerLimit) {\r\n errors.lowerLimit = true;\r\n isValid = false;\r\n }\r\n if (rules.upperLimit !== undefined && numValue > rules.upperLimit) {\r\n errors.upperLimit = true;\r\n isValid = false;\r\n }\r\n // If no validation errors, number is valid - clear pattern error\r\n if (isValid) {\r\n errors.pattern = false;\r\n }\r\n }\r\n }\r\n } else if (getInputType() === 'number' && val && val.trim() === '') {\r\n // Empty number field - only invalid if required\r\n // Don't set pattern error for empty values\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties, getInputType]);\r\n\r\n // Handle value changes\r\n // CRITICAL: Use componentIdRef to ensure we're using the correct component ID\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n // CRITICAL: Use componentIdRef.current to ensure we're using the correct ID\r\n // This prevents ID collisions if the id prop somehow changes\r\n const currentId = componentIdRef.current;\r\n const change: IFormControlChange = {\r\n id: currentId, // Use the ref to ensure correct ID\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n \r\n // Debug: Log value changes to identify issues\r\n if (currentId !== id) {\r\n console.error(`[DfFormInput] ID mismatch in handleValueChange! ref: ${currentId}, prop: ${id}`);\r\n }\r\n \r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField, componentIdRef]);\r\n\r\n // Handle input change\r\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = e.target.value;\r\n handleValueChange(newValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n setIsFocused(true);\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsFocused(false);\r\n setIsTouched(true);\r\n \r\n // Always trigger validation on blur in test mode for any field with validation rules\r\n if (mode === 'test' && onValueChange) {\r\n const validation = validateField(value);\r\n const change: IFormControlChange = {\r\n id,\r\n value: value,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n \r\n onValueChange(change);\r\n }\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Reset touched state and value when switching modes\r\n useEffect(() => {\r\n if (mode === 'edit') {\r\n setIsTouched(false);\r\n // Reset value to default value when switching to edit mode\r\n const defaultValue = properties?.basic?.defaultValue || '';\r\n setValue(defaultValue);\r\n } else if (mode === 'test') {\r\n setIsTouched(false);\r\n // Reset value to empty when switching to test mode for fresh start\r\n setValue('');\r\n }\r\n }, [mode, properties?.basic?.defaultValue]);\r\n\r\n // Update value when formValue prop changes (but don't override user input)\r\n // CRITICAL: Only update if formValue is actually for THIS component's ID\r\n // Use componentIdRef to ensure we're checking against the correct component ID\r\n useEffect(() => {\r\n const currentComponentId = componentIdRef.current;\r\n const newValue = getStringValue(formValue || properties?.basic?.defaultValue || '');\r\n \r\n // CRITICAL: Only update if this formValue is actually meant for this component\r\n // Check if formValue matches what should be stored for this component's ID\r\n // This prevents cross-component value syncing when IDs are duplicated\r\n \r\n // Only update if the new value is different and we're not currently focused\r\n // Also, don't override with empty value if user has typed something\r\n // CRITICAL FIX: Don't reset user input when formValue becomes empty\r\n if (newValue !== value && !isFocused && !(newValue === '' && String(value || '').trim() !== '')) {\r\n // Additional check: Only update if formValue is not undefined/null (meaning it's actually set for this component)\r\n // If formValue is undefined, it means this component hasn't been initialized yet, so don't override local state\r\n if (formValue !== undefined && formValue !== null) {\r\n // Double-check: Only update if the ID matches (safety check against ID collisions)\r\n if (currentComponentId === id) {\r\n setValue(newValue);\r\n } else {\r\n console.error(`[DfFormInput] ID mismatch! componentIdRef: ${currentComponentId}, prop id: ${id}`);\r\n }\r\n }\r\n } else if (newValue === '' && String(value || '').trim() !== '' && !isFocused) {\r\n // Don't clear user input\r\n }\r\n }, [formValue, value, isFocused, properties?.basic?.defaultValue, id]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clear value when switching away from test mode\r\n useEffect(() => {\r\n if (mode !== 'test') {\r\n setValue('');\r\n }\r\n }, [mode]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get input classes\r\n const getInputClasses = (): string => {\r\n const base = 'form-control';\r\n \r\n // Only show validation errors in test mode\r\n if (mode === 'test') {\r\n const validation = validateField(value);\r\n const hasLocalError = !validation.isValid && isTouched;\r\n const hasExternalError = validationErrors[id] && (isTouched || formSubmitted);\r\n const error = (hasLocalError || hasExternalError) ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n }\r\n \r\n return `${base} ${className}`.trim();\r\n };\r\n\r\n // Evaluate threshold conditions\r\n const evaluateThresholdCondition = useCallback((condition: any, currentVal: string | number): boolean => {\r\n if (!currentVal || currentVal === '') return false;\r\n \r\n const numValue = typeof currentVal === 'string' ? parseFloat(currentVal) : currentVal;\r\n const thresholdValue = typeof condition.value === 'string' ? parseFloat(condition.value) : condition.value;\r\n \r\n if (isNaN(numValue) || isNaN(thresholdValue)) return false;\r\n\r\n switch (condition.operator) {\r\n case 'greaterThan':\r\n return numValue > thresholdValue;\r\n case 'lessThan':\r\n return numValue < thresholdValue;\r\n case 'greaterThanOrEqual':\r\n return numValue >= thresholdValue;\r\n case 'lessThanOrEqual':\r\n return numValue <= thresholdValue;\r\n case 'equals':\r\n return numValue === thresholdValue;\r\n case 'notEquals':\r\n return numValue !== thresholdValue;\r\n default:\r\n return false;\r\n }\r\n }, []);\r\n\r\n // Get condition conditions and evaluate them\r\n const thresholdConditions = useMemo(() => {\r\n return (properties as any)?.condition?.conditions || [];\r\n }, [(properties as any)?.condition]);\r\n\r\n // Clear dismissed alerts when value changes\r\n useEffect(() => {\r\n if (value !== previousValue) {\r\n setDismissedAlerts(new Set());\r\n setPreviousValue(value);\r\n }\r\n }, [value, previousValue]);\r\n\r\n const activeThresholdCondition = useMemo(() => {\r\n if (mode !== 'test' || !value || value === '') {\r\n return null;\r\n }\r\n \r\n // Check which conditions are currently met\r\n const metConditions = thresholdConditions.filter((condition: any) => \r\n evaluateThresholdCondition(condition, value)\r\n );\r\n \r\n // If no conditions are met, return null\r\n if (metConditions.length === 0) {\r\n return null;\r\n }\r\n \r\n // Find the first condition that is met and not dismissed\r\n // Note: We still return the condition even if an issue is raised, so we can show the indicator\r\n for (const condition of metConditions) {\r\n if (!dismissedAlerts.has(condition.id)) {\r\n return condition;\r\n }\r\n }\r\n \r\n // If all met conditions are dismissed, return null (alert won't show)\r\n return null;\r\n }, [value, thresholdConditions, dismissedAlerts, mode, evaluateThresholdCondition, raisedThresholdIssues]);\r\n\r\n\r\n const handleDismissAlert = useCallback((conditionId: string) => {\r\n setDismissedAlerts(prev => new Set(prev).add(conditionId));\r\n }, []);\r\n\r\n const currentInputType = getInputType();\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <>\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\" ref={inputWrapperRef}>\r\n <input\r\n type={currentInputType}\r\n id={id}\r\n value={value}\r\n onChange={handleInputChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n placeholder={properties.basic.placeholder}\r\n disabled={shouldDisable}\r\n readOnly={readonly || properties?.validation?.readonly}\r\n className={getInputClasses()}\r\n />\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(value)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n\r\n\r\n </div>\r\n </div>\r\n {/* Threshold Alert - Show when condition is met */}\r\n {activeThresholdCondition && mode === 'test' && (() => {\r\n const issueRaised = raisedThresholdIssues?.has(activeThresholdCondition.id) || false;\r\n // Detect if we're inside a table cell or datagrid for compact mode\r\n // Check if parent element is a table cell or datagrid\r\n const isInTable = inputWrapperRef.current?.closest('.table-cell') !== null ||\r\n inputWrapperRef.current?.closest('.cell-content') !== null ||\r\n inputWrapperRef.current?.closest('.datagrid-table-view') !== null ||\r\n inputWrapperRef.current?.closest('.datagrid-list-view') !== null ||\r\n className.includes('table-cell') || \r\n className.includes('cell-content');\r\n return (\r\n <ThresholdAlert\r\n key={`${activeThresholdCondition.id}-${issueRaised}`}\r\n component={properties}\r\n condition={activeThresholdCondition}\r\n currentValue={value}\r\n thresholdValue={activeThresholdCondition.value}\r\n formTemplateId={formTemplateId}\r\n onDismiss={() => handleDismissAlert(activeThresholdCondition.id)}\r\n onIssueRaised={onThresholdIssueRaised}\r\n isIssueRaised={issueRaised}\r\n compact={isInTable}\r\n />\r\n );\r\n })()}\r\n </>\r\n );\r\n};\r\n\r\nexport default DfFormInput;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ITextareaComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormTextareaProps {\r\n id: string;\r\n properties: ITextareaComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormTextarea: React.FC<DfFormTextareaProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [value, setValue] = useState<string>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!val || val.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n // Length validations\r\n if (properties?.validation?.minLength && val && val.length < properties.validation.minLength) {\r\n errors.minLength = true;\r\n isValid = false;\r\n }\r\n\r\n if (properties?.validation?.maxLength && val && val.length > properties.validation.maxLength) {\r\n errors.maxLength = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle textarea change\r\n const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n const newValue = e.target.value;\r\n handleValueChange(newValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes (only on initial load or when component is reset)\r\n useEffect(() => {\r\n // Only update if the current value is empty (initial state) or if formValue is explicitly set\r\n // This prevents the component from resetting user input when they blur the field\r\n if (value === '' && formValue !== '') {\r\n setValue(formValue);\r\n }\r\n }, [formValue]); // Remove value and isFocused from dependencies to prevent reset on blur\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clear value when switching away from test mode\r\n useEffect(() => {\r\n if (mode !== 'test') {\r\n setValue('');\r\n }\r\n }, [mode]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get textarea classes\r\n const getTextareaClasses = (): string => {\r\n const base = 'form-textarea';\r\n const validation = validateField(value);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n const rows = properties?.validation?.rows || 4;\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <textarea\r\n id={id}\r\n value={value}\r\n onChange={handleTextareaChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n placeholder={properties.basic.placeholder}\r\n disabled={shouldDisable}\r\n readOnly={readonly || properties?.validation?.readonly}\r\n rows={rows}\r\n className={getTextareaClasses()}\r\n />\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(value)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormTextarea;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ISelectComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormSelectProps {\r\n id: string;\r\n properties: ISelectComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string | string[];\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormSelect: React.FC<DfFormSelectProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [selectedValue, setSelectedValue] = useState<string | string[]>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Check if multiple selection is enabled\r\n const isMultiple = properties?.validation?.multiple || false;\r\n\r\n // Validate field\r\n const validateField = useCallback((value: string | string[]): { isValid: boolean; errors: Record<string, boolean> } => {\r\n const errors: Record<string, boolean> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required) {\r\n if (isMultiple) {\r\n if (!Array.isArray(value) || value.length === 0) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n } else {\r\n if (!value || (typeof value === 'string' && value.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n }\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties, isMultiple]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string | string[]) => {\r\n setSelectedValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle select change\r\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\r\n if (isMultiple) {\r\n const selectedOptions = Array.from(e.target.selectedOptions, option => option.value);\r\n handleValueChange(selectedOptions);\r\n } else {\r\n handleValueChange(e.target.value);\r\n }\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n if (JSON.stringify(formValue) !== JSON.stringify(selectedValue)) {\r\n setSelectedValue(formValue);\r\n }\r\n }, [formValue, selectedValue]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get select classes\r\n const getSelectClasses = (): string => {\r\n const base = 'form-select';\r\n const validation = validateField(selectedValue);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <select\r\n id={id}\r\n value={isMultiple ? selectedValue as string[] : selectedValue as string}\r\n onChange={handleSelectChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable}\r\n multiple={isMultiple}\r\n className={getSelectClasses()}\r\n >\r\n {!isMultiple && (\r\n <option value=\"\">\r\n {properties.basic.placeholder || 'Select an option'}\r\n </option>\r\n )}\r\n {(properties.options || []).map((option, index) => (\r\n <option \r\n key={index} \r\n value={option.value}\r\n disabled={option.disabled}\r\n >\r\n {option.label}\r\n </option>\r\n ))}\r\n </select>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormSelect;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ICheckboxComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormCheckboxProps {\r\n id: string;\r\n properties: ICheckboxComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string[];\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormCheckbox: React.FC<DfFormCheckboxProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = [],\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n \r\n // Use formValue directly instead of local state to avoid conflicts\r\n const selectedValues = Array.isArray(formValue) ? formValue : [];\r\n\r\n // Validate field\r\n const validateField = useCallback((values: string[]): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && values.length === 0) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValues: string[]) => {\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValues);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValues,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField, selectedValues]);\r\n\r\n // Handle checkbox change\r\n const handleCheckboxChange = (optionValue: string, checked: boolean) => {\r\n \r\n let newValues: string[];\r\n \r\n if (checked) {\r\n newValues = [...selectedValues, optionValue];\r\n } else {\r\n newValues = selectedValues.filter(value => value !== optionValue);\r\n }\r\n \r\n handleValueChange(newValues);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Log formValue changes for debugging\r\n useEffect(() => {\r\n }, [formValue, id, selectedValues]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get layout class for inline/vertical layout\r\n const getLayoutClass = (): string => {\r\n return properties?.basic?.inlineLayout ? 'inline-layout' : 'vertical-layout';\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <>\r\n <div className={`form-group checkbox-group ${getLabelAlignmentClass()} ${getLayoutClass()} ${className}`}>\r\n {!hideLabel && properties.basic.label ? (\r\n <>\r\n <label className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n \r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onChange={(e) => {\r\n handleCheckboxChange(option.value, e.target.checked);\r\n }}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValues)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </>\r\n ) : (\r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onChange={(e) => {\r\n handleCheckboxChange(option.value, e.target.checked);\r\n }}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValues)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n )}\r\n\r\n </div>\r\n </>\r\n );\r\n};\r\n\r\nexport default DfFormCheckbox;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n IRadioComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormRadioProps {\r\n id: string;\r\n properties: IRadioComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormRadio: React.FC<DfFormRadioProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [selectedValue, setSelectedValue] = useState<string>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((value: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!value || value.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setSelectedValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle radio change\r\n const handleRadioChange = (optionValue: string) => {\r\n handleValueChange(optionValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n if (formValue !== selectedValue) {\r\n setSelectedValue(formValue);\r\n }\r\n }, [formValue, selectedValue]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get layout class for inline/vertical layout\r\n const getLayoutClass = (): string => {\r\n return properties?.basic?.inlineLayout ? 'inline-layout' : 'vertical-layout';\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <>\r\n <div className={`form-group radio-group ${getLabelAlignmentClass()} ${getLayoutClass()} ${className}`}>\r\n {!hideLabel && properties.basic.label ? (\r\n <>\r\n <label className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n \r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"radio\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValue === option.value}\r\n onChange={() => handleRadioChange(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </>\r\n ) : (\r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"radio\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValue === option.value}\r\n onChange={() => handleRadioChange(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n )}\r\n\r\n </div>\r\n </>\r\n );\r\n};\r\n\r\nexport default DfFormRadio;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ISegmentComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\nimport './df-form-segment.scss';\r\n\r\ninterface DfFormSegmentProps {\r\n id: string;\r\n properties: ISegmentComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormSegment: React.FC<DfFormSegmentProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [selectedValue, setSelectedValue] = useState<string>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((value: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!value || value.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n\r\n // Handle segment button click\r\n const handleSegmentClick = useCallback((optionValue: string) => {\r\n setSelectedValue(optionValue);\r\n setIsTouched(true);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(optionValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: optionValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n } as IFormControlChange;\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n if (formValue !== selectedValue) {\r\n setSelectedValue(formValue);\r\n }\r\n }, [formValue, selectedValue]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get segment container class (matching Angular approach)\r\n const getSegmentContainerClass = (): string => {\r\n return properties?.basic?.inlineLayout ? 'inline-layout' : 'grid-layout';\r\n };\r\n\r\n\r\n\r\n\r\n // Get button type for styling (pass/fail) - fallback for backward compatibility\r\n const getButtonType = (optionValue: string): 'pass' | 'fail' => {\r\n const value = optionValue?.toLowerCase();\r\n if (value === 'pass' || value === 'yes') {\r\n return 'pass';\r\n }\r\n if (value === 'fail' || value === 'no') {\r\n return 'fail';\r\n }\r\n return 'pass';\r\n };\r\n\r\n // Get button icon based on option - use custom icon if available, otherwise fallback\r\n const getButtonIcon = (option: any): string => {\r\n if (option?.icon !== undefined && option.icon !== '') {\r\n return option.icon;\r\n }\r\n // Fallback to old logic\r\n const buttonType = getButtonType(option?.value || option);\r\n return buttonType === 'pass' ? '✓' : '×';\r\n };\r\n\r\n // Get button styles based on option - use custom colors if available\r\n const getButtonStyles = (option: any, isSelected: boolean): React.CSSProperties => {\r\n const hasCustomColors = option?.color || option?.backgroundColor;\r\n \r\n if (hasCustomColors) {\r\n return {\r\n color: isSelected ? '#ffffff' : (option.color || '#00814b'),\r\n backgroundColor: isSelected ? (option.color || '#00814b') : (option.backgroundColor || '#34bd4914'),\r\n borderColor: option.color || '#00814b'\r\n };\r\n }\r\n \r\n // Fallback to old logic - no inline styles, use CSS classes\r\n return {};\r\n };\r\n\r\n // Get button class - use custom class if custom colors exist, otherwise use pass/fail\r\n const getButtonClass = (option: any): string => {\r\n const hasCustomColors = option?.color || option?.backgroundColor;\r\n \r\n if (hasCustomColors) {\r\n return 'segment-button-label segment-button-custom';\r\n }\r\n \r\n // Fallback to old logic\r\n const buttonType = getButtonType(option?.value || option);\r\n return `segment-button-label ${buttonType === 'pass' ? 'pass-button' : 'fail-button'}`;\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n return (\r\n <>\r\n <div className={`form-group segment-group ${getLabelAlignmentClass()} ${className}`}>\r\n {!hideLabel && properties.basic.label ? (\r\n <>\r\n <label className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n \r\n <div className=\"form-segment-wrapper\">\r\n <div className={`form-segment-container ${getSegmentContainerClass()}`}>\r\n {(properties.options || []).map((option, index) => {\r\n const isSelected = selectedValue === option.value;\r\n const buttonStyles = getButtonStyles(option, isSelected);\r\n const buttonClass = getButtonClass(option);\r\n const buttonIcon = getButtonIcon(option);\r\n \r\n return (\r\n <div key={index} className={`form-segment-option ${isSelected ? 'selected' : ''}`}>\r\n <input\r\n type=\"radio\"\r\n id={`${id}_option_${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={isSelected}\r\n onChange={() => !shouldDisable && !option.disabled && handleSegmentClick(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-segment-radio\"\r\n />\r\n <label\r\n htmlFor={`${id}_option_${index}`}\r\n className={buttonClass}\r\n style={Object.keys(buttonStyles).length > 0 ? buttonStyles : undefined}\r\n >\r\n {buttonIcon && <span className=\"segment-icon\">{buttonIcon}</span>}\r\n <span className=\"segment-text\">{option.value}</span>\r\n </label>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n\r\n </div>\r\n\r\n </>\r\n ) : (\r\n <div className=\"form-segment-wrapper\">\r\n <div className={`form-segment-container ${getSegmentContainerClass()}`}>\r\n {(properties.options || []).map((option, index) => {\r\n const isSelected = selectedValue === option.value;\r\n const buttonStyles = getButtonStyles(option, isSelected);\r\n const buttonClass = getButtonClass(option);\r\n const buttonIcon = getButtonIcon(option);\r\n \r\n return (\r\n <div key={index} className={`form-segment-option ${isSelected ? 'selected' : ''}`}>\r\n <input\r\n type=\"radio\"\r\n id={`${id}_option_${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={isSelected}\r\n onChange={() => !shouldDisable && !option.disabled && handleSegmentClick(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-segment-radio\"\r\n />\r\n <label\r\n htmlFor={`${id}_option_${index}`}\r\n className={buttonClass}\r\n style={Object.keys(buttonStyles).length > 0 ? buttonStyles : undefined}\r\n >\r\n {buttonIcon && <span className=\"segment-icon\">{buttonIcon}</span>}\r\n <span className=\"segment-text\">{option.value}</span>\r\n </label>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n \r\n\r\n\r\n\r\n </div>\r\n )}\r\n\r\n \r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </>\r\n \r\n );\r\n};\r\n\r\n\r\n\r\nexport default DfFormSegment;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n IDateComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormDateTimeProps {\r\n id: string;\r\n properties: IDateComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormDateTime: React.FC<DfFormDateTimeProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n // Helper function to convert formValue to proper date string format\r\n const convertToDateString = useCallback((val: any): string => {\r\n if (!val) return '';\r\n \r\n // If it's already a string, check if it's a valid date format\r\n if (typeof val === 'string') {\r\n // Check if it's already in yyyy-MM-dd format\r\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(val)) {\r\n return val;\r\n }\r\n // Check if it's in datetime-local format (yyyy-MM-ddTHH:mm)\r\n if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/.test(val)) {\r\n return val;\r\n }\r\n // Try to parse as date and convert\r\n const date = new Date(val);\r\n if (!isNaN(date.getTime())) {\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n if (dateTimeMode === 'datetime') {\r\n // Format as datetime-local: yyyy-MM-ddTHH:mm\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const day = String(date.getDate()).padStart(2, '0');\r\n const hours = String(date.getHours()).padStart(2, '0');\r\n const minutes = String(date.getMinutes()).padStart(2, '0');\r\n return `${year}-${month}-${day}T${hours}:${minutes}`;\r\n } else if (dateTimeMode === 'time') {\r\n // Format as time: HH:mm\r\n const hours = String(date.getHours()).padStart(2, '0');\r\n const minutes = String(date.getMinutes()).padStart(2, '0');\r\n return `${hours}:${minutes}`;\r\n } else {\r\n // Format as date: yyyy-MM-dd\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const day = String(date.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n }\r\n }\r\n return val; // Return as-is if can't parse\r\n }\r\n \r\n // If it's a Date object\r\n if (val instanceof Date) {\r\n if (isNaN(val.getTime())) return '';\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n if (dateTimeMode === 'datetime') {\r\n const year = val.getFullYear();\r\n const month = String(val.getMonth() + 1).padStart(2, '0');\r\n const day = String(val.getDate()).padStart(2, '0');\r\n const hours = String(val.getHours()).padStart(2, '0');\r\n const minutes = String(val.getMinutes()).padStart(2, '0');\r\n return `${year}-${month}-${day}T${hours}:${minutes}`;\r\n } else if (dateTimeMode === 'time') {\r\n const hours = String(val.getHours()).padStart(2, '0');\r\n const minutes = String(val.getMinutes()).padStart(2, '0');\r\n return `${hours}:${minutes}`;\r\n } else {\r\n const year = val.getFullYear();\r\n const month = String(val.getMonth() + 1).padStart(2, '0');\r\n const day = String(val.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n }\r\n }\r\n \r\n // If it's an object, try to extract date value\r\n if (typeof val === 'object' && val !== null) {\r\n // Try common date object properties\r\n if ('value' in val && val.value) {\r\n return convertToDateString(val.value);\r\n }\r\n if ('date' in val && val.date) {\r\n return convertToDateString(val.date);\r\n }\r\n // Try to parse as ISO string if it has toString\r\n try {\r\n const dateStr = String(val);\r\n const date = new Date(dateStr);\r\n if (!isNaN(date.getTime())) {\r\n return convertToDateString(date);\r\n }\r\n } catch (e) {\r\n // Ignore\r\n }\r\n return '';\r\n }\r\n \r\n return '';\r\n }, [properties]);\r\n\r\n const initialValue = convertToDateString(formValue);\r\n const [value, setValue] = useState<string>(initialValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [isFocused, setIsFocused] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Get dateTimeMode to determine validation type\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n const trimmedVal = val ? String(val).trim() : '';\r\n\r\n // Required validation - only check if field is required\r\n if (properties?.validation?.required && (!trimmedVal || trimmedVal === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n\r\n // Only validate format if there's a value (non-required fields can be empty)\r\n if (trimmedVal && trimmedVal !== '') {\r\n if (dateTimeMode === 'time') {\r\n // Validate time format (HH:MM or HH:MM:SS)\r\n // HTML5 time input returns format HH:MM or HH:MM:SS\r\n const timeRegex = /^([0-1][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;\r\n if (!timeRegex.test(trimmedVal)) {\r\n errors.invalidDate = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n // Time is valid, no errors\r\n } else if (dateTimeMode === 'datetime') {\r\n // Validate datetime format\r\n const selectedDate = new Date(trimmedVal);\r\n if (isNaN(selectedDate.getTime())) {\r\n errors.invalidDate = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n \r\n // Date range validations for datetime\r\n if (properties?.validation?.minDate) {\r\n const minDate = new Date(properties.validation.minDate);\r\n if (selectedDate < minDate) {\r\n errors.minDate = true;\r\n errors.minDateMessage = `Date and time must be on or after ${minDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n\r\n if (properties?.validation?.maxDate) {\r\n const maxDate = new Date(properties.validation.maxDate);\r\n if (selectedDate > maxDate) {\r\n errors.maxDate = true;\r\n errors.maxDateMessage = `Date and time must be on or before ${maxDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n } else {\r\n // Validate date format (date mode)\r\n const selectedDate = new Date(trimmedVal);\r\n if (isNaN(selectedDate.getTime())) {\r\n errors.invalidDate = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n \r\n // Date range validations for date\r\n if (properties?.validation?.minDate) {\r\n const minDate = new Date(properties.validation.minDate);\r\n if (selectedDate < minDate) {\r\n errors.minDate = true;\r\n errors.minDateMessage = `Date must be on or after ${minDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n\r\n if (properties?.validation?.maxDate) {\r\n const maxDate = new Date(properties.validation.maxDate);\r\n if (selectedDate > maxDate) {\r\n errors.maxDate = true;\r\n errors.maxDateMessage = `Date must be on or before ${maxDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle date change\r\n const handleDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = e.target.value;\r\n handleValueChange(newValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n setIsFocused(true);\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsFocused(false);\r\n setIsTouched(true);\r\n \r\n // Validate on blur and notify parent\r\n if (onValueChange) {\r\n const validation = validateField(value);\r\n const change: IFormControlChange = {\r\n id,\r\n value: value,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n const convertedValue = convertToDateString(formValue);\r\n if (convertedValue !== value && !isFocused) {\r\n setValue(convertedValue);\r\n }\r\n }, [formValue, value, isFocused, convertToDateString]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get date classes\r\n const getDateClasses = (): string => {\r\n const base = 'form-date';\r\n const validation = validateField(value);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n // Determine input type based on dateTimeMode\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n const getInputType = (): string => {\r\n switch (dateTimeMode) {\r\n case 'time':\r\n return 'time';\r\n case 'datetime':\r\n return 'datetime-local';\r\n case 'date':\r\n default:\r\n return 'date';\r\n }\r\n };\r\n\r\n const inputType = getInputType();\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <input\r\n type={inputType}\r\n id={id}\r\n value={value}\r\n onChange={handleDateChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable}\r\n readOnly={readonly || properties?.validation?.readonly}\r\n min={properties?.validation?.minDate}\r\n max={properties?.validation?.maxDate}\r\n className={getDateClasses()}\r\n />\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(value)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormDateTime;\r\n","import React, { useState, useEffect, useRef, useCallback } from 'react';\r\nimport { \r\n ISignatureComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormSignatureProps {\r\n id: string;\r\n properties: ISignatureComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormSignature: React.FC<DfFormSignatureProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const [isDrawing, setIsDrawing] = useState<boolean>(false);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [signatureData, setSignatureData] = useState<string>(formValue);\r\n const [isSaving, setIsSaving] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!val || val.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setSignatureData(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Get theme-aware colors\r\n const getThemeColors = useCallback(() => {\r\n const isDarkMode = document.documentElement.classList.contains('dark') || \r\n document.documentElement.getAttribute('data-theme') === 'dark';\r\n \r\n // Get CSS variable values\r\n const computedStyle = getComputedStyle(document.documentElement);\r\n let backgroundColor = computedStyle.getPropertyValue('--df-color-fb-input-bg').trim();\r\n \r\n // If CSS variable is not available or empty, use fallback\r\n if (!backgroundColor) {\r\n backgroundColor = isDarkMode ? '#2c2e34' : '#ffffff';\r\n }\r\n \r\n const strokeColor = isDarkMode ? '#ffffff' : '#000000';\r\n \r\n return {\r\n strokeColor,\r\n backgroundColor\r\n };\r\n }, []);\r\n\r\n // Load signature from data URL\r\n const loadSignature = useCallback((dataURL: string) => {\r\n if (!dataURL) { \r\n return;\r\n }\r\n \r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n const img = new Image();\r\n img.onload = () => {\r\n // Clear canvas\r\n ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n \r\n // Set background\r\n const colors = getThemeColors();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n \r\n // Calculate scaling to fit the signature properly\r\n const canvasAspectRatio = canvas.width / canvas.height;\r\n const imgAspectRatio = img.width / img.height;\r\n \r\n let drawWidth = canvas.width;\r\n let drawHeight = canvas.height;\r\n let drawX = 0;\r\n let drawY = 0;\r\n \r\n if (imgAspectRatio > canvasAspectRatio) {\r\n // Image is wider than canvas\r\n drawHeight = canvas.width / imgAspectRatio;\r\n drawY = (canvas.height - drawHeight) / 2;\r\n } else {\r\n // Image is taller than canvas\r\n drawWidth = canvas.height * imgAspectRatio;\r\n drawX = (canvas.width - drawWidth) / 2;\r\n }\r\n \r\n // Draw the signature image with proper scaling\r\n ctx.drawImage(img, drawX, drawY, drawWidth, drawHeight);\r\n };\r\n \r\n img.onerror = (error) => {\r\n console.error('DfFormSignature: error loading image', {\r\n id,\r\n error,\r\n dataURL: dataURL.substring(0, 50) + '...'\r\n });\r\n };\r\n \r\n img.src = dataURL;\r\n }, [getThemeColors, id]);\r\n\r\n // Initialize canvas\r\n const initializeCanvas = useCallback(() => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n // Get the display size\r\n const rect = canvas.getBoundingClientRect();\r\n \r\n // Set canvas size to match display size\r\n canvas.width = rect.width;\r\n canvas.height = rect.height;\r\n \r\n // Ensure canvas is properly sized\r\n canvas.style.width = rect.width + 'px';\r\n canvas.style.height = rect.height + 'px';\r\n \r\n const colors = getThemeColors();\r\n \r\n // Set drawing styles\r\n ctx.strokeStyle = colors.strokeColor;\r\n ctx.lineWidth = 2;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n \r\n // Set background only if canvas is empty\r\n if (!signatureData) {\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n } else {\r\n loadSignature(signatureData);\r\n }\r\n }, [signatureData, getThemeColors, loadSignature]);\r\n\r\n // Handle viewport changes and device view switches\r\n const handleViewportChange = useCallback(() => {\r\n // Small delay to ensure DOM has updated after viewport change\r\n setTimeout(() => {\r\n initializeCanvas();\r\n }, 100);\r\n }, [initializeCanvas]);\r\n\r\n // Listen for viewport changes and device view switches\r\n useEffect(() => {\r\n // Listen for window resize events\r\n const handleResize = () => {\r\n handleViewportChange();\r\n };\r\n\r\n // Listen for device view changes by observing class changes on the form canvas container\r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && \r\n (mutation.attributeName === 'class')) {\r\n const target = mutation.target as HTMLElement;\r\n // Check if the class change is related to device view switching\r\n if (target.classList.contains('form-canvas-container') && \r\n (target.classList.contains('mobile-view') || \r\n target.classList.contains('tablet-view') || \r\n target.classList.contains('desktop-view'))) {\r\n handleViewportChange();\r\n }\r\n }\r\n });\r\n });\r\n\r\n // Start observing the document for class changes\r\n observer.observe(document.body, {\r\n attributes: true,\r\n attributeFilter: ['class'],\r\n subtree: true\r\n });\r\n\r\n // Add resize listener\r\n window.addEventListener('resize', handleResize);\r\n\r\n // Cleanup\r\n return () => {\r\n observer.disconnect();\r\n window.removeEventListener('resize', handleResize);\r\n };\r\n }, [handleViewportChange]);\r\n\r\n\r\n // Get accurate coordinates relative to canvas\r\n const getCanvasCoordinates = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) return { x: 0, y: 0 };\r\n \r\n const rect = canvas.getBoundingClientRect();\r\n const scaleX = canvas.width / rect.width;\r\n const scaleY = canvas.height / rect.height;\r\n \r\n const clientX = e.type.includes('mouse') \r\n ? (e as React.MouseEvent).clientX\r\n : (e as React.TouchEvent).touches[0].clientX;\r\n const clientY = e.type.includes('mouse')\r\n ? (e as React.MouseEvent).clientY\r\n : (e as React.TouchEvent).touches[0].clientY;\r\n \r\n return {\r\n x: (clientX - rect.left) * scaleX,\r\n y: (clientY - rect.top) * scaleY\r\n };\r\n }, []);\r\n\r\n // Start drawing\r\n const startDrawing = (e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\r\n if (readonly || disabled || properties?.validation?.readonly) return;\r\n \r\n // Check if the click is on the clear button area\r\n const target = e.target as HTMLElement;\r\n if (target.closest('.clear-signature-btn')) {\r\n return; // Don't start drawing if clicking on the clear button\r\n }\r\n \r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n setIsDrawing(true);\r\n setIsTouched(true);\r\n \r\n const canvas = canvasRef.current;\r\n if (!canvas) return;\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n \r\n const { x, y } = getCanvasCoordinates(e);\r\n \r\n // Set drawing styles\r\n const colors = getThemeColors();\r\n ctx.strokeStyle = colors.strokeColor;\r\n ctx.lineWidth = 2;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n \r\n ctx.beginPath();\r\n ctx.moveTo(x, y);\r\n };\r\n\r\n // Draw\r\n const draw = (e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\r\n if (!isDrawing) return;\r\n \r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n const { x, y } = getCanvasCoordinates(e);\r\n\r\n ctx.lineTo(x, y);\r\n ctx.stroke();\r\n };\r\n\r\n // Check if canvas has content\r\n const hasCanvasContent = (canvas: HTMLCanvasElement): boolean => {\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return false;\r\n \r\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n const data = imageData.data;\r\n \r\n // Check if any pixel is not white (has content)\r\n for (let i = 0; i < data.length; i += 4) {\r\n const r = data[i];\r\n const g = data[i + 1];\r\n const b = data[i + 2];\r\n const a = data[i + 3];\r\n \r\n // If pixel is not white or transparent, canvas has content\r\n if (a > 0 && (r < 255 || g < 255 || b < 255)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n };\r\n\r\n // Stop drawing\r\n const stopDrawing = () => {\r\n if (!isDrawing) return;\r\n \r\n setIsDrawing(false);\r\n setIsSaving(true); // Set saving flag\r\n \r\n // Convert canvas to data URL\r\n const canvas = canvasRef.current;\r\n if (canvas) {\r\n // Check if canvas has content before saving\r\n hasCanvasContent(canvas);\r\n \r\n const dataURL = canvas.toDataURL('image/png');\r\n \r\n setSignatureData(dataURL);\r\n handleValueChange(dataURL);\r\n \r\n // Clear saving flag after a short delay\r\n setTimeout(() => {\r\n setIsSaving(false);\r\n }, 100);\r\n } else {\r\n setIsSaving(false);\r\n }\r\n };\r\n\r\n // Clear signature\r\n const clearSignature = (e?: React.MouseEvent) => {\r\n e?.preventDefault();\r\n e?.stopPropagation();\r\n\r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n // Get the display dimensions\r\n const rect = canvas.getBoundingClientRect();\r\n \r\n // Reset canvas dimensions to force a complete clear\r\n canvas.width = rect.width;\r\n canvas.height = rect.height;\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n // Set theme-aware background\r\n const colors = getThemeColors();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n \r\n // Reset drawing styles\r\n ctx.strokeStyle = colors.strokeColor;\r\n ctx.lineWidth = 2;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n \r\n // Update state\r\n setSignatureData('');\r\n handleValueChange('');\r\n };\r\n\r\n\r\n // Update canvas colors when theme changes\r\n const updateCanvasColors = useCallback(() => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) return;\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n \r\n const colors = getThemeColors();\r\n \r\n // Update stroke color\r\n ctx.strokeStyle = colors.strokeColor;\r\n \r\n // If canvas is empty, update background color\r\n if (!signatureData) {\r\n const rect = canvas.getBoundingClientRect();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n } else {\r\n // If there's signature data, we need to redraw with new background\r\n // Save the current signature data\r\n const currentSignature = signatureData;\r\n \r\n // Clear and redraw with new background\r\n const rect = canvas.getBoundingClientRect();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n \r\n // Reload the signature with new background\r\n if (currentSignature) {\r\n loadSignature(currentSignature);\r\n }\r\n }\r\n }, [getThemeColors, signatureData, loadSignature]);\r\n\r\n // Listen for theme changes and update canvas colors\r\n useEffect(() => {\r\n const handleThemeChange = () => {\r\n updateCanvasColors();\r\n };\r\n\r\n // Listen for class changes on document element\r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && \r\n (mutation.attributeName === 'class' || mutation.attributeName === 'data-theme')) {\r\n handleThemeChange();\r\n }\r\n });\r\n });\r\n\r\n observer.observe(document.documentElement, {\r\n attributes: true,\r\n attributeFilter: ['class', 'data-theme']\r\n });\r\n\r\n return () => {\r\n observer.disconnect();\r\n };\r\n }, [updateCanvasColors]);\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes (but don't override user input)\r\n useEffect(() => {\r\n // Only update if the formValue is different and we're not currently drawing or saving\r\n // Also, don't reset if the user has drawn something (signatureData is not empty)\r\n // CRITICAL FIX: Don't reload signature if we're currently saving (prevents flicker)\r\n if (formValue !== signatureData && !isDrawing && !isSaving && (signatureData === '' || formValue !== '')) {\r\n // Additional check: don't reload if the formValue is the same as current signatureData\r\n if (formValue === signatureData) {\r\n return;\r\n }\r\n setSignatureData(formValue);\r\n if (formValue) {\r\n loadSignature(formValue);\r\n }\r\n } else if (formValue === '' && signatureData !== '' && !isDrawing && !isSaving) {\r\n } else if (isSaving) {\r\n }\r\n }, [formValue, signatureData, isDrawing, isSaving]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clear signature when switching away from test mode\r\n useEffect(() => {\r\n if (mode !== 'test') {\r\n setSignatureData('');\r\n // Clear the canvas as well\r\n const canvas = canvasRef.current;\r\n if (canvas) {\r\n const ctx = canvas.getContext('2d');\r\n if (ctx) {\r\n const rect = canvas.getBoundingClientRect();\r\n canvas.width = rect.width;\r\n canvas.height = rect.height;\r\n const colors = getThemeColors();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n }\r\n }\r\n }\r\n }, [mode]);\r\n\r\n // Initialize canvas on mount and when mode changes\r\n useEffect(() => {\r\n initializeCanvas();\r\n }, [mode]); // Only reinitialize when mode changes, not when signatureData changes\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get signature classes\r\n const getSignatureClasses = (): string => {\r\n const base = 'form-signature';\r\n const validation = validateField(signatureData);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <div className=\"signature-container\" style={{ \r\n position: 'relative',\r\n width: '100%',\r\n maxWidth: '100%',\r\n overflow: 'hidden'\r\n }}>\r\n <canvas\r\n ref={canvasRef}\r\n id={id}\r\n className={getSignatureClasses()}\r\n onMouseDown={startDrawing}\r\n onMouseMove={draw}\r\n onMouseUp={stopDrawing}\r\n onMouseLeave={stopDrawing}\r\n onTouchStart={startDrawing}\r\n onTouchMove={draw}\r\n onTouchEnd={stopDrawing}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n style={{\r\n width: '100%',\r\n height: '150px',\r\n border: '2px solid var(--df-color-primary-border)',\r\n borderRadius: '6px',\r\n cursor: shouldDisable ? 'not-allowed' : 'crosshair',\r\n backgroundColor: 'var(--df-color-fb-input-bg)',\r\n touchAction: 'none', // Prevent scrolling when drawing on mobile\r\n userSelect: 'none' // Prevent text selection\r\n }}\r\n />\r\n \r\n {!shouldDisable && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => clearSignature(e)}\r\n className=\"clear-signature-btn\"\r\n style={{\r\n position: 'absolute',\r\n bottom: '8px',\r\n right: '8px',\r\n padding: '4px 8px',\r\n backgroundColor: 'var(--df-color-error-primary)',\r\n color: 'white',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n fontSize: '0.75rem',\r\n fontWeight: '500',\r\n zIndex: 10,\r\n transition: 'all 0.2s ease',\r\n minWidth: '60px',\r\n minHeight: '28px'\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = 'var(--df-color-error-dark, #dc2626)';\r\n e.currentTarget.style.transform = 'scale(1.05)';\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'var(--df-color-error-primary)';\r\n e.currentTarget.style.transform = 'scale(1)';\r\n }}\r\n >\r\n Clear\r\n </button>\r\n )}\r\n </div>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(signatureData)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormSignature;\r\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { \r\n IFileUploadComponent, \r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface IFileDataObject {\r\n name?: string;\r\n fileName?: string;\r\n type?: string;\r\n fileType?: string;\r\n mimeType?: string;\r\n size?: number;\r\n fileSize?: number;\r\n url?: string;\r\n path?: string;\r\n data?: string;\r\n}\r\n\r\ninterface DfFormFileUploadProps {\r\n id: string;\r\n properties: IFileUploadComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: File[] | FileList | IFileDataObject[] | string[] | null;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\ninterface IFilePreview {\r\n file: File;\r\n id: string;\r\n preview?: string;\r\n size: number;\r\n type: string;\r\n name: string;\r\n}\r\n\r\nexport const DfFormFileUpload: React.FC<DfFormFileUploadProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = null,\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'test',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [files, setFiles] = useState<IFilePreview[]>([]);\r\n const [isDragOver, setIsDragOver] = useState<boolean>(false);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n // Convert FileList or File[] to IFilePreview[]\r\n const convertToFilePreviews = useCallback((fileList: FileList | File[] | IFileDataObject[] | string[] | null): IFilePreview[] => {\r\n if (!fileList) return [];\r\n \r\n const fileArray = Array.isArray(fileList) ? fileList : Array.from(fileList);\r\n const results: IFilePreview[] = [];\r\n \r\n fileArray.forEach((file, index) => {\r\n // CRITICAL: Handle API data structure where file is an object with name, type, size, data, url\r\n if (file && typeof file === 'object' && !(file instanceof File) && !(file instanceof Blob)) {\r\n const fileObj = file as any;\r\n // Check if it's an API file object with data/url properties\r\n if (fileObj.data || fileObj.url || (fileObj.name && fileObj.type)) {\r\n const fileName = fileObj.name || fileObj.fileName || `file-${index}`;\r\n const fileSize = fileObj.size || fileObj.fileSize || 0;\r\n const fileType = fileObj.type || fileObj.fileType || fileObj.mimeType || '';\r\n \r\n // CRITICAL: Handle base64 data from API\r\n let preview: string | undefined;\r\n if (fileObj.url) {\r\n // Use URL if available (may be data URI)\r\n preview = fileObj.url;\r\n } else if (fileObj.data) {\r\n // Handle base64 data\r\n const fileData = fileObj.data;\r\n if (typeof fileData === 'string') {\r\n if (fileData.startsWith('data:')) {\r\n preview = fileData;\r\n } else {\r\n // Base64 string without prefix - add data URI prefix\r\n const cleanedData = fileData.replace(/\\s/g, '');\r\n if (/^[A-Za-z0-9+/=]+$/.test(cleanedData) && cleanedData.length > 10) {\r\n // Detect image type from base64 or use provided type\r\n let detectedType = fileType;\r\n if (!detectedType) {\r\n if (cleanedData.startsWith('/9j/') || cleanedData.startsWith('iVBORw0KGgoAAAANSUhEUgAA')) {\r\n detectedType = 'image/jpeg';\r\n } else if (cleanedData.startsWith('iVBORw0KGgo')) {\r\n detectedType = 'image/png';\r\n } else if (cleanedData.startsWith('R0lGOD')) {\r\n detectedType = 'image/gif';\r\n } else if (cleanedData.startsWith('UklGR')) {\r\n detectedType = 'image/webp';\r\n } else {\r\n detectedType = 'image/png'; // Default\r\n }\r\n }\r\n preview = `data:${detectedType};base64,${cleanedData}`;\r\n } else {\r\n preview = fileData; // Might be a URL\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Create a minimal File object for the interface\r\n const fileInstance = new File([], fileName, { type: fileType });\r\n \r\n results.push({\r\n file: fileInstance,\r\n id: `${id}-file-${index}`,\r\n size: fileSize,\r\n type: fileType,\r\n name: fileName,\r\n preview\r\n });\r\n \r\n return; // Skip to next file\r\n }\r\n }\r\n // Check if file is actually a File object\r\n const isFileObject = (file as any) instanceof File || (file as any) instanceof Blob;\r\n \r\n // If it's a string (URL), create a mock File-like object for display\r\n let preview: string | undefined;\r\n let fileSize = 0;\r\n let fileType = '';\r\n let fileName = '';\r\n let fileObj: File;\r\n \r\n if (isFileObject) {\r\n // It's a real File/Blob object\r\n const fileInstance = file as File;\r\n fileSize = fileInstance.size || 0;\r\n fileType = fileInstance.type || '';\r\n fileName = fileInstance.name || `file-${index}`;\r\n fileObj = fileInstance;\r\n \r\n // Create object URL only for image files\r\n if (fileType.startsWith('image/')) {\r\n try {\r\n preview = URL.createObjectURL(fileInstance);\r\n } catch (error) {\r\n console.error('Error creating object URL:', error);\r\n preview = undefined;\r\n }\r\n }\r\n } else if (typeof file === 'string') {\r\n // It's a string (URL or base64)\r\n const fileString = file as string;\r\n \r\n // CRITICAL: Handle base64 strings that might not have the data: prefix\r\n // Check if it's a base64 string (starts with common base64 patterns or is long base64-like string)\r\n // Also check for base64 strings that might have been encoded differently\r\n const cleanedString = fileString.replace(/\\s/g, '');\r\n const isBase64String = cleanedString.length > 50 && \r\n /^[A-Za-z0-9+/=]+$/.test(cleanedString) && \r\n !fileString.startsWith('http') && \r\n !fileString.startsWith('https') &&\r\n !fileString.startsWith('data:') &&\r\n !fileString.startsWith('blob:') &&\r\n !fileString.startsWith('/');\r\n \r\n // If it's a base64 string without prefix, add the data URI prefix\r\n let processedFileString = fileString;\r\n if (isBase64String) {\r\n // Try to detect image type from base64 patterns\r\n // JPEG: starts with /9j/\r\n // PNG: starts with iVBORw0KGgo\r\n // GIF: starts with R0lGOD\r\n // WebP: starts with UklGR\r\n let imageType = 'image/png'; // Default to PNG\r\n if (cleanedString.startsWith('/9j/') || cleanedString.startsWith('iVBORw0KGgoAAAANSUhEUgAA')) {\r\n imageType = 'image/jpeg';\r\n } else if (cleanedString.startsWith('iVBORw0KGgo')) {\r\n imageType = 'image/png';\r\n } else if (cleanedString.startsWith('R0lGOD')) {\r\n imageType = 'image/gif';\r\n } else if (cleanedString.startsWith('UklGR')) {\r\n imageType = 'image/webp';\r\n }\r\n processedFileString = `data:${imageType};base64,${cleanedString}`;\r\n }\r\n \r\n // Try to extract filename from URL\r\n let extractedFileName = '';\r\n if (processedFileString.startsWith('data:')) {\r\n // For data URIs, try to extract filename from the data URI itself if available\r\n // Format: data:image/png;base64,... or data:image/png;filename=example.png;base64,...\r\n const filenameMatch = processedFileString.match(/filename=([^;]+)/i);\r\n if (filenameMatch) {\r\n extractedFileName = decodeURIComponent(filenameMatch[1]);\r\n } else {\r\n // Fallback: use a generic name based on type\r\n const typeMatch = processedFileString.match(/data:([^;]+)/);\r\n if (typeMatch) {\r\n const mimeType = typeMatch[1];\r\n const extension = mimeType.includes('image') ? (mimeType.includes('jpeg') ? 'jpg' : 'png') : \r\n mimeType.includes('pdf') ? 'pdf' :\r\n mimeType.includes('word') ? 'doc' :\r\n mimeType.includes('excel') ? 'xls' : 'file';\r\n extractedFileName = `file-${index + 1}.${extension}`;\r\n } else {\r\n extractedFileName = `file-${index + 1}`;\r\n }\r\n }\r\n } else if (processedFileString.startsWith('http://') || processedFileString.startsWith('https://') || processedFileString.startsWith('blob:')) {\r\n // Extract filename from URL path\r\n try {\r\n const url = new URL(fileString);\r\n const pathname = url.pathname;\r\n const urlFileName = pathname.split('/').pop() || '';\r\n if (urlFileName && urlFileName.includes('.')) {\r\n extractedFileName = decodeURIComponent(urlFileName);\r\n } else {\r\n // Try to get from query params or use index\r\n const queryFileName = url.searchParams.get('filename') || url.searchParams.get('name');\r\n extractedFileName = queryFileName ? decodeURIComponent(queryFileName) : `file-${index + 1}`;\r\n }\r\n } catch (e) {\r\n // If URL parsing fails, try simple extraction\r\n const lastSlash = fileString.lastIndexOf('/');\r\n const lastPart = lastSlash >= 0 ? fileString.substring(lastSlash + 1) : fileString;\r\n const questionMark = lastPart.indexOf('?');\r\n const fileNamePart = questionMark >= 0 ? lastPart.substring(0, questionMark) : lastPart;\r\n if (fileNamePart && fileNamePart.includes('.')) {\r\n extractedFileName = decodeURIComponent(fileNamePart);\r\n } else {\r\n extractedFileName = `file-${index + 1}`;\r\n }\r\n }\r\n } else {\r\n extractedFileName = `file-${index + 1}`;\r\n }\r\n \r\n fileName = extractedFileName || `file-${index + 1}`;\r\n \r\n // Extract file type from data URI (use processedFileString)\r\n if (processedFileString.startsWith('data:')) {\r\n const semicolonIndex = processedFileString.indexOf(';');\r\n if (semicolonIndex > 5) {\r\n fileType = processedFileString.substring(5, semicolonIndex);\r\n } else {\r\n fileType = 'application/octet-stream';\r\n }\r\n } else {\r\n // Try to infer from file extension or default to image/png for URLs\r\n const extensionMatch = processedFileString.match(/\\.(jpg|jpeg|png|gif|webp|svg|pdf|doc|docx|xls|xlsx|zip|rar)$/i) || \r\n fileName.match(/\\.(jpg|jpeg|png|gif|webp|svg|pdf|doc|docx|xls|xlsx|zip|rar)$/i);\r\n if (extensionMatch) {\r\n const ext = extensionMatch[1].toLowerCase();\r\n const mimeTypes: Record<string, string> = {\r\n jpg: 'image/jpeg',\r\n jpeg: 'image/jpeg',\r\n png: 'image/png',\r\n gif: 'image/gif',\r\n webp: 'image/webp',\r\n svg: 'image/svg+xml',\r\n pdf: 'application/pdf',\r\n doc: 'application/msword',\r\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n xls: 'application/vnd.ms-excel',\r\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n zip: 'application/zip',\r\n rar: 'application/x-rar-compressed'\r\n };\r\n fileType = mimeTypes[ext] || 'application/octet-stream';\r\n } else {\r\n // If it's a base64 string, default to image type\r\n fileType = isBase64String ? 'image/png' : 'application/octet-stream';\r\n }\r\n }\r\n \r\n // Use the processed string as preview if it's an image URL/data URI\r\n if (processedFileString.startsWith('data:image') || processedFileString.startsWith('http://') || processedFileString.startsWith('https://') || processedFileString.startsWith('blob:')) {\r\n preview = processedFileString;\r\n }\r\n \r\n // Create a minimal File object for the interface\r\n fileObj = new File([], fileName, { type: fileType });\r\n } else if (file && typeof file === 'object') {\r\n // It might be an object with file properties (from API response)\r\n const fileObject = file as any;\r\n fileName = fileObject.name || fileObject.fileName || `file-${index}`;\r\n fileSize = fileObject.size || fileObject.fileSize || 0;\r\n fileType = fileObject.type || fileObject.fileType || fileObject.mimeType || '';\r\n \r\n // Check if there's a URL or path property\r\n if (fileObject.url || fileObject.path) {\r\n preview = fileObject.url || fileObject.path;\r\n } else if (fileType.startsWith('image/') && fileObject.data) {\r\n // Handle base64 data\r\n const fileData = fileObject.data;\r\n if (typeof fileData === 'string') {\r\n if (fileData.startsWith('data:')) {\r\n preview = fileData;\r\n } else {\r\n // Check if it's a base64 string without prefix\r\n const cleanedData = fileData.replace(/\\s/g, '');\r\n if (/^[A-Za-z0-9+/=]+$/.test(cleanedData) && cleanedData.length > 50) {\r\n preview = `data:${fileType};base64,${cleanedData}`;\r\n } else {\r\n preview = fileData; // Might be a URL\r\n }\r\n }\r\n } else {\r\n preview = undefined;\r\n }\r\n }\r\n \r\n // Create a minimal File object for the interface\r\n fileObj = new File([], fileName, { type: fileType });\r\n } else {\r\n // Unknown format, skip\r\n return;\r\n }\r\n \r\n results.push({\r\n file: fileObj,\r\n id: `${id}-file-${index}`,\r\n size: fileSize,\r\n type: fileType,\r\n name: fileName,\r\n preview\r\n });\r\n });\r\n \r\n return results;\r\n }, [id]);\r\n\r\n // Validate files - disabled for file upload component\r\n const validateFiles = useCallback((): { isValid: boolean; errors: Record<string, any> } => {\r\n // Always return valid since we're not maintaining validation\r\n return { isValid: true, errors: {} };\r\n }, []);\r\n\r\n // Handle file selection\r\n const handleFileSelect = useCallback((selectedFiles: FileList | File[]) => {\r\n if (readonly || disabled) return;\r\n\r\n const newFiles = convertToFilePreviews(selectedFiles);\r\n // If files already exist, always append new files (for \"add more\" functionality)\r\n // If no files exist, replace (regardless of multiple setting)\r\n const shouldAppend = files.length > 0;\r\n const allFiles = shouldAppend ? [...files, ...newFiles] : newFiles;\r\n \r\n // Apply max files limit\r\n const maxFiles = properties?.validation?.maxFiles || Infinity;\r\n const limitedFiles = allFiles.slice(0, maxFiles);\r\n \r\n setFiles(limitedFiles);\r\n setIsTouched(true);\r\n \r\n if (onValueChange) {\r\n const validation = validateFiles();\r\n const change: IFormControlChange = {\r\n id,\r\n value: limitedFiles.map(f => f.file),\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [files, properties, readonly, disabled, onValueChange, validateFiles, convertToFilePreviews, id]);\r\n\r\n // Handle drag events\r\n const handleDragOver = (e: React.DragEvent) => {\r\n e.preventDefault();\r\n if (!readonly && !disabled) {\r\n setIsDragOver(true);\r\n }\r\n };\r\n\r\n const handleDragLeave = (e: React.DragEvent) => {\r\n e.preventDefault();\r\n setIsDragOver(false);\r\n };\r\n\r\n const handleDrop = (e: React.DragEvent) => {\r\n e.preventDefault();\r\n setIsDragOver(false);\r\n \r\n if (readonly || disabled) return;\r\n \r\n const droppedFiles = e.dataTransfer.files;\r\n if (droppedFiles.length > 0) {\r\n handleFileSelect(droppedFiles);\r\n }\r\n };\r\n\r\n // Handle file input change\r\n const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const selectedFiles = e.target.files;\r\n if (selectedFiles && selectedFiles.length > 0) {\r\n handleFileSelect(selectedFiles);\r\n // Reset input value to allow selecting the same file again\r\n e.target.value = '';\r\n }\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n \r\n if (mode === 'test' && onValueChange) {\r\n const validation = validateFiles();\r\n const change: IFormControlChange = {\r\n id,\r\n value: files.map(f => f.file),\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Remove file\r\n const removeFile = (fileId: string) => {\r\n if (readonly || disabled) return;\r\n \r\n const updatedFiles = files.filter(f => f.id !== fileId);\r\n setFiles(updatedFiles);\r\n setIsTouched(true);\r\n \r\n if (onValueChange) {\r\n const validation = validateFiles();\r\n const change: IFormControlChange = {\r\n id,\r\n value: updatedFiles.map(f => f.file),\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n };\r\n\r\n // Format file size\r\n const formatFileSize = (bytes: number): string => {\r\n if (bytes === 0) return '0 Bytes';\r\n const k = 1024;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\r\n };\r\n\r\n // Get file icon based on type\r\n const getFileIcon = (fileType: string): string => {\r\n if (fileType.startsWith('image/')) return '🖼️';\r\n if (fileType.startsWith('video/')) return '🎥';\r\n if (fileType.startsWith('audio/')) return '🎵';\r\n if (fileType.includes('pdf')) return '📄';\r\n if (fileType.includes('word') || fileType.includes('document')) return '📝';\r\n if (fileType.includes('excel') || fileType.includes('spreadsheet')) return '📊';\r\n if (fileType.includes('zip') || fileType.includes('rar')) return '📦';\r\n return '📁';\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Reset touched state when switching modes, but preserve files\r\n useEffect(() => {\r\n if (mode === 'edit') {\r\n setIsTouched(false);\r\n // Don't clear files - let formValue prop handle the state\r\n } else if (mode === 'test') {\r\n setIsTouched(false);\r\n // Don't clear files - let formValue prop handle the state\r\n }\r\n }, [mode]);\r\n\r\n // Update value when formValue prop changes or on mount\r\n // CRITICAL: This must run whenever formValue changes to display API images\r\n useEffect(() => {\r\n // CRITICAL: Always convert formValue, even if it's null/undefined (will return empty array)\r\n // Use a ref to track previous formValue to detect actual changes\r\n const newFiles = convertToFilePreviews(formValue);\r\n \r\n // CRITICAL: Check if formValue actually changed or if it's the first load with data\r\n // This ensures base64 data from API is properly displayed\r\n const hasFormValue = formValue !== null && formValue !== undefined && \r\n ((Array.isArray(formValue) && formValue.length > 0) ||\r\n (typeof formValue === 'string' && String(formValue).trim() !== '') ||\r\n (typeof formValue === 'object' && !Array.isArray(formValue) && Object.keys(formValue).length > 0));\r\n \r\n // Always update if formValue has data, or if files array is empty and formValue exists\r\n if (hasFormValue || (files.length === 0 && formValue !== null && formValue !== undefined)) {\r\n // Force update to ensure API images are displayed\r\n setFiles(newFiles);\r\n } else if (formValue === null || formValue === undefined || \r\n (Array.isArray(formValue) && formValue.length === 0)) {\r\n // Clear files if formValue is explicitly null/empty\r\n if (files.length > 0) {\r\n setFiles([]);\r\n }\r\n }\r\n }, [formValue, convertToFilePreviews, files.length]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clean up object URLs (only for blob URLs, not data URIs or http URLs)\r\n useEffect(() => {\r\n return () => {\r\n files.forEach(file => {\r\n if (file.preview && file.preview.startsWith('blob:')) {\r\n try {\r\n URL.revokeObjectURL(file.preview);\r\n } catch (error) {\r\n console.error('Error revoking object URL:', error);\r\n }\r\n }\r\n });\r\n };\r\n }, [files]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get upload area classes\r\n const getUploadAreaClasses = (): string => {\r\n const base = 'file-upload-area';\r\n const dragOverClass = isDragOver ? 'drag-over' : '';\r\n const readonlyClass = readonly ? 'readonly' : '';\r\n const disabledClass = disabled ? 'disabled' : '';\r\n \r\n // No validation logic - always return base classes\r\n return `${base} ${dragOverClass} ${readonlyClass} ${disabledClass} ${className}`.trim();\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n const isMultiple = properties?.validation?.multiple || false;\r\n const acceptTypes = properties?.validation?.accept || '*/*';\r\n const maxFiles = properties?.validation?.maxFiles || Infinity;\r\n const canAddMoreFiles = files.length < maxFiles && (isMultiple || maxFiles > 1);\r\n const isEditMode = mode === 'edit';\r\n const isPreviewOrTestMode = mode === 'preview' || mode === 'test';\r\n\r\n // Filter image files for preview/test mode display\r\n const imageFiles = files.filter(file => file.type.startsWith('image/'));\r\n const nonImageFiles = files.filter(file => !file.type.startsWith('image/'));\r\n const hasImages = imageFiles.length > 0;\r\n const shouldShowImageDisplay = isPreviewOrTestMode && hasImages;\r\n\r\n // Handle add more files button click\r\n const handleAddMoreFiles = (e: React.MouseEvent<HTMLButtonElement>) => {\r\n e.stopPropagation();\r\n if (!shouldDisable && fileInputRef.current && isEditMode) {\r\n // Reset input value to allow selecting the same file again\r\n fileInputRef.current.value = '';\r\n fileInputRef.current.click();\r\n }\r\n };\r\n\r\n // Render image display for preview/test mode\r\n if (shouldShowImageDisplay) {\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic?.label || 'Attachments'}\r\n {properties.validation?.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"file-upload-wrapper\">\r\n <div className=\"file-image-display\">\r\n {imageFiles.map((file) => (\r\n <div key={file.id} className=\"file-image-container\">\r\n {file.preview && (\r\n <img \r\n src={file.preview} \r\n alt={file.name} \r\n className=\"file-image-preview\"\r\n />\r\n )}\r\n <div className=\"file-image-info\">\r\n <div className=\"file-name\" title={file.name}>{file.name}</div>\r\n <div className=\"file-size\">{formatFileSize(file.size)}</div>\r\n </div>\r\n </div>\r\n ))}\r\n {nonImageFiles.length > 0 && (\r\n <div className=\"file-other-files\">\r\n <div className=\"file-other-files-label\">Other Files:</div>\r\n {nonImageFiles.map((file) => (\r\n <div key={file.id} className=\"file-item-minimal\">\r\n <div className=\"file-icon\">{getFileIcon(file.type)}</div>\r\n <div className=\"file-info\">\r\n <div className=\"file-name\" title={file.name}>{file.name}</div>\r\n <div className=\"file-size\">{formatFileSize(file.size)}</div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateFiles()}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic?.label || 'Attachments'}\r\n {properties.validation?.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"file-upload-wrapper\">\r\n <div\r\n className={getUploadAreaClasses()}\r\n onDragOver={handleDragOver}\r\n onDragLeave={handleDragLeave}\r\n onDrop={handleDrop}\r\n onClick={(e) => {\r\n // Only trigger file picker in edit mode when no files exist and not clicking on file items\r\n const target = e.target as HTMLElement;\r\n const isClickOnFileItem = target.closest('.file-item') !== null;\r\n const isClickOnRemoveButton = target.closest('.file-remove') !== null;\r\n \r\n if (isEditMode && !shouldDisable && files.length === 0 && !isClickOnFileItem && !isClickOnRemoveButton) {\r\n fileInputRef.current?.click();\r\n }\r\n }}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n tabIndex={shouldDisable ? -1 : 0}\r\n >\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n id={id}\r\n multiple={isMultiple}\r\n accept={acceptTypes}\r\n onChange={handleFileInputChange}\r\n disabled={shouldDisable}\r\n style={{ display: 'none' }}\r\n />\r\n \r\n {files.length === 0 ? (\r\n <div \r\n className=\"upload-placeholder\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n if (isEditMode && !shouldDisable) {\r\n fileInputRef.current?.click();\r\n }\r\n }}\r\n >\r\n <div className=\"upload-icon\">📁</div>\r\n <div className=\"upload-text\">\r\n {/* <p>Drop files here or click to browse</p> */}\r\n {properties.basic.placeholder && (\r\n <p className=\"upload-hint\">{properties.basic.placeholder}</p>\r\n )}\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"file-list\">\r\n {files.map((file) => (\r\n <div key={file.id} className=\"file-item\">\r\n <div className=\"file-preview\">\r\n {file.preview ? (\r\n <img src={file.preview} alt={file.name} className=\"file-image\" />\r\n ) : (\r\n <div className=\"file-icon\">{getFileIcon(file.type)}</div>\r\n )}\r\n </div>\r\n <div className=\"file-info\">\r\n <div className=\"file-name\" title={file.name}>{file.name}</div>\r\n <div className=\"file-size\">{formatFileSize(file.size)}</div>\r\n </div>\r\n {isEditMode && !shouldDisable && (\r\n <button\r\n type=\"button\"\r\n className=\"file-remove\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n removeFile(file.id);\r\n }}\r\n aria-label={`Remove ${file.name}`}\r\n >\r\n ✕\r\n </button>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {files.length > 0 && canAddMoreFiles && !shouldDisable && isEditMode && (\r\n <button\r\n type=\"button\"\r\n className=\"file-add-more\"\r\n onClick={handleAddMoreFiles}\r\n aria-label=\"Add more files\"\r\n >\r\n <svg\r\n className=\"file-add-icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n >\r\n <path d=\"M12 5v14M5 12h14\" />\r\n </svg>\r\n <span className=\"file-add-text\">Add More Files</span>\r\n </button>\r\n )}\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateFiles()}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormFileUpload;\r\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { \r\n ILocationComponent, \r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\nimport { MapPin, Navigation, X, Loader2 } from 'lucide-react';\r\n\r\ninterface DfFormLocationProps {\r\n id: string;\r\n properties: ILocationComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: ILocationData | null;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\ninterface ILocationData {\r\n latitude: number;\r\n longitude: number;\r\n accuracy?: number;\r\n timestamp?: number;\r\n address?: string;\r\n placeName?: string;\r\n city?: string;\r\n country?: string;\r\n}\r\n\r\ninterface IMapMarker {\r\n lat: number;\r\n lng: number;\r\n isCurrentLocation?: boolean;\r\n}\r\n\r\nexport const DfFormLocation: React.FC<DfFormLocationProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = null,\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'test',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [locationData, setLocationData] = useState<ILocationData | null>(formValue);\r\n const [isLoading, setIsLoading] = useState<boolean>(false);\r\n const [error, setError] = useState<string>('');\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [showMap, setShowMap] = useState<boolean>(false);\r\n const [mapCenter, setMapCenter] = useState<{ lat: number; lng: number }>({ lat: 40.7128, lng: -74.0060 });\r\n const [mapMarker, setMapMarker] = useState<IMapMarker | null>(null);\r\n const [mapZoom, setMapZoom] = useState<number>(10);\r\n const [searchQuery, setSearchQuery] = useState<string>('');\r\n const [isSearching, setIsSearching] = useState<boolean>(false);\r\n const mapRef = useRef<HTMLDivElement>(null);\r\n const [isDragging, setIsDragging] = useState<boolean>(false);\r\n const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null);\r\n const [isReverseGeocoding, setIsReverseGeocoding] = useState<boolean>(false);\r\n\r\n // Update location data when formValue prop changes\r\n // CRITICAL: Only update if formValue is actually provided (not default/cached)\r\n useEffect(() => {\r\n if (formValue && formValue.latitude && formValue.longitude) {\r\n // Only set location if it's a valid location (not default coordinates)\r\n // Check if it's not the default New York coordinates\r\n const isDefaultLocation = formValue.latitude === 40.7128 && formValue.longitude === -74.0060;\r\n if (!isDefaultLocation) {\r\n setLocationData(formValue);\r\n setMapMarker({\r\n lat: formValue.latitude,\r\n lng: formValue.longitude,\r\n isCurrentLocation: false\r\n });\r\n setMapCenter({ lat: formValue.latitude, lng: formValue.longitude });\r\n }\r\n } else {\r\n // Only clear if formValue is explicitly null/undefined, not if it's missing\r\n if (formValue === null || formValue === undefined) {\r\n setLocationData(null);\r\n setMapMarker(null);\r\n }\r\n }\r\n }, [formValue]);\r\n\r\n // Initialize map with default center (New York)\r\n useEffect(() => {\r\n if (showMap && mapCenter.lat === 40.7128 && mapCenter.lng === -74.0060) {\r\n // Map is already initialized with default center\r\n }\r\n }, [showMap, mapCenter]);\r\n\r\n // Close map and reset map-related state when component becomes disabled (e.g., switching to edit mode)\r\n useEffect(() => {\r\n if (readonly || disabled) {\r\n // Close map if component is disabled/readonly (edit/preview mode)\r\n if (showMap) {\r\n setShowMap(false);\r\n }\r\n // Reset search query and dragging state\r\n if (searchQuery) {\r\n setSearchQuery('');\r\n }\r\n if (isDragging) {\r\n setIsDragging(false);\r\n setDragStart(null);\r\n }\r\n }\r\n }, [readonly, disabled]);\r\n\r\n // Reverse geocoding to get address details\r\n const reverseGeocode = useCallback(async (lat: number, lng: number) => {\r\n setIsReverseGeocoding(true);\r\n try {\r\n const response = await fetch(\r\n `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&addressdetails=1&zoom=18`\r\n );\r\n const data = await response.json();\r\n \r\n if (data && data.address) {\r\n const address = data.address;\r\n return {\r\n placeName: data.display_name || '',\r\n city: address.city || address.town || address.village || address.municipality || '',\r\n country: address.country || ''\r\n };\r\n }\r\n } catch (err) {\r\n console.error('Reverse geocoding failed:', err);\r\n } finally {\r\n setIsReverseGeocoding(false);\r\n }\r\n return { placeName: '', city: '', country: '' };\r\n }, []);\r\n\r\n // Update location data with reverse geocoding\r\n const updateLocationWithAddress = useCallback(async (lat: number, lng: number, existingData?: Partial<ILocationData>) => {\r\n const addressData = await reverseGeocode(lat, lng);\r\n const location: ILocationData = {\r\n latitude: lat,\r\n longitude: lng,\r\n timestamp: Date.now(),\r\n placeName: addressData.placeName,\r\n city: addressData.city,\r\n country: addressData.country,\r\n address: addressData.placeName,\r\n ...existingData\r\n };\r\n \r\n setLocationData(location);\r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: false\r\n });\r\n setIsTouched(true);\r\n\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: location,\r\n isValid: true,\r\n errors: {},\r\n };\r\n onValueChange(change);\r\n }\r\n }, [reverseGeocode, id, onValueChange]);\r\n\r\n // Get current location using geolocation API\r\n // CRITICAL: Support both mobile (Capacitor) and web browsers\r\n const getCurrentLocation = useCallback(async () => {\r\n if (readonly || disabled) return;\r\n\r\n setIsLoading(true);\r\n setError('');\r\n\r\n // Check if we're in a Capacitor/Ionic environment (mobile app)\r\n const isCapacitor = typeof (window as any).Capacitor !== 'undefined';\r\n \r\n if (isCapacitor) {\r\n try {\r\n // Use Capacitor Geolocation plugin for mobile devices\r\n const { Geolocation } = (window as any).Capacitor.Plugins;\r\n \r\n if (Geolocation) {\r\n try {\r\n // Request permissions first (required for mobile)\r\n const permissionStatus = await Geolocation.requestPermissions();\r\n \r\n if (permissionStatus.location !== 'granted') {\r\n setIsLoading(false);\r\n setError('Location permission is required. Please enable location access in your device settings.');\r\n return;\r\n }\r\n \r\n // Get position using Capacitor Geolocation\r\n const position = await Geolocation.getCurrentPosition({\r\n enableHighAccuracy: properties.validation?.enableHighAccuracy ?? true,\r\n timeout: properties.validation?.timeout ?? 10000,\r\n maximumAge: properties.validation?.maximumAge ?? 300000\r\n });\r\n \r\n const lat = position.coords.latitude;\r\n const lng = position.coords.longitude;\r\n \r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: true\r\n });\r\n setMapCenter({ lat, lng });\r\n setIsTouched(true);\r\n \r\n // Update location with reverse geocoding\r\n await updateLocationWithAddress(lat, lng, {\r\n accuracy: position.coords.accuracy,\r\n timestamp: Date.now()\r\n });\r\n \r\n setIsLoading(false);\r\n setError(''); // Clear any previous errors\r\n return; // Success - exit early\r\n } catch (capError: any) {\r\n setIsLoading(false);\r\n // Handle Capacitor-specific errors\r\n if (capError.message?.includes('permission') || capError.message?.includes('denied')) {\r\n setError('Location permission is required. Please enable location access in your device settings.');\r\n } else if (capError.message?.includes('timeout')) {\r\n setError('Location request timed out. Please try again.');\r\n } else {\r\n setError('Unable to retrieve your location. Please try again.');\r\n }\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n // Capacitor not properly initialized, fall through to web geolocation\r\n console.warn('Capacitor Geolocation not available, falling back to web geolocation');\r\n }\r\n }\r\n\r\n // Fallback to standard web geolocation API (for browsers)\r\n if (!navigator.geolocation) {\r\n setIsLoading(false);\r\n setError('Geolocation is not supported by this browser.');\r\n return;\r\n }\r\n\r\n const options: PositionOptions = {\r\n enableHighAccuracy: properties.validation?.enableHighAccuracy ?? true,\r\n timeout: properties.validation?.timeout ?? 10000,\r\n maximumAge: properties.validation?.maximumAge ?? 300000 // 5 minutes\r\n };\r\n\r\n navigator.geolocation.getCurrentPosition(\r\n async (position) => {\r\n const lat = position.coords.latitude;\r\n const lng = position.coords.longitude;\r\n \r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: true\r\n });\r\n setMapCenter({ lat, lng });\r\n setIsTouched(true);\r\n \r\n // Update location with reverse geocoding\r\n await updateLocationWithAddress(lat, lng, {\r\n accuracy: position.coords.accuracy,\r\n timestamp: position.timestamp\r\n });\r\n \r\n setIsLoading(false);\r\n setError(''); // Clear any previous errors\r\n },\r\n (error) => {\r\n setIsLoading(false);\r\n let errorMessage = 'Unable to retrieve your location.';\r\n \r\n switch (error.code) {\r\n case error.PERMISSION_DENIED:\r\n errorMessage = 'Location access denied by user. Please enable location access in your browser/device settings.';\r\n break;\r\n case error.POSITION_UNAVAILABLE:\r\n errorMessage = 'Location information is unavailable.';\r\n break;\r\n case error.TIMEOUT:\r\n errorMessage = 'Location request timed out. Please try again.';\r\n break;\r\n }\r\n \r\n setError(errorMessage);\r\n },\r\n options\r\n );\r\n }, [readonly, disabled, properties, updateLocationWithAddress]);\r\n\r\n // Clear location data\r\n const clearLocation = useCallback(() => {\r\n if (readonly || disabled) return;\r\n\r\n setLocationData(null);\r\n setMapMarker(null);\r\n setError('');\r\n setIsTouched(true);\r\n\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: null,\r\n isValid: true,\r\n errors: {},\r\n };\r\n onValueChange(change);\r\n }\r\n }, [readonly, disabled, id, onValueChange]);\r\n\r\n // Toggle map visibility\r\n const toggleMap = useCallback(() => {\r\n if (readonly || disabled) return;\r\n setShowMap(!showMap);\r\n }, [readonly, disabled, showMap]);\r\n\r\n // Convert pixel coordinates to lat/lng using proper Web Mercator projection\r\n const pixelToLatLng = useCallback((x: number, y: number, center: { lat: number; lng: number }, zoom: number, width: number, height: number) => {\r\n // Calculate pixel offset from center\r\n const offsetX = x - width / 2;\r\n const offsetY = y - height / 2;\r\n \r\n // Convert to meters (approximate)\r\n const metersPerPixel = (156543.03392 * Math.cos(center.lat * Math.PI / 180)) / Math.pow(2, zoom);\r\n const metersX = offsetX * metersPerPixel;\r\n const metersY = offsetY * metersPerPixel;\r\n \r\n // Convert meters to lat/lng\r\n const lat = center.lat + (metersY / 111320);\r\n const lng = center.lng + (metersX / (111320 * Math.cos(center.lat * Math.PI / 180)));\r\n \r\n return { lat, lng };\r\n }, []);\r\n\r\n // Handle map mouse down (start drag)\r\n const handleMapMouseDown = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\r\n if (readonly || disabled || !mapRef.current) return;\r\n if (event.button !== 0) return; // Only handle left mouse button\r\n \r\n setIsDragging(true);\r\n setDragStart({ x: event.clientX, y: event.clientY });\r\n event.preventDefault();\r\n }, [readonly, disabled]);\r\n\r\n // Handle map mouse move (during drag)\r\n const handleMapMouseMove = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\r\n if (!isDragging || !dragStart || !mapRef.current) return;\r\n \r\n const deltaX = event.clientX - dragStart.x;\r\n const deltaY = event.clientY - dragStart.y;\r\n \r\n // Convert pixel offset to lat/lng offset\r\n const metersPerPixel = (156543.03392 * Math.cos(mapCenter.lat * Math.PI / 180)) / Math.pow(2, mapZoom);\r\n const latOffset = -(deltaY * metersPerPixel) / 111320;\r\n const lngOffset = (deltaX * metersPerPixel) / (111320 * Math.cos(mapCenter.lat * Math.PI / 180));\r\n \r\n setMapCenter({\r\n lat: mapCenter.lat + latOffset,\r\n lng: mapCenter.lng + lngOffset\r\n });\r\n \r\n setDragStart({ x: event.clientX, y: event.clientY });\r\n }, [isDragging, dragStart, mapCenter, mapZoom]);\r\n\r\n // Handle map mouse up (end drag or click)\r\n const handleMapMouseUp = useCallback(async (event: React.MouseEvent<HTMLDivElement>) => {\r\n if (!mapRef.current) return;\r\n \r\n if (isDragging && dragStart) {\r\n // Check if it was a drag (moved more than 5 pixels)\r\n const deltaX = Math.abs(event.clientX - dragStart.x);\r\n const deltaY = Math.abs(event.clientY - dragStart.y);\r\n \r\n if (deltaX > 5 || deltaY > 5) {\r\n // It was a drag, just update the center\r\n setIsDragging(false);\r\n setDragStart(null);\r\n return;\r\n }\r\n }\r\n \r\n // It was a click, select location\r\n if (readonly || disabled) {\r\n setIsDragging(false);\r\n setDragStart(null);\r\n return;\r\n }\r\n \r\n const rect = mapRef.current.getBoundingClientRect();\r\n const x = event.clientX - rect.left;\r\n const y = event.clientY - rect.top;\r\n \r\n const { lat, lng } = pixelToLatLng(x, y, mapCenter, mapZoom, rect.width, rect.height);\r\n \r\n // Update location with reverse geocoding\r\n await updateLocationWithAddress(lat, lng);\r\n \r\n setIsDragging(false);\r\n setDragStart(null);\r\n }, [readonly, disabled, mapRef, mapCenter, mapZoom, pixelToLatLng, updateLocationWithAddress, isDragging, dragStart]);\r\n\r\n // Search for location using Nominatim API (OpenStreetMap)\r\n const searchLocation = useCallback(async (query: string) => {\r\n if (!query.trim() || readonly || disabled) return;\r\n\r\n setIsSearching(true);\r\n setError('');\r\n\r\n try {\r\n const response = await fetch(\r\n `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&limit=5&addressdetails=1`\r\n );\r\n const results = await response.json();\r\n\r\n if (results && results.length > 0) {\r\n const firstResult = results[0];\r\n const lat = parseFloat(firstResult.lat);\r\n const lng = parseFloat(firstResult.lon);\r\n\r\n // Extract address components\r\n const address = firstResult.address || {};\r\n const location: ILocationData = {\r\n latitude: lat,\r\n longitude: lng,\r\n address: firstResult.display_name,\r\n placeName: firstResult.display_name,\r\n city: address.city || address.town || address.village || address.municipality || '',\r\n country: address.country || '',\r\n timestamp: Date.now()\r\n };\r\n\r\n setLocationData(location);\r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: false\r\n });\r\n setMapCenter({ lat, lng });\r\n setIsTouched(true);\r\n\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: location,\r\n isValid: true,\r\n errors: {},\r\n };\r\n onValueChange(change);\r\n }\r\n } else {\r\n setError('No locations found for your search.');\r\n }\r\n } catch (err) {\r\n setError('Failed to search for location. Please try again.');\r\n } finally {\r\n setIsSearching(false);\r\n }\r\n }, [readonly, disabled, id, onValueChange]);\r\n\r\n // Handle search input change\r\n const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setSearchQuery(event.target.value);\r\n };\r\n\r\n // Handle search form submission\r\n const handleSearchSubmit = (event: React.FormEvent) => {\r\n event.preventDefault();\r\n if (searchQuery.trim()) {\r\n searchLocation(searchQuery);\r\n }\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Format coordinates for display\r\n const formatCoordinates = (lat: number | undefined, lng: number | undefined): string => {\r\n if (lat === undefined || lng === undefined || isNaN(lat) || isNaN(lng)) {\r\n return '';\r\n }\r\n return `${Number(lat).toFixed(6)}, ${Number(lng).toFixed(6)}`;\r\n };\r\n\r\n // Format accuracy for display\r\n const formatAccuracy = (accuracy?: number): string => {\r\n if (!accuracy) return '';\r\n return `±${Math.round(accuracy)}m`;\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n const label = properties?.basic?.label || 'Location';\r\n const description = properties?.basic?.description || '';\r\n\r\n return (\r\n <div className={`form-group ${hideLabel ? 'no-label' : ''} ${className}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {label}\r\n {properties?.validation?.required && <span className=\"required-indicator\">*</span>}\r\n </label>\r\n )}\r\n\r\n {description && (\r\n <div className=\"form-group-description\">\r\n {description}\r\n </div>\r\n )}\r\n\r\n <div className=\"location-wrapper\">\r\n {/* Hide buttons when readonly and location data exists (submission view) */}\r\n {!(readonly && locationData) && (\r\n <div className=\"location-controls\">\r\n <button\r\n type=\"button\"\r\n className={`location-btn ${isLoading ? 'loading' : ''}`}\r\n onClick={getCurrentLocation}\r\n disabled={shouldDisable || isLoading}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n tabIndex={shouldDisable ? -1 : 0}\r\n >\r\n {isLoading ? (\r\n <>\r\n <Loader2 size={16} className=\"loading-spinner\" />\r\n Getting Location...\r\n </>\r\n ) : (\r\n <>\r\n <Navigation size={16} />\r\n Get Current Location\r\n </>\r\n )}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n className=\"location-btn secondary\"\r\n onClick={toggleMap}\r\n disabled={shouldDisable}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n tabIndex={shouldDisable ? -1 : 0}\r\n >\r\n <MapPin size={16} />\r\n {showMap ? 'Hide Map' : 'Choose on Map'}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {locationData && (\r\n <div className=\"location-display\">\r\n {/* Hide clear button when readonly (submission view) */}\r\n {!readonly && (\r\n <button\r\n type=\"button\"\r\n className=\"location-clear-btn\"\r\n onClick={clearLocation}\r\n disabled={shouldDisable}\r\n title=\"Clear location\"\r\n >\r\n <X size={16} />\r\n </button>\r\n )}\r\n {locationData.placeName && (\r\n <div className=\"location-place-name\">\r\n <strong>Place:</strong> {locationData.placeName}\r\n </div>\r\n )}\r\n {(locationData.city || locationData.country) && (\r\n <div className=\"location-address\">\r\n <strong>Address:</strong> {[locationData.city, locationData.country].filter(Boolean).join(', ')}\r\n </div>\r\n )}\r\n <div className=\"location-coordinates\">\r\n <strong>Coordinates:</strong> {formatCoordinates(locationData.latitude, locationData.longitude)}\r\n </div>\r\n {locationData.accuracy && (\r\n <div className=\"location-accuracy\">\r\n <strong>Accuracy:</strong> {formatAccuracy(locationData.accuracy)}\r\n </div>\r\n )}\r\n {locationData.timestamp && (\r\n <div className=\"location-timestamp\">\r\n <strong>Captured:</strong> {new Date(locationData.timestamp).toLocaleString()}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Hide map when readonly (submission view) */}\r\n {showMap && !readonly && (\r\n <div className=\"location-map-container\">\r\n <div className=\"location-map-header\">\r\n <h4>Select Location on Map</h4>\r\n <p>Search for a place or click on the map to select a location</p>\r\n </div>\r\n \r\n {/* Search functionality */}\r\n <div className=\"location-search\">\r\n <form onSubmit={handleSearchSubmit} className=\"search-form\">\r\n <div className=\"search-input-group\">\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={handleSearchChange}\r\n placeholder=\"Search for a place (e.g., New York, Paris, Tokyo)\"\r\n className=\"search-input\"\r\n disabled={shouldDisable || isSearching}\r\n />\r\n <button\r\n type=\"submit\"\r\n className=\"search-btn\"\r\n disabled={shouldDisable || isSearching || !searchQuery.trim()}\r\n >\r\n {isSearching ? (\r\n <Loader2 size={16} className=\"loading-spinner\" />\r\n ) : (\r\n 'Search'\r\n )}\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n\r\n {/* Map container */}\r\n <div \r\n ref={mapRef}\r\n className={`location-map ${isDragging ? 'dragging' : ''}`}\r\n onMouseDown={handleMapMouseDown}\r\n onMouseMove={handleMapMouseMove}\r\n onMouseUp={handleMapMouseUp}\r\n onMouseLeave={() => {\r\n setIsDragging(false);\r\n setDragStart(null);\r\n }}\r\n style={{\r\n position: 'relative',\r\n height: '400px',\r\n border: '2px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n cursor: isDragging ? 'grabbing' : 'grab',\r\n background: `url(https://tile.openstreetmap.org/${mapZoom}/${Math.floor((mapCenter.lng + 180) / 360 * Math.pow(2, mapZoom))}/${Math.floor((1 - Math.log(Math.tan(mapCenter.lat * Math.PI / 180) + 1 / Math.cos(mapCenter.lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, mapZoom))}.png) center/cover no-repeat`,\r\n userSelect: 'none'\r\n }}\r\n >\r\n {/* Map marker */}\r\n {mapMarker && (\r\n <div\r\n className={`map-marker ${mapMarker.isCurrentLocation ? 'current-location' : 'selected-location'}`}\r\n style={{\r\n position: 'absolute',\r\n left: '50%',\r\n top: '50%',\r\n transform: 'translate(-50%, -100%)',\r\n zIndex: 10\r\n }}\r\n >\r\n <MapPin size={24} />\r\n </div>\r\n )}\r\n \r\n {/* Map center indicator */}\r\n <div\r\n className=\"map-center-indicator\"\r\n style={{\r\n position: 'absolute',\r\n left: '50%',\r\n top: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n width: '4px',\r\n height: '4px',\r\n backgroundColor: 'var(--df-color-primary)',\r\n borderRadius: '50%',\r\n zIndex: 5\r\n }}\r\n />\r\n\r\n {/* Map controls */}\r\n <div className=\"map-controls\">\r\n <button\r\n type=\"button\"\r\n className=\"map-zoom-btn\"\r\n onClick={() => setMapZoom(prev => Math.min(18, prev + 1))}\r\n disabled={mapZoom >= 18}\r\n >\r\n +\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"map-zoom-btn\"\r\n onClick={() => setMapZoom(prev => Math.max(1, prev - 1))}\r\n disabled={mapZoom <= 1}\r\n >\r\n −\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <div className=\"location-map-instructions\">\r\n <p><strong>Instructions:</strong></p>\r\n <ul>\r\n <li>Search for a place using the search box above</li>\r\n <li>Click anywhere on the map to select a location</li>\r\n <li>Drag the map to pan around</li>\r\n <li>Use the zoom buttons (+/−) to zoom in/out</li>\r\n <li>Use \"Get Current Location\" to automatically detect your position</li>\r\n </ul>\r\n </div>\r\n \r\n {isReverseGeocoding && (\r\n <div className=\"location-loading\">\r\n <Loader2 size={16} className=\"loading-spinner\" />\r\n <span>Loading address details...</span>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"location-error\">\r\n {error}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={{ isValid: true, errors: {} }}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormLocation;\r\n","import React from 'react';\r\nimport { IHeadingComponent } from '../df-form-preview-interfaces';\r\n\r\ninterface DfFormHeadingProps {\r\n id: string;\r\n properties: IHeadingComponent;\r\n mode?: 'edit' | 'preview' | 'test';\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormHeading: React.FC<DfFormHeadingProps> = ({\r\n id,\r\n properties,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const level = (properties.styles as any)?.level ?? properties.basic.level ?? 1;\r\n const text = properties.basic.label;\r\n \r\n // Get heading classes\r\n const getHeadingClasses = (): string => {\r\n const base = 'form-heading';\r\n const levelClass = `h${level}`;\r\n const alignment = properties?.styles?.textAlign ? `text-${properties.styles.textAlign}` : '';\r\n return `${base} ${levelClass} ${alignment} ${className}`.trim();\r\n };\r\n\r\n // Get inline styles\r\n const getInlineStyles = (): React.CSSProperties => {\r\n const styles: React.CSSProperties = {};\r\n \r\n if (properties?.styles?.fontSize) {\r\n styles.fontSize = properties.styles.fontSize;\r\n }\r\n \r\n if (properties?.styles?.color) {\r\n styles.color = properties.styles.color;\r\n }\r\n \r\n return styles;\r\n };\r\n\r\n // Render the appropriate heading element\r\n const renderHeading = () => {\r\n const headingProps = {\r\n id,\r\n className: getHeadingClasses(),\r\n style: getInlineStyles(),\r\n };\r\n\r\n switch (level) {\r\n case 1:\r\n return <h1 {...headingProps}>{text}</h1>;\r\n case 2:\r\n return <h2 {...headingProps}>{text}</h2>;\r\n case 3:\r\n return <h3 {...headingProps}>{text}</h3>;\r\n case 4:\r\n return <h4 {...headingProps}>{text}</h4>;\r\n case 5:\r\n return <h5 {...headingProps}>{text}</h5>;\r\n case 6:\r\n return <h6 {...headingProps}>{text}</h6>;\r\n default:\r\n return <h1 {...headingProps}>{text}</h1>;\r\n }\r\n };\r\n\r\n // If hideLabel is true, don't render the heading\r\n if (hideLabel) {\r\n return null;\r\n }\r\n \r\n return renderHeading();\r\n};\r\n\r\nexport default DfFormHeading;\r\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { Bold, Italic, Image, List, ListOrdered } from 'lucide-react';\r\nimport { \r\n IInstructionComponent, \r\n IFormControlChange\r\n} from '../df-form-preview-interfaces';\r\n\r\ninterface DfFormInstructionProps {\r\n id: string;\r\n properties: IInstructionComponent;\r\n mode?: 'edit' | 'preview' | 'test';\r\n formValue?: any; // Add formValue prop to receive data from formValues\r\n onValueChange?: (change: IFormControlChange) => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormInstruction: React.FC<DfFormInstructionProps> = ({\r\n id,\r\n properties,\r\n mode = 'preview',\r\n formValue,\r\n onValueChange,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [htmlContent, setHtmlContent] = useState<string>('');\r\n const [listStyle, setListStyle] = useState<'none' | 'numbers' | 'bullets' | 'alpha'>(\r\n properties.validation?.listStyle || 'numbers'\r\n );\r\n const [selectedColor, setSelectedColor] = useState<string>('#000000');\r\n const editorRef = useRef<HTMLDivElement>(null);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const isUserInputRef = useRef(false);\r\n const isEditable = mode === 'edit';\r\n\r\n // Track previous properties to detect actual changes\r\n const prevPropsRef = useRef<{ instructions: string[]; listStyle: string; formValue: any }>({ \r\n instructions: [], \r\n listStyle: 'numbers',\r\n formValue: undefined\r\n });\r\n const prevModeRef = useRef<string>(mode);\r\n \r\n // Initialize content from properties - update when properties change or mode changes\r\n useEffect(() => {\r\n // CRITICAL: Check formValue first (from API/formValues), then fallback to properties\r\n // Handle different data formats for instructions\r\n let propsInstructions: string[] = [];\r\n let propsListStyle: 'none' | 'numbers' | 'bullets' | 'alpha' = 'numbers';\r\n \r\n // Priority 1: Check formValue (from API response or formValues state)\r\n if (formValue !== undefined && formValue !== null) {\r\n if (typeof formValue === 'object' && formValue.instructions) {\r\n // If formValue is an object with instructions property\r\n if (Array.isArray(formValue.instructions)) {\r\n propsInstructions = formValue.instructions;\r\n } else if (typeof formValue.instructions === 'string') {\r\n propsInstructions = [formValue.instructions];\r\n }\r\n // Check for listStyle in formValue\r\n if (formValue.listStyle) {\r\n propsListStyle = formValue.listStyle;\r\n }\r\n } else if (Array.isArray(formValue)) {\r\n propsInstructions = formValue;\r\n } else if (typeof formValue === 'string') {\r\n propsInstructions = [formValue];\r\n }\r\n }\r\n \r\n // Priority 2: Check properties.basic.value (API data structure)\r\n if (propsInstructions.length === 0 && properties.basic?.value) {\r\n const basicValue = properties.basic.value as any;\r\n if (basicValue && typeof basicValue === 'object' && !Array.isArray(basicValue) && basicValue.instructions) {\r\n // API structure: basic.value.instructions\r\n if (Array.isArray(basicValue.instructions)) {\r\n propsInstructions = basicValue.instructions;\r\n } else if (typeof basicValue.instructions === 'string') {\r\n propsInstructions = [basicValue.instructions];\r\n }\r\n // Get listStyle from basic.value.listStyle\r\n if (basicValue.listStyle && typeof basicValue.listStyle === 'string') {\r\n propsListStyle = basicValue.listStyle as 'none' | 'numbers' | 'bullets' | 'alpha';\r\n }\r\n } else if (Array.isArray(basicValue)) {\r\n propsInstructions = basicValue;\r\n } else if (typeof basicValue === 'string') {\r\n propsInstructions = [basicValue];\r\n }\r\n }\r\n \r\n // Priority 3: Fallback to properties.basic.instructions if formValue is empty\r\n if (propsInstructions.length === 0 && properties.basic?.instructions) {\r\n if (Array.isArray(properties.basic.instructions)) {\r\n propsInstructions = properties.basic.instructions;\r\n } else if (typeof properties.basic.instructions === 'string') {\r\n // If it's a string, try to parse it or use it as single instruction\r\n propsInstructions = [properties.basic.instructions];\r\n }\r\n }\r\n \r\n // Get listStyle from validation or basic.value\r\n if (!propsListStyle || propsListStyle === 'numbers') {\r\n propsListStyle = properties.validation?.listStyle || \r\n (properties.basic?.value as any)?.listStyle || \r\n 'numbers';\r\n }\r\n \r\n // Check if properties have actually changed\r\n const propsChanged = \r\n JSON.stringify(propsInstructions) !== JSON.stringify(prevPropsRef.current.instructions) ||\r\n propsListStyle !== prevPropsRef.current.listStyle;\r\n \r\n // Check if mode changed (e.g., switching from preview to edit)\r\n const modeChanged = mode !== prevModeRef.current;\r\n \r\n // CRITICAL: Check if formValue actually changed (for API data)\r\n // Use deep comparison to detect changes\r\n const formValueChanged = JSON.stringify(formValue) !== JSON.stringify(prevPropsRef.current.formValue);\r\n \r\n // CRITICAL: Also check if formValue was previously empty/null and now has data\r\n const formValueWasEmpty = !prevPropsRef.current.formValue || \r\n (Array.isArray(prevPropsRef.current.formValue) && prevPropsRef.current.formValue.length === 0) ||\r\n (typeof prevPropsRef.current.formValue === 'string' && prevPropsRef.current.formValue.trim() === '');\r\n const formValueNowHasData = formValue !== undefined && formValue !== null && \r\n ((Array.isArray(formValue) && formValue.length > 0) ||\r\n (typeof formValue === 'string' && formValue.trim() !== '') ||\r\n (typeof formValue === 'object' && Object.keys(formValue).length > 0));\r\n const formValueJustLoaded = formValueWasEmpty && formValueNowHasData;\r\n \r\n // Update if properties changed, mode changed, formValue changed (API data), or formValue just loaded\r\n if (propsChanged || modeChanged || formValueChanged || formValueJustLoaded) {\r\n // CRITICAL: Decode URL-encoded HTML strings (e.g., \\u003Cul\\u003E -> <ul>)\r\n const decodeHtml = (str: string): string => {\r\n if (typeof str !== 'string') return str;\r\n // Decode Unicode escape sequences\r\n return str.replace(/\\\\u([0-9a-fA-F]{4})/g, (match, code) => {\r\n return String.fromCharCode(parseInt(code, 16));\r\n });\r\n };\r\n \r\n // Decode all instruction strings\r\n const decodedInstructions = propsInstructions.map(inst => {\r\n if (typeof inst === 'string') {\r\n return decodeHtml(inst);\r\n }\r\n return inst;\r\n });\r\n \r\n const hasHtml = decodedInstructions.some(inst => typeof inst === 'string' && /<[^>]+>/.test(inst));\r\n let expectedContent = '';\r\n \r\n if (decodedInstructions.length > 0) {\r\n if (hasHtml) {\r\n // Already has HTML - just join and use as is\r\n expectedContent = decodedInstructions.join('');\r\n } else {\r\n const listTag = propsListStyle === 'numbers' ? 'ol' : propsListStyle === 'bullets' ? 'ul' : 'div';\r\n const listItems = decodedInstructions\r\n .filter(inst => inst && typeof inst === 'string')\r\n .map(inst => `<li>${inst.replace(/\\n/g, '<br>')}</li>`)\r\n .join('');\r\n \r\n if (listTag === 'div') {\r\n expectedContent = decodedInstructions\r\n .filter(inst => inst && typeof inst === 'string')\r\n .map(inst => `<div>${inst.replace(/\\n/g, '<br>')}</div>`)\r\n .join('');\r\n } else {\r\n expectedContent = `<${listTag}>${listItems}</${listTag}>`;\r\n }\r\n }\r\n }\r\n \r\n // Update state\r\n setListStyle(propsListStyle);\r\n setHtmlContent(expectedContent);\r\n \r\n // Update editor content when switching to edit mode or when properties change\r\n if (isEditable && editorRef.current) {\r\n // When switching to edit mode, always load from properties\r\n // When properties change, update if content is different\r\n if (modeChanged || (propsChanged && editorRef.current.innerHTML.trim() !== expectedContent.trim())) {\r\n editorRef.current.innerHTML = expectedContent;\r\n }\r\n }\r\n \r\n // Update previous refs\r\n prevPropsRef.current = { \r\n instructions: propsInstructions, \r\n listStyle: propsListStyle,\r\n formValue: formValue\r\n };\r\n prevModeRef.current = mode;\r\n }\r\n }, [formValue, properties.basic?.instructions, properties.validation?.listStyle, mode, isEditable]);\r\n\r\n // Sync htmlContent to editor when it changes (but not on user input)\r\n // This is mainly for when properties change externally\r\n useEffect(() => {\r\n if (isEditable && editorRef.current) {\r\n const currentEditorContent = editorRef.current.innerHTML.trim();\r\n const htmlContentTrimmed = htmlContent.trim();\r\n \r\n // Only update if content is different and it's not from user input\r\n if (htmlContentTrimmed !== currentEditorContent && !isUserInputRef.current) {\r\n editorRef.current.innerHTML = htmlContent;\r\n }\r\n }\r\n \r\n // Reset user input flag after a delay to allow for property updates\r\n if (isUserInputRef.current) {\r\n const timeout = setTimeout(() => {\r\n isUserInputRef.current = false;\r\n }, 200);\r\n return () => clearTimeout(timeout);\r\n }\r\n }, [htmlContent, isEditable]);\r\n\r\n // Handle content change - always save when content changes\r\n const handleContentChange = useCallback(() => {\r\n if (!editorRef.current) return;\r\n \r\n isUserInputRef.current = true;\r\n const content = editorRef.current.innerHTML.trim();\r\n \r\n // Always save the current content, even if it appears unchanged\r\n // This ensures data is persisted when user types and saves quickly\r\n const htmlInstructions = content ? [content] : [];\r\n \r\n // Always call onValueChange to ensure data is saved to field state\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: {\r\n instructions: htmlInstructions,\r\n listStyle\r\n },\r\n isValid: true,\r\n errors: {}\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n // Update state only if content actually changed (to avoid unnecessary re-renders)\r\n if (content !== htmlContent) {\r\n setHtmlContent(content);\r\n }\r\n }, [id, listStyle, onValueChange, htmlContent]);\r\n\r\n // Save on blur to ensure data is persisted when user leaves the editor\r\n const handleBlur = useCallback(() => {\r\n if (!editorRef.current) return;\r\n \r\n const content = editorRef.current.innerHTML.trim();\r\n const htmlInstructions = content ? [content] : [];\r\n \r\n // Always save on blur to ensure persistence\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: {\r\n instructions: htmlInstructions,\r\n listStyle\r\n },\r\n isValid: true,\r\n errors: {}\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n // Update state to match\r\n setHtmlContent(content);\r\n isUserInputRef.current = false;\r\n }, [id, listStyle, onValueChange]);\r\n\r\n // Format text command\r\n const executeCommand = useCallback((command: string, value?: string) => {\r\n document.execCommand(command, false, value);\r\n editorRef.current?.focus();\r\n handleContentChange();\r\n }, [handleContentChange]);\r\n\r\n // Handle bold\r\n const handleBold = useCallback(() => {\r\n executeCommand('bold');\r\n }, [executeCommand]);\r\n\r\n // Handle italic\r\n const handleItalic = useCallback(() => {\r\n executeCommand('italic');\r\n }, [executeCommand]);\r\n\r\n // Handle color\r\n const handleColorChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const color = e.target.value;\r\n setSelectedColor(color);\r\n executeCommand('foreColor', color);\r\n }, [executeCommand]);\r\n\r\n // Handle list style change\r\n const handleListStyleChange = useCallback((style: 'none' | 'numbers' | 'bullets' | 'alpha') => {\r\n setListStyle(style);\r\n \r\n if (!editorRef.current) return;\r\n \r\n // Save current selection\r\n const selection = window.getSelection();\r\n const range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;\r\n \r\n // Get current content\r\n let currentContent = editorRef.current.innerHTML;\r\n \r\n // Convert existing lists to the new format\r\n if (style === 'numbers') {\r\n // Convert ul to ol\r\n currentContent = currentContent.replace(/<ul>/gi, '<ol>').replace(/<\\/ul>/gi, '</ol>');\r\n // If no list exists, wrap content in ol\r\n if (!currentContent.includes('<ol>') && !currentContent.includes('<ul>')) {\r\n const lines = currentContent.split(/<br\\s*\\/?>/i).filter(line => line.trim());\r\n if (lines.length > 0) {\r\n currentContent = '<ol>' + lines.map(line => `<li>${line}</li>`).join('') + '</ol>';\r\n }\r\n }\r\n } else if (style === 'bullets') {\r\n // Convert ol to ul\r\n currentContent = currentContent.replace(/<ol>/gi, '<ul>').replace(/<\\/ol>/gi, '</ul>');\r\n // If no list exists, wrap content in ul\r\n if (!currentContent.includes('<ol>') && !currentContent.includes('<ul>')) {\r\n const lines = currentContent.split(/<br\\s*\\/?>/i).filter(line => line.trim());\r\n if (lines.length > 0) {\r\n currentContent = '<ul>' + lines.map(line => `<li>${line}</li>`).join('') + '</ul>';\r\n }\r\n }\r\n } else {\r\n // Remove list formatting\r\n currentContent = currentContent.replace(/<\\/?[ou]l>/gi, '').replace(/<li>/gi, '<div>').replace(/<\\/li>/gi, '</div>');\r\n }\r\n \r\n // Update editor content\r\n editorRef.current.innerHTML = currentContent;\r\n setHtmlContent(currentContent);\r\n \r\n // Restore selection if possible\r\n if (range && selection) {\r\n try {\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n } catch (e) {\r\n // Ignore selection errors\r\n }\r\n }\r\n \r\n // Trigger change\r\n handleContentChange();\r\n \r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: {\r\n instructions: currentContent ? [currentContent] : [],\r\n listStyle: style\r\n },\r\n isValid: true,\r\n errors: {}\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, handleContentChange, onValueChange]);\r\n\r\n // Handle image upload\r\n const handleImageUpload = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0];\r\n if (!file || !file.type.startsWith('image/')) return;\r\n \r\n const reader = new FileReader();\r\n reader.onload = (event) => {\r\n const imageUrl = event.target?.result as string;\r\n if (imageUrl && editorRef.current) {\r\n // Insert image at cursor position\r\n const img = document.createElement('img');\r\n img.src = imageUrl;\r\n img.style.maxWidth = '100%';\r\n img.style.height = 'auto';\r\n \r\n const selection = window.getSelection();\r\n if (selection && selection.rangeCount > 0) {\r\n const range = selection.getRangeAt(0);\r\n range.deleteContents();\r\n range.insertNode(img);\r\n } else {\r\n editorRef.current.appendChild(img);\r\n }\r\n \r\n handleContentChange();\r\n }\r\n };\r\n reader.readAsDataURL(file);\r\n \r\n // Reset file input\r\n if (fileInputRef.current) {\r\n fileInputRef.current.value = '';\r\n }\r\n }, [handleContentChange]);\r\n\r\n // Handle paste events to clean up pasted content\r\n const handlePaste = useCallback((e: React.ClipboardEvent) => {\r\n e.preventDefault();\r\n const text = e.clipboardData.getData('text/plain');\r\n const selection = window.getSelection();\r\n \r\n if (selection && selection.rangeCount > 0) {\r\n const range = selection.getRangeAt(0);\r\n range.deleteContents();\r\n const textNode = document.createTextNode(text);\r\n range.insertNode(textNode);\r\n range.setStartAfter(textNode);\r\n range.collapse(true);\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n }\r\n \r\n handleContentChange();\r\n }, [handleContentChange]);\r\n\r\n // Check if command is active\r\n const isCommandActive = useCallback((command: string): boolean => {\r\n return document.queryCommandState(command);\r\n }, []);\r\n\r\n return (\r\n <div className={`form-group instruction-group ${className}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"instruction-label\">\r\n {'Instructions'}\r\n </label>\r\n )}\r\n\r\n {/* Rich Text Editor - Only show in edit mode */}\r\n {isEditable ? (\r\n <div className=\"instruction-rich-editor\">\r\n {/* Toolbar */}\r\n <div className=\"instruction-toolbar\">\r\n <div className=\"toolbar-group\">\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${isCommandActive('bold') ? 'active' : ''}`}\r\n onClick={handleBold}\r\n title=\"Bold\"\r\n aria-label=\"Bold\"\r\n >\r\n <Bold size={16} />\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${isCommandActive('italic') ? 'active' : ''}`}\r\n onClick={handleItalic}\r\n title=\"Italic\"\r\n aria-label=\"Italic\"\r\n >\r\n <Italic size={16} />\r\n </button>\r\n </div>\r\n \r\n <div className=\"toolbar-separator\" />\r\n \r\n <div className=\"toolbar-group\">\r\n <div className=\"color-picker-wrapper\">\r\n <input\r\n type=\"color\"\r\n value={selectedColor}\r\n onChange={handleColorChange}\r\n className=\"color-picker-input\"\r\n title=\"Text Color\"\r\n />\r\n <label className=\"color-picker-label\" title=\"Text Color\">\r\n <span style={{ color: selectedColor }}>A</span>\r\n </label>\r\n </div>\r\n </div>\r\n \r\n <div className=\"toolbar-separator\" />\r\n \r\n <div className=\"toolbar-group\">\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${listStyle === 'bullets' ? 'active' : ''}`}\r\n onClick={() => handleListStyleChange('bullets')}\r\n title=\"Bullet List\"\r\n aria-label=\"Bullet List\"\r\n >\r\n <List size={16} />\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${listStyle === 'numbers' ? 'active' : ''}`}\r\n onClick={() => handleListStyleChange('numbers')}\r\n title=\"Numbered List\"\r\n aria-label=\"Numbered List\"\r\n >\r\n <ListOrdered size={16} />\r\n </button>\r\n </div>\r\n \r\n <div className=\"toolbar-separator\" />\r\n \r\n <div className=\"toolbar-group\">\r\n <button\r\n type=\"button\"\r\n className=\"toolbar-btn\"\r\n onClick={() => fileInputRef.current?.click()}\r\n title=\"Insert Image\"\r\n aria-label=\"Insert Image\"\r\n >\r\n <Image size={16} />\r\n </button>\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n onChange={handleImageUpload}\r\n style={{ display: 'none' }}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Editor */}\r\n <div\r\n ref={editorRef}\r\n contentEditable\r\n className=\"instruction-editor-content\"\r\n onInput={handleContentChange}\r\n onBlur={handleBlur}\r\n onPaste={handlePaste}\r\n data-placeholder=\"Enter instructions (press Enter for a new line)...\"\r\n suppressContentEditableWarning\r\n />\r\n </div>\r\n ) : (\r\n /* Preview Mode - Show formatted content */\r\n <div className={`instruction-preview-wrapper ${listStyle === 'numbers' ? 'instruction-list-numbers' : listStyle === 'bullets' ? 'instruction-list-bullets' : ''}`}>\r\n {htmlContent ? (\r\n <div \r\n className=\"instruction-preview-content\"\r\n dangerouslySetInnerHTML={{ __html: htmlContent }}\r\n />\r\n ) : (\r\n <div className=\"instruction-empty\">\r\n <p>No instructions provided</p>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormInstruction;\r\n\r\n","import React, { useState, useCallback, useEffect, useRef } from 'react';\r\nimport { MessageSquare, Paperclip, Mail, AlertCircle, X, Check, ChevronDown, ChevronUp } from 'lucide-react';\r\nimport { FormComponentType as TFormComponent } from './df-form-controls/df-form-preview-interfaces';\r\nimport { RaiseIssueModal } from './components/RaiseIssueModal';\r\nimport './ComponentActionFeatures.scss';\r\n\r\n// Attachment Thumbnails Component\r\nconst AttachmentThumbnails: React.FC<{\r\n attachments: File[] | null;\r\n onRemove: (index: number) => void;\r\n}> = ({ attachments, onRemove }) => {\r\n const [objectUrls, setObjectUrls] = useState<Map<number, string>>(new Map());\r\n\r\n useEffect(() => {\r\n if (!attachments) {\r\n // Cleanup all URLs\r\n setObjectUrls(prev => {\r\n prev.forEach(url => URL.revokeObjectURL(url));\r\n return new Map();\r\n });\r\n return;\r\n }\r\n\r\n const newUrls = new Map<number, string>();\r\n attachments.forEach((file, index) => {\r\n if (file.type.startsWith('image/')) {\r\n const url = URL.createObjectURL(file);\r\n newUrls.set(index, url);\r\n }\r\n });\r\n\r\n // Cleanup old URLs that are no longer needed\r\n setObjectUrls(prev => {\r\n prev.forEach((url, index) => {\r\n if (!newUrls.has(index)) {\r\n URL.revokeObjectURL(url);\r\n }\r\n });\r\n return newUrls;\r\n });\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n newUrls.forEach(url => URL.revokeObjectURL(url));\r\n };\r\n }, [attachments]);\r\n\r\n if (!attachments || attachments.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"attachment-thumbnails-container\">\r\n {attachments.map((file, index) => {\r\n const isImage = file.type.startsWith('image/');\r\n const objectUrl = objectUrls.get(index);\r\n \r\n return (\r\n <div key={index} className=\"attachment-thumbnail\">\r\n {isImage && objectUrl ? (\r\n <>\r\n <img src={objectUrl} alt={file.name} />\r\n <button\r\n type=\"button\"\r\n className=\"thumbnail-remove-btn\"\r\n onClick={() => onRemove(index)}\r\n title=\"Remove attachment\"\r\n >\r\n <X size={14} />\r\n </button>\r\n </>\r\n ) : (\r\n <>\r\n <div className=\"file-icon-placeholder\">\r\n <Paperclip size={20} />\r\n </div>\r\n <span className=\"file-name\">{file.name}</span>\r\n <button\r\n type=\"button\"\r\n className=\"thumbnail-remove-btn\"\r\n onClick={() => onRemove(index)}\r\n title=\"Remove attachment\"\r\n >\r\n <X size={14} />\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n\r\ninterface IComponentActionFeaturesProps {\r\n component: TFormComponent;\r\n mode: 'edit' | 'preview' | 'test';\r\n formTemplateId?: string;\r\n formValue?: any;\r\n onNotesChange?: (notes: string) => void;\r\n onAttachmentChange?: (files: File[] | null) => void;\r\n notes?: string;\r\n attachments?: File[] | null;\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void;\r\n onThresholdIssueRaised?: (conditionId: string) => void;\r\n onBasicPropertyActionCompletion?: (action: 'notes' | 'attachments' | 'email' | 'issue', completed: boolean) => void;\r\n}\r\n\r\nexport const ComponentActionFeatures: React.FC<IComponentActionFeaturesProps> = ({\r\n component,\r\n mode,\r\n formTemplateId,\r\n formValue,\r\n onNotesChange,\r\n onAttachmentChange,\r\n notes = '',\r\n attachments = null,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onBasicPropertyActionCompletion\r\n}) => {\r\n const [localNotes, setLocalNotes] = useState<string>(notes || '');\r\n const [localAttachments, setLocalAttachments] = useState<File[] | null>(attachments || null);\r\n const [showNotesInput, setShowNotesInput] = useState<boolean>(false);\r\n const [showRaiseIssueModal, setShowRaiseIssueModal] = useState<boolean>(false);\r\n const [emailSent, setEmailSent] = useState<boolean>(false);\r\n const [issueRaised, setIssueRaised] = useState<boolean>(false);\r\n const [actionsExpanded, setActionsExpanded] = useState<boolean>(false);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const previousFormValueRef = useRef<any>(formValue);\r\n const notesInitializedRef = useRef<boolean>(false);\r\n const attachmentsInitializedRef = useRef<boolean>(false);\r\n\r\n // Initialize local state from props on mount\r\n useEffect(() => {\r\n if (!notesInitializedRef.current && notes !== undefined && notes !== null) {\r\n const notesStr = typeof notes === 'string' ? notes : String(notes || '');\r\n setLocalNotes(notesStr);\r\n notesInitializedRef.current = true;\r\n }\r\n }, [notes]);\r\n\r\n useEffect(() => {\r\n if (!attachmentsInitializedRef.current && attachments !== undefined) {\r\n setLocalAttachments(attachments);\r\n attachmentsInitializedRef.current = true;\r\n }\r\n }, [attachments]);\r\n\r\n // Sync local state with props when they change (but don't override if user is actively editing or has local data)\r\n useEffect(() => {\r\n if (notesInitializedRef.current && !showNotesInput && notes !== undefined && notes !== null) {\r\n const notesStr = typeof notes === 'string' ? notes : String(notes || '');\r\n // Only sync if local notes are empty or props have a different value\r\n // Also check if notes prop matches localNotes to avoid unnecessary updates\r\n if ((!localNotes || String(localNotes || '').trim() === '') && notesStr && notesStr.trim() !== '') {\r\n // Only update if local is empty and prop has value\r\n setLocalNotes(notesStr);\r\n } else if (notesStr && notesStr.trim() !== '' && notesStr !== localNotes) {\r\n // Only update if prop has a different non-empty value\r\n setLocalNotes(notesStr);\r\n }\r\n }\r\n }, [notes, showNotesInput, localNotes]);\r\n\r\n useEffect(() => {\r\n if (attachmentsInitializedRef.current && attachments !== undefined) {\r\n // Only sync if local attachments are null or props have different attachments\r\n if (!localAttachments || (attachments && attachments.length > 0 && attachments !== localAttachments)) {\r\n setLocalAttachments(attachments);\r\n }\r\n }\r\n }, [attachments, localAttachments]);\r\n\r\n // Reset state when formValue changes for option-based components only\r\n // For ALL other components (input, textarea, date, signature, location, etc.), preserve notes and attachments\r\n useEffect(() => {\r\n const isOptionBasedComponent = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');\r\n \r\n // Only reset for option-based components when the selected option actually changes\r\n if (isOptionBasedComponent) {\r\n const previousValue = previousFormValueRef.current;\r\n const currentValue = formValue;\r\n \r\n // Check if the value actually changed (not just initialized)\r\n // For checkbox, compare arrays properly\r\n let valueChanged = false;\r\n if (component.name === 'checkbox') {\r\n const prevArray = Array.isArray(previousValue) ? previousValue : (previousValue ? [previousValue] : []);\r\n const currArray = Array.isArray(currentValue) ? currentValue : (currentValue ? [currentValue] : []);\r\n valueChanged = JSON.stringify(prevArray.sort()) !== JSON.stringify(currArray.sort());\r\n } else {\r\n valueChanged = previousValue !== currentValue && previousValue !== undefined;\r\n }\r\n \r\n if (valueChanged) {\r\n // Only reset action states, but preserve notes and attachments if they exist in props\r\n setEmailSent(false);\r\n setIssueRaised(false);\r\n setShowRaiseIssueModal(false);\r\n setShowNotesInput(false);\r\n setActionsExpanded(false);\r\n \r\n // For option-based components, notes/attachments should be preserved per option\r\n // Only reset if props don't have them AND we're switching to a different option\r\n // Check if notes exist in props first\r\n const notesStr = typeof notes === 'string' ? notes : String(notes || '');\r\n if (!notesStr || notesStr.trim() === '') {\r\n // Only clear if we're switching options and there are no saved notes\r\n setLocalNotes('');\r\n } else {\r\n // Keep the notes from props\r\n setLocalNotes(notesStr);\r\n }\r\n \r\n if (!attachments || attachments.length === 0) {\r\n setLocalAttachments(null);\r\n } else {\r\n // Keep the attachments from props\r\n setLocalAttachments(attachments);\r\n }\r\n }\r\n \r\n previousFormValueRef.current = currentValue;\r\n }\r\n // For ALL non-option-based components (input, textarea, date, signature, location, etc.),\r\n // NEVER reset notes/attachments when form value changes - they should persist\r\n // Just update the ref to track value changes for future comparisons\r\n if (!isOptionBasedComponent) {\r\n previousFormValueRef.current = formValue;\r\n }\r\n }, [formValue, component.name, notes, attachments]);\r\n\r\n // Helper function to evaluate threshold conditions\r\n const evaluateThresholdCondition = useCallback((condition: any, value: any): boolean => {\r\n const { operator, value: conditionValue } = condition;\r\n const stringValue = String(value).toLowerCase();\r\n const stringConditionValue = String(conditionValue).toLowerCase();\r\n\r\n switch (operator) {\r\n case 'equals':\r\n return stringValue === stringConditionValue || String(value) === String(conditionValue);\r\n case 'notEquals':\r\n return stringValue !== stringConditionValue && String(value) !== String(conditionValue);\r\n case 'greaterThan':\r\n return Number(value) > Number(conditionValue);\r\n case 'lessThan':\r\n return Number(value) < Number(conditionValue);\r\n case 'greaterThanOrEqual':\r\n return Number(value) >= Number(conditionValue);\r\n case 'lessThanOrEqual':\r\n return Number(value) <= Number(conditionValue);\r\n default:\r\n return false;\r\n }\r\n }, []);\r\n\r\n // Find active threshold condition(s) for this component\r\n const getActiveThresholdConditions = useCallback((): any[] => {\r\n const hasValidFormValue = formValue !== undefined && \r\n formValue !== null && \r\n formValue !== '' && \r\n !(Array.isArray(formValue) && formValue.length === 0);\r\n if (!hasValidFormValue) return [];\r\n const condition = (component as any).condition;\r\n if (!condition || !condition.conditions || condition.conditions.length === 0) return [];\r\n \r\n const activeConditions: any[] = [];\r\n \r\n if (component.name === 'checkbox' && Array.isArray(formValue)) {\r\n formValue.forEach((value: any) => {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, value)\r\n );\r\n if (matchingCondition && !activeConditions.find(c => c.id === matchingCondition.id)) {\r\n activeConditions.push(matchingCondition);\r\n }\r\n });\r\n } else {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, formValue)\r\n );\r\n if (matchingCondition) {\r\n activeConditions.push(matchingCondition);\r\n }\r\n }\r\n \r\n return activeConditions;\r\n }, [component, formValue, evaluateThresholdCondition]);\r\n\r\n const handleNotesChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n const value = e.target.value;\r\n setLocalNotes(value);\r\n if (onNotesChange) {\r\n onNotesChange(value);\r\n }\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n const isCompleted = String(value || '').trim().length > 0;\r\n activeConditions.forEach(condition => {\r\n if (condition.enableNotes === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'notes', isCompleted);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('notes', isCompleted);\r\n }\r\n }, [onNotesChange, getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleNotesSave = useCallback(() => {\r\n // Save notes and close input - always save even if empty\r\n if (onNotesChange) {\r\n const notesStr = typeof localNotes === 'string' ? localNotes : String(localNotes || '');\r\n // Call the callback to persist notes\r\n onNotesChange(notesStr);\r\n // Use setTimeout to ensure the callback completes before closing\r\n // This prevents the sync effect from overwriting the saved notes\r\n setTimeout(() => {\r\n setShowNotesInput(false);\r\n }, 0);\r\n } else {\r\n // If no callback, just close immediately\r\n setShowNotesInput(false);\r\n }\r\n }, [localNotes, onNotesChange]);\r\n\r\n const handleNotesBlur = useCallback(() => {\r\n // Save notes when blurring\r\n handleNotesSave();\r\n }, [handleNotesSave]);\r\n\r\n const handleNotesKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n // Save on Ctrl+Enter or Cmd+Enter\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {\r\n e.preventDefault();\r\n handleNotesSave();\r\n }\r\n }, [handleNotesSave]);\r\n\r\n const handleNotesIconClick = useCallback(() => {\r\n setShowNotesInput(true);\r\n }, []);\r\n\r\n const handleNotesSummaryClick = useCallback(() => {\r\n setShowNotesInput(true);\r\n }, []);\r\n\r\n const handleAttachmentIconClick = useCallback(() => {\r\n fileInputRef.current?.click();\r\n }, []);\r\n\r\n const handleFileChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = e.target.files;\r\n if (files && files.length > 0) {\r\n const fileArray = Array.from(files);\r\n setLocalAttachments(fileArray);\r\n if (onAttachmentChange) {\r\n onAttachmentChange(fileArray);\r\n }\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableAttachment === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'attachments', true);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('attachments', true);\r\n }\r\n }\r\n // Reset input so same file can be selected again\r\n if (fileInputRef.current) {\r\n fileInputRef.current.value = '';\r\n }\r\n }, [onAttachmentChange, getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleRemoveAttachment = useCallback((index: number) => {\r\n if (localAttachments) {\r\n const newAttachments = localAttachments.filter((_, i) => i !== index);\r\n if (newAttachments.length === 0) {\r\n setLocalAttachments(null);\r\n if (onAttachmentChange) {\r\n onAttachmentChange(null);\r\n }\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableAttachment === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'attachments', false);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('attachments', false);\r\n }\r\n } else {\r\n setLocalAttachments(newAttachments);\r\n if (onAttachmentChange) {\r\n onAttachmentChange(newAttachments);\r\n }\r\n }\r\n }\r\n }, [localAttachments, onAttachmentChange, getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleSendEmailClick = useCallback(() => {\r\n // Immediately send email\r\n setEmailSent(true);\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableSendEmail === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'email', true);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('email', true);\r\n }\r\n \r\n // TODO: Call send email API when available\r\n setTimeout(() => {\r\n setEmailSent(false);\r\n }, 3000);\r\n }, [getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleRaiseIssueClick = useCallback(() => {\r\n setShowRaiseIssueModal(true);\r\n }, []);\r\n\r\n const handleRaiseIssueClose = useCallback(() => {\r\n setShowRaiseIssueModal(false);\r\n }, []);\r\n\r\n const handleRaiseIssueSuccess = useCallback(() => {\r\n setShowRaiseIssueModal(false);\r\n setIssueRaised(true);\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n \r\n if (hasComponentThresholdConditions) {\r\n // For threshold conditions, notify each active condition that issue was raised\r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableRaiseIssue === true && onThresholdIssueRaised) {\r\n onThresholdIssueRaised(condition.id);\r\n }\r\n });\r\n } else if (onBasicPropertyActionCompletion) {\r\n // For basic property actions (no threshold conditions)\r\n onBasicPropertyActionCompletion('issue', true);\r\n }\r\n }, [component, onBasicPropertyActionCompletion, getActiveThresholdConditions, onThresholdIssueRaised]);\r\n\r\n // Only show in test mode\r\n if (mode !== 'test') {\r\n return null;\r\n }\r\n\r\n // Check if this is an option-based component\r\n const isOptionBasedComponent = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');\r\n const componentOptions = (component as any).basic?.options || (component as any).options || [];\r\n\r\n let enableNotes = false;\r\n let enableAttachment = false;\r\n let enableRaiseIssue = false;\r\n let enableSendEmail = false;\r\n let selectedOption: any = null;\r\n\r\n const hasValidFormValue = formValue !== undefined && \r\n formValue !== null && \r\n formValue !== '' && \r\n !(Array.isArray(formValue) && formValue.length === 0);\r\n\r\n const condition = (component as any).condition;\r\n const hasThresholdConditions = condition && condition.conditions && condition.conditions.length > 0;\r\n \r\n if (hasThresholdConditions && hasValidFormValue) {\r\n if (component.name === 'checkbox' && Array.isArray(formValue)) {\r\n const selectedValues = formValue;\r\n for (const value of selectedValues) {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, value)\r\n );\r\n if (matchingCondition) {\r\n enableNotes = enableNotes || (matchingCondition.enableNotes === true);\r\n enableAttachment = enableAttachment || (matchingCondition.enableAttachment === true);\r\n enableRaiseIssue = enableRaiseIssue || (matchingCondition.enableRaiseIssue === true);\r\n enableSendEmail = enableSendEmail || (matchingCondition.enableSendEmail === true);\r\n }\r\n }\r\n } else if (isOptionBasedComponent) {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, formValue)\r\n );\r\n if (matchingCondition) {\r\n enableNotes = matchingCondition.enableNotes === true;\r\n enableAttachment = matchingCondition.enableAttachment === true;\r\n enableRaiseIssue = matchingCondition.enableRaiseIssue === true;\r\n enableSendEmail = matchingCondition.enableSendEmail === true;\r\n }\r\n } else {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, formValue)\r\n );\r\n if (matchingCondition) {\r\n enableNotes = matchingCondition.enableNotes === true;\r\n enableAttachment = matchingCondition.enableAttachment === true;\r\n enableRaiseIssue = matchingCondition.enableRaiseIssue === true;\r\n enableSendEmail = matchingCondition.enableSendEmail === true;\r\n }\r\n }\r\n }\r\n\r\n if (!hasThresholdConditions) {\r\n // First, get component-level actions as fallback\r\n const componentBasic = component.basic as any;\r\n const componentLevelNotes = componentBasic?.enableNotes === true;\r\n const componentLevelAttachment = componentBasic?.enableAttachment === true;\r\n const componentLevelRaiseIssue = componentBasic?.enableRaiseIssue === true;\r\n const componentLevelSendEmail = componentBasic?.enableSendEmail === true;\r\n \r\n if (isOptionBasedComponent) {\r\n if (hasValidFormValue) {\r\n // Value is selected, check option-level actions\r\n if (component.name === 'checkbox') {\r\n const selectedValues = Array.isArray(formValue) ? formValue : [formValue];\r\n selectedValues.forEach((value: any) => {\r\n const option = componentOptions.find((opt: any) => {\r\n if (!opt || !opt.value) return false;\r\n if (opt.value === value) return true;\r\n if (String(opt.value) === String(value)) return true;\r\n if (opt.label === value || String(opt.label) === String(value)) return true;\r\n return false;\r\n });\r\n if (option) {\r\n // Check if option has actions enabled\r\n enableNotes = enableNotes || (option.enableNotes === true);\r\n enableAttachment = enableAttachment || (option.enableAttachment === true);\r\n enableRaiseIssue = enableRaiseIssue || (option.enableRaiseIssue === true);\r\n enableSendEmail = enableSendEmail || (option.enableSendEmail === true);\r\n if (!selectedOption) {\r\n selectedOption = option;\r\n }\r\n }\r\n });\r\n // Always include component-level actions as fallback\r\n enableNotes = enableNotes || componentLevelNotes;\r\n enableAttachment = enableAttachment || componentLevelAttachment;\r\n enableRaiseIssue = enableRaiseIssue || componentLevelRaiseIssue;\r\n enableSendEmail = enableSendEmail || componentLevelSendEmail;\r\n } else {\r\n selectedOption = componentOptions.find((opt: any) => {\r\n if (!opt || !opt.value) return false;\r\n if (opt.value === formValue) return true;\r\n if (String(opt.value) === String(formValue)) return true;\r\n if (opt.label === formValue || String(opt.label) === String(formValue)) return true;\r\n return false;\r\n });\r\n if (selectedOption) {\r\n const optionNotes = selectedOption.enableNotes === true;\r\n const optionAttachment = selectedOption.enableAttachment === true;\r\n const optionRaiseIssue = selectedOption.enableRaiseIssue === true;\r\n const optionSendEmail = selectedOption.enableSendEmail === true;\r\n \r\n // Use option-level actions if set, otherwise fallback to component-level\r\n enableNotes = optionNotes || componentLevelNotes;\r\n enableAttachment = optionAttachment || componentLevelAttachment;\r\n enableRaiseIssue = optionRaiseIssue || componentLevelRaiseIssue;\r\n enableSendEmail = optionSendEmail || componentLevelSendEmail;\r\n } else {\r\n // No option found, use component-level actions\r\n enableNotes = componentLevelNotes;\r\n enableAttachment = componentLevelAttachment;\r\n enableRaiseIssue = componentLevelRaiseIssue;\r\n enableSendEmail = componentLevelSendEmail;\r\n }\r\n }\r\n } else {\r\n // No value selected, but still show component-level actions if enabled\r\n enableNotes = componentLevelNotes;\r\n enableAttachment = componentLevelAttachment;\r\n enableRaiseIssue = componentLevelRaiseIssue;\r\n enableSendEmail = componentLevelSendEmail;\r\n }\r\n } else {\r\n // Not an option-based component, use component-level actions\r\n enableNotes = componentLevelNotes;\r\n enableAttachment = componentLevelAttachment;\r\n enableRaiseIssue = componentLevelRaiseIssue;\r\n enableSendEmail = componentLevelSendEmail;\r\n }\r\n }\r\n\r\n if (!enableNotes && !enableAttachment && !enableRaiseIssue && !enableSendEmail) {\r\n return null;\r\n }\r\n\r\n const activeConditions = getActiveThresholdConditions();\r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n \r\n const isNotesMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableNotes === true) \r\n : false;\r\n const isAttachmentsMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableAttachment === true) \r\n : false;\r\n const isSendEmailMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableSendEmail === true) \r\n : false;\r\n const isRaiseIssueMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableRaiseIssue === true) \r\n : false;\r\n\r\n const hasNotes = String(localNotes || '').trim().length > 0;\r\n const hasAttachments = localAttachments && localAttachments.length > 0;\r\n const attachmentCount = localAttachments ? localAttachments.length : 0;\r\n\r\n return (\r\n <>\r\n <div className=\"component-action-features\">\r\n {/* Icon Toolbar */}\r\n <div className=\"action-icons-toolbar\">\r\n {enableNotes && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${hasNotes ? 'active' : ''} ${isNotesMandatory ? 'mandatory' : ''}`}\r\n onClick={handleNotesIconClick}\r\n title=\"Add Notes\"\r\n >\r\n <MessageSquare size={14} fill={hasNotes ? 'currentColor' : 'none'} />\r\n {isNotesMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {enableAttachment && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${hasAttachments ? 'active' : ''} ${isAttachmentsMandatory ? 'mandatory' : ''}`}\r\n onClick={handleAttachmentIconClick}\r\n title=\"Add Attachment\"\r\n >\r\n <Paperclip size={14} fill={hasAttachments ? 'currentColor' : 'none'} />\r\n {attachmentCount > 0 && <span className=\"attachment-count-badge\">{attachmentCount}</span>}\r\n {isAttachmentsMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {enableSendEmail && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${emailSent ? 'active sent' : ''} ${isSendEmailMandatory ? 'mandatory' : ''}`}\r\n onClick={handleSendEmailClick}\r\n disabled={emailSent}\r\n title=\"Send Email\"\r\n >\r\n {emailSent ? (\r\n <>\r\n <Check size={14} />\r\n </>\r\n ) : (\r\n <Mail size={14} fill={emailSent ? 'currentColor' : 'none'} />\r\n )}\r\n {isSendEmailMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {enableRaiseIssue && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${issueRaised ? 'active' : ''} ${isRaiseIssueMandatory ? 'mandatory' : ''}`}\r\n onClick={handleRaiseIssueClick}\r\n title=\"Raise an Issue\"\r\n >\r\n <AlertCircle size={14} fill={issueRaised ? 'currentColor' : 'none'} />\r\n {isRaiseIssueMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {/* Accordion Toggle Button - Show if there are notes or attachments */}\r\n {((hasNotes && enableNotes) || (hasAttachments && enableAttachment)) && (\r\n <button\r\n type=\"button\"\r\n className=\"action-icon-button accordion-toggle\"\r\n onClick={() => setActionsExpanded(!actionsExpanded)}\r\n title={actionsExpanded ? 'Collapse' : 'Expand'}\r\n >\r\n {actionsExpanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Notes Input Overlay */}\r\n {showNotesInput && enableNotes && (\r\n <div className=\"notes-input-overlay\">\r\n <textarea\r\n className=\"action-notes-textarea\"\r\n value={localNotes}\r\n onChange={handleNotesChange}\r\n onBlur={handleNotesBlur}\r\n onKeyDown={handleNotesKeyDown}\r\n placeholder=\"Explain which protocols were not followed (Press Ctrl+Enter to save)\"\r\n rows={4}\r\n autoFocus\r\n />\r\n <div className=\"notes-input-actions\">\r\n <button\r\n type=\"button\"\r\n className=\"notes-save-button\"\r\n onClick={handleNotesSave}\r\n title=\"Save notes (Ctrl+Enter)\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"notes-cancel-button\"\r\n onClick={() => {\r\n setShowNotesInput(false);\r\n }}\r\n title=\"Cancel\"\r\n >\r\n Cancel\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Notes and Attachments Content - Controlled by Accordion */}\r\n {actionsExpanded && (\r\n <div className=\"actions-content\">\r\n {/* Notes Summary */}\r\n {!showNotesInput && hasNotes && enableNotes && (\r\n <div className=\"notes-summary-section\">\r\n <div className=\"notes-full-text\" onClick={handleNotesSummaryClick}>\r\n <span className=\"notes-label\">Notes:</span> {localNotes}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Attachment Thumbnails */}\r\n {hasAttachments && enableAttachment && (\r\n <div className=\"attachments-section\">\r\n <AttachmentThumbnails\r\n attachments={localAttachments}\r\n onRemove={handleRemoveAttachment}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Hidden File Input */}\r\n {enableAttachment && (\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n multiple\r\n accept=\"image/*,.pdf\"\r\n onChange={handleFileChange}\r\n style={{ display: 'none' }}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Raise Issue Modal */}\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={selectedOption ? {\r\n ...component,\r\n basic: {\r\n ...(component.basic as any),\r\n label: `${(component.basic as any)?.label || 'Component'} - ${selectedOption.label || selectedOption.value}`,\r\n value: selectedOption.value || (component.basic as any)?.value || ''\r\n } as any\r\n } : component}\r\n formTemplateId={formTemplateId || ''}\r\n notes={localNotes}\r\n attachments={localAttachments}\r\n />\r\n )}\r\n </>\r\n );\r\n};\r\n","import React from 'react';\r\nimport { Paperclip } from 'lucide-react';\r\nimport { FormComponentType as TFormComponent } from '../df-form-controls/df-form-preview-interfaces';\r\nimport './ComponentSubmissionActions.scss';\r\n\r\ninterface IComponentSubmissionActionsProps {\r\n component: TFormComponent;\r\n}\r\n\r\ninterface IAttachmentData {\r\n name: string;\r\n type: string;\r\n size: number;\r\n data: string;\r\n}\r\n\r\n// Attachment Thumbnails Component for Submission View\r\nconst SubmissionAttachmentThumbnails: React.FC<{\r\n attachments: IAttachmentData[];\r\n}> = ({ attachments }) => {\r\n // Convert base64 data to data URI for display\r\n const getImageSrc = (attachment: IAttachmentData): string => {\r\n if (!attachment.data) return '';\r\n \r\n // If already a data URI, return as is\r\n if (attachment.data.startsWith('data:')) {\r\n return attachment.data;\r\n }\r\n \r\n // Convert base64 to data URI\r\n const mimeType = attachment.type || 'image/png';\r\n return `data:${mimeType};base64,${attachment.data}`;\r\n };\r\n\r\n if (!attachments || attachments.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"attachment-thumbnails-container\">\r\n {attachments.map((attachment, index) => {\r\n const isImage = attachment.type?.startsWith('image/') || false;\r\n const imageSrc = isImage ? getImageSrc(attachment) : '';\r\n \r\n return (\r\n <div key={index} className=\"attachment-thumbnail\">\r\n {isImage && imageSrc ? (\r\n <img src={imageSrc} alt={attachment.name || `Attachment ${index + 1}`} />\r\n ) : (\r\n <div className=\"file-icon-placeholder\">\r\n <Paperclip size={20} />\r\n <span className=\"file-name\">{attachment.name || `File ${index + 1}`}</span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n\r\nexport const ComponentSubmissionActions: React.FC<IComponentSubmissionActionsProps> = ({\r\n component\r\n}) => {\r\n // Extract notes and attachments from component.basic\r\n const notes = (component as any).basic?.notes || '';\r\n const attachments = ((component as any).basic?.attachments || []) as IAttachmentData[];\r\n\r\n const hasNotes = notes && notes.trim().length > 0;\r\n const hasAttachments = attachments && attachments.length > 0;\r\n\r\n // Don't render if there are no notes or attachments\r\n if (!hasNotes && !hasAttachments) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"component-submission-actions\">\r\n {/* Notes and Attachments Content - Always visible */}\r\n <div className=\"actions-content\">\r\n {/* Notes Summary */}\r\n {hasNotes && (\r\n <div className=\"notes-summary-section\">\r\n <div className=\"notes-full-text\">\r\n <span className=\"notes-label\">Notes:</span> {notes}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Attachment Thumbnails */}\r\n {hasAttachments && (\r\n <div className=\"attachments-section\">\r\n <SubmissionAttachmentThumbnails attachments={attachments} />\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n","import React, { useState, useCallback, useEffect } from 'react'\r\nimport { useDroppable } from '@dnd-kit/core'\r\nimport { useSortable, SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { ChevronDown, ChevronRight, GripVertical, Edit, Trash2 } from 'lucide-react'\r\nimport { ISectionComponent, FormComponentType, IFormControlChange } from '../df-form-preview-interfaces'\r\n\r\n// Import form control components for rendering children\r\nimport { DfFormInput } from '../df-form-input'\r\nimport { DfFormTextarea } from '../df-form-textarea'\r\nimport { DfFormSelect } from '../df-form-select'\r\nimport { DfFormCheckbox } from '../df-form-checkbox'\r\nimport { DfFormRadio } from '../df-form-radio'\r\nimport { DfFormDateTime } from '../df-form-date-time'\r\nimport { DfFormSignature } from '../df-form-signature'\r\nimport { DfFormHeading } from '../df-form-heading'\r\nimport { ComponentActionFeatures } from '../../ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from '../../components/ComponentSubmissionActions'\r\n\r\ninterface DfFormSectionProps {\r\n id: string\r\n properties: ISectionComponent\r\n validationErrors?: Record<string, any>\r\n formValue?: any\r\n formData?: Record<string, any>\r\n readonly?: boolean\r\n disabled?: boolean\r\n touchedFields?: Record<string, boolean>\r\n formSubmitted?: boolean\r\n mode?: 'edit' | 'preview' | 'test'\r\n onValueChange?: (change: IFormControlChange) => void\r\n onBlur?: () => void\r\n onFocus?: () => void\r\n onSelect?: () => void\r\n isSelected?: boolean\r\n className?: string\r\n // Section-specific props\r\n onSectionSelect?: (section: ISectionComponent) => void\r\n onSectionDelete?: (sectionId: string) => void\r\n onChildrenChange?: (children: FormComponentType[]) => void\r\n onChildSelect?: (child: FormComponentType) => void\r\n onChildDelete?: (childId: string) => void\r\n selectedChild?: FormComponentType | null\r\n renderFormComponent?: (field: FormComponentType) => React.ReactNode\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\n// Draggable child component for items inside the section\r\ninterface DraggableChildProps {\r\n child: FormComponentType\r\n selectedChild: FormComponentType | null\r\n mode: 'edit' | 'preview' | 'test'\r\n onChildSelect: (child: FormComponentType) => void\r\n onChildDelete: (child: FormComponentType, event: React.MouseEvent) => void\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n isOverlay?: boolean\r\n isChildrenEditMode?: boolean\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst DraggableChild: React.FC<DraggableChildProps> = ({\r\n child,\r\n selectedChild,\r\n mode,\r\n onChildSelect,\r\n onChildDelete,\r\n renderFormComponent,\r\n isOverlay = false,\r\n isChildrenEditMode = false,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const formValue = formData[child.id];\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = mode === 'preview' && (\r\n ((child as any).basic?.notes && (child as any).basic.notes.trim().length > 0) ||\r\n ((child as any).basic?.attachments && Array.isArray((child as any).basic.attachments) && (child as any).basic.attachments.length > 0)\r\n );\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n isSorting,\r\n } = useSortable({\r\n id: child.id,\r\n disabled: isOverlay || mode !== 'edit',\r\n })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n // opacity: isDragging ? 0.3 : 1,\r\n zIndex: isDragging ? 1000 : 'auto',\r\n }\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n style={style}\r\n className={`form-component section-child ${selectedChild?.id === child.id ? 'selected' : ''} ${isDragging ? 'dragging' : ''} ${isSorting ? 'sorting' : ''} ${isChildrenEditMode ? 'children-edit-active' : ''}`}\r\n onClick={() => !isDragging && onChildSelect(child)}\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {/* Drag Handle - Show in edit mode or when children edit mode is active */}\r\n {(mode === 'edit' || isChildrenEditMode) && (\r\n <div \r\n className=\"child-drag-handle\" \r\n {...listeners} \r\n {...attributes}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n >\r\n <GripVertical size={14} />\r\n </div>\r\n )}\r\n \r\n {/* Child Content */}\r\n <div className=\"form-component-content section-child-content\">\r\n {/* Child Actions - Show in edit mode or when children edit mode is active */}\r\n {(mode === 'edit' || isChildrenEditMode) && (\r\n <div className=\"component-actions child-actions\">\r\n <button\r\n className=\"btn edit-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onChildSelect(child)\r\n }}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n title=\"Edit properties\"\r\n >\r\n <Edit size={12} />\r\n </button>\r\n <button\r\n className=\"btn delete-btn\"\r\n onClick={(e) => onChildDelete(child, e)}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n title=\"Delete component\"\r\n >\r\n <Trash2 size={12} />\r\n </button>\r\n </div>\r\n )}\r\n\r\n <div className=\"component-preview child-preview\">\r\n {renderFormComponent(child)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(child.name) && (\r\n <ComponentActionFeatures\r\n component={child as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(child.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(child.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={child as any}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport const DfFormSection: React.FC<DfFormSectionProps> = ({\r\n id,\r\n properties,\r\n mode = 'edit',\r\n formData = {},\r\n onValueChange,\r\n onSelect,\r\n isSelected = false,\r\n className = '',\r\n onSectionSelect,\r\n onChildSelect,\r\n onChildDelete,\r\n selectedChild,\r\n renderFormComponent,\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const [isCollapsed, setIsCollapsed] = useState(properties.basic.collapsed)\r\n const [isEditingTitle, setIsEditingTitle] = useState(false)\r\n const [isEditingDescription, setIsEditingDescription] = useState(false)\r\n const [sectionTitle, setSectionTitle] = useState(properties.basic.label)\r\n const [sectionDescription, setSectionDescription] = useState(properties.basic.description)\r\n const [children, setChildren] = useState<FormComponentType[]>(properties.children || [])\r\n const [isChildrenEditMode, setIsChildrenEditMode] = useState(false)\r\n\r\n // Sync children with properties changes\r\n useEffect(() => {\r\n setChildren(properties.children || [])\r\n }, [properties.children])\r\n\r\n // Sync basic props (label, description) with incoming properties updates\r\n useEffect(() => {\r\n setSectionTitle(properties.basic.label)\r\n setSectionDescription(properties.basic.description)\r\n }, [properties.basic.label, properties.basic.description])\r\n\r\n // Make the section a drop target - Only in edit mode\r\n const { setNodeRef, isOver } = useDroppable({\r\n id: `section-${id}`,\r\n disabled: mode !== 'edit'\r\n })\r\n\r\n // Decide visibility after all hooks are called to keep hooks order stable\r\n const shouldHideInCurrentMode = (mode === 'preview' || mode === 'test') && (!(properties.children && properties.children.length > 0))\r\n\r\n // Handle section title change\r\n const handleTitleChange = useCallback((newTitle: string) => {\r\n setSectionTitle(newTitle)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, label: newTitle } }\r\n })\r\n }, [id, properties, onValueChange])\r\n\r\n // Handle section description change\r\n const handleDescriptionChange = useCallback((newDescription: string) => {\r\n setSectionDescription(newDescription)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, description: newDescription } }\r\n })\r\n }, [id, properties, onValueChange])\r\n\r\n // Handle child selection\r\n const handleChildSelect = useCallback((child: FormComponentType) => {\r\n onChildSelect?.(child)\r\n }, [onChildSelect])\r\n\r\n // Handle child deletion\r\n const handleChildDelete = useCallback((child: FormComponentType, event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n \r\n // Update local children state immediately for responsive UI\r\n const newChildren = children.filter(c => c.id !== child.id)\r\n setChildren(newChildren)\r\n \r\n // Notify parent component - this will trigger the useEffect to sync\r\n onChildDelete?.(child.id)\r\n }, [onChildDelete, children, id])\r\n\r\n // Handle section selection\r\n const handleSectionSelect = useCallback(() => {\r\n onSectionSelect?.(properties)\r\n onSelect?.()\r\n }, [onSectionSelect, onSelect, properties])\r\n\r\n // Handle section double-click to activate children edit mode\r\n const handleSectionDoubleClick = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n if (mode === 'edit' && children.length > 0) {\r\n setIsChildrenEditMode(!isChildrenEditMode)\r\n }\r\n }, [mode, children.length, isChildrenEditMode])\r\n\r\n // Toggle collapse state\r\n const toggleCollapse = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n setIsCollapsed(!isCollapsed)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, collapsed: !isCollapsed } }\r\n })\r\n }, [isCollapsed, id, properties, onValueChange])\r\n\r\n // Use the provided render function or fallback to default\r\n const renderComponent = renderFormComponent || useCallback((field: FormComponentType) => {\r\n const commonProps = {\r\n id: field.id,\r\n properties: field,\r\n validationErrors: {},\r\n formValue: formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : ''), // CRITICAL: Always get formValue from formData in package\r\n touchedFields: {},\r\n formSubmitted: false,\r\n mode,\r\n onValueChange: onValueChange, // Pass the parent's onValueChange to child components\r\n onBlur: () => {},\r\n onFocus: () => {}\r\n }\r\n\r\n switch (field.name) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'number-input':\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={field as any}\r\n inputType={field.name === 'text-input' ? 'text' : \r\n field.name === 'number-input' ? 'number' : 'email'}\r\n readonly={false} // CRITICAL: Always editable in package\r\n disabled={false} // CRITICAL: Never disabled in package\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={field as any} readonly={false} disabled={false} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} disabled={false} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} formValue={[]} disabled={false} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} readonly={false} disabled={false} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={field as any} />\r\n \r\n case 'heading':\r\n return <DfFormHeading {...commonProps} properties={field as any} />\r\n \r\n default:\r\n return (\r\n <div className=\"form-group\">\r\n <div className=\"form-group-label\">\r\n Unsupported Component: {field.name}\r\n </div>\r\n </div>\r\n )\r\n }\r\n }, [mode, onValueChange, formData])\r\n\r\n if (shouldHideInCurrentMode) {\r\n return null\r\n }\r\n\r\n // Filter out dimension-related styles for sections as they should be flexible containers\r\n const sectionStyles = {\r\n backgroundColor: properties.styles?.backgroundColor || 'var(--df-color-fb-container)',\r\n borderColor: properties.styles?.borderColor || 'var(--df-color-fb-border)',\r\n borderWidth: properties.styles?.borderWidth || '2px',\r\n borderRadius: properties.styles?.borderRadius || '8px',\r\n padding: properties.styles?.padding || '16px',\r\n margin: properties.styles?.margin || '16px 0',\r\n // Explicitly exclude dimension properties\r\n // width, height, minWidth, maxWidth, minHeight, maxHeight should not be applied\r\n };\r\n\r\n return (\r\n <div \r\n ref={setNodeRef}\r\n className={`df-form-section ${isSelected ? 'selected' : ''} ${isOver ? 'drag-over' : ''} ${className}`}\r\n style={sectionStyles}\r\n >\r\n {/* Section Header */}\r\n <div \r\n className={`section-header ${isChildrenEditMode ? 'children-edit-mode' : ''}`}\r\n onClick={handleSectionSelect}\r\n onDoubleClick={handleSectionDoubleClick}\r\n >\r\n <div className=\"section-header-content\">\r\n {/* Section Title with inline collapse icon */}\r\n <div className=\"section-title\">\r\n {/* Left side: collapse icon in all modes */}\r\n <span\r\n className=\"section-toggle\"\r\n title={isCollapsed ? 'Expand section' : 'Collapse section'}\r\n role=\"button\"\r\n tabIndex={0}\r\n onClick={(e) => { e.stopPropagation(); toggleCollapse(e) }}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleCollapse(e as any) } }}\r\n style={{ marginRight: '8px', display: 'inline-flex', alignItems: 'center' }}\r\n >\r\n {isCollapsed ? <ChevronRight size={18} /> : <ChevronDown size={18} />}\r\n </span>\r\n\r\n {mode === 'edit' && isEditingTitle ? (\r\n <input\r\n type=\"text\"\r\n value={sectionTitle}\r\n onChange={(e) => setSectionTitle(e.target.value)}\r\n onBlur={() => {\r\n setIsEditingTitle(false)\r\n handleTitleChange(sectionTitle)\r\n }}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n setIsEditingTitle(false)\r\n handleTitleChange(sectionTitle)\r\n }\r\n }}\r\n className=\"section-title-input\"\r\n autoFocus\r\n />\r\n ) : (\r\n <h3 \r\n className=\"section-title-text\"\r\n onDoubleClick={() => mode === 'edit' && setIsEditingTitle(true)}\r\n style={{ display: 'inline', margin: 0 }}\r\n >\r\n {sectionTitle || 'Untitled Section'}\r\n </h3>\r\n )}\r\n </div>\r\n\r\n </div>\r\n \r\n {/* Section Description (below header) */}\r\n {(sectionDescription || mode === 'edit') && (\r\n <div className=\"section-description\">\r\n {mode === 'edit' && isEditingDescription ? (\r\n <textarea\r\n value={sectionDescription}\r\n onChange={(e) => setSectionDescription(e.target.value)}\r\n onBlur={() => {\r\n setIsEditingDescription(false)\r\n handleDescriptionChange(sectionDescription)\r\n }}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter' && e.ctrlKey) {\r\n setIsEditingDescription(false)\r\n handleDescriptionChange(sectionDescription)\r\n }\r\n }}\r\n className=\"section-description-input\"\r\n placeholder=\"Section description (optional)\"\r\n autoFocus\r\n />\r\n ) : (\r\n <p \r\n className=\"section-description-text\"\r\n onDoubleClick={() => mode === 'edit' && setIsEditingDescription(true)}\r\n >\r\n {sectionDescription || 'Section description'}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n\r\n \r\n </div>\r\n\r\n {/* Section Content */}\r\n {!isCollapsed && (\r\n <div \r\n className={`section-content ${isOver ? 'drag-over' : ''} ${children.length === 0 ? 'empty' : 'has-children'}`}\r\n onClick={(e) => {\r\n // Only select section if clicking on the background, not on child components\r\n if (e.target === e.currentTarget) {\r\n handleSectionSelect()\r\n }\r\n }}\r\n >\r\n <SortableContext items={children.map(c => c.id)} strategy={verticalListSortingStrategy}>\r\n {children.length === 0 ? (\r\n <div \r\n className=\"section-empty-state\" \r\n onClick={handleSectionSelect}\r\n style={{\r\n textAlign: 'center',\r\n color: '#6b7280',\r\n fontSize: '14px',\r\n padding: '40px 20px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n gap: '8px',\r\n cursor: 'pointer',\r\n border: '2px dotted #d1d5db',\r\n borderRadius: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n transition: 'all 0.3s ease',\r\n margin: '16px 0'\r\n }}\r\n >\r\n {/* <div style={{ fontSize: '24px', opacity: 0.5 }}>📋</div> */}\r\n <div style={{ \r\n fontWeight: '500',\r\n color: isOver ? '#3b82f6' : '#374151'\r\n }}>\r\n {isOver ? 'Drop components here' : 'Empty Section'}\r\n </div>\r\n <div style={{ \r\n fontSize: '12px',\r\n color: '#9ca3af'\r\n }}>\r\n Drag and drop components here to create your section\r\n </div>\r\n </div>\r\n ) : (\r\n children.map((child) => (\r\n <DraggableChild\r\n key={child.id}\r\n child={child}\r\n selectedChild={selectedChild || null}\r\n mode={mode}\r\n onChildSelect={handleChildSelect}\r\n onChildDelete={handleChildDelete}\r\n renderFormComponent={renderComponent}\r\n isChildrenEditMode={isChildrenEditMode}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n />\r\n ))\r\n )}\r\n </SortableContext>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormSection\r\n","import React, { useState, useCallback, useEffect, useRef } from 'react'\r\nimport { useDroppable } from '@dnd-kit/core'\r\nimport { useSortable, SortableContext, horizontalListSortingStrategy } from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { ChevronDown, ChevronRight, GripVertical, Edit, Trash2, Grid } from 'lucide-react'\r\nimport { IDataGridComponent, FormComponentType, IFormControlChange, DataGridEntry } from '../df-form-preview-interfaces'\r\nimport './df-form-grid.scss'\r\n\r\n// Import form control components for rendering children\r\nimport { DfFormInput } from '../df-form-input'\r\nimport { DfFormTextarea } from '../df-form-textarea'\r\nimport { DfFormSelect } from '../df-form-select'\r\nimport { DfFormCheckbox } from '../df-form-checkbox'\r\nimport { DfFormRadio } from '../df-form-radio'\r\nimport { DfFormDateTime } from '../df-form-date-time'\r\nimport { DfFormSignature } from '../df-form-signature'\r\nimport { DfFormHeading } from '../df-form-heading'\r\nimport { DfFormInstruction } from '../df-form-instruction'\r\nimport { ComponentActionFeatures } from '../../ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from '../../components/ComponentSubmissionActions'\r\n\r\ninterface DfFormDataGridProps {\r\n id: string\r\n properties: IDataGridComponent\r\n validationErrors?: Record<string, any>\r\n formValue?: any\r\n formData?: Record<string, any>\r\n readonly?: boolean\r\n disabled?: boolean\r\n touchedFields?: Record<string, boolean>\r\n formSubmitted?: boolean\r\n mode?: 'edit' | 'preview' | 'test'\r\n onValueChange?: (change: IFormControlChange) => void\r\n onBlur?: () => void\r\n onFocus?: () => void\r\n onSelect?: () => void\r\n isSelected?: boolean\r\n className?: string\r\n // DataGrid-specific props\r\n onDataGridSelect?: (dataGrid: IDataGridComponent) => void\r\n onDataGridDelete?: (dataGridId: string) => void\r\n onEntryChange?: (entryIndex: number, components: FormComponentType[]) => void\r\n onComponentSelect?: (component: FormComponentType) => void\r\n onComponentDelete?: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n selectedComponent?: FormComponentType | null\r\n renderFormComponent?: (field: FormComponentType, hideLabel?: boolean) => React.ReactNode\r\n // Additional props for consistency with other components\r\n onDataGridUpdate?: (dataGridId: string, updates: Partial<IDataGridComponent>) => void\r\n onEntryAdd?: () => void\r\n onEntryRemove?: (entryIndex: number) => void\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\n// Draggable component for items inside grid entries\r\ninterface DraggableGridComponentProps {\r\n component: FormComponentType\r\n selectedComponent: FormComponentType | null\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n isOverlay?: boolean\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst DraggableGridComponent: React.FC<DraggableGridComponentProps> = ({\r\n component,\r\n selectedComponent,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n renderFormComponent,\r\n isOverlay = false,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const formValue = formData[component.id];\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = mode === 'preview' && (\r\n ((component as any).basic?.notes && (component as any).basic.notes.trim().length > 0) ||\r\n ((component as any).basic?.attachments && Array.isArray((component as any).basic.attachments) && (component as any).basic.attachments.length > 0)\r\n );\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n isSorting,\r\n } = useSortable({\r\n id: component.id,\r\n disabled: isOverlay,\r\n })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.3 : 1,\r\n zIndex: isDragging ? 1000 : 'auto',\r\n }\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n style={{\r\n ...style,\r\n border: selectedComponent?.id === component.id ? '2px solid #3b82f6' : '1px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n padding: '12px',\r\n position: 'relative',\r\n minHeight: '80px',\r\n transition: 'all 0.2s ease',\r\n boxShadow: selectedComponent?.id === component.id ? '0 4px 12px rgba(59, 130, 246, 0.15)' : '0 1px 3px rgba(0, 0, 0, 0.1)',\r\n cursor: 'pointer'\r\n }}\r\n className={`form-component grid-component ${selectedComponent?.id === component.id ? 'selected' : ''} ${isDragging ? 'dragging' : ''} ${isSorting ? 'sorting' : ''}`}\r\n onClick={() => !isDragging && onComponentSelect(component)}\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {/* Drag Handle - Only visible in edit mode */}\r\n {mode === 'edit' && (\r\n <div \r\n className=\"component-drag-handle\" \r\n {...listeners} \r\n {...attributes}\r\n onClick={(e) => e.stopPropagation()}\r\n style={{ \r\n position: 'absolute',\r\n top: '50%',\r\n left: '4px',\r\n transform: 'translateY(-50%)',\r\n padding: '4px',\r\n backgroundColor: '#f3f4f6',\r\n borderRadius: '4px',\r\n cursor: 'grab',\r\n opacity: 1,\r\n zIndex: 10,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center'\r\n }}\r\n >\r\n <GripVertical size={12} color=\"var(--df-color-text-light)\" />\r\n </div>\r\n )}\r\n\r\n {/* Component Content */}\r\n <div \r\n className=\"component-content\"\r\n style={{\r\n paddingTop: mode === 'edit' ? '24px' : '0',\r\n paddingLeft: mode === 'edit' ? '28px' : '0',\r\n minHeight: '60px'\r\n }}\r\n >\r\n {renderFormComponent(component)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(component.name) && (\r\n <ComponentActionFeatures\r\n component={component as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(component.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(component.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={component as any}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n {mode === 'edit' && (\r\n <div \r\n className=\"component-actions\" \r\n style={{ \r\n position: 'absolute',\r\n top: '4px',\r\n right: '4px',\r\n display: 'flex',\r\n gap: '4px',\r\n opacity: 1,\r\n zIndex: 10\r\n }}\r\n >\r\n {/* Edit Button */}\r\n {onComponentEdit && (\r\n <button\r\n className=\"component-edit-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentEdit(component)\r\n }}\r\n type=\"button\"\r\n title=\"Edit Component\"\r\n style={{\r\n padding: '4px',\r\n backgroundColor: '#3b82f6',\r\n color: '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease'\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = '#2563eb'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = '#3b82f6'\r\n }}\r\n >\r\n <Edit size={12} />\r\n </button>\r\n )}\r\n \r\n {/* Delete Button */}\r\n <button\r\n className=\"component-delete-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentDelete(component, e)\r\n }}\r\n type=\"button\"\r\n title=\"Delete Component\"\r\n style={{\r\n padding: '4px',\r\n backgroundColor: '#ef4444',\r\n color: '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease'\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = '#dc2626'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = '#ef4444'\r\n }}\r\n >\r\n <Trash2 size={12} />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Simple Grid Drop Zone Component\r\ninterface GridDropZoneProps {\r\n gridComponents: FormComponentType[]\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n selectedComponent: FormComponentType | null\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n gridId: string // Add unique grid ID prop\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst GridDropZone: React.FC<GridDropZoneProps> = ({\r\n gridComponents,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n onComponentUpdate,\r\n selectedComponent,\r\n renderFormComponent,\r\n gridId,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const { setNodeRef, isOver } = useDroppable({\r\n id: `grid-drop-zone-${gridId}`,\r\n disabled: mode !== 'edit'\r\n })\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n className=\"grid-drop-zone\"\r\n style={{\r\n border: isOver ? '2px dashed #3b82f6' : '2px dashed #d1d5db',\r\n borderRadius: '8px',\r\n padding: '16px',\r\n backgroundColor: isOver ? 'var(--df-color-primary-light)' : 'var(--df-color-fb-container)',\r\n minHeight: '120px',\r\n transition: 'all 0.2s ease',\r\n position: 'relative'\r\n }}\r\n >\r\n {gridComponents.length > 0 ? (\r\n <>\r\n <SortableContext items={gridComponents.map(c => c.id)} strategy={horizontalListSortingStrategy}>\r\n <div style={{ \r\n display: 'flex',\r\n flexDirection: 'row',\r\n flexWrap: 'nowrap',\r\n gap: '12px',\r\n alignItems: 'start',\r\n marginBottom: gridComponents.length > 0 ? '12px' : '0',\r\n overflowX: 'auto',\r\n width: '100%'\r\n }}>\r\n {gridComponents.map((component) => (\r\n <div key={component.id} style={{ flex: '1 1 0', minWidth: '200px', maxWidth: '100%' }}>\r\n <DraggableGridComponent\r\n component={component}\r\n selectedComponent={selectedComponent}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect}\r\n onComponentDelete={onComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n onComponentUpdate={onComponentUpdate}\r\n renderFormComponent={renderFormComponent}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n </SortableContext>\r\n \r\n {/* Additional Drop Zone for More Components */}\r\n <div style={{\r\n border: isOver ? '2px dashed #3b82f6' : '1px dashed var(--df-color-fb-border)',\r\n borderRadius: '6px',\r\n padding: '12px',\r\n backgroundColor: isOver ? 'var(--df-color-primary-light)' : 'var(--df-color-fb-container)',\r\n textAlign: 'center',\r\n color: 'var(--df-color-text-light)',\r\n fontSize: '12px',\r\n transition: 'all 0.2s ease',\r\n minHeight: '40px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center'\r\n }}>\r\n {isOver ? (\r\n <span style={{ color: '#3b82f6', fontWeight: '500' }}>\r\n Drop component here to add to grid\r\n </span>\r\n ) : (\r\n <span>\r\n + Drop more components here\r\n </span>\r\n )}\r\n </div>\r\n </>\r\n ) : (\r\n <div style={{ \r\n textAlign: 'center', \r\n color: 'var(--df-color-text-light)', \r\n fontSize: '14px',\r\n padding: '40px 20px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n gap: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n border: '1px dashed var(--df-color-fb-border)',\r\n borderRadius: '8px'\r\n }}>\r\n {/* <div style={{ \r\n fontSize: '24px',\r\n opacity: 0.5\r\n }}>\r\n 📋\r\n </div> */}\r\n <div style={{ \r\n fontWeight: '500',\r\n color: isOver ? 'var(--df-color-primary)' : 'var(--df-color-text-dark)'\r\n }}>\r\n {isOver ? 'Drop components here' : 'Empty DataGrid'}\r\n </div>\r\n <div style={{ \r\n fontSize: '12px',\r\n color: '#9ca3af'\r\n }}>\r\n Drag and drop components here to create your grid\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Table View Component for Preview/Test Mode\r\ninterface TableViewProps {\r\n templateComponents: FormComponentType[]\r\n dataEntries: any[]\r\n renderFormComponent: (field: FormComponentType, hideLabel?: boolean) => React.ReactNode\r\n renderComponent?: (field: FormComponentType, hideLabel?: boolean) => React.ReactNode\r\n mode?: 'edit' | 'preview' | 'test'\r\n allowAddRemoveEntries?: boolean\r\n addAnotherText?: string\r\n removeText?: string\r\n maxEntries?: number\r\n minEntries?: number\r\n displayAsGrid?: boolean\r\n onAddEntry?: () => void\r\n onRemoveEntry?: (entryIndex: number) => void\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n datagridId?: string // Add datagrid ID prop\r\n}\r\n\r\nconst TableView: React.FC<TableViewProps> = ({\r\n templateComponents,\r\n dataEntries,\r\n renderFormComponent,\r\n renderComponent: internalRenderComponent,\r\n mode = 'preview',\r\n allowAddRemoveEntries = true,\r\n addAnotherText = 'Add Another',\r\n removeText = 'Remove',\r\n maxEntries = 10,\r\n minEntries = 1,\r\n displayAsGrid = true,\r\n onAddEntry,\r\n onRemoveEntry,\r\n formData: _formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange,\r\n datagridId = '' // Add datagrid ID with default\r\n}) => {\r\n\r\n if (templateComponents.length === 0) {\r\n return (\r\n <div style={{ \r\n textAlign: 'center', \r\n padding: '40px', \r\n color: 'var(--df-color-text-light)',\r\n border: '1px dashed #d1d5db',\r\n borderRadius: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)'\r\n }}>\r\n No components defined. Add components to see the {displayAsGrid ? 'table' : 'list'} view.\r\n </div>\r\n )\r\n }\r\n\r\n // Render as Grid/Table View\r\n if (displayAsGrid) {\r\n return (\r\n <div className=\"datagrid-table-view\" style={{ \r\n border: '1px solid var(--df-color-fb-border)', \r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n maxWidth: '100%'\r\n }}>\r\n {/* Scroll Indicator */}\r\n <div style={{\r\n position: 'absolute',\r\n top: '8px',\r\n right: '8px',\r\n zIndex: 10,\r\n fontSize: '12px',\r\n color: 'var(--df-color-text-light)',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n padding: '4px 8px',\r\n borderRadius: '4px',\r\n border: '1px solid var(--df-color-fb-border)',\r\n opacity: templateComponents.length > 4 ? 1 : 0,\r\n transition: 'opacity 0.2s ease'\r\n }}>\r\n ← Scroll →\r\n </div>\r\n\r\n {/* Horizontal Scrollable Container */}\r\n <div \r\n className=\"table-scroll-container\"\r\n style={{\r\n overflowX: 'auto',\r\n overflowY: 'hidden',\r\n maxWidth: '100%',\r\n scrollbarWidth: 'thin',\r\n scrollbarColor: 'var(--df-color-fb-border) var(--df-color-fb-icon-bg)',\r\n position: 'relative'\r\n }}\r\n >\r\n {/* Table Headers */}\r\n <div className=\"table-headers\" style={{\r\n display: 'grid',\r\n gridTemplateColumns: `repeat(${templateComponents.length}, minmax(150px, 1fr))`,\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n borderBottom: '2px solid var(--df-color-fb-border)',\r\n minWidth: `${templateComponents.length * 150}px`\r\n }}>\r\n {templateComponents.map((component, index) => (\r\n <div key={`header-${component.id}`} style={{\r\n padding: '12px 16px',\r\n fontWeight: '600',\r\n color: 'var(--df-color-text-dark)',\r\n borderRight: index < templateComponents.length - 1 ? '1px solid var(--df-color-fb-border)' : 'none',\r\n fontSize: '14px',\r\n minWidth: '150px',\r\n whiteSpace: 'nowrap',\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis'\r\n }}>\r\n {component.basic?.label || `Column ${index + 1}`}\r\n </div>\r\n ))}\r\n </div>\r\n \r\n {/* Table Rows */}\r\n {dataEntries.length > 0 ? (\r\n dataEntries.map((entry, entryIndex) => (\r\n <div key={entry.id} className=\"table-row\" style={{\r\n display: 'grid',\r\n gridTemplateColumns: `repeat(${templateComponents.length}, minmax(150px, 1fr))`,\r\n borderBottom: entryIndex < dataEntries.length - 1 ? '1px solid var(--df-color-fb-border)' : 'none',\r\n backgroundColor: entryIndex % 2 === 0 ? 'var(--df-color-fb-container)' : 'var(--df-color-fb-bg)',\r\n position: 'relative',\r\n minWidth: `${templateComponents.length * 150}px`,\r\n isolation: 'isolate' // Create new stacking context for buttons\r\n }}>\r\n {templateComponents.map((templateComponent, componentIndex) => {\r\n // Find the corresponding component in this entry by position/index, not by name/label\r\n // This ensures each template component maps to the correct entry component\r\n let entryComponent = entry.components?.[componentIndex]\r\n \r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = templateComponent.id || `component-${componentIndex}`;\r\n const expectedUniqueId = `${baseComponentId}-entry-${datagridId}-${entryIndex}-${componentIndex}`;\r\n \r\n // If no component found at this index, create one from the template\r\n if (!entryComponent) {\r\n entryComponent = {\r\n ...templateComponent,\r\n id: expectedUniqueId,\r\n basic: {\r\n ...templateComponent.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear any default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n } else {\r\n // CRITICAL: Ensure the component has the correct unique ID\r\n // If the ID doesn't match the expected pattern, update it\r\n if (entryComponent.id !== expectedUniqueId) {\r\n entryComponent = {\r\n ...entryComponent,\r\n id: expectedUniqueId, // Update to the correct unique ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n } else {\r\n // Preserve the original ID if it's already correct\r\n entryComponent = {\r\n ...entryComponent,\r\n id: entryComponent.id, // Keep the original ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n }\r\n }\r\n \r\n return (\r\n <div key={`${entry.id}-${componentIndex}`} style={{\r\n padding: '12px 16px',\r\n borderRight: componentIndex < templateComponents.length - 1 ? '1px solid var(--df-color-fb-border)' : 'none',\r\n minHeight: '60px',\r\n minWidth: '150px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n overflow: 'visible', // CRITICAL: Allow buttons to be visible\r\n position: 'relative',\r\n zIndex: 1\r\n }}>\r\n <div style={{\r\n width: '100%',\r\n minWidth: '120px',\r\n overflow: 'hidden',\r\n position: 'relative',\r\n zIndex: 1\r\n }}>\r\n {/* Use internal renderComponent if available, otherwise use renderFormComponent from parent */}\r\n {/* This ensures each entry component gets its own isolated form value using unique IDs */}\r\n {internalRenderComponent ? internalRenderComponent(entryComponent, true) : renderFormComponent(entryComponent, true)}\r\n </div>\r\n </div>\r\n )\r\n })}\r\n \r\n {/* Remove button for each row when more than 1 entry exists */}\r\n {allowAddRemoveEntries && dataEntries.length > minEntries && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length <= minEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onRemoveEntry) {\r\n try {\r\n onRemoveEntry(entryIndex);\r\n } catch (error) {\r\n console.error('Error removing entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length <= minEntries}\r\n style={{\r\n position: 'absolute',\r\n top: '8px',\r\n right: '8px',\r\n padding: '4px 8px',\r\n backgroundColor: dataEntries.length <= minEntries ? '#f3f4f6' : '#ef4444',\r\n color: dataEntries.length <= minEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length <= minEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '4px',\r\n zIndex: 1000,\r\n minWidth: '24px',\r\n height: '24px',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto' // CRITICAL: Ensure button can receive clicks\r\n }}\r\n title={removeText}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#dc2626';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#ef4444';\r\n }\r\n }}\r\n >\r\n <span style={{ fontSize: '14px' }}>×</span>\r\n </button>\r\n )}\r\n </div>\r\n ))\r\n ) : (\r\n <div style={{\r\n padding: '40px',\r\n textAlign: 'center',\r\n color: 'var(--df-color-text-light)',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n borderTop: '1px solid var(--df-color-fb-border)'\r\n }}>\r\n No data entries. {allowAddRemoveEntries ? 'Click \"Add Another\" to add entries.' : 'Use the properties panel to add entries.'}\r\n </div>\r\n )}\r\n\r\n </div>\r\n\r\n {/* Add Another button - Moved outside scrollable container */}\r\n {/* CRITICAL: Always show in package (no mode check) - all functionality enabled */}\r\n {allowAddRemoveEntries && (\r\n <div style={{\r\n padding: '16px',\r\n backgroundColor: 'var(--df-color-fb-bg)',\r\n borderTop: '1px solid var(--df-color-fb-border)',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n position: 'sticky',\r\n bottom: 0,\r\n zIndex: 5\r\n }}>\r\n <button\r\n type=\"button\" // CRITICAL: Prevent form submission/navigation\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length >= maxEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onAddEntry) {\r\n try {\r\n onAddEntry();\r\n } catch (error) {\r\n console.error('Error adding entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length >= maxEntries}\r\n style={{\r\n padding: '8px 16px',\r\n backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',\r\n color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '6px',\r\n fontSize: '14px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length >= maxEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto', // CRITICAL: Ensure button can receive clicks\r\n zIndex: 1000 // CRITICAL: Ensure button is above other elements\r\n }}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#059669';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#10b981';\r\n }\r\n }}\r\n >\r\n <span style={{ fontSize: '16px' }}>+</span>\r\n {addAnotherText}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n // Render as List/Card View\r\n return (\r\n <div className=\"datagrid-list-view\" style={{ \r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '12px',\r\n backgroundColor: 'var(--df-color-fb-container)'\r\n }}>\r\n {dataEntries.length > 0 ? (\r\n dataEntries.map((entry, entryIndex) => (\r\n <div key={entry.id} className=\"list-entry\" style={{\r\n border: '1px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n padding: '16px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n position: 'relative',\r\n transition: 'all 0.2s ease'\r\n }}>\r\n {/* Entry Header */}\r\n <div style={{\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: '12px',\r\n paddingBottom: '8px',\r\n borderBottom: '1px solid var(--df-color-fb-border)'\r\n }}>\r\n <span style={{\r\n fontWeight: '600',\r\n color: 'var(--df-color-text-dark)',\r\n fontSize: '14px'\r\n }}>\r\n Entry #{entryIndex + 1}\r\n </span>\r\n \r\n {/* Remove button for each entry when more than 1 entry exists */}\r\n {allowAddRemoveEntries && dataEntries.length > 1 && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length <= minEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onRemoveEntry) {\r\n try {\r\n onRemoveEntry(entryIndex);\r\n } catch (error) {\r\n console.error('Error removing entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length <= minEntries}\r\n style={{\r\n padding: '4px 8px',\r\n backgroundColor: dataEntries.length <= minEntries ? '#f3f4f6' : '#ef4444',\r\n color: dataEntries.length <= minEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length <= minEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '4px',\r\n minWidth: '24px',\r\n height: '24px',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto', // CRITICAL: Ensure button can receive clicks\r\n zIndex: 1000 // CRITICAL: Ensure button is above other elements\r\n }}\r\n title={removeText}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#dc2626';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#ef4444';\r\n }\r\n }}\r\n >\r\n <span style={{ fontSize: '14px' }}>×</span>\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Entry Fields */}\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',\r\n gap: '16px'\r\n }}>\r\n {templateComponents.map((templateComponent, componentIndex) => {\r\n // Find the corresponding component in this entry by index first, then by name+label\r\n let entryComponent = entry.components?.[componentIndex]\r\n \r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = templateComponent.id || `component-${componentIndex}`;\r\n const expectedUniqueId = `${baseComponentId}-entry-${datagridId}-${entryIndex}-${componentIndex}`;\r\n \r\n // If no component at this index, try to find by name+label\r\n if (!entryComponent) {\r\n entryComponent = entry.components?.find((comp: any) => \r\n comp.name === templateComponent.name && \r\n comp.basic?.label === templateComponent.basic?.label\r\n )\r\n }\r\n \r\n // If no matching component found, use the template component\r\n if (!entryComponent) {\r\n entryComponent = {\r\n ...templateComponent,\r\n id: expectedUniqueId,\r\n basic: {\r\n ...templateComponent.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear any default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n } else {\r\n // CRITICAL: Ensure the component has the correct unique ID\r\n // If the ID doesn't match the expected pattern, update it\r\n if (entryComponent.id !== expectedUniqueId) {\r\n entryComponent = {\r\n ...entryComponent,\r\n id: expectedUniqueId, // Update to the correct unique ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n } else {\r\n // Preserve the original ID if it's already correct\r\n entryComponent = {\r\n ...entryComponent,\r\n id: entryComponent.id, // Keep the original ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n }\r\n }\r\n \r\n return (\r\n <div key={`${entry.id}-${componentIndex}`} style={{\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '4px'\r\n }}>\r\n <label style={{\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n color: 'var(--df-color-text-light)',\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.05em'\r\n }}>\r\n {templateComponent.basic?.label || `Field ${componentIndex + 1}`}\r\n </label>\r\n <div style={{\r\n minHeight: '40px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n flexDirection: 'column',\r\n width: '100%'\r\n }}>\r\n {/* Use internal renderComponent if available, otherwise use renderFormComponent from parent */}\r\n {/* This ensures each entry component gets its own isolated form value using unique IDs */}\r\n {internalRenderComponent ? internalRenderComponent(entryComponent) : renderFormComponent(entryComponent)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(entryComponent.name) && (\r\n <ComponentActionFeatures\r\n component={entryComponent as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={_formData[entryComponent.id]}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(entryComponent.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(entryComponent.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {mode === 'preview' && (\r\n (() => {\r\n const hasSubmissionData = (\r\n ((entryComponent as any).basic?.notes && (entryComponent as any).basic.notes.trim().length > 0) ||\r\n ((entryComponent as any).basic?.attachments && Array.isArray((entryComponent as any).basic.attachments) && (entryComponent as any).basic.attachments.length > 0)\r\n );\r\n return hasSubmissionData ? (\r\n <ComponentSubmissionActions\r\n component={entryComponent as any}\r\n />\r\n ) : null;\r\n })()\r\n )}\r\n </div>\r\n </div>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n ))\r\n ) : (\r\n <div style={{\r\n padding: '40px',\r\n textAlign: 'center',\r\n color: 'var(--df-color-text-light)',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n border: '1px dashed #d1d5db',\r\n borderRadius: '8px'\r\n }}>\r\n No data entries. {allowAddRemoveEntries ? 'Click \"Add Another\" to add entries.' : 'Use the properties panel to add entries.'}\r\n </div>\r\n )}\r\n\r\n {/* Add Another button below the list for test mode */}\r\n {mode === 'test' && allowAddRemoveEntries && (\r\n <div style={{\r\n padding: '16px',\r\n backgroundColor: '#f8f9fa',\r\n border: '1px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n display: 'flex',\r\n justifyContent: 'center'\r\n }}>\r\n <button\r\n type=\"button\" // CRITICAL: Prevent form submission/navigation\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length >= maxEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onAddEntry) {\r\n try {\r\n onAddEntry();\r\n } catch (error) {\r\n console.error('Error adding entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length >= maxEntries}\r\n style={{\r\n padding: '8px 16px',\r\n backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',\r\n color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '6px',\r\n fontSize: '14px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length >= maxEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto', // CRITICAL: Ensure button can receive clicks\r\n zIndex: 1000 // CRITICAL: Ensure button is above other elements\r\n }}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#059669'\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#10b981'\r\n }\r\n }}\r\n >\r\n <span>+</span>\r\n {addAnotherText}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n\r\nexport const DfFormDataGrid: React.FC<DfFormDataGridProps> = ({\r\n id,\r\n properties,\r\n mode = 'edit',\r\n formData = {},\r\n validationErrors = {},\r\n touchedFields = {},\r\n formSubmitted = false,\r\n onValueChange,\r\n onSelect,\r\n isSelected = false,\r\n className = '',\r\n onDataGridSelect,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n onComponentUpdate,\r\n selectedComponent,\r\n renderFormComponent,\r\n onEntryAdd,\r\n onEntryRemove,\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const [isCollapsed, setIsCollapsed] = useState(false)\r\n const hasInitialized = useRef(false)\r\n\r\n // Get all components in the grid\r\n let gridComponents = properties.templateComponents || []\r\n const dataEntries = properties.entries || []\r\n \r\n \r\n // Fallback: If no template components but we have entries, extract template from first entry\r\n if (gridComponents.length === 0 && dataEntries.length > 0 && dataEntries[0].components) {\r\n gridComponents = dataEntries[0].components.map((comp: any) => ({\r\n ...comp,\r\n id: comp.id?.replace(/-entry-\\d+$/, '') || comp.id, // Remove entry suffix for template\r\n basic: {\r\n ...comp.basic,\r\n showLabel: true // Show labels in template\r\n }\r\n }))\r\n }\r\n\r\n // Initialize template components if empty (only in edit mode)\r\n useEffect(() => {\r\n if (mode === 'edit' && !properties.templateComponents && onValueChange && hasInitialized.current) {\r\n const newValue = { \r\n ...properties, \r\n templateComponents: []\r\n }\r\n // Only call onValueChange if the data actually changed\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n hasInitialized.current = true\r\n }, [properties.templateComponents, id, onValueChange, properties, mode])\r\n\r\n // Sync template components with existing entries and create initial entry if needed\r\n useEffect(() => {\r\n if (gridComponents.length > 0) {\r\n // In test mode, ensure we have at least one entry if entries are empty\r\n if (mode === 'test' && dataEntries.length === 0 && hasInitialized.current) {\r\n const firstEntry = {\r\n id: `entry-${id}-0`,\r\n index: 0,\r\n components: gridComponents.map((comp, componentIndex) => {\r\n const baseComponentId = comp.id || `component-${componentIndex}`;\r\n return {\r\n ...comp,\r\n id: `${baseComponentId}-entry-${id}-0-${componentIndex}`,\r\n basic: {\r\n ...comp.basic,\r\n showLabel: false,\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n };\r\n }),\r\n styles: {}\r\n }\r\n \r\n if (onValueChange) {\r\n const newValue = { ...properties, entries: [firstEntry] }\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n return\r\n }\r\n \r\n // Only run this effect if we're in edit mode and there are actual changes needed\r\n if (mode !== 'edit' || !hasInitialized.current) {\r\n return // Don't run sync logic in preview mode or on first render\r\n }\r\n \r\n \r\n // Force update entries that don't have proper unique IDs\r\n const needsIdUpdate = dataEntries.some(entry => \r\n entry.components?.some((comp: any, index: number) => {\r\n const expectedId = `${gridComponents[index]?.id}-entry-${entry.index}-${index}`\r\n return comp.id !== expectedId\r\n })\r\n )\r\n \r\n if (needsIdUpdate && onValueChange) {\r\n const updatedEntries = dataEntries.map(entry => ({\r\n ...entry,\r\n components: entry.components?.map((comp: any, index: number) => ({\r\n ...comp,\r\n id: `${gridComponents[index]?.id}-entry-${entry.index}-${index}`\r\n })) || []\r\n }))\r\n \r\n // Only call onValueChange if the data actually changed\r\n const newValue = { ...properties, entries: updatedEntries }\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n return // Exit early to avoid double processing\r\n }\r\n // If no entries exist, create the first entry (only in edit mode, test mode handled above)\r\n if (dataEntries.length === 0 && mode === 'edit') {\r\n const firstEntry = {\r\n id: `entry-${id}-0`,\r\n index: 0,\r\n components: gridComponents.map((comp, componentIndex) => {\r\n const baseComponentId = comp.id || `component-${componentIndex}`;\r\n return {\r\n ...comp,\r\n id: `${baseComponentId}-entry-${id}-0-${componentIndex}`,\r\n basic: {\r\n ...comp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n };\r\n }),\r\n styles: {}\r\n }\r\n\r\n if (onValueChange) {\r\n const newValue = { ...properties, entries: [firstEntry] }\r\n // Only call onValueChange if the data actually changed\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n } else if (dataEntries.length > 0) {\r\n // Update existing entries to include all template components and sync their properties\r\n const needsUpdate = dataEntries.some(entry => {\r\n // Check if entry is missing any template components or if existing components need updates\r\n return gridComponents.some((templateComp, componentIndex) => {\r\n const existingComponent = entry.components?.[componentIndex]\r\n \r\n if (!existingComponent) {\r\n return true // Missing component at this index\r\n }\r\n \r\n // Check if component has proper unique ID\r\n const expectedId = `${templateComp.id}-entry-${entry.index}-${componentIndex}`\r\n const hasProperId = existingComponent.id === expectedId\r\n \r\n // Check if existing component needs to be updated with new template properties\r\n // Compare key properties that should be synced\r\n const needsPropertyUpdate = \r\n JSON.stringify((existingComponent.basic as any)?.options) !== JSON.stringify((templateComp.basic as any)?.options) ||\r\n (existingComponent.basic as any)?.placeholder !== (templateComp.basic as any)?.placeholder ||\r\n (existingComponent.basic as any)?.defaultValue !== (templateComp.basic as any)?.defaultValue ||\r\n (existingComponent.basic as any)?.label !== (templateComp.basic as any)?.label ||\r\n existingComponent.validation?.required !== templateComp.validation?.required\r\n return !hasProperId || needsPropertyUpdate\r\n })\r\n })\r\n\r\n if (needsUpdate && onValueChange) {\r\n const updatedEntries = dataEntries.map(entry => {\r\n // Use index-based matching to ensure each template component maps to the correct entry component\r\n const updatedComponents = gridComponents.map((templateComp, componentIndex) => {\r\n // Find existing component by index first\r\n let existingComponent: FormComponentType | undefined = entry.components?.[componentIndex]\r\n \r\n // If no component at this index, try to find by name+label (for backward compatibility)\r\n if (!existingComponent) {\r\n existingComponent = entry.components?.find((comp: any) => \r\n comp.name === templateComp.name && \r\n comp.basic?.label === templateComp.basic?.label\r\n ) as FormComponentType | undefined\r\n }\r\n \r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = templateComp.id || `component-${componentIndex}`;\r\n const uniqueId = `${baseComponentId}-entry-${id}-${entry.index}-${componentIndex}`\r\n \r\n if (existingComponent) {\r\n // Update existing component with new template properties while ensuring unique ID\r\n // CRITICAL: Don't preserve value from basic - form values should come from formData\r\n const updatedComponent = {\r\n ...templateComp,\r\n id: uniqueId, // Always use the unique ID pattern\r\n basic: {\r\n ...templateComp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n\r\n return updatedComponent\r\n } else {\r\n // Create new component based on template\r\n const newComponent = {\r\n ...templateComp,\r\n id: uniqueId,\r\n basic: {\r\n ...templateComp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n \r\n return newComponent\r\n }\r\n })\r\n\r\n return {\r\n ...entry,\r\n components: updatedComponents\r\n }\r\n })\r\n\r\n const newValue = { ...properties, entries: updatedEntries }\r\n // Only call onValueChange if the data actually changed\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n }\r\n }\r\n }, [gridComponents, dataEntries, id, onValueChange, properties, mode, properties.templateComponents])\r\n\r\n const handleDataGridClick = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n onSelect?.()\r\n onDataGridSelect?.(properties)\r\n }, [onSelect, onDataGridSelect, properties])\r\n\r\n const toggleCollapse = (event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n setIsCollapsed(!isCollapsed)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, collapsed: !isCollapsed } }\r\n })\r\n }\r\n\r\n const handleComponentDelete = useCallback((component: FormComponentType, event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n \r\n // Call the parent's component delete handler first\r\n if (onComponentDelete) {\r\n onComponentDelete(component, event)\r\n }\r\n \r\n // Remove from grid template components\r\n const updatedComponents = gridComponents.filter(comp => comp.id !== component.id)\r\n \r\n // Remove from all existing entries by matching component name and label\r\n const updatedEntries = dataEntries.map(entry => ({\r\n ...entry,\r\n components: entry.components?.filter((entryComp: any) => \r\n !(entryComp.name === component.name && entryComp.basic?.label === component.basic?.label)\r\n ) || []\r\n }))\r\n \r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { \r\n ...properties, \r\n templateComponents: updatedComponents,\r\n entries: updatedEntries\r\n }\r\n })\r\n }\r\n }, [onComponentDelete, properties, onValueChange, id, gridComponents, dataEntries])\r\n\r\n const handleComponentUpdate = useCallback((componentId: string, updates: Partial<FormComponentType>) => {\r\n // Call the parent's component update handler first\r\n if (onComponentUpdate) {\r\n onComponentUpdate(componentId, updates)\r\n }\r\n \r\n // Update the component in grid template components\r\n const updatedComponents = gridComponents.map(comp => \r\n comp.id === componentId ? { ...comp, ...updates } : comp\r\n )\r\n \r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, templateComponents: updatedComponents }\r\n })\r\n }\r\n }, [onComponentUpdate, properties, onValueChange, id, gridComponents])\r\n\r\n // Handle component value change for form data updates (test mode)\r\n const handleComponentValueChange = useCallback((change: IFormControlChange) => {\r\n if (mode === 'test') {\r\n // In test mode, update form data through the parent's onValueChange\r\n // This allows the form data to be updated for interactive components\r\n if (onValueChange) {\r\n onValueChange({\r\n id: change.id,\r\n value: change.value\r\n })\r\n }\r\n }\r\n // CRITICAL: Always handle value changes in package (like test mode)\r\n }, [onValueChange])\r\n\r\n const handleAddEntry = useCallback(() => {\r\n // CRITICAL: Always use the latest properties.entries to ensure we're working with current state\r\n const currentEntries = properties.entries || [];\r\n const newEntryIndex = currentEntries.length;\r\n // CRITICAL: Use a unique entry ID that includes the datagrid ID to prevent conflicts\r\n const newEntryId = `entry-${id}-${newEntryIndex}`;\r\n \r\n const newEntry: DataGridEntry = {\r\n id: newEntryId,\r\n index: newEntryIndex,\r\n components: gridComponents.map((comp, componentIndex) => {\r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = comp.id || `component-${componentIndex}`;\r\n const uniqueComponentId = `${baseComponentId}-entry-${id}-${newEntryIndex}-${componentIndex}`;\r\n \r\n return {\r\n ...comp,\r\n id: uniqueComponentId, // Make each component unique per entry and position\r\n basic: {\r\n ...comp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear any default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n };\r\n }) as FormComponentType[],\r\n styles: {}\r\n }\r\n \r\n const updatedEntries = [...currentEntries, newEntry]\r\n \r\n // CRITICAL: Update via onValueChange first to update internal state\r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, entries: updatedEntries }\r\n })\r\n }\r\n \r\n // CRITICAL: Call onEntryAdd immediately (matching main app behavior)\r\n // The parent's onEntryAdd will sync formComponents with the updated entries\r\n onEntryAdd?.()\r\n }, [properties, onValueChange, id, onEntryAdd, gridComponents])\r\n\r\n const handleRemoveEntry = useCallback((entryIndex: number) => {\r\n const updatedEntries = properties.entries\r\n .filter((_, index) => index !== entryIndex)\r\n .map((entry, index) => ({ ...entry, index, id: `entry-${id}-${index}` }))\r\n \r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, entries: updatedEntries }\r\n })\r\n }\r\n }, [properties, onValueChange, id, onEntryRemove])\r\n\r\n\r\n // Use our own render function to ensure proper onComponentUpdate handling\r\n const renderComponent = useCallback((field: FormComponentType, hideLabel: boolean = false) => {\r\n // CRITICAL: Always get formValue from formData in package (like test mode)\r\n // This ensures each entry component gets its own value, not shared with other entries or sections\r\n const formValue = formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '')\r\n \r\n const commonProps = {\r\n id: field.id, // Use the unique ID from the field\r\n properties: field,\r\n validationErrors: validationErrors || {},\r\n formValue: formValue, // This uses the unique ID to get the correct value\r\n touchedFields: touchedFields || {},\r\n formSubmitted: formSubmitted || false,\r\n mode,\r\n hideLabel,\r\n onValueChange: handleComponentValueChange, // This will update formData using the unique ID\r\n onBlur: () => {},\r\n onFocus: () => {}\r\n }\r\n\r\n switch (field.name) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'number-input':\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={field as any}\r\n inputType={field.name === 'text-input' ? 'text' : \r\n field.name === 'number-input' ? 'number' : 'email'}\r\n readonly={false} // CRITICAL: Always editable in package\r\n disabled={false} // CRITICAL: Never disabled in package\r\n hideLabel={hideLabel}\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={field as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} formValue={[]} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={field as any} hideLabel={hideLabel} />\r\n \r\n case 'heading':\r\n return <DfFormHeading {...commonProps} properties={field as any} hideLabel={hideLabel} />\r\n \r\n case 'instructions':\r\n return <DfFormInstruction {...commonProps} properties={field as any} hideLabel={hideLabel} />\r\n \r\n default:\r\n return <div className=\"unknown-component\">Unknown component: {field.name}</div>\r\n }\r\n }, [mode, handleComponentValueChange, formData, validationErrors, touchedFields, formSubmitted])\r\n\r\n const gridStyle = {\r\n backgroundColor: properties.styles.backgroundColor || 'var(--df-color-fb-container)',\r\n borderColor: properties.styles.borderColor || 'var(--df-color-fb-border)',\r\n borderWidth: properties.styles.borderWidth || '2px',\r\n borderRadius: properties.styles.borderRadius || '8px',\r\n padding: properties.styles.padding || '16px',\r\n margin: properties.styles.margin || '16px 0'\r\n }\r\n\r\n // Always render the grid - let GridDropZone handle empty state\r\n\r\n return (\r\n <div\r\n className={`form-group df-form-datagrid ${isSelected ? 'selected' : ''} ${className}`}\r\n onClick={handleDataGridClick}\r\n style={gridStyle}\r\n >\r\n {/* Grid Header */}\r\n <div className=\"grid-header\">\r\n <div className=\"grid-title\" onClick={toggleCollapse}>\r\n <div className=\"title-content\" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\r\n {isCollapsed ? <ChevronRight size={16} /> : <ChevronDown size={16} />}\r\n <Grid size={16} />\r\n <span className=\"grid-label\" style={{ fontWeight: '600' }}>{properties.basic.label}</span>\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\" style={{ color: '#ef4444' }}>*</span>\r\n )}\r\n </div>\r\n </div>\r\n \r\n </div>\r\n\r\n {/* Grid Description */}\r\n {properties.basic.description && !isCollapsed && (\r\n <div className=\"grid-description\" style={{ marginTop: '8px', color: 'var(--df-color-text-light)', fontSize: '14px' }}>\r\n {properties.basic.description}\r\n </div>\r\n )}\r\n\r\n {/* Grid Content */}\r\n {!isCollapsed && (\r\n <div className=\"grid-content\" style={{ marginTop: '16px' }}>\r\n {mode === 'edit' ? (\r\n <GridDropZone\r\n gridComponents={gridComponents}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect || (() => {})}\r\n onComponentDelete={handleComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n onComponentUpdate={handleComponentUpdate}\r\n selectedComponent={selectedComponent || null}\r\n renderFormComponent={renderFormComponent || renderComponent}\r\n gridId={id}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n ) : (\r\n /* Table View for Preview/Test Mode */\r\n <TableView\r\n templateComponents={gridComponents}\r\n dataEntries={dataEntries}\r\n renderFormComponent={renderFormComponent || renderComponent}\r\n mode={mode}\r\n allowAddRemoveEntries={properties.datagrid?.allowAddRemoveEntries ?? true}\r\n addAnotherText={properties.datagrid?.addAnotherText ?? 'Add Entry'}\r\n removeText={properties.datagrid?.removeText ?? 'Remove'}\r\n maxEntries={properties.datagrid?.maxEntries ?? 10}\r\n minEntries={properties.datagrid?.minEntries ?? 1}\r\n displayAsGrid={properties.datagrid?.displayAsGrid ?? true}\r\n onAddEntry={onEntryAdd ? onEntryAdd : handleAddEntry}\r\n onRemoveEntry={onEntryRemove ? onEntryRemove : handleRemoveEntry}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n datagridId={id}\r\n />\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormDataGrid","import React, { useState, useEffect, useCallback, useRef } from 'react'\r\nimport { \r\n FormComponentType, \r\n IFormControlChange, \r\n IFormValidationErrors\r\n} from './df-form-controls/df-form-preview-interfaces'\r\nimport { conditionalLogicService } from './services/conditionalLogicService'\r\nimport { FormComponentType as TFormComponent } from './df-form-controls/df-form-preview-interfaces'\r\nimport { toastService } from './services/toast.service'\r\n\r\n// Import form control components\r\nimport { DfFormInput } from './df-form-controls/df-form-input'\r\nimport { DfFormTextarea } from './df-form-controls/df-form-textarea'\r\nimport { DfFormSelect } from './df-form-controls/df-form-select'\r\nimport { DfFormCheckbox } from './df-form-controls/df-form-checkbox'\r\nimport { DfFormRadio } from './df-form-controls/df-form-radio'\r\nimport { DfFormSegment } from './df-form-controls/df-form-segment'\r\nimport { DfFormDateTime } from './df-form-controls/df-form-date-time'\r\nimport { DfFormSignature } from './df-form-controls/df-form-signature'\r\nimport { DfFormFileUpload } from './df-form-controls/df-form-file-upload'\r\nimport { DfFormLocation } from './df-form-controls/df-form-location'\r\nimport { DfFormHeading } from './df-form-controls/df-form-heading'\r\nimport { DfFormInstruction } from './df-form-controls/df-form-instruction'\r\nimport { DfFormSection } from './df-form-controls/df-form-section/df-form-section'\r\nimport { DfFormDataGrid } from './df-form-controls/df-form-grid/df-form-grid'\r\nimport { ComponentActionFeatures } from './ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from './components/ComponentSubmissionActions'\r\n\r\n// Import styles\r\nimport './DfFormPreview.scss'\r\n\r\n// Dynamic imports to avoid circular dependencies\r\nconst DfFormTable = React.lazy(() => import('./df-form-controls/df-form-table/df-form-table'))\r\n\r\nexport type DeviceType = 'desktop' | 'tablet' | 'mobile'\r\n\r\nexport interface DfFormPreviewProps {\r\n formComponents: FormComponentType[]\r\n formData?: any\r\n currentDevice?: DeviceType\r\n isPreviewMode?: boolean\r\n initialFormData?: FormComponentType[]\r\n onSubmit?: (formData: FormComponentType[]) => void\r\n onFormDataChange?: (formData: FormComponentType[]) => void\r\n formTitle?: string\r\n formDescription?: string\r\n formTemplateId?: string\r\n // Optional component management props for edit mode\r\n onComponentSelect?: (component: FormComponentType) => void\r\n onComponentDelete?: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n selectedComponent?: FormComponentType | null\r\n}\r\n\r\nexport const DfFormPreview: React.FC<DfFormPreviewProps> = ({\r\n formComponents = [],\r\n currentDevice = 'desktop',\r\n isPreviewMode = false,\r\n initialFormData = [],\r\n onSubmit,\r\n onFormDataChange,\r\n formTitle,\r\n formDescription,\r\n formTemplateId,\r\n // Add component management props for edit mode\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n onComponentUpdate,\r\n selectedComponent\r\n}) => {\r\n // Form state\r\n const [formValues, setFormValues] = useState<Record<string, any>>({})\r\n const [validationErrors, setValidationErrors] = useState<IFormValidationErrors>({})\r\n const [formSubmitted, setFormSubmitted] = useState(false)\r\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({})\r\n const [componentVisibility, setComponentVisibility] = useState<Record<string, boolean>>({})\r\n // Track raised issues for threshold conditions (Set of condition IDs)\r\n const [raisedThresholdIssues, setRaisedThresholdIssues] = useState<Set<string>>(new Set())\r\n // Track threshold action completions: Map<conditionId, { notesCompleted, attachmentsCompleted, emailSent }>\r\n const [thresholdActionCompletions, setThresholdActionCompletions] = useState<Map<string, { notesCompleted: boolean; attachmentsCompleted: boolean; emailSent: boolean }>>(new Map())\r\n // Track threshold validation state for submit button\r\n const [thresholdValidationState, setThresholdValidationState] = useState<{ isValid: boolean; errorMessage?: string }>({ isValid: true })\r\n\r\n // Initialize form state\r\n useEffect(() => {\r\n initializeFormState()\r\n }, [formComponents, initialFormData])\r\n\r\n // Recursive function to initialize values from nested components\r\n const initializeComponentValues = (components: any[], values: Record<string, any>) => {\r\n components.forEach(component => {\r\n if (component.id) {\r\n // Always initialize component in form state, even with empty values\r\n // This ensures that value changes are tracked properly\r\n if ('value' in component.basic && component.basic.value !== undefined) {\r\n values[component.id] = component.basic.value\r\n }\r\n // Fallback to defaultValue if no value\r\n else if ('defaultValue' in component.basic && component.basic.defaultValue !== undefined) {\r\n values[component.id] = component.basic.defaultValue\r\n }\r\n // If neither value nor defaultValue exists, initialize with appropriate default based on component type\r\n else {\r\n // For checkbox and multi-select components, initialize with empty array\r\n if (component.name === 'checkbox' || component.name === 'select') {\r\n values[component.id] = []\r\n } else {\r\n // For other components, initialize with empty string\r\n values[component.id] = ''\r\n }\r\n }\r\n }\r\n\r\n // Handle nested components in table cells\r\n if (component.cells && Array.isArray(component.cells)) {\r\n component.cells.forEach((row: any[], _rowIndex: number) => {\r\n if (Array.isArray(row)) {\r\n row.forEach((cell: any, _cellIndex: number) => {\r\n if (cell && cell.components && Array.isArray(cell.components)) {\r\n initializeComponentValues(cell.components, values)\r\n }\r\n })\r\n }\r\n })\r\n }\r\n\r\n // Handle nested components in datagrid entries\r\n if (component.entries && Array.isArray(component.entries)) {\r\n component.entries.forEach((entry: any, _entryIndex: number) => {\r\n if (entry && entry.components && Array.isArray(entry.components)) {\r\n initializeComponentValues(entry.components, values)\r\n }\r\n })\r\n }\r\n \r\n // Handle file component - initialize with file data if present\r\n if (component.name === 'file' && component.basic) {\r\n const fileData = (component.basic as any).files || (component.basic as any).attachments || (component.basic as any).value;\r\n if (fileData) {\r\n values[component.id] = fileData;\r\n }\r\n }\r\n \r\n // Handle instructions component - ensure instructions array exists and initialize formValue\r\n if (component.name === 'instructions' && component.basic) {\r\n if (!(component.basic as any).instructions) {\r\n // Initialize empty instructions array if not present\r\n (component.basic as any).instructions = [];\r\n }\r\n // CRITICAL: Initialize formValue for instructions from API data\r\n // Check if component has value from API (could be in basic.value, basic.instructions, or formData)\r\n const instructionValue = (component.basic as any).value || (component.basic as any).instructions;\r\n if (instructionValue) {\r\n // Store instruction data in formValues so it can be passed to DfFormInstruction\r\n values[component.id] = instructionValue;\r\n }\r\n }\r\n\r\n // Handle nested components in section children\r\n if (component.children && Array.isArray(component.children)) {\r\n initializeComponentValues(component.children, values)\r\n }\r\n })\r\n }\r\n\r\n const initializeFormState = useCallback(() => {\r\n const initialValues: Record<string, any> = {}\r\n const seenIds = new Set<string>();\r\n \r\n // Validate component IDs for uniqueness\r\n const validateComponentIds = (components: any[]): void => {\r\n components.forEach(component => {\r\n if (component.id) {\r\n if (seenIds.has(component.id)) {\r\n console.error(`[DfFormPreview] Duplicate component ID detected: ${component.id}. Component:`, component);\r\n // Generate a unique ID for duplicate\r\n component.id = `${component.id}-duplicate-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\r\n console.warn(`[DfFormPreview] Generated new unique ID: ${component.id}`);\r\n }\r\n seenIds.add(component.id);\r\n }\r\n \r\n // Recursively validate nested components\r\n if (component.children && Array.isArray(component.children)) {\r\n validateComponentIds(component.children);\r\n }\r\n if (component.cells && Array.isArray(component.cells)) {\r\n component.cells.forEach((row: any[]) => {\r\n if (Array.isArray(row)) {\r\n row.forEach((cell: any) => {\r\n if (cell && cell.components && Array.isArray(cell.components)) {\r\n validateComponentIds(cell.components);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n if (component.entries && Array.isArray(component.entries)) {\r\n component.entries.forEach((entry: any) => {\r\n if (entry && entry.components && Array.isArray(entry.components)) {\r\n validateComponentIds(entry.components);\r\n }\r\n });\r\n }\r\n });\r\n };\r\n \r\n // Validate all component IDs for uniqueness\r\n if (formComponents && formComponents.length > 0) {\r\n validateComponentIds(formComponents);\r\n }\r\n if (initialFormData && initialFormData.length > 0) {\r\n validateComponentIds(initialFormData);\r\n }\r\n \r\n // Initialize form values from initial data\r\n if (initialFormData && initialFormData.length > 0) {\r\n initializeComponentValues(initialFormData, initialValues)\r\n }\r\n \r\n // Initialize form values from form components (for submitted data)\r\n if (formComponents && formComponents.length > 0) {\r\n initializeComponentValues(formComponents, initialValues)\r\n }\r\n setFormValues(initialValues)\r\n\r\n // Evaluate initial conditional logic\r\n evaluateConditionalLogic()\r\n }, [initialFormData, formComponents])\r\n\r\n // Recursive function to evaluate conditional logic for nested components\r\n const evaluateComponentConditionalLogic = (components: any[], visibility: Record<string, boolean>) => {\r\n components.forEach(component => {\r\n if (component.id) {\r\n // Skip conditional logic for table and datagrid components - they are always visible\r\n if (component.name === 'table' || component.name === 'datagrid') {\r\n visibility[component.id] = true\r\n } else if (component.conditional) {\r\n // Use the proper conditional logic service\r\n const result = conditionalLogicService.evaluateConditionalLogic(\r\n component.conditional,\r\n formComponents,\r\n formValues\r\n )\r\n visibility[component.id] = result.shouldShow\r\n } else {\r\n // No conditional logic means always show\r\n visibility[component.id] = true\r\n }\r\n }\r\n\r\n // Handle nested components in table cells\r\n if (component.cells && Array.isArray(component.cells)) {\r\n component.cells.forEach((row: any[]) => {\r\n row.forEach((cell: any) => {\r\n if (cell.components && Array.isArray(cell.components)) {\r\n evaluateComponentConditionalLogic(cell.components, visibility)\r\n }\r\n })\r\n })\r\n }\r\n\r\n // Handle nested components in datagrid entries\r\n if (component.entries && Array.isArray(component.entries)) {\r\n component.entries.forEach((entry: any) => {\r\n if (entry.components && Array.isArray(entry.components)) {\r\n evaluateComponentConditionalLogic(entry.components, visibility)\r\n }\r\n })\r\n }\r\n\r\n // Handle nested components in section children\r\n if (component.children && Array.isArray(component.children)) {\r\n evaluateComponentConditionalLogic(component.children, visibility)\r\n }\r\n })\r\n }\r\n\r\n // Evaluate conditional logic for all components\r\n const evaluateConditionalLogic = useCallback(() => {\r\n const visibility: Record<string, boolean> = {}\r\n \r\n if (formComponents && formComponents.length > 0) {\r\n evaluateComponentConditionalLogic(formComponents, visibility)\r\n }\r\n \r\n setComponentVisibility(visibility)\r\n }, [formComponents, formValues])\r\n\r\n // Check if a component should be visible based on conditional logic\r\n const shouldShowComponent = useCallback((componentId: string): boolean => {\r\n // Find the component to check its type\r\n const component = formComponents.find(comp => comp.id === componentId)\r\n \r\n // Table and datagrid components are always visible (no conditional logic)\r\n if (component && (component.name === 'table' || component.name === 'datagrid')) {\r\n return true\r\n }\r\n \r\n const isVisible = componentVisibility[componentId] !== false\r\n return isVisible\r\n }, [componentVisibility, formComponents])\r\n\r\n // Handle form value changes and re-evaluate conditional logic\r\n const onFormValueChange = useCallback((change: IFormControlChange) => {\r\n // CRITICAL: Validate that change.id is valid and unique\r\n if (!change.id || typeof change.id !== 'string' || change.id.trim() === '') {\r\n console.error('[DfFormPreview] Invalid component ID in onFormValueChange:', change);\r\n return;\r\n }\r\n \r\n // CRITICAL: Check if multiple components share this ID (ID collision detection)\r\n const componentsWithSameId = formComponents.filter(comp => comp.id === change.id);\r\n if (componentsWithSameId.length > 1) {\r\n console.error(`[DfFormPreview] ID COLLISION DETECTED! Multiple components share ID \"${change.id}\":`, \r\n componentsWithSameId.map(c => ({ id: c.id, name: c.name, label: c.basic?.label })));\r\n // Don't update - this would cause all components with this ID to get the same value\r\n return;\r\n }\r\n \r\n // Debug: Log value changes to identify ID collisions\r\n const existingValue = formValues[change.id];\r\n if (existingValue !== undefined && existingValue !== change.value) {\r\n console.log('[DfFormPreview] Updating form value:', {\r\n id: change.id,\r\n oldValue: existingValue,\r\n newValue: change.value\r\n });\r\n }\r\n \r\n const newFormValues = {\r\n ...formValues,\r\n [change.id]: change.value\r\n }\r\n setFormValues(newFormValues)\r\n \r\n // Clear raised issues for this component when value changes\r\n // This ensures that if threshold condition changes, user must raise issue again\r\n const component = formComponents.find(comp => comp.id === change.id);\r\n if (component) {\r\n const threshold = (component as any)?.threshold;\r\n if (threshold && threshold.conditions && threshold.conditions.length > 0) {\r\n setRaisedThresholdIssues(prev => {\r\n const newSet = new Set(prev);\r\n threshold.conditions.forEach((condition: any) => {\r\n newSet.delete(condition.id);\r\n });\r\n return newSet;\r\n });\r\n }\r\n }\r\n \r\n // Recursive function to update component values\r\n const updateComponentValue = (components: FormComponentType[]): FormComponentType[] => {\r\n return components.map(component => {\r\n if (component.id === change.id) {\r\n if ('defaultValue' in component.basic) {\r\n return {\r\n ...component,\r\n basic: {\r\n ...component.basic,\r\n value: change.value ?? component.basic.defaultValue,\r\n defaultValue: change.value\r\n }\r\n } as FormComponentType\r\n }\r\n }\r\n \r\n // Recursively update nested components\r\n if (component.name === 'section' && (component as any).children) {\r\n return {\r\n ...component,\r\n children: updateComponentValue((component as any).children)\r\n } as FormComponentType\r\n }\r\n \r\n if (component.name === 'table' && (component as any).cells) {\r\n return {\r\n ...component,\r\n cells: (component as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n const updatedCell = { ...cell };\r\n if (updatedCell.components) {\r\n updatedCell.components = updateComponentValue(updatedCell.components);\r\n }\r\n return updatedCell;\r\n })\r\n )\r\n } as FormComponentType\r\n }\r\n \r\n if (component.name === 'datagrid' && (component as any).entries) {\r\n return {\r\n ...component,\r\n entries: (component as any).entries.map((entry: any) => {\r\n const updatedEntry = { ...entry };\r\n if (updatedEntry.components) {\r\n updatedEntry.components = updateComponentValue(updatedEntry.components);\r\n }\r\n return updatedEntry;\r\n })\r\n } as FormComponentType\r\n }\r\n \r\n return component\r\n })\r\n }\r\n \r\n // Update form components\r\n const updatedComponents = updateComponentValue(formComponents)\r\n \r\n onFormDataChange?.(updatedComponents)\r\n \r\n // Clear validation errors when user starts typing and re-validate\r\n if (validationErrors[change.id]) {\r\n setValidationErrors(prev => ({\r\n ...prev,\r\n [change.id]: ''\r\n }))\r\n }\r\n \r\n // Re-validate the field after value change (only in test mode)\r\n if (!isPreviewMode) {\r\n setTimeout(() => {\r\n validateField(change.id)\r\n }, 100)\r\n }\r\n \r\n // Re-evaluate conditional logic with new form values\r\n setTimeout(() => {\r\n const visibility: Record<string, boolean> = {}\r\n \r\n formComponents.forEach(component => {\r\n // Skip conditional logic for table and datagrid components - they are always visible\r\n if (component.name === 'table' || component.name === 'datagrid') {\r\n visibility[component.id] = true\r\n } else if (component.conditional) {\r\n const result = conditionalLogicService.evaluateConditionalLogic(\r\n component.conditional,\r\n formComponents,\r\n newFormValues\r\n )\r\n visibility[component.id] = result.shouldShow\r\n } else {\r\n visibility[component.id] = true\r\n }\r\n })\r\n \r\n setComponentVisibility(visibility)\r\n }, 0)\r\n }, [formComponents, formValues, validationErrors, onFormDataChange])\r\n\r\n // Recursive function to find a component by ID in nested structures\r\n const findComponentById = useCallback((components: FormComponentType[], fieldId: string): FormComponentType | null => {\r\n for (const comp of components) {\r\n if (comp.id === fieldId) {\r\n return comp\r\n }\r\n \r\n // Check nested components in sections\r\n if (comp.name === 'section' && (comp as any).children) {\r\n const found = findComponentById((comp as any).children, fieldId)\r\n if (found) return found\r\n }\r\n \r\n // Check nested components in table cells\r\n if (comp.name === 'table' && (comp as any).cells) {\r\n for (const row of (comp as any).cells) {\r\n for (const cell of row) {\r\n if (cell.components) {\r\n const found = findComponentById(cell.components, fieldId)\r\n if (found) return found\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Check nested components in datagrid entries\r\n if (comp.name === 'datagrid' && (comp as any).entries) {\r\n for (const entry of (comp as any).entries) {\r\n if (entry.components) {\r\n const found = findComponentById(entry.components, fieldId)\r\n if (found) return found\r\n }\r\n }\r\n }\r\n }\r\n return null\r\n }, [])\r\n\r\n // Validate individual field\r\n const validateField = useCallback((fieldId: string) => {\r\n // Only validate in test mode\r\n if (isPreviewMode) return\r\n \r\n // Find component recursively (handles nested components)\r\n const component = findComponentById(formComponents, fieldId)\r\n if (!component) return\r\n\r\n // Get current value from form values (real-time input)\r\n const currentValue = formValues[fieldId] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n\r\n let errorMessage = ''\r\n\r\n // Check for required validation\r\n if (component.validation.required && !hasValue) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} is required`\r\n }\r\n // Check for email validation\r\n else if (component.name === 'email-input' && hasValue && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/.test(currentValue)) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be a valid email`\r\n }\r\n // Check for minLength validation\r\n else if (component.validation.minLength && hasValue && currentValue.length < component.validation.minLength) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be at least ${component.validation.minLength} characters`\r\n }\r\n // Check for maxLength validation\r\n else if (component.validation.maxLength && hasValue && currentValue.length > component.validation.maxLength) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be no more than ${component.validation.maxLength} characters`\r\n }\r\n // Check for number validations\r\n else if (component.name === 'number-input' && hasValue) {\r\n const numValue = parseFloat(String(currentValue))\r\n if (isNaN(numValue)) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be a valid number`\r\n } else {\r\n const numberValidation = component.validation as any\r\n // CRITICAL: Check min/max first, then lowerLimit/upperLimit\r\n // Only show error if validation actually fails\r\n if (numberValidation.min !== undefined && numValue < numberValidation.min) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be at least ${numberValidation.min}`\r\n } else if (numberValidation.max !== undefined && numValue > numberValidation.max) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be no more than ${numberValidation.max}`\r\n } else if (numberValidation.lowerLimit !== undefined && numValue < numberValidation.lowerLimit) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `You are under the limit. ${fieldLabel} must be at least ${numberValidation.lowerLimit}`\r\n } else if (numberValidation.upperLimit !== undefined && numValue > numberValidation.upperLimit) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `You crossed the limit. ${fieldLabel} must be no more than ${numberValidation.upperLimit}`\r\n }\r\n // If no validation errors, errorMessage remains empty (valid)\r\n }\r\n }\r\n \r\n // Always set the error message (empty string if valid) to clear previous errors\r\n setValidationErrors(prev => ({\r\n ...prev,\r\n [fieldId]: errorMessage\r\n }))\r\n }, [formComponents, isPreviewMode, formValues, findComponentById])\r\n\r\n // Handle form control blur\r\n const onFormControlBlur = useCallback((fieldId: string) => {\r\n setTouchedFields(prev => ({\r\n ...prev,\r\n [fieldId]: true\r\n }))\r\n // Validate field on blur (only in test mode)\r\n if (!isPreviewMode) {\r\n // Use setTimeout to ensure formValues are updated\r\n setTimeout(() => {\r\n validateField(fieldId)\r\n }, 0)\r\n }\r\n }, [isPreviewMode, validateField])\r\n\r\n // Handle form control focus\r\n const onFormControlFocus = useCallback((fieldId: string) => {\r\n // Clear validation errors when field is focused\r\n if (validationErrors[fieldId]) {\r\n setValidationErrors(prev => ({\r\n ...prev,\r\n [fieldId]: ''\r\n }))\r\n }\r\n }, [validationErrors])\r\n\r\n // Disabled automatic validation to let DfFormInput handle its own validation\r\n // This prevents conflicts between external and local validation\r\n // useEffect(() => {\r\n // if (!isPreviewMode && Object.keys(formValues).length > 0) {\r\n // // Validate all form components when form values change (but not on initial load)\r\n // formComponents.forEach(component => {\r\n // validateField(component.id)\r\n // })\r\n // }\r\n // }, [formValues, validateField, isPreviewMode, formComponents])\r\n\r\n // Enhanced form validity check\r\n const isFormValid = useCallback((): boolean => {\r\n return formComponents.every(component => {\r\n // Use real-time form values instead of component values\r\n const currentValue = formValues[component.id] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n \r\n if (component.validation.required && !hasValue) {\r\n return false\r\n }\r\n return true\r\n })\r\n }, [formComponents, formValues])\r\n\r\n // Evaluate threshold condition (handles both numeric and string values)\r\n const evaluateThresholdCondition = useCallback((condition: any, currentVal: string | number | string[]): boolean => {\r\n // Handle array values (for checkbox)\r\n if (Array.isArray(currentVal)) {\r\n return currentVal.some(val => evaluateThresholdCondition(condition, val));\r\n }\r\n \r\n if (currentVal === undefined || currentVal === null || currentVal === '') return false;\r\n \r\n // Try numeric comparison first\r\n const numValue = typeof currentVal === 'string' ? parseFloat(currentVal) : currentVal;\r\n const thresholdValue = typeof condition.value === 'string' ? parseFloat(condition.value) : condition.value;\r\n \r\n // If both are valid numbers, use numeric comparison\r\n if (!isNaN(numValue) && !isNaN(thresholdValue)) {\r\n switch (condition.operator) {\r\n case 'greaterThan':\r\n return numValue > thresholdValue;\r\n case 'lessThan':\r\n return numValue < thresholdValue;\r\n case 'greaterThanOrEqual':\r\n return numValue >= thresholdValue;\r\n case 'lessThanOrEqual':\r\n return numValue <= thresholdValue;\r\n case 'equals':\r\n return numValue === thresholdValue;\r\n case 'notEquals':\r\n return numValue !== thresholdValue;\r\n default:\r\n return false;\r\n }\r\n }\r\n \r\n // For string comparison (checkbox, radio, select, segment)\r\n const stringValue = String(currentVal).toLowerCase();\r\n const stringConditionValue = String(condition.value).toLowerCase();\r\n \r\n switch (condition.operator) {\r\n case 'equals':\r\n return stringValue === stringConditionValue || String(currentVal) === String(condition.value);\r\n case 'notEquals':\r\n return stringValue !== stringConditionValue && String(currentVal) !== String(condition.value);\r\n case 'greaterThan':\r\n case 'lessThan':\r\n case 'greaterThanOrEqual':\r\n case 'lessThanOrEqual':\r\n // For string values, these operators don't make sense, return false\r\n return false;\r\n default:\r\n return false;\r\n }\r\n }, []);\r\n\r\n // Get all met threshold conditions that require issue to be raised\r\n const getMetThresholdConditions = useCallback((): Array<{ componentId: string; condition: any; componentLabel: string }> => {\r\n if (isPreviewMode) return [];\r\n \r\n const metConditions: Array<{ componentId: string; condition: any; componentLabel: string }> = [];\r\n \r\n formComponents.forEach(component => {\r\n const condition = (component as any)?.condition;\r\n if (!condition || !condition.conditions || condition.conditions.length === 0) {\r\n return;\r\n }\r\n \r\n const currentValue = formValues[component.id];\r\n // Check if value is valid (not undefined, null, empty string, or empty array)\r\n const hasValidValue = currentValue !== undefined && \r\n currentValue !== null && \r\n currentValue !== '' && \r\n !(Array.isArray(currentValue) && currentValue.length === 0);\r\n \r\n if (!hasValidValue) {\r\n return;\r\n }\r\n \r\n condition.conditions.forEach((cond: any) => {\r\n // All met threshold conditions require raising an issue (mandatory)\r\n if (evaluateThresholdCondition(cond, currentValue)) {\r\n metConditions.push({\r\n componentId: component.id,\r\n condition: cond,\r\n componentLabel: component.basic?.label || 'Field'\r\n });\r\n }\r\n });\r\n });\r\n \r\n return metConditions;\r\n }, [formComponents, formValues, isPreviewMode, evaluateThresholdCondition]);\r\n\r\n // Validate threshold conditions - check if all met conditions have all mandatory actions completed\r\n const validateThresholdConditions = useCallback((): { isValid: boolean; errorMessage?: string } => {\r\n if (isPreviewMode) return { isValid: true };\r\n \r\n const metConditions = getMetThresholdConditions();\r\n \r\n if (metConditions.length === 0) {\r\n return { isValid: true };\r\n }\r\n \r\n // Check each met condition for all mandatory actions\r\n for (const { condition, componentLabel } of metConditions) {\r\n const completions = thresholdActionCompletions.get(condition.id) || { notesCompleted: false, attachmentsCompleted: false, emailSent: false };\r\n const missingActions: string[] = [];\r\n \r\n // Check if raise issue is required and completed\r\n if (condition.enableRaiseIssue === true && !raisedThresholdIssues.has(condition.id)) {\r\n missingActions.push('raise an issue');\r\n }\r\n \r\n // Check if notes are required and completed\r\n if (condition.enableNotes === true && !completions.notesCompleted) {\r\n missingActions.push('add notes');\r\n }\r\n \r\n // Check if attachments are required and completed\r\n if (condition.enableAttachment === true && !completions.attachmentsCompleted) {\r\n missingActions.push('add attachments');\r\n }\r\n \r\n // Check if send email is required and completed\r\n if (condition.enableSendEmail === true && !completions.emailSent) {\r\n missingActions.push('send email');\r\n }\r\n \r\n if (missingActions.length > 0) {\r\n const actionsText = missingActions.length === 1 \r\n ? missingActions[0] \r\n : missingActions.slice(0, -1).join(', ') + ' and ' + missingActions[missingActions.length - 1];\r\n return {\r\n isValid: false,\r\n errorMessage: `Please ${actionsText} for the threshold condition met in \"${componentLabel}\". You cannot submit the form until all required actions are completed.`\r\n };\r\n }\r\n }\r\n \r\n return { isValid: true };\r\n }, [isPreviewMode, getMetThresholdConditions, raisedThresholdIssues, thresholdActionCompletions]);\r\n\r\n // Callback to mark threshold issue as raised\r\n const handleThresholdIssueRaised = useCallback((conditionId: string) => {\r\n if (conditionId) {\r\n setRaisedThresholdIssues(prev => {\r\n const newSet = new Set(prev);\r\n newSet.add(conditionId);\r\n return newSet;\r\n });\r\n }\r\n }, []);\r\n\r\n // Callback to update threshold action completions\r\n const handleThresholdActionCompletion = useCallback((conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => {\r\n if (conditionId) {\r\n setThresholdActionCompletions(prev => {\r\n const newMap = new Map(prev);\r\n const current = newMap.get(conditionId) || { notesCompleted: false, attachmentsCompleted: false, emailSent: false };\r\n if (action === 'notes') {\r\n newMap.set(conditionId, { ...current, notesCompleted: completed });\r\n } else if (action === 'attachments') {\r\n newMap.set(conditionId, { ...current, attachmentsCompleted: completed });\r\n } else if (action === 'email') {\r\n newMap.set(conditionId, { ...current, emailSent: completed });\r\n }\r\n return newMap;\r\n });\r\n }\r\n }, []);\r\n\r\n // Update threshold validation state when form values, raised issues, or action completions change\r\n useEffect(() => {\r\n if (!isPreviewMode) {\r\n const validation = validateThresholdConditions();\r\n setThresholdValidationState(validation);\r\n }\r\n }, [formValues, raisedThresholdIssues, thresholdActionCompletions, isPreviewMode, validateThresholdConditions]);\r\n\r\n // Validate all fields\r\n const validateAllFields = useCallback((): boolean => {\r\n // Only validate in test mode\r\n if (isPreviewMode) return true\r\n \r\n let isValid = true\r\n setFormSubmitted(true)\r\n const errors: IFormValidationErrors = {}\r\n\r\n formComponents.forEach(component => {\r\n // Use real-time form values instead of component values\r\n const currentValue = formValues[component.id] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n\r\n if (component.validation.required && !hasValue) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n const errorMessage = customMessage || `${fieldLabel} is required`\r\n errors[component.id] = errorMessage\r\n isValid = false\r\n } else {\r\n errors[component.id] = ''\r\n }\r\n\r\n setTouchedFields(prev => ({\r\n ...prev,\r\n [component.id]: true\r\n }))\r\n })\r\n\r\n setValidationErrors(errors)\r\n return isValid\r\n }, [formComponents, isPreviewMode, formValues])\r\n\r\n // Handle form submission\r\n const handleSubmit = useCallback(() => {\r\n setFormSubmitted(true)\r\n\r\n if (!validateAllFields()) {\r\n // Focus on the first invalid field\r\n const firstErrorField = formComponents.find(comp => {\r\n const currentValue = formValues[comp.id] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n \r\n return comp.validation.required && !hasValue\r\n })\r\n if (firstErrorField) {\r\n const errorElement = document.getElementById(firstErrorField.id)\r\n if (errorElement) {\r\n errorElement.focus()\r\n }\r\n }\r\n return\r\n }\r\n\r\n // Validate threshold conditions - ensure all met conditions have issues raised\r\n const thresholdValidation = validateThresholdConditions();\r\n if (!thresholdValidation.isValid) {\r\n // Show error message\r\n if (thresholdValidation.errorMessage) {\r\n toastService.showError(thresholdValidation.errorMessage);\r\n }\r\n // Focus on the first component with unmet threshold condition\r\n const metConditions = getMetThresholdConditions();\r\n const firstUnmet = metConditions.find(\r\n ({ condition }) => !raisedThresholdIssues.has(condition.id)\r\n );\r\n if (firstUnmet) {\r\n const errorElement = document.getElementById(firstUnmet.componentId);\r\n if (errorElement) {\r\n errorElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Recursive function to update component values from form state\r\n const updateComponentValues = (components: FormComponentType[]): FormComponentType[] => {\r\n return components.map(component => {\r\n const userValue = formValues[component.id]\r\n let finalValue = userValue\r\n \r\n // Debug: Log all form values to see what's being tracked\r\n if (component.name === 'text-input' && component.basic?.label === 'New text input') {\r\n }\r\n \r\n if (finalValue === undefined) {\r\n if ('value' in component.basic && component.basic.value !== undefined) {\r\n finalValue = component.basic.value\r\n } else if ('defaultValue' in component.basic && component.basic.defaultValue !== undefined) {\r\n finalValue = component.basic.defaultValue\r\n } else {\r\n finalValue = ''\r\n }\r\n }\r\n\r\n // Debug table cell components\r\n if (component.name === 'text-input' && component.basic?.label === 'New text input') {\r\n }\r\n\r\n const updatedComponent = {\r\n ...component,\r\n basic: {\r\n ...component.basic,\r\n value: finalValue,\r\n defaultValue: finalValue\r\n }\r\n } as FormComponentType\r\n\r\n // Recursively update nested components\r\n if (updatedComponent.name === 'section' && (updatedComponent as any).children) {\r\n (updatedComponent as any).children = updateComponentValues((updatedComponent as any).children);\r\n }\r\n \r\n if (updatedComponent.name === 'table' && (updatedComponent as any).cells) {\r\n (updatedComponent as any).cells = (updatedComponent as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n const updatedCell = { ...cell };\r\n if (updatedCell.components) {\r\n updatedCell.components = updateComponentValues(updatedCell.components);\r\n }\r\n return updatedCell;\r\n })\r\n );\r\n }\r\n \r\n if (updatedComponent.name === 'datagrid' && (updatedComponent as any).entries) {\r\n (updatedComponent as any).entries = (updatedComponent as any).entries.map((entry: any) => {\r\n const updatedEntry = { ...entry };\r\n if (updatedEntry.components) {\r\n updatedEntry.components = updateComponentValues(updatedEntry.components);\r\n }\r\n return updatedEntry;\r\n });\r\n }\r\n\r\n return updatedComponent;\r\n });\r\n };\r\n\r\n // Prepare final form data\r\n const finalFormData = updateComponentValues(formComponents)\r\n\r\n onSubmit?.(finalFormData)\r\n }, [formComponents, formValues, validateAllFields, onSubmit])\r\n\r\n // Get preview classes\r\n const getPreviewClasses = useCallback(() => {\r\n return {\r\n [`device-${currentDevice}`]: true,\r\n readonly: isPreviewMode\r\n }\r\n }, [currentDevice, isPreviewMode])\r\n\r\n // Render form component based on type\r\n // CRITICAL: Use a ref to cache generated IDs so they don't change on re-render\r\n // This prevents ID regeneration which causes component remounting and state loss\r\n const componentIdCacheRef = useRef<Map<string, string>>(new Map());\r\n const componentCounterRef = useRef<number>(0);\r\n \r\n const renderFormComponent = (component: FormComponentType) => {\r\n // CRITICAL: Ensure component has a valid unique ID\r\n // NEVER regenerate IDs - always use existing or cached ID\r\n let finalComponentId: string;\r\n \r\n if (component.id && typeof component.id === 'string' && component.id.trim() !== '') {\r\n // Component already has an ID - use it (most common case)\r\n finalComponentId = component.id;\r\n } else {\r\n // Component is missing an ID - need to generate and cache it\r\n // Create a stable cache key using component properties that don't change\r\n const label = (component.basic as any)?.label || '';\r\n const name = component.name || 'unknown';\r\n // Use a combination that's stable across renders\r\n const cacheKey = `${name}-${label}`;\r\n \r\n // Check if we've already generated an ID for a component with these properties\r\n let cachedId = componentIdCacheRef.current.get(cacheKey);\r\n \r\n if (!cachedId) {\r\n // Generate a new ID only once and cache it permanently\r\n // Use a counter to ensure uniqueness even if multiple components have same name+label\r\n componentCounterRef.current += 1;\r\n cachedId = `generated-${name}-${componentCounterRef.current}-${Math.random().toString(36).substr(2, 9)}`;\r\n componentIdCacheRef.current.set(cacheKey, cachedId);\r\n console.warn('[DfFormPreview] Generated and cached ID for component:', cachedId, 'key:', cacheKey);\r\n }\r\n \r\n finalComponentId = cachedId;\r\n \r\n // Create a new component object with the cached ID (don't mutate original)\r\n component = {\r\n ...component,\r\n id: finalComponentId\r\n };\r\n }\r\n \r\n // CRITICAL: Use the finalComponentId we determined above\r\n const componentId = finalComponentId;\r\n const formValue = formValues[componentId]\r\n \r\n // Debug: Log if formValue is being shared incorrectly\r\n if (formValue !== undefined) {\r\n // Check if this value is being used by multiple components\r\n const componentsWithSameValue = formComponents.filter(comp => \r\n comp.id !== componentId && formValues[comp.id] === formValue\r\n );\r\n if (componentsWithSameValue.length > 0) {\r\n console.warn(`[DfFormPreview] Component ${componentId} shares form value with other components:`, \r\n componentsWithSameValue.map(c => c.id));\r\n }\r\n }\r\n \r\n const commonProps = {\r\n id: componentId, // Use the validated component ID\r\n validationErrors,\r\n formValue: formValue, // This should be unique per component ID\r\n touchedFields,\r\n formSubmitted,\r\n mode: 'test' as 'preview' | 'test', // CRITICAL: Always use 'test' mode in package - all functionality enabled\r\n readonly: false, // CRITICAL: Always allow editing in package\r\n onValueChange: onFormValueChange, // This will use change.id which should match componentId\r\n onBlur: () => onFormControlBlur(componentId),\r\n onFocus: () => onFormControlFocus(componentId)\r\n }\r\n\r\n switch (component.name) {\r\n case 'text-input':\r\n case 'number-input':\r\n case 'email-input':\r\n // Regular text/email/number input\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={component as any}\r\n inputType={component.name === 'text-input' ? 'text' : \r\n component.name === 'number-input' ? 'number' : 'email'}\r\n formTemplateId={formTemplateId}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n raisedThresholdIssues={raisedThresholdIssues}\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={component as any} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} />\r\n \r\n case 'segment':\r\n // Map basic.options to top-level options for segment component\r\n const segmentProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n return <DfFormSegment {...commonProps} properties={segmentProps as any} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={component as any} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={component as any} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={component as any} />\r\n \r\n case 'heading':\r\n return (\r\n <DfFormHeading\r\n {...commonProps}\r\n properties={component as any}\r\n />\r\n )\r\n \r\n case 'instructions':\r\n // CRITICAL: Pass formValue to instructions component so it can display API data\r\n // Also check component.basic.value for API data structure\r\n const instructionFormValue = formValue || \r\n (component.basic as any)?.value || \r\n null;\r\n return (\r\n <DfFormInstruction\r\n {...commonProps}\r\n properties={component as any}\r\n formValue={instructionFormValue}\r\n />\r\n )\r\n \r\n case 'location':\r\n return <DfFormLocation {...commonProps} properties={component as any} />\r\n \r\n case 'section':\r\n return (\r\n <DfFormSection\r\n {...commonProps}\r\n properties={component as any}\r\n formData={formValues}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n renderFormComponent={(field: FormComponentType) => {\r\n // Ensure the nested component gets the proper form value\r\n // const fieldValue = formValues[field.id] || (field.basic as any)?.value || (field.basic as any)?.defaultValue || ''\r\n return renderFormComponent(field)\r\n }}\r\n />\r\n )\r\n \r\n case 'table':\r\n\r\n return (\r\n <React.Suspense fallback={<div>Loading table...</div>}>\r\n <DfFormTable \r\n {...commonProps} \r\n properties={component as any}\r\n formData={formValues}\r\n formTemplateId={formTemplateId}\r\n mode={commonProps.mode}\r\n validationErrors={validationErrors}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n onNotesChange={(componentId: string, notes: string) => {\r\n // Handle notes change for table cell components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).cells) {\r\n const updatedCells = (comp as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n if (cell.components) {\r\n const updatedCellComponents = cell.components.map((cellComp: any) => {\r\n if (cellComp.id === componentId) {\r\n return {\r\n ...cellComp,\r\n basic: {\r\n ...cellComp.basic,\r\n notes\r\n }\r\n }\r\n }\r\n return cellComp\r\n })\r\n return { ...cell, components: updatedCellComponents }\r\n }\r\n return cell\r\n })\r\n )\r\n return { ...comp, cells: updatedCells }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n onAttachmentChange={(componentId: string, attachments: File[] | null) => {\r\n // Handle attachment change for table cell components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).cells) {\r\n const updatedCells = (comp as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n if (cell.components) {\r\n const updatedCellComponents = cell.components.map((cellComp: any) => {\r\n if (cellComp.id === componentId) {\r\n return {\r\n ...cellComp,\r\n basic: {\r\n ...cellComp.basic,\r\n attachments: attachments || []\r\n }\r\n }\r\n }\r\n return cellComp\r\n })\r\n return { ...cell, components: updatedCellComponents }\r\n }\r\n return cell\r\n })\r\n )\r\n return { ...comp, cells: updatedCells }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n renderFormComponent={(field: FormComponentType) => {\r\n // CRITICAL: Pass the field to renderFormComponent which has access to latest formValues\r\n // renderFormComponent uses formValues[field.id] internally, so it will get the correct value\r\n return renderFormComponent(field)\r\n }}\r\n />\r\n </React.Suspense>\r\n )\r\n \r\n case 'datagrid':\r\n return (\r\n <DfFormDataGrid\r\n {...commonProps}\r\n properties={component as any}\r\n formData={formValues}\r\n formTemplateId={formTemplateId}\r\n mode={commonProps.mode}\r\n validationErrors={validationErrors}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n onComponentSelect={onComponentSelect}\r\n onComponentDelete={onComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n onComponentUpdate={onComponentUpdate}\r\n selectedComponent={selectedComponent}\r\n onValueChange={(change: IFormControlChange) => {\r\n // Handle datagrid value changes (entries updates)\r\n if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {\r\n // Update formComponents with new entries structure\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n ...change.value\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n // Also update formValues for nested components\r\n if (change.value.entries && Array.isArray(change.value.entries)) {\r\n change.value.entries.forEach((entry: any) => {\r\n if (entry.components && Array.isArray(entry.components)) {\r\n entry.components.forEach((nestedComp: any) => {\r\n const nestedValue = formValues[nestedComp.id];\r\n if (nestedValue !== undefined) {\r\n // Value already exists, keep it\r\n } else {\r\n // Initialize with defaultValue if available\r\n const defaultValue = nestedComp.basic?.defaultValue;\r\n if (defaultValue !== undefined) {\r\n setFormValues(prev => ({\r\n ...prev,\r\n [nestedComp.id]: defaultValue\r\n }))\r\n }\r\n }\r\n })\r\n }\r\n })\r\n }\r\n } else {\r\n // For nested component value changes, use the regular handler\r\n onFormValueChange(change)\r\n }\r\n }}\r\n onEntryAdd={() => {\r\n // CRITICAL: Entry has already been added via onValueChange in DfFormDataGrid\r\n // Get the updated component from formComponents (which should have been updated by onValueChange)\r\n const currentComponent = formComponents.find(comp => comp.id === component.id);\r\n if (currentComponent && (currentComponent as any).entries) {\r\n // Entry should already be in the component via onValueChange\r\n // Just ensure formComponents is in sync (no-op if already synced)\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n // Ensure entries are properly structured\r\n return {\r\n ...comp,\r\n entries: (comp as any).entries || []\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n } else {\r\n // Fallback: If component doesn't have entries yet, try to get from formValues\r\n setTimeout(() => {\r\n const datagridValue = formValues[component.id];\r\n if (datagridValue && typeof datagridValue === 'object' && 'entries' in datagridValue) {\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n entries: datagridValue.entries\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }\r\n }, 100)\r\n }\r\n }}\r\n onEntryRemove={(entryIndex: number) => {\r\n // Handle entry remove - update form components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).entries) {\r\n const currentEntries = (comp as any).entries || []\r\n const updatedEntries = currentEntries\r\n .filter((_: any, index: number) => index !== entryIndex)\r\n .map((entry: any, index: number) => ({\r\n ...entry,\r\n index,\r\n id: `entry-${comp.id}-${index}`,\r\n components: entry.components?.map((comp: any, compIndex: number) => {\r\n const templateComp = ((comp as any).templateComponents || [])[compIndex]\r\n return {\r\n ...comp,\r\n id: templateComp ? `${templateComp.id}-entry-${index}-${compIndex}` : comp.id\r\n }\r\n }) || []\r\n }))\r\n return {\r\n ...comp,\r\n entries: updatedEntries\r\n }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n onNotesChange={(componentId: string, notes: string) => {\r\n // Handle notes change for datagrid entry components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).entries) {\r\n const updatedEntries = (comp as any).entries.map((entry: any) => {\r\n if (entry.components) {\r\n const updatedComponents = entry.components.map((entryComp: any) => {\r\n if (entryComp.id === componentId) {\r\n return {\r\n ...entryComp,\r\n basic: {\r\n ...entryComp.basic,\r\n notes\r\n }\r\n }\r\n }\r\n return entryComp\r\n })\r\n return { ...entry, components: updatedComponents }\r\n }\r\n return entry\r\n })\r\n return { ...comp, entries: updatedEntries }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n onAttachmentChange={(componentId: string, attachments: File[] | null) => {\r\n // Handle attachment change for datagrid entry components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).entries) {\r\n const updatedEntries = (comp as any).entries.map((entry: any) => {\r\n if (entry.components) {\r\n const updatedComponents = entry.components.map((entryComp: any) => {\r\n if (entryComp.id === componentId) {\r\n return {\r\n ...entryComp,\r\n basic: {\r\n ...entryComp.basic,\r\n attachments: attachments || []\r\n }\r\n }\r\n }\r\n return entryComp\r\n })\r\n return { ...entry, components: updatedComponents }\r\n }\r\n return entry\r\n })\r\n return { ...comp, entries: updatedEntries }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n renderFormComponent={(field: FormComponentType) => {\r\n // Ensure the nested component gets the proper form value\r\n return renderFormComponent(field)\r\n }}\r\n />\r\n )\r\n \r\n case 'file':\r\n // Get file value from formValues, or from component basic properties\r\n // CRITICAL: Check basic.value first (API data structure), then formValue\r\n const fileFormValue = formValue || \r\n (component.basic as any)?.value || \r\n (component.basic as any)?.files || \r\n (component.basic as any)?.attachments || \r\n null;\r\n return (\r\n <DfFormFileUpload \r\n {...commonProps} \r\n properties={component as any}\r\n formValue={fileFormValue}\r\n />\r\n )\r\n \r\n \r\n default:\r\n return (\r\n <div className=\"form-group\">\r\n <div className=\"form-group-label\">\r\n Unsupported Component: {component.name}\r\n </div>\r\n </div>\r\n )\r\n }\r\n }\r\n\r\n return (\r\n <div className=\"form-preview-container\">\r\n <div className=\"form-preview-wrapper\">\r\n <div className={`form-preview ${Object.entries(getPreviewClasses()).map(([key, value]: [string, boolean]) => value ? key : '').join(' ')}`}>\r\n {/* Form Canvas Header - You can implement this separately */}\r\n <div className=\"form-canvas-header\">\r\n {/* <FormCanvasHeader \r\n formData={formData}\r\n disableSaveDraft={false}\r\n disableCancel={false}\r\n disableSubmit={false}\r\n showTags={false}\r\n /> */}\r\n </div>\r\n\r\n {formComponents.length === 0 ? (\r\n <div className=\"empty-state\">\r\n <div className=\"empty-state-card\">\r\n <div className=\"empty-state-preview-area\">\r\n <span className=\"empty-state-placeholder\">\r\n Add components to see the form preview\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n ) : (\r\n <form className=\"form-preview-form\" onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>\r\n {/* Form Title and Description */}\r\n {(formTitle || formDescription) && (\r\n <div className=\"form-header\">\r\n {formTitle && (\r\n <h1 className=\"form-title\">{formTitle}</h1>\r\n )}\r\n {formDescription && (\r\n <p className=\"form-description\">{formDescription}</p>\r\n )}\r\n </div>\r\n )}\r\n\r\n {formComponents.map((component) => {\r\n const basic = component.basic as any;\r\n const formValue = formValues[component.id];\r\n const isOptionBased = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');\r\n const componentOptions = (component as any).options || basic?.options || [];\r\n \r\n // Get column class from component styles\r\n const getColumnClass = (): string => {\r\n const column = (component as any)?.styles?.column;\r\n // Section and table components should always be full width\r\n if (component.name === 'section' || component.name === 'table' || component.name === 'datagrid') {\r\n return 'col-12';\r\n }\r\n // Map column value to class name\r\n if (column === 3) return 'col-3';\r\n if (column === 6) return 'col-6';\r\n if (column === 9) return 'col-9';\r\n if (column === 12) return 'col-12';\r\n // Default to full width if no column specified\r\n return 'col-12';\r\n };\r\n \r\n const columnClass = getColumnClass();\r\n \r\n // Check if component or selected option has action features\r\n let hasActionFeatures = false;\r\n if (!isPreviewMode) {\r\n if (isOptionBased && formValue !== undefined && formValue !== null && formValue !== '') {\r\n if (component.name === 'checkbox') {\r\n const selectedValues = Array.isArray(formValue) ? formValue : [formValue];\r\n hasActionFeatures = selectedValues.some((value: string) => {\r\n const option = componentOptions.find((opt: any) => opt.value === value);\r\n return option && (option.enableNotes || option.enableAttachment || option.enableRaiseIssue || option.enableSendEmail);\r\n });\r\n } else {\r\n const selectedOption = componentOptions.find((opt: any) => opt.value === formValue);\r\n hasActionFeatures = selectedOption && (selectedOption.enableNotes || selectedOption.enableAttachment || selectedOption.enableRaiseIssue || selectedOption.enableSendEmail);\r\n }\r\n } else {\r\n hasActionFeatures = basic?.enableNotes || basic?.enableAttachment || basic?.enableRaiseIssue || basic?.enableSendEmail;\r\n }\r\n }\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = isPreviewMode && (\r\n ((component as any).basic?.notes && (component as any).basic.notes.trim().length > 0) ||\r\n ((component as any).basic?.attachments && Array.isArray((component as any).basic.attachments) && (component as any).basic.attachments.length > 0)\r\n );\r\n\r\n return (\r\n <div \r\n key={component.id} \r\n className={`form-group ${columnClass} ${hasActionFeatures || hasSubmissionData ? 'has-action-features' : ''}`}\r\n style={{ display: shouldShowComponent(component.id) ? 'block' : 'none' }}\r\n >\r\n {renderFormComponent(component)}\r\n {/* Action Features - Only show in test mode, exclude certain component types */}\r\n {!isPreviewMode && !['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(component.name) && (\r\n <ComponentActionFeatures\r\n component={component as any}\r\n mode={isPreviewMode ? 'preview' : 'test'}\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n onNotesChange={(notes: string) => {\r\n // Handle notes change for regular components - update component.basic.notes\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n basic: {\r\n ...comp.basic,\r\n notes: notes || ''\r\n } as any\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents as FormComponentType[])\r\n }}\r\n onAttachmentChange={(attachments: File[] | null) => {\r\n // Handle attachment change for regular components - update component.basic.attachments\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n basic: {\r\n ...comp.basic,\r\n attachments: attachments || []\r\n } as any\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents as FormComponentType[])\r\n }}\r\n notes={(component as any).basic?.notes || ''}\r\n attachments={(component as any).basic?.attachments || null}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {isPreviewMode && hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={component as any}\r\n />\r\n )}\r\n </div>\r\n );\r\n })}\r\n \r\n {!isPreviewMode && (\r\n <div className=\"form-actions\">\r\n <button\r\n type=\"submit\"\r\n disabled={!isFormValid() || !thresholdValidationState.isValid}\r\n className=\"form-submit-button\"\r\n title={!thresholdValidationState.isValid ? thresholdValidationState.errorMessage : ''}\r\n >\r\n Submit\r\n </button>\r\n </div>\r\n )}\r\n </form>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormPreview\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport './df-form-comments.scss';\r\n\r\ninterface DfFormCommentsProps {\r\n comment?: string;\r\n onSave?: (comment: string) => void;\r\n placeholder?: string;\r\n className?: string;\r\n disabled?: boolean;\r\n}\r\n\r\nexport const DfFormComments: React.FC<DfFormCommentsProps> = ({\r\n comment = '',\r\n onSave,\r\n placeholder = 'Enter your reason...',\r\n className = '',\r\n disabled = false\r\n}) => {\r\n const [isExpanded, setIsExpanded] = useState<boolean>(true);\r\n const [currentComment, setCurrentComment] = useState<string>(comment);\r\n const [hasChanges, setHasChanges] = useState<boolean>(false);\r\n\r\n // Update local state when comment prop changes\r\n useEffect(() => {\r\n setCurrentComment(comment);\r\n setHasChanges(false);\r\n }, [comment]);\r\n\r\n // Handle input changes\r\n const handleInputChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = event.target.value;\r\n setCurrentComment(newValue);\r\n setHasChanges(newValue !== comment);\r\n }, [comment]);\r\n\r\n // Handle input blur with auto-save\r\n const handleInputBlur = useCallback(() => {\r\n if (hasChanges && onSave && !disabled) {\r\n onSave(currentComment);\r\n setHasChanges(false);\r\n }\r\n }, [hasChanges, onSave, currentComment, disabled]);\r\n\r\n // Handle input focus\r\n const handleInputFocus = useCallback(() => {\r\n // Focus handler if needed\r\n }, []);\r\n\r\n // Toggle comments section\r\n const toggleComments = useCallback(() => {\r\n if (!disabled) {\r\n setIsExpanded(!isExpanded);\r\n }\r\n }, [isExpanded, disabled]);\r\n\r\n\r\n return (\r\n <div className={`df-form-comments ${className}`}>\r\n <div className=\"df-form-comments__header\">\r\n <h3 className=\"df-form-comments__title\">Comments</h3>\r\n <button\r\n className=\"df-form-comments__toggle\"\r\n type=\"button\"\r\n onClick={toggleComments}\r\n aria-expanded={isExpanded}\r\n aria-label=\"Toggle comments section\"\r\n disabled={disabled}\r\n >\r\n {isExpanded ? (\r\n <span className=\"df-form-comments__toggle-icon\">▼</span>\r\n ) : (\r\n <span className=\"df-form-comments__toggle-icon\">▶</span>\r\n )}\r\n </button>\r\n </div>\r\n\r\n <div className={`df-form-comments__content ${isExpanded ? 'df-form-comments__content--expanded' : ''}`}>\r\n <div className=\"df-form-comments__input-container\">\r\n <div className=\"df-form-comments__input-line\">\r\n <input\r\n type=\"text\"\r\n id=\"comment-input\"\r\n className=\"df-form-comments__input\"\r\n value={currentComment}\r\n onChange={handleInputChange}\r\n onBlur={handleInputBlur}\r\n onFocus={handleInputFocus}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n />\r\n </div>\r\n \r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormComments;\r\n","import React, { useState, useCallback, useEffect, useRef, useMemo } from 'react'\r\nimport { useDroppable } from '@dnd-kit/core'\r\nimport { useSortable, SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { ChevronDown, ChevronRight, GripVertical, Edit, Trash2, Table } from 'lucide-react'\r\nimport { ITableComponent, FormComponentType, IFormControlChange, TableCell } from '../df-form-preview-interfaces'\r\nimport { v4 as uuidv4 } from 'uuid'\r\nimport './df-form-table.scss'\r\n\r\n// Import form control components for rendering children\r\nimport { DfFormInput } from '../df-form-input'\r\nimport { DfFormTextarea } from '../df-form-textarea'\r\nimport { DfFormSelect } from '../df-form-select'\r\nimport { DfFormCheckbox } from '../df-form-checkbox'\r\nimport { DfFormRadio } from '../df-form-radio'\r\nimport { DfFormDateTime } from '../df-form-date-time'\r\nimport { DfFormSignature } from '../df-form-signature'\r\nimport { DfFormHeading } from '../df-form-heading'\r\nimport { ComponentActionFeatures } from '../../ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from '../../components/ComponentSubmissionActions'\r\n\r\n// Function to ensure table cell components have proper IDs\r\nconst ensureComponentHasId = (component: FormComponentType): FormComponentType => {\r\n if (!component.id) {\r\n return {\r\n ...component,\r\n id: uuidv4()\r\n }\r\n }\r\n return component\r\n}\r\n\r\ninterface DfFormTableProps {\r\n id: string\r\n properties: ITableComponent\r\n validationErrors?: Record<string, any>\r\n formValue?: any\r\n formData?: Record<string, any>\r\n readonly?: boolean\r\n disabled?: boolean\r\n touchedFields?: Record<string, boolean>\r\n formSubmitted?: boolean\r\n mode?: 'edit' | 'preview' | 'test'\r\n onValueChange?: (change: IFormControlChange) => void\r\n onBlur?: () => void\r\n onFocus?: () => void\r\n onSelect?: () => void\r\n isSelected?: boolean\r\n className?: string\r\n // Table-specific props\r\n onTableSelect?: (table: ITableComponent) => void\r\n onTableDelete?: (tableId: string) => void\r\n onCellChange?: (row: number, column: number, components: FormComponentType[]) => void\r\n onComponentSelect?: (component: FormComponentType) => void\r\n onComponentDelete?: (componentId: string) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n selectedComponent?: FormComponentType | null\r\n renderFormComponent?: (field: FormComponentType) => React.ReactNode\r\n // Additional props for consistency with section component\r\n onTableUpdate?: (tableId: string, updates: Partial<ITableComponent>) => void\r\n onCellAdd?: (row: number, column: number) => void\r\n onCellRemove?: (row: number, column: number) => void\r\n onRowAdd?: () => void\r\n onRowRemove?: (rowIndex: number) => void\r\n onColumnAdd?: () => void\r\n onColumnRemove?: (columnIndex: number) => void\r\n // Props for action features\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\n// Simple component for preview mode (no drag handles or action buttons)\r\ninterface SimpleTableComponentProps {\r\n component: FormComponentType\r\n mode: 'edit' | 'preview' | 'test'\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst SimpleTableComponent: React.FC<SimpleTableComponentProps> = ({\r\n component,\r\n mode,\r\n renderFormComponent,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const formValue = formData[component.id]\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = mode === 'preview' && (\r\n ((component as any).basic?.notes && (component as any).basic.notes.trim().length > 0) ||\r\n ((component as any).basic?.attachments && Array.isArray((component as any).basic.attachments) && (component as any).basic.attachments.length > 0)\r\n );\r\n \r\n return (\r\n <div className=\"simple-table-component\">\r\n {renderFormComponent(component)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(component.name) && (\r\n <ComponentActionFeatures\r\n component={component as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(component.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(component.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={component as any}\r\n />\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Draggable component for items inside table cells\r\ninterface DraggableTableComponentProps {\r\n component: FormComponentType\r\n selectedComponent: FormComponentType | null\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n isOverlay?: boolean\r\n}\r\n\r\nconst DraggableTableComponent: React.FC<DraggableTableComponentProps> = ({\r\n component,\r\n selectedComponent,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n renderFormComponent,\r\n isOverlay = false,\r\n}) => {\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n isSorting,\r\n } = useSortable({\r\n id: component.id,\r\n disabled: isOverlay, // Only disable when it's an overlay, allow dragging in edit mode\r\n })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.3 : 1,\r\n zIndex: isDragging ? 1000 : 'auto',\r\n }\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n style={style}\r\n className={`form-component table-component ${selectedComponent?.id === component.id ? 'selected' : ''} ${isDragging ? 'dragging' : ''} ${isSorting ? 'sorting' : ''}`}\r\n onClick={() => !isDragging && onComponentSelect(component)}\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {/* Drag Handle - Only visible in edit mode */}\r\n {mode === 'edit' && (\r\n <div \r\n className=\"component-drag-handle\" \r\n {...listeners} \r\n {...attributes}\r\n onClick={(e) => e.stopPropagation()}\r\n style={{ opacity: 1 }}\r\n >\r\n <GripVertical size={14} />\r\n </div>\r\n )}\r\n\r\n {/* Component Content */}\r\n <div className=\"component-content\">\r\n {renderFormComponent(component)}\r\n </div>\r\n\r\n {/* Action Buttons - Only show in edit mode */}\r\n {mode === 'edit' && (\r\n <div className=\"component-actions\" style={{ opacity: 1 }}>\r\n {/* Edit Button */}\r\n {onComponentEdit && (\r\n <button\r\n className=\"component-edit-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentEdit(component)\r\n }}\r\n type=\"button\"\r\n title=\"Edit Component\"\r\n >\r\n <Edit size={12} />\r\n </button>\r\n )}\r\n \r\n {/* Delete Button */}\r\n <button\r\n className=\"component-delete-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentDelete(component, e)\r\n }}\r\n type=\"button\"\r\n title=\"Delete Component\"\r\n >\r\n <Trash2 size={12} />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Table Cell Component\r\ninterface TableCellComponentProps {\r\n cell: TableCell\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n selectedComponent: FormComponentType | null\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n tableId: string\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst TableCellComponent: React.FC<TableCellComponentProps> = ({\r\n cell,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n selectedComponent,\r\n renderFormComponent,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n tableId,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const dropZoneId = `table-cell-${tableId}-${cell.row}-${cell.column}`\r\n \r\n const { setNodeRef, isOver } = useDroppable({\r\n id: dropZoneId,\r\n disabled: mode !== 'edit',\r\n data: {\r\n type: 'table-cell',\r\n tableId: tableId,\r\n cell: cell,\r\n row: cell.row,\r\n column: cell.column\r\n }\r\n })\r\n\r\n // In preview/test mode, show empty cells as transparent spaces to maintain positioning\r\n // Don't hide them completely to preserve the table structure\r\n\r\n const cellStyle = {\r\n ...cell.styles,\r\n backgroundColor: isOver ? 'var(--df-color-primary-light)' : cell.styles?.backgroundColor || 'transparent',\r\n minHeight: cell.styles?.minHeight || (mode === 'preview' || mode === 'test') ? '40px' : '60px',\r\n padding: cell.styles?.padding || (mode === 'preview' || mode === 'test') ? '8px' : '8px',\r\n border: (mode === 'preview' || mode === 'test') ? 'none' : \r\n (isOver ? '2px dashed var(--df-color-primary)' : cell.styles?.borderColor ? `1px solid ${cell.styles.borderColor}` : '1px solid var(--df-color-fb-border)'),\r\n borderRadius: (mode === 'preview' || mode === 'test') ? '0' : '4px',\r\n position: 'relative' as const,\r\n verticalAlign: cell.styles?.verticalAlign || 'top'\r\n }\r\n\r\n return (\r\n <td\r\n ref={setNodeRef}\r\n style={cellStyle}\r\n className={`table-cell ${isOver ? 'drag-over' : ''}`}\r\n >\r\n <div className=\"cell-content\">\r\n {cell.components && Array.isArray(cell.components) && cell.components.length > 0 ? (\r\n mode === 'edit' ? (\r\n <SortableContext items={cell.components.map(c => c.id || uuidv4())} strategy={verticalListSortingStrategy}>\r\n {cell.components.map((component) => {\r\n const componentWithId = ensureComponentHasId(component)\r\n return (\r\n <DraggableTableComponent\r\n key={componentWithId.id}\r\n component={componentWithId}\r\n selectedComponent={selectedComponent}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect}\r\n onComponentDelete={onComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n renderFormComponent={renderFormComponent}\r\n />\r\n )\r\n })}\r\n </SortableContext>\r\n ) : (\r\n // In preview/test mode, use simple components without drag handles\r\n // CRITICAL: Use component.id directly as key - don't regenerate IDs on every render\r\n cell.components.map((component) => {\r\n // Only ensure ID if it's truly missing - don't regenerate existing IDs\r\n const componentWithId = component.id ? component : ensureComponentHasId(component);\r\n return (\r\n <SimpleTableComponent\r\n key={componentWithId.id}\r\n component={componentWithId}\r\n mode={mode}\r\n renderFormComponent={renderFormComponent}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n )\r\n })\r\n )\r\n ) : (\r\n // Only show drop zone content in edit mode\r\n mode === 'edit' ? (\r\n <div className=\"empty-cell-placeholder\">\r\n <div className=\"cell-info\">\r\n <span className=\"drop-zone-text\">Drag and Drop a form component</span>\r\n <span className=\"cell-coordinates\">Cell ({cell.row + 1}, {cell.column + 1})</span>\r\n </div>\r\n </div>\r\n ) : (\r\n // In preview/test mode, show empty cell as transparent space to maintain positioning\r\n <div style={{ \r\n minHeight: '20px', \r\n backgroundColor: 'transparent',\r\n visibility: 'hidden' // Hide content but maintain space\r\n }}>\r\n \r\n </div>\r\n )\r\n )}\r\n </div>\r\n </td>\r\n )\r\n}\r\n\r\nexport const DfFormTable: React.FC<DfFormTableProps> = ({\r\n id,\r\n properties,\r\n mode = 'edit',\r\n formData = {},\r\n validationErrors = {},\r\n touchedFields = {},\r\n formSubmitted = false,\r\n onValueChange,\r\n onSelect,\r\n isSelected = false,\r\n className = '',\r\n onTableSelect,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n selectedComponent,\r\n renderFormComponent,\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const [isCollapsed, setIsCollapsed] = useState(false) // Always start expanded to show drop zones\r\n\r\n // Check if table has any components in any cells\r\n const hasAnyComponents = properties.cells?.some(row => \r\n row.some(cell => cell.components && cell.components.length > 0)\r\n ) || false\r\n\r\n // Initialize and update table cells when rows/columns change\r\n // CRITICAL: Skip cell initialization updates to prevent flickering when user types\r\n useEffect(() => {\r\n // Skip updates to prevent flickering - cells are already initialized\r\n return;\r\n \r\n // Get rows and columns from table properties (where they're actually stored)\r\n const currentRows = properties.table?.rows || properties.basic?.rows || 3\r\n const currentColumns = properties.table?.columns || properties.basic?.columns || 3\r\n const currentCells = properties.cells || []\r\n \r\n // Check if we need to update the table structure\r\n const needsUpdate = currentCells.length === 0 || \r\n currentCells.length !== currentRows || \r\n (currentCells.length > 0 && currentCells[0].length !== currentColumns)\r\n \r\n if (needsUpdate) {\r\n const newCells: TableCell[][] = []\r\n \r\n for (let row = 0; row < currentRows; row++) {\r\n const rowCells: TableCell[] = []\r\n for (let col = 0; col < currentColumns; col++) {\r\n const cellId = `cell-${row}-${col}`\r\n \r\n // Try to preserve existing components if the cell exists\r\n let existingComponents: FormComponentType[] = []\r\n if (currentCells[row] && currentCells[row][col]) {\r\n existingComponents = (currentCells[row][col].components || []).map(ensureComponentHasId)\r\n }\r\n \r\n rowCells.push({\r\n id: cellId,\r\n row,\r\n column: col,\r\n components: existingComponents,\r\n styles: {}\r\n })\r\n }\r\n newCells.push(rowCells)\r\n }\r\n \r\n onValueChange?.({\r\n id,\r\n value: { ...properties, cells: newCells }\r\n })\r\n }\r\n }, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, properties.cells, id, onValueChange]) // Watch for rows/columns changes\r\n\r\n const handleTableClick = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n onSelect?.()\r\n onTableSelect?.(properties)\r\n }, [onSelect, onTableSelect, properties])\r\n\r\n const toggleCollapse = (event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n setIsCollapsed(!isCollapsed)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...(properties.basic || {}), collapsed: !isCollapsed } }\r\n })\r\n }\r\n\r\n\r\n const handleComponentDelete = useCallback((component: FormComponentType, event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n\r\n // Find and remove the component from the table cell\r\n const updatedCells = properties.cells.map(row => \r\n row.map(cell => {\r\n if (cell.components && cell.components.some(comp => comp.id === component.id)) { \r\n const filteredComponents = cell.components.filter(comp => comp.id !== component.id)\r\n \r\n return {\r\n ...cell,\r\n components: filteredComponents\r\n }\r\n }\r\n return cell\r\n })\r\n )\r\n \r\n // Update the table with the modified cells\r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, cells: updatedCells }\r\n })\r\n } else {\r\n }\r\n \r\n // Don't call parent delete handler for table cell components\r\n // The parent delete handler is for deleting entire fields, not components within table cells\r\n }, [onComponentDelete, properties, onValueChange, id])\r\n\r\n // CRITICAL FIX: Ensure all table cell components have proper IDs with table and cell position\r\n // Use useMemo to prevent ID regeneration on every render\r\n const cellsWithIds = useMemo(() => {\r\n if (!properties.cells) return [];\r\n \r\n return properties.cells.map((row: any[], rowIndex: number) => \r\n row.map((cell: any, cellIndex: number) => ({\r\n ...cell,\r\n components: (cell.components && Array.isArray(cell.components)) \r\n ? cell.components.map((comp: any, compIndex: number) => {\r\n // CRITICAL: Only generate ID if it's missing - never regenerate existing IDs\r\n // This prevents component remounting and losing input state\r\n if (comp.id && typeof comp.id === 'string' && comp.id.trim() !== '') {\r\n // ID already exists - keep it as is\r\n return comp;\r\n }\r\n \r\n // Generate unique ID that includes table ID, row, cell, and component index\r\n // This ensures no conflicts with other components\r\n const uniqueId = `${comp.name || 'component'}-table-${id}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;\r\n return {\r\n ...comp,\r\n id: uniqueId\r\n }\r\n })\r\n : []\r\n }))\r\n )\r\n }, [properties.cells, id]) // Only recalculate if cells or table ID changes\r\n \r\n // CRITICAL FIX: Update the parent component with the cells that have proper IDs\r\n // Skip this in package to prevent flickering - cells are managed by parent\r\n // useEffect(() => {\r\n // // Disabled to prevent flickering when user types\r\n // }, [])\r\n \r\n // CRITICAL: Create a stable renderComponent that doesn't recreate on every render\r\n // Match main app implementation - directly access formData from closure\r\n const renderComponent = renderFormComponent || useCallback((field: FormComponentType) => {\r\n // CRITICAL: Only ensure ID if it's missing - don't regenerate existing IDs\r\n // This prevents component remounting and losing input state\r\n const componentWithId = field.id ? field : ensureComponentHasId(field)\r\n \r\n // Get form value - directly access formData from closure (matches main app)\r\n const formValue = formData[componentWithId.id] || ('defaultValue' in componentWithId.basic ? componentWithId.basic.defaultValue || '' : '');\r\n \r\n const commonProps = {\r\n id: componentWithId.id,\r\n properties: componentWithId,\r\n validationErrors: {},\r\n formValue: formValue,\r\n touchedFields: {},\r\n formSubmitted: false,\r\n mode,\r\n onValueChange: (change: IFormControlChange) => {\r\n // Forward the change to parent's onValueChange to update formValues\r\n onValueChange?.(change)\r\n },\r\n onBlur: () => {},\r\n onFocus: () => {}\r\n }\r\n\r\n switch (componentWithId.name) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'number-input':\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={componentWithId as any}\r\n inputType={componentWithId.name === 'text-input' ? 'text' : \r\n componentWithId.name === 'number-input' ? 'number' : 'email'}\r\n readonly={false} // CRITICAL: Always editable in package\r\n disabled={false} // CRITICAL: Never disabled in package\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={componentWithId as any} readonly={false} disabled={false} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...componentWithId,\r\n options: (componentWithId as any).basic?.options || []\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} disabled={false} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...componentWithId,\r\n options: (componentWithId as any).basic?.options || []\r\n }\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} formValue={[]} disabled={false} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...componentWithId,\r\n options: (componentWithId as any).basic?.options || []\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} readonly={false} disabled={false} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={componentWithId as any} readonly={false} disabled={false} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={componentWithId as any} readonly={false} disabled={false} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={componentWithId as any} />\r\n \r\n case 'heading':\r\n return <DfFormHeading {...commonProps} properties={componentWithId as any} />\r\n \r\n default:\r\n return <div className=\"unknown-component\">Unknown component: {componentWithId.name}</div>\r\n }\r\n }, [renderFormComponent, mode, formData, onValueChange]) // Include renderFormComponent, formData and onValueChange to ensure latest values are used\r\n\r\n const tableStyle = {\r\n backgroundColor: properties.styles?.backgroundColor || 'var(--df-color-fb-container)',\r\n borderColor: properties.styles?.borderColor || 'var(--df-color-fb-border)',\r\n borderWidth: properties.styles?.borderWidth || '2px',\r\n borderRadius: properties.styles?.borderRadius || '8px',\r\n padding: properties.styles?.padding || '16px',\r\n margin: properties.styles?.margin || '16px 0'\r\n }\r\n\r\n const tableElementStyle: React.CSSProperties = {\r\n width: '100%',\r\n minWidth: '600px', // Ensure minimum width to trigger horizontal scroll\r\n borderCollapse: (mode === 'preview' || mode === 'test') ? 'separate' : 'collapse',\r\n tableLayout: 'fixed',\r\n border: (mode === 'preview' || mode === 'test') ? '1px solid var(--df-color-fb-border)' : 'none'\r\n }\r\n\r\n // Don't render the table if it has no components and we're in preview mode\r\n // Test mode should always show tables so users can interact with them\r\n if (!hasAnyComponents && mode === 'preview') {\r\n return null\r\n }\r\n\r\n\r\n return (\r\n <div\r\n className={`form-group df-form-table ${isSelected ? 'selected' : ''} ${mode === 'preview' ? 'preview-mode' : mode === 'test' ? 'test-mode' : ''} ${className}`}\r\n onClick={handleTableClick}\r\n style={tableStyle}\r\n >\r\n {/* Table Header */}\r\n <div className=\"table-header\">\r\n <div className=\"table-title\" onClick={toggleCollapse}>\r\n <div className=\"title-content\">\r\n {isCollapsed ? <ChevronRight size={16} /> : <ChevronDown size={16} />}\r\n <Table size={16} />\r\n <span className=\"table-label\">{properties.basic?.label || 'Table'}</span>\r\n {properties.validation?.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </div>\r\n </div>\r\n \r\n \r\n </div>\r\n\r\n {/* Table Description */}\r\n {properties.basic?.description && !isCollapsed && (\r\n <div className=\"table-description\">\r\n {properties.basic.description}\r\n </div>\r\n )}\r\n\r\n {/* Table Content */}\r\n {!isCollapsed && (\r\n <div className=\"table-content\">\r\n {(() => {\r\n return null\r\n })()}\r\n <table style={tableElementStyle}>\r\n {/* Column Headers */}\r\n {properties.table?.displayAsTable && (mode === 'edit' || properties.table?.showColumns) && (\r\n <thead>\r\n <tr className=\"table-header-row\">\r\n {Array.from({ length: properties.table?.columns || properties.basic?.columns || 3 }, (_, colIndex) => {\r\n // Parse column names from the comma-separated string\r\n const columnNames = properties.table?.columnNames?.split(',').map(name => name.trim()) || []\r\n const columnName = columnNames[colIndex] || `Column ${colIndex + 1}`\r\n \r\n return (\r\n <th \r\n key={`header-${colIndex}`}\r\n className=\"table-header-cell\"\r\n style={{\r\n backgroundColor: properties.styles.headerBackgroundColor || (mode === 'preview' || mode === 'test') ? 'var(--df-color-fb-container)' : 'var(--df-color-fb-container)',\r\n color: properties.styles.headerTextColor || 'var(--df-color-text-dark)',\r\n padding: '12px',\r\n border: (mode === 'preview' || mode === 'test') ? '1px solid var(--df-color-fb-border)' : '1px solid var(--df-color-fb-border)',\r\n fontWeight: '600',\r\n fontSize: '14px',\r\n textAlign: 'center'\r\n }}\r\n >\r\n {columnName}\r\n </th>\r\n )\r\n })}\r\n </tr>\r\n </thead>\r\n )}\r\n <tbody>\r\n {cellsWithIds.map((row, rowIndex) => (\r\n <tr \r\n key={rowIndex}\r\n className=\"table-row\"\r\n >\r\n {row.map((cell) => (\r\n <TableCellComponent\r\n key={cell.id}\r\n cell={cell}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect || (() => {})}\r\n onComponentDelete={handleComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n selectedComponent={selectedComponent || null}\r\n renderFormComponent={renderComponent}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n tableId={id}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n ))}\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormTable","// Form Builder Schema Model - Package version\r\n// Defines enums and base types for form component configurations\r\n\r\nimport { FormComponentType, IConditionalLogic, ICondition } from '../df-form-controls/df-form-preview-interfaces';\r\n\r\n// Re-export types from interfaces\r\nexport type { FormComponentType, IConditionalLogic, ICondition };\r\n\r\nexport type TComponentCategory = 'Basic' | 'Advanced' | 'Layout' | 'Custom';\r\n\r\nexport type TBasicComponentName =\r\n | 'text-input'\r\n | 'number-input'\r\n | 'email-input'\r\n | 'textarea'\r\n | 'select'\r\n | 'checkbox'\r\n | 'radio'\r\n | 'segment'\r\n | 'date-picker'\r\n | 'datetime-picker'\r\n | 'info'\r\n | 'signature'\r\n | 'heading'\r\n | 'instructions'\r\n | 'section'\r\n | 'table'\r\n | 'datagrid'\r\n | 'file'\r\n | 'location';\r\n\r\nexport type TComponentName = TBasicComponentName;\r\n\r\nexport enum ELabelAlignment {\r\n Top = 'top',\r\n Left = 'left',\r\n}\r\n\r\nexport interface IOption {\r\n label: string;\r\n value: string;\r\n selected?: boolean;\r\n enableNotes?: boolean;\r\n enableAttachment?: boolean;\r\n enableRaiseIssue?: boolean;\r\n enableSendEmail?: boolean;\r\n color?: string;\r\n backgroundColor?: string;\r\n icon?: string;\r\n}\r\n\r\nexport type TCheckboxValue = string | string[];\r\n\r\nexport interface IBaseProps {\r\n label: string;\r\n value: string;\r\n defaultValue: string | number;\r\n placeholder?: string;\r\n options?: any[];\r\n description?: string;\r\n collapsed?: boolean;\r\n valid?: boolean;\r\n enableNotes?: boolean;\r\n enableAttachment?: boolean;\r\n enableRaiseIssue?: boolean;\r\n enableSendEmail?: boolean;\r\n}\r\n\r\nexport interface IBaseValidationProps {\r\n required: boolean;\r\n customValidationMessage: string;\r\n readonly: boolean;\r\n}\r\n\r\nexport interface IBaseStyleProps {\r\n labelAlignment: ELabelAlignment;\r\n width?: number;\r\n height?: number;\r\n minWidth?: number;\r\n maxWidth?: number;\r\n minHeight?: number;\r\n maxHeight?: number;\r\n column?: number;\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n borderRadius?: string;\r\n padding?: string;\r\n margin?: string;\r\n}\r\n\r\nexport type TInputComponentType = 'text' | 'number' | 'email';\r\n\r\nexport interface IBaseInputComponent {\r\n inputType: TInputComponentType;\r\n}\r\n\r\nexport interface IBaseComponent {\r\n id: string;\r\n _id: string;\r\n name: TComponentName;\r\n category: TComponentCategory;\r\n basic: IBaseProps;\r\n validation: IBaseValidationProps;\r\n styles: IBaseStyleProps;\r\n position: number;\r\n options: any[];\r\n conditional: IConditionalLogic;\r\n}\r\n\r\n// Type alias for compatibility\r\nexport type TFormComponent = FormComponentType;\r\n\r\n"],"names":["process","env","NODE_ENV","jsxRuntimeModule","exports","f","require$$0","k","Symbol","for","l","m","Object","prototype","hasOwnProperty","n","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","ReactCurrentOwner","p","key","ref","__self","__source","q","c","a","g","b","d","e","h","call","defaultProps","$$typeof","type","props","_owner","current","reactJsxRuntime_production_min","jsx","jsxs","REACT_MODULE_REFERENCE","React","REACT_ELEMENT_TYPE","REACT_PORTAL_TYPE","REACT_FRAGMENT_TYPE","REACT_STRICT_MODE_TYPE","REACT_PROFILER_TYPE","REACT_PROVIDER_TYPE","REACT_CONTEXT_TYPE","REACT_FORWARD_REF_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_MEMO_TYPE","REACT_LAZY_TYPE","REACT_OFFSCREEN_TYPE","MAYBE_ITERATOR_SYMBOL","iterator","ReactSharedInternals","error","format","_len2","arguments","length","args","Array","_key2","level","stack","ReactDebugCurrentFrame","getStackAddendum","concat","argsWithFormat","map","item","String","unshift","Function","apply","console","printWarning","getContextName","displayName","getComponentNameFromType","tag","name","_context","outerType","innerType","wrapperName","functionName","getWrappedName","render","outerName","lazyComponent","payload","_payload","init","_init","x","prevLog","prevInfo","prevWarn","prevError","prevGroup","prevGroupCollapsed","prevGroupEnd","assign","disabledDepth","disabledLog","__reactDisabledLog","prefix","ReactCurrentDispatcher","describeBuiltInComponentFrame","source","ownerFn","undefined","Error","match","trim","componentFrameCache","reentry","PossiblyWeakMap","WeakMap","Map","describeNativeComponentFrame","fn","construct","control","frame","get","previousDispatcher","previousPrepareStackTrace","prepareStackTrace","log","info","warn","group","groupCollapsed","groupEnd","configurable","enumerable","value","writable","defineProperties","disableLogs","Fake","defineProperty","set","Reflect","sample","sampleLines","split","controlLines","s","_frame","replace","includes","reenableLogs","syntheticFrame","describeUnknownElementTypeFrameInDEV","isReactComponent","loggedTypeFailures","setCurrentlyValidatingElement","element","owner","_source","setExtraStackFrame","isArrayImpl","isArray","testStringCoercion","checkKeyStringCoercion","willCoercionThrow","toStringTag","constructor","typeName","specialPropKeyWarningShown","specialPropRefWarningShown","didWarnAboutStringRefs","RESERVED_PROPS","jsxDEV","config","maybeKey","self","propName","getter","getOwnPropertyDescriptor","isReactWarning","hasValidKey","hasValidRef","stateNode","componentName","warnIfStringRefCannotBeAutoConverted","warnAboutAccessingKey","defineKeyPropWarningGetter","warnAboutAccessingRef","defineRefPropWarningGetter","_store","freeze","ReactElement","propTypesMisspellWarningShown","ReactCurrentOwner$1","ReactDebugCurrentFrame$1","setCurrentlyValidatingElement$1","isValidElement","object","getDeclarationErrorAddendum","ownerHasKeyUseWarning","validateExplicitKey","parentType","validated","currentComponentErrorInfo","parentName","getCurrentComponentErrorInfo","childOwner","validateChildKeys","node","i","child","iteratorFn","maybeIterable","maybeIterator","getIteratorFn","entries","step","next","done","validatePropTypes","propTypes","typeSpecs","values","location","has","bind","typeSpecName","error$1","err","ex","message","checkPropTypes","PropTypes","getDefaultProps","isReactClassApproved","didWarnAboutKeySpread","jsxWithValidation","isStaticChildren","validType","getModuleId","isValidElementType","keys","typeString","sourceInfo","fileName","lineNumber","getSourceInfoErrorAddendum","children","filter","beforeExample","join","fragment","validateFragmentProps","reactJsxRuntime_development","Fragment","ConditionalLogicService","getInstance","instance","getAvailableComponentsForConditional","formSchema","excludeComponentId","component","id","label","basic","sort","localeCompare","getApplicableOperators","componentType","validateConditionalLogic","conditional","errors","action","push","when","conditions","forEach","condition","index","find","comp","this","operator","isValidConditionValue","isValid","evaluateConditionalLogic","formValues","shouldShow","evaluatedConditions","componentValue","getComponentValue","result","evaluateCondition","determineFinalResult","componentId","defaultValue","evaluateCheckboxCondition","isEqual","isEmpty","contains","isGreaterThan","isLessThan","isGreaterThanOrEqual","isLessThanOrEqual","expectedValue","isChecked","isCheckboxChecked","toLowerCase","conditionsMet","finalResult","every","some","val","keysA","keysB","container","searchValue","numA","Number","numB","isNaN","Date","parse","createDefaultConditionalLogic","getOperatorDisplayText","equals","notEquals","notContains","isNotEmpty","greaterThan","lessThan","greaterThanOrEqual","lessThanOrEqual","getActionDisplayText","show","hide","always","getConditionalLogicSummary","actionText","conditionTexts","formatConditionValue","operatorText","conditionalLogicService","toastService","toasts","listeners","defaultDuration","timeouts","generateId","now","toString","Math","random","substr","notifyListeners","listener","addToast","toast","setTimeout","removeToast","duration","clearTimeout","showSuccess","showError","showWarning","showInfo","clearAll","timeout","subscribe","getToasts","DfFormErrorMsg","validationErrors","fieldId","touchedFields","formSubmitted","properties","localValidation","isTouched","localIsTouched","mode","getDefaultErrorMessage","errorType","fieldLabel","customMessage","validation","customValidationMessage","dateTimeMode","minLength","maxLength","min","max","numberValidation","lowerLimit","numberValidationUpper","upperLimit","errorMessage","actualErrors","firstError","fieldErrors","getErrorMessage","_jsx","className","EIssueStatus","RaiseIssueModal","isOpen","onClose","onSuccess","formTemplateId","notes","attachments","issue","onCreateIssue","onUpdateIssue","user","availableUsers","title","setTitle","useState","description","setDescription","workOrderNumber","setWorkOrderNumber","assetNumber","setAssetNumber","priority","setPriority","status","setStatus","OPEN","assignee","setAssignee","comments","setComments","isSubmitting","setIsSubmitting","isEditMode","useEffect","issueStatus","normalizedStatus","IN_PROGRESS","REJECTED","RESOLVE","componentLabel","desc","updateIssueStatus","async","newStatus","updateData","_id","statusMessages","modalContent","onClick","_jsxs","stopPropagation","AlertTriangle","size","X","issueNumber","readOnly","onChange","target","placeholder","User","firstName","lastName","Calendar","createdAt","toLocaleString","year","month","day","hour","minute","hour12","rows","disabled","userName","MessageSquare","_Fragment","componentData","issueData","createdIssue","createPortal","document","body","ThresholdAlert","currentValue","thresholdValue","onIssueRaised","isIssueRaised","compact","showRaiseIssueModal","setShowRaiseIssueModal","setIssue","isLoadingIssue","setIsLoadingIssue","localIssueRaised","setLocalIssueRaised","getOperatorSymbol","handleRaiseIssueClick","useCallback","handleRaiseIssueClose","handleRaiseIssueSuccess","fill","operatorSymbol","getConditionMessage","DfFormInput","formValue","inputType","readonly","onValueChange","onBlur","onFocus","hideLabel","onThresholdIssueRaised","raisedThresholdIssues","Set","getStringValue","componentIdRef","useRef","inputWrapperRef","initialValue","setValue","setIsTouched","isFocused","setIsFocused","dismissedAlerts","setDismissedAlerts","previousValue","setPreviousValue","getInputType","validateField","rules","required","email","textValidation","buildValidationRules","test","trimmedVal","numValue","parseFloat","pattern","isPartialInput","handleValueChange","newValue","currentId","change","currentComponentId","evaluateThresholdCondition","currentVal","thresholdConditions","useMemo","activeThresholdCondition","metConditions","handleDismissAlert","conditionId","prev","add","currentInputType","shouldDisable","alignment","styles","labelAlignment","getLabelAlignmentClass","htmlFor","base","hasLocalError","hasExternalError","getInputClasses","issueRaised","isInTable","closest","onDismiss","DfFormTextarea","DfFormSelect","selectedValue","setSelectedValue","isMultiple","multiple","JSON","stringify","selectedOptions","from","option","options","DfFormCheckbox","selectedValues","newValues","handleCheckboxChange","optionValue","checked","handleFocus","handleBlur","inlineLayout","DfFormRadio","handleRadioChange","DfFormSegment","handleSegmentClick","getSegmentContainerClass","getButtonType","getButtonIcon","icon","getButtonStyles","isSelected","color","backgroundColor","borderColor","getButtonClass","buttonStyles","buttonClass","buttonIcon","style","DfFormDateTime","convertToDateString","date","getTime","getFullYear","getMonth","padStart","getDate","getHours","getMinutes","dateStr","invalidDate","selectedDate","minDate","minDateMessage","toLocaleDateString","maxDate","maxDateMessage","convertedValue","DfFormSignature","canvasRef","isDrawing","setIsDrawing","signatureData","setSignatureData","isSaving","setIsSaving","getThemeColors","isDarkMode","documentElement","classList","getAttribute","getComputedStyle","getPropertyValue","strokeColor","loadSignature","dataURL","canvas","ctx","getContext","img","Image","onload","clearRect","width","height","colors","fillStyle","fillRect","canvasAspectRatio","imgAspectRatio","drawWidth","drawHeight","drawX","drawY","drawImage","onerror","substring","src","initializeCanvas","rect","getBoundingClientRect","strokeStyle","lineWidth","lineCap","lineJoin","handleViewportChange","handleResize","observer","MutationObserver","mutations","mutation","attributeName","observe","attributes","attributeFilter","subtree","window","addEventListener","disconnect","removeEventListener","getCanvasCoordinates","y","scaleX","scaleY","clientX","touches","clientY","left","top","startDrawing","preventDefault","beginPath","moveTo","draw","lineTo","stroke","stopDrawing","data","getImageData","r","hasCanvasContent","toDataURL","updateCanvasColors","currentSignature","position","maxWidth","overflow","onMouseDown","onMouseMove","onMouseUp","onMouseLeave","onTouchStart","onTouchMove","onTouchEnd","border","borderRadius","cursor","touchAction","userSelect","clearSignature","bottom","right","padding","fontSize","fontWeight","zIndex","transition","minWidth","minHeight","onMouseEnter","currentTarget","transform","DfFormFileUpload","files","setFiles","isDragOver","setIsDragOver","fileInputRef","convertToFilePreviews","fileList","fileArray","results","file","File","Blob","fileObj","url","fileSize","fileType","mimeType","preview","fileData","startsWith","cleanedData","detectedType","fileInstance","URL","createObjectURL","fileString","cleanedString","isBase64String","processedFileString","imageType","extractedFileName","filenameMatch","decodeURIComponent","typeMatch","urlFileName","pathname","pop","queryFileName","searchParams","lastSlash","lastIndexOf","lastPart","questionMark","indexOf","fileNamePart","semicolonIndex","extensionMatch","jpg","jpeg","png","gif","webp","svg","pdf","doc","docx","xls","xlsx","zip","rar","fileObject","path","validateFiles","handleFileSelect","selectedFiles","newFiles","allFiles","maxFiles","Infinity","limitedFiles","slice","formatFileSize","bytes","floor","pow","toFixed","getFileIcon","revokeObjectURL","acceptTypes","accept","canAddMoreFiles","isPreviewOrTestMode","imageFiles","nonImageFiles","hasImages","alt","onDragOver","onDragLeave","onDrop","droppedFiles","dataTransfer","isClickOnFileItem","isClickOnRemoveButton","click","tabIndex","display","fileId","updatedFiles","removeFile","viewBox","strokeWidth","strokeLinecap","strokeLinejoin","DfFormLocation","locationData","setLocationData","isLoading","setIsLoading","setError","showMap","setShowMap","mapCenter","setMapCenter","lat","lng","mapMarker","setMapMarker","mapZoom","setMapZoom","searchQuery","setSearchQuery","isSearching","setIsSearching","mapRef","isDragging","setIsDragging","dragStart","setDragStart","isReverseGeocoding","setIsReverseGeocoding","latitude","longitude","isCurrentLocation","reverseGeocode","response","fetch","json","address","placeName","display_name","city","town","village","municipality","country","updateLocationWithAddress","existingData","addressData","timestamp","getCurrentLocation","Capacitor","Geolocation","Plugins","requestPermissions","getCurrentPosition","enableHighAccuracy","maximumAge","coords","accuracy","capError","navigator","geolocation","code","PERMISSION_DENIED","POSITION_UNAVAILABLE","TIMEOUT","clearLocation","toggleMap","pixelToLatLng","center","zoom","offsetX","offsetY","metersPerPixel","cos","PI","metersX","metersY","handleMapMouseDown","event","button","handleMapMouseMove","deltaX","deltaY","latOffset","lngOffset","handleMapMouseUp","abs","searchLocation","query","encodeURIComponent","firstResult","lon","Loader2","Navigation","MapPin","Boolean","round","onSubmit","background","tan","DfFormHeading","text","getInlineStyles","headingProps","textAlign","renderHeading","DfFormInstruction","htmlContent","setHtmlContent","listStyle","setListStyle","selectedColor","setSelectedColor","editorRef","isUserInputRef","isEditable","prevPropsRef","instructions","prevModeRef","propsInstructions","propsListStyle","basicValue","propsChanged","modeChanged","formValueChanged","formValueWasEmpty","formValueNowHasData","decodeHtml","str","fromCharCode","parseInt","decodedInstructions","inst","hasHtml","expectedContent","listTag","listItems","innerHTML","currentEditorContent","handleContentChange","content","executeCommand","command","execCommand","focus","handleBold","handleItalic","handleColorChange","handleListStyleChange","selection","getSelection","range","rangeCount","getRangeAt","currentContent","lines","line","removeAllRanges","addRange","handleImageUpload","reader","FileReader","imageUrl","createElement","deleteContents","insertNode","appendChild","readAsDataURL","handlePaste","clipboardData","getData","textNode","createTextNode","setStartAfter","collapse","isCommandActive","queryCommandState","Bold","Italic","List","ListOrdered","contentEditable","onInput","onPaste","suppressContentEditableWarning","dangerouslySetInnerHTML","__html","AttachmentThumbnails","onRemove","objectUrls","setObjectUrls","newUrls","isImage","objectUrl","Paperclip","ComponentActionFeatures","onNotesChange","onAttachmentChange","onThresholdActionCompletion","onBasicPropertyActionCompletion","localNotes","setLocalNotes","localAttachments","setLocalAttachments","showNotesInput","setShowNotesInput","emailSent","setEmailSent","setIssueRaised","actionsExpanded","setActionsExpanded","previousFormValueRef","notesInitializedRef","attachmentsInitializedRef","notesStr","isOptionBasedComponent","valueChanged","prevArray","currArray","conditionValue","stringValue","stringConditionValue","getActiveThresholdConditions","activeConditions","matchingCondition","cond","handleNotesChange","isCompleted","enableNotes","componentCondition","handleNotesSave","handleNotesBlur","handleNotesKeyDown","ctrlKey","metaKey","handleNotesIconClick","handleNotesSummaryClick","handleAttachmentIconClick","handleFileChange","enableAttachment","handleRemoveAttachment","newAttachments","_","handleSendEmailClick","enableSendEmail","enableRaiseIssue","componentOptions","selectedOption","hasValidFormValue","hasThresholdConditions","componentBasic","componentLevelNotes","componentLevelAttachment","componentLevelRaiseIssue","componentLevelSendEmail","opt","optionNotes","optionAttachment","optionRaiseIssue","optionSendEmail","hasComponentThresholdConditions","isNotesMandatory","isAttachmentsMandatory","isSendEmailMandatory","isRaiseIssueMandatory","hasNotes","hasAttachments","attachmentCount","Check","Mail","AlertCircle","ChevronUp","ChevronDown","onKeyDown","autoFocus","SubmissionAttachmentThumbnails","attachment","imageSrc","getImageSrc","ComponentSubmissionActions","DraggableChild","selectedChild","onChildSelect","onChildDelete","renderFormComponent","isOverlay","isChildrenEditMode","formData","hasSubmissionData","setNodeRef","isSorting","useSortable","CSS","Transform","role","GripVertical","Edit","Trash2","DfFormSection","onSelect","onSectionSelect","isCollapsed","setIsCollapsed","collapsed","isEditingTitle","setIsEditingTitle","isEditingDescription","setIsEditingDescription","sectionTitle","setSectionTitle","sectionDescription","setSectionDescription","setChildren","setIsChildrenEditMode","isOver","useDroppable","shouldHideInCurrentMode","handleTitleChange","newTitle","handleDescriptionChange","newDescription","handleChildSelect","handleChildDelete","newChildren","handleSectionSelect","handleSectionDoubleClick","toggleCollapse","renderComponent","field","commonProps","selectProps","checkboxProps","radioProps","sectionStyles","borderWidth","margin","onDoubleClick","marginRight","alignItems","ChevronRight","SortableContext","items","strategy","verticalListSortingStrategy","flexDirection","gap","DraggableGridComponent","selectedComponent","onComponentSelect","onComponentDelete","onComponentEdit","opacity","boxShadow","justifyContent","paddingTop","paddingLeft","GridDropZone","gridComponents","onComponentUpdate","gridId","horizontalListSortingStrategy","flexWrap","marginBottom","overflowX","flex","TableView","templateComponents","dataEntries","internalRenderComponent","allowAddRemoveEntries","addAnotherText","removeText","maxEntries","minEntries","displayAsGrid","onAddEntry","onRemoveEntry","_formData","datagridId","overflowY","scrollbarWidth","scrollbarColor","gridTemplateColumns","borderBottom","borderRight","whiteSpace","textOverflow","entry","entryIndex","isolation","templateComponent","componentIndex","entryComponent","components","expectedUniqueId","showLabel","pointerEvents","borderTop","paddingBottom","textTransform","letterSpacing","DfFormDataGrid","onDataGridSelect","onEntryAdd","onEntryRemove","hasInitialized","firstEntry","baseComponentId","expectedId","updatedEntries","templateComp","existingComponent","hasProperId","needsPropertyUpdate","updatedComponents","uniqueId","handleDataGridClick","handleComponentDelete","entryComp","handleComponentUpdate","updates","handleComponentValueChange","handleAddEntry","currentEntries","newEntryIndex","newEntry","uniqueComponentId","handleRemoveEntry","gridStyle","Grid","marginTop","datagrid","DfFormTable","lazy","Promise","resolve","then","dfFormTable","DfFormPreview","formComponents","currentDevice","isPreviewMode","initialFormData","onFormDataChange","formTitle","formDescription","setFormValues","setValidationErrors","setFormSubmitted","setTouchedFields","componentVisibility","setComponentVisibility","setRaisedThresholdIssues","thresholdActionCompletions","setThresholdActionCompletions","thresholdValidationState","setThresholdValidationState","initializeFormState","initializeComponentValues","cells","row","_rowIndex","cell","_cellIndex","_entryIndex","instructionValue","initialValues","seenIds","validateComponentIds","evaluateComponentConditionalLogic","visibility","shouldShowComponent","onFormValueChange","componentsWithSameId","existingValue","oldValue","newFormValues","threshold","newSet","delete","updateComponentValue","updatedCell","updatedEntry","findComponentById","found","hasValue","onFormControlBlur","onFormControlFocus","isFormValid","getMetThresholdConditions","validateThresholdConditions","completions","notesCompleted","attachmentsCompleted","missingActions","handleThresholdIssueRaised","handleThresholdActionCompletion","completed","newMap","validateAllFields","handleSubmit","firstErrorField","errorElement","getElementById","thresholdValidation","firstUnmet","scrollIntoView","behavior","block","updateComponentValues","finalValue","updatedComponent","finalFormData","getPreviewClasses","componentIdCacheRef","componentCounterRef","finalComponentId","cacheKey","cachedId","componentsWithSameValue","segmentProps","instructionFormValue","Suspense","fallback","updatedCells","updatedCellComponents","cellComp","nestedComp","currentComponent","datagridValue","compIndex","fileFormValue","isOptionBased","columnClass","column","getColumnClass","hasActionFeatures","DfFormComments","comment","onSave","isExpanded","setIsExpanded","currentComment","setCurrentComment","hasChanges","setHasChanges","handleInputChange","handleInputBlur","handleInputFocus","toggleComments","ensureComponentHasId","uuidv4","SimpleTableComponent","DraggableTableComponent","TableCellComponent","tableId","dropZoneId","cellStyle","verticalAlign","componentWithId","onTableSelect","hasAnyComponents","table","columns","handleTableClick","filteredComponents","cellsWithIds","rowIndex","cellIndex","tableStyle","tableElementStyle","borderCollapse","tableLayout","Table","displayAsTable","showColumns","colIndex","columnName","columnNames","headerBackgroundColor","headerTextColor","ELabelAlignment"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../node_modules/react/jsx-runtime.js","../node_modules/react/cjs/react-jsx-runtime.production.min.js","../node_modules/react/cjs/react-jsx-runtime.development.js","../src/services/conditionalLogicService.ts","../src/services/toast.service.ts","../src/df-form-controls/df-form-error-msg/DfFormErrorMsg.tsx","../src/components/RaiseIssueModal.tsx","../src/ThresholdAlert.tsx","../src/df-form-controls/df-form-input/DfFormInput.tsx","../src/df-form-controls/df-form-textarea/DfFormTextarea.tsx","../src/df-form-controls/df-form-select/DfFormSelect.tsx","../src/df-form-controls/df-form-checkbox/DfFormCheckbox.tsx","../src/df-form-controls/df-form-radio/DfFormRadio.tsx","../src/df-form-controls/df-form-segment/DfFormSegment.tsx","../src/df-form-controls/df-form-date-time/DfFormDateTime.tsx","../src/df-form-controls/df-form-signature/DfFormSignature.tsx","../src/df-form-controls/df-form-file-upload/DfFormFileUpload.tsx","../src/df-form-controls/df-form-location/DfFormLocation.tsx","../src/df-form-controls/df-form-heading/DfFormHeading.tsx","../src/df-form-controls/df-form-instruction/DfFormInstruction.tsx","../src/ComponentActionFeatures.tsx","../src/components/ComponentSubmissionActions.tsx","../src/df-form-controls/df-form-section/df-form-section.tsx","../src/df-form-controls/df-form-grid/df-form-grid.tsx","../src/DfFormPreview.tsx","../src/df-form-controls/df-form-comments/DfFormComments.tsx","../src/df-form-controls/df-form-table/df-form-table.tsx","../src/types/form-builder-schema.model.ts"],"sourcesContent":["'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.min.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n","/**\n * @license React\n * react-jsx-runtime.production.min.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n'use strict';var f=require(\"react\"),k=Symbol.for(\"react.element\"),l=Symbol.for(\"react.fragment\"),m=Object.prototype.hasOwnProperty,n=f.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,p={key:!0,ref:!0,__self:!0,__source:!0};\nfunction q(c,a,g){var b,d={},e=null,h=null;void 0!==g&&(e=\"\"+g);void 0!==a.key&&(e=\"\"+a.key);void 0!==a.ref&&(h=a.ref);for(b in a)m.call(a,b)&&!p.hasOwnProperty(b)&&(d[b]=a[b]);if(c&&c.defaultProps)for(b in a=c.defaultProps,a)void 0===d[b]&&(d[b]=a[b]);return{$$typeof:k,type:c,key:e,ref:h,props:d,_owner:n.current}}exports.Fragment=l;exports.jsx=q;exports.jsxs=q;\n","/**\n * @license React\n * react-jsx-runtime.development.js\n *\n * Copyright (c) Facebook, Inc. and its affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n'use strict';\n\nif (process.env.NODE_ENV !== \"production\") {\n (function() {\n'use strict';\n\nvar React = require('react');\n\n// ATTENTION\n// When adding new symbols to this file,\n// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'\n// The Symbol used to tag the ReactElement-like types.\nvar REACT_ELEMENT_TYPE = Symbol.for('react.element');\nvar REACT_PORTAL_TYPE = Symbol.for('react.portal');\nvar REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');\nvar REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');\nvar REACT_PROFILER_TYPE = Symbol.for('react.profiler');\nvar REACT_PROVIDER_TYPE = Symbol.for('react.provider');\nvar REACT_CONTEXT_TYPE = Symbol.for('react.context');\nvar REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');\nvar REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');\nvar REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');\nvar REACT_MEMO_TYPE = Symbol.for('react.memo');\nvar REACT_LAZY_TYPE = Symbol.for('react.lazy');\nvar REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nvar FAUX_ITERATOR_SYMBOL = '@@iterator';\nfunction getIteratorFn(maybeIterable) {\n if (maybeIterable === null || typeof maybeIterable !== 'object') {\n return null;\n }\n\n var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL];\n\n if (typeof maybeIterator === 'function') {\n return maybeIterator;\n }\n\n return null;\n}\n\nvar ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;\n\nfunction error(format) {\n {\n {\n for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n printWarning('error', format, args);\n }\n }\n}\n\nfunction printWarning(level, format, args) {\n // When changing this logic, you might want to also\n // update consoleWithStackDev.www.js as well.\n {\n var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n var stack = ReactDebugCurrentFrame.getStackAddendum();\n\n if (stack !== '') {\n format += '%s';\n args = args.concat([stack]);\n } // eslint-disable-next-line react-internal/safe-string-coercion\n\n\n var argsWithFormat = args.map(function (item) {\n return String(item);\n }); // Careful: RN currently depends on this prefix\n\n argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it\n // breaks IE9: https://github.com/facebook/react/issues/13610\n // eslint-disable-next-line react-internal/no-production-logging\n\n Function.prototype.apply.call(console[level], console, argsWithFormat);\n }\n}\n\n// -----------------------------------------------------------------------------\n\nvar enableScopeAPI = false; // Experimental Create Event Handle API.\nvar enableCacheElement = false;\nvar enableTransitionTracing = false; // No known bugs, but needs performance testing\n\nvar enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber\n// stuff. Intended to enable React core members to more easily debug scheduling\n// issues in DEV builds.\n\nvar enableDebugTracing = false; // Track which Fiber(s) schedule render work.\n\nvar REACT_MODULE_REFERENCE;\n\n{\n REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');\n}\n\nfunction isValidElementType(type) {\n if (typeof type === 'string' || typeof type === 'function') {\n return true;\n } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).\n\n\n if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {\n return true;\n }\n\n if (typeof type === 'object' && type !== null) {\n if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object\n // types supported by any Flight configuration anywhere since\n // we don't know which Flight build this will end up being used\n // with.\n type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction getWrappedName(outerType, innerType, wrapperName) {\n var displayName = outerType.displayName;\n\n if (displayName) {\n return displayName;\n }\n\n var functionName = innerType.displayName || innerType.name || '';\n return functionName !== '' ? wrapperName + \"(\" + functionName + \")\" : wrapperName;\n} // Keep in sync with react-reconciler/getComponentNameFromFiber\n\n\nfunction getContextName(type) {\n return type.displayName || 'Context';\n} // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead.\n\n\nfunction getComponentNameFromType(type) {\n if (type == null) {\n // Host root, text node or just invalid type.\n return null;\n }\n\n {\n if (typeof type.tag === 'number') {\n error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.');\n }\n }\n\n if (typeof type === 'function') {\n return type.displayName || type.name || null;\n }\n\n if (typeof type === 'string') {\n return type;\n }\n\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return 'Fragment';\n\n case REACT_PORTAL_TYPE:\n return 'Portal';\n\n case REACT_PROFILER_TYPE:\n return 'Profiler';\n\n case REACT_STRICT_MODE_TYPE:\n return 'StrictMode';\n\n case REACT_SUSPENSE_TYPE:\n return 'Suspense';\n\n case REACT_SUSPENSE_LIST_TYPE:\n return 'SuspenseList';\n\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_CONTEXT_TYPE:\n var context = type;\n return getContextName(context) + '.Consumer';\n\n case REACT_PROVIDER_TYPE:\n var provider = type;\n return getContextName(provider._context) + '.Provider';\n\n case REACT_FORWARD_REF_TYPE:\n return getWrappedName(type, type.render, 'ForwardRef');\n\n case REACT_MEMO_TYPE:\n var outerName = type.displayName || null;\n\n if (outerName !== null) {\n return outerName;\n }\n\n return getComponentNameFromType(type.type) || 'Memo';\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n return getComponentNameFromType(init(payload));\n } catch (x) {\n return null;\n }\n }\n\n // eslint-disable-next-line no-fallthrough\n }\n }\n\n return null;\n}\n\nvar assign = Object.assign;\n\n// Helpers to patch console.logs to avoid logging during side-effect free\n// replaying on render function. This currently only patches the object\n// lazily which won't cover if the log function was extracted eagerly.\n// We could also eagerly patch the method.\nvar disabledDepth = 0;\nvar prevLog;\nvar prevInfo;\nvar prevWarn;\nvar prevError;\nvar prevGroup;\nvar prevGroupCollapsed;\nvar prevGroupEnd;\n\nfunction disabledLog() {}\n\ndisabledLog.__reactDisabledLog = true;\nfunction disableLogs() {\n {\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n prevLog = console.log;\n prevInfo = console.info;\n prevWarn = console.warn;\n prevError = console.error;\n prevGroup = console.group;\n prevGroupCollapsed = console.groupCollapsed;\n prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099\n\n var props = {\n configurable: true,\n enumerable: true,\n value: disabledLog,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n info: props,\n log: props,\n warn: props,\n error: props,\n group: props,\n groupCollapsed: props,\n groupEnd: props\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n disabledDepth++;\n }\n}\nfunction reenableLogs() {\n {\n disabledDepth--;\n\n if (disabledDepth === 0) {\n /* eslint-disable react-internal/no-production-logging */\n var props = {\n configurable: true,\n enumerable: true,\n writable: true\n }; // $FlowFixMe Flow thinks console is immutable.\n\n Object.defineProperties(console, {\n log: assign({}, props, {\n value: prevLog\n }),\n info: assign({}, props, {\n value: prevInfo\n }),\n warn: assign({}, props, {\n value: prevWarn\n }),\n error: assign({}, props, {\n value: prevError\n }),\n group: assign({}, props, {\n value: prevGroup\n }),\n groupCollapsed: assign({}, props, {\n value: prevGroupCollapsed\n }),\n groupEnd: assign({}, props, {\n value: prevGroupEnd\n })\n });\n /* eslint-enable react-internal/no-production-logging */\n }\n\n if (disabledDepth < 0) {\n error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.');\n }\n }\n}\n\nvar ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher;\nvar prefix;\nfunction describeBuiltInComponentFrame(name, source, ownerFn) {\n {\n if (prefix === undefined) {\n // Extract the VM specific prefix used by each line.\n try {\n throw Error();\n } catch (x) {\n var match = x.stack.trim().match(/\\n( *(at )?)/);\n prefix = match && match[1] || '';\n }\n } // We use the prefix to ensure our stacks line up with native stack frames.\n\n\n return '\\n' + prefix + name;\n }\n}\nvar reentry = false;\nvar componentFrameCache;\n\n{\n var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map;\n componentFrameCache = new PossiblyWeakMap();\n}\n\nfunction describeNativeComponentFrame(fn, construct) {\n // If something asked for a stack inside a fake render, it should get ignored.\n if ( !fn || reentry) {\n return '';\n }\n\n {\n var frame = componentFrameCache.get(fn);\n\n if (frame !== undefined) {\n return frame;\n }\n }\n\n var control;\n reentry = true;\n var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined.\n\n Error.prepareStackTrace = undefined;\n var previousDispatcher;\n\n {\n previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function\n // for warnings.\n\n ReactCurrentDispatcher.current = null;\n disableLogs();\n }\n\n try {\n // This should throw.\n if (construct) {\n // Something should be setting the props in the constructor.\n var Fake = function () {\n throw Error();\n }; // $FlowFixMe\n\n\n Object.defineProperty(Fake.prototype, 'props', {\n set: function () {\n // We use a throwing setter instead of frozen or non-writable props\n // because that won't throw in a non-strict mode function.\n throw Error();\n }\n });\n\n if (typeof Reflect === 'object' && Reflect.construct) {\n // We construct a different control for this case to include any extra\n // frames added by the construct call.\n try {\n Reflect.construct(Fake, []);\n } catch (x) {\n control = x;\n }\n\n Reflect.construct(fn, [], Fake);\n } else {\n try {\n Fake.call();\n } catch (x) {\n control = x;\n }\n\n fn.call(Fake.prototype);\n }\n } else {\n try {\n throw Error();\n } catch (x) {\n control = x;\n }\n\n fn();\n }\n } catch (sample) {\n // This is inlined manually because closure doesn't do it for us.\n if (sample && control && typeof sample.stack === 'string') {\n // This extracts the first frame from the sample that isn't also in the control.\n // Skipping one frame that we assume is the frame that calls the two.\n var sampleLines = sample.stack.split('\\n');\n var controlLines = control.stack.split('\\n');\n var s = sampleLines.length - 1;\n var c = controlLines.length - 1;\n\n while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) {\n // We expect at least one stack frame to be shared.\n // Typically this will be the root most one. However, stack frames may be\n // cut off due to maximum stack limits. In this case, one maybe cut off\n // earlier than the other. We assume that the sample is longer or the same\n // and there for cut off earlier. So we should find the root most frame in\n // the sample somewhere in the control.\n c--;\n }\n\n for (; s >= 1 && c >= 0; s--, c--) {\n // Next we find the first one that isn't the same which should be the\n // frame that called our sample function and the control.\n if (sampleLines[s] !== controlLines[c]) {\n // In V8, the first line is describing the message but other VMs don't.\n // If we're about to return the first line, and the control is also on the same\n // line, that's a pretty good indicator that our sample threw at same line as\n // the control. I.e. before we entered the sample frame. So we ignore this result.\n // This can happen if you passed a class to function component, or non-function.\n if (s !== 1 || c !== 1) {\n do {\n s--;\n c--; // We may still have similar intermediate frames from the construct call.\n // The next one that isn't the same should be our match though.\n\n if (c < 0 || sampleLines[s] !== controlLines[c]) {\n // V8 adds a \"new\" prefix for native classes. Let's remove it to make it prettier.\n var _frame = '\\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled \"<anonymous>\"\n // but we have a user-provided \"displayName\"\n // splice it in to make the stack more readable.\n\n\n if (fn.displayName && _frame.includes('<anonymous>')) {\n _frame = _frame.replace('<anonymous>', fn.displayName);\n }\n\n {\n if (typeof fn === 'function') {\n componentFrameCache.set(fn, _frame);\n }\n } // Return the line we found.\n\n\n return _frame;\n }\n } while (s >= 1 && c >= 0);\n }\n\n break;\n }\n }\n }\n } finally {\n reentry = false;\n\n {\n ReactCurrentDispatcher.current = previousDispatcher;\n reenableLogs();\n }\n\n Error.prepareStackTrace = previousPrepareStackTrace;\n } // Fallback to just using the name if we couldn't make it throw.\n\n\n var name = fn ? fn.displayName || fn.name : '';\n var syntheticFrame = name ? describeBuiltInComponentFrame(name) : '';\n\n {\n if (typeof fn === 'function') {\n componentFrameCache.set(fn, syntheticFrame);\n }\n }\n\n return syntheticFrame;\n}\nfunction describeFunctionComponentFrame(fn, source, ownerFn) {\n {\n return describeNativeComponentFrame(fn, false);\n }\n}\n\nfunction shouldConstruct(Component) {\n var prototype = Component.prototype;\n return !!(prototype && prototype.isReactComponent);\n}\n\nfunction describeUnknownElementTypeFrameInDEV(type, source, ownerFn) {\n\n if (type == null) {\n return '';\n }\n\n if (typeof type === 'function') {\n {\n return describeNativeComponentFrame(type, shouldConstruct(type));\n }\n }\n\n if (typeof type === 'string') {\n return describeBuiltInComponentFrame(type);\n }\n\n switch (type) {\n case REACT_SUSPENSE_TYPE:\n return describeBuiltInComponentFrame('Suspense');\n\n case REACT_SUSPENSE_LIST_TYPE:\n return describeBuiltInComponentFrame('SuspenseList');\n }\n\n if (typeof type === 'object') {\n switch (type.$$typeof) {\n case REACT_FORWARD_REF_TYPE:\n return describeFunctionComponentFrame(type.render);\n\n case REACT_MEMO_TYPE:\n // Memo may contain any component type so we recursively resolve it.\n return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn);\n\n case REACT_LAZY_TYPE:\n {\n var lazyComponent = type;\n var payload = lazyComponent._payload;\n var init = lazyComponent._init;\n\n try {\n // Lazy may contain any component type so we recursively resolve it.\n return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn);\n } catch (x) {}\n }\n }\n }\n\n return '';\n}\n\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\n\nvar loggedTypeFailures = {};\nvar ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement(element) {\n {\n if (element) {\n var owner = element._owner;\n var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n ReactDebugCurrentFrame.setExtraStackFrame(stack);\n } else {\n ReactDebugCurrentFrame.setExtraStackFrame(null);\n }\n }\n}\n\nfunction checkPropTypes(typeSpecs, values, location, componentName, element) {\n {\n // $FlowFixMe This is okay but Flow doesn't know it.\n var has = Function.call.bind(hasOwnProperty);\n\n for (var typeSpecName in typeSpecs) {\n if (has(typeSpecs, typeSpecName)) {\n var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to\n // fail the render phase where it didn't fail before. So we log it.\n // After these have been cleaned up, we'll let them throw.\n\n try {\n // This is intentionally an invariant that gets caught. It's the same\n // behavior as without this statement except with a better message.\n if (typeof typeSpecs[typeSpecName] !== 'function') {\n // eslint-disable-next-line react-internal/prod-error-codes\n var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.');\n err.name = 'Invariant Violation';\n throw err;\n }\n\n error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED');\n } catch (ex) {\n error$1 = ex;\n }\n\n if (error$1 && !(error$1 instanceof Error)) {\n setCurrentlyValidatingElement(element);\n\n error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1);\n\n setCurrentlyValidatingElement(null);\n }\n\n if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) {\n // Only monitor this failure once because there tends to be a lot of the\n // same error.\n loggedTypeFailures[error$1.message] = true;\n setCurrentlyValidatingElement(element);\n\n error('Failed %s type: %s', location, error$1.message);\n\n setCurrentlyValidatingElement(null);\n }\n }\n }\n }\n}\n\nvar isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare\n\nfunction isArray(a) {\n return isArrayImpl(a);\n}\n\n/*\n * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol\n * and Temporal.* types. See https://github.com/facebook/react/pull/22064.\n *\n * The functions in this module will throw an easier-to-understand,\n * easier-to-debug exception with a clear errors message message explaining the\n * problem. (Instead of a confusing exception thrown inside the implementation\n * of the `value` object).\n */\n// $FlowFixMe only called in DEV, so void return is not possible.\nfunction typeName(value) {\n {\n // toStringTag is needed for namespaced types like Temporal.Instant\n var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag;\n var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object';\n return type;\n }\n} // $FlowFixMe only called in DEV, so void return is not possible.\n\n\nfunction willCoercionThrow(value) {\n {\n try {\n testStringCoercion(value);\n return false;\n } catch (e) {\n return true;\n }\n }\n}\n\nfunction testStringCoercion(value) {\n // If you ended up here by following an exception call stack, here's what's\n // happened: you supplied an object or symbol value to React (as a prop, key,\n // DOM attribute, CSS property, string ref, etc.) and when React tried to\n // coerce it to a string using `'' + value`, an exception was thrown.\n //\n // The most common types that will cause this exception are `Symbol` instances\n // and Temporal objects like `Temporal.Instant`. But any object that has a\n // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this\n // exception. (Library authors do this to prevent users from using built-in\n // numeric operators like `+` or comparison operators like `>=` because custom\n // methods are needed to perform accurate arithmetic or comparison.)\n //\n // To fix the problem, coerce this object or symbol value to a string before\n // passing it to React. The most reliable way is usually `String(value)`.\n //\n // To find which value is throwing, check the browser or debugger console.\n // Before this exception was thrown, there should be `console.error` output\n // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the\n // problem and how that type was used: key, atrribute, input value prop, etc.\n // In most cases, this console output also shows the component and its\n // ancestor components where the exception happened.\n //\n // eslint-disable-next-line react-internal/safe-string-coercion\n return '' + value;\n}\nfunction checkKeyStringCoercion(value) {\n {\n if (willCoercionThrow(value)) {\n error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value));\n\n return testStringCoercion(value); // throw (to help callers find troubleshooting comments)\n }\n }\n}\n\nvar ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner;\nvar RESERVED_PROPS = {\n key: true,\n ref: true,\n __self: true,\n __source: true\n};\nvar specialPropKeyWarningShown;\nvar specialPropRefWarningShown;\nvar didWarnAboutStringRefs;\n\n{\n didWarnAboutStringRefs = {};\n}\n\nfunction hasValidRef(config) {\n {\n if (hasOwnProperty.call(config, 'ref')) {\n var getter = Object.getOwnPropertyDescriptor(config, 'ref').get;\n\n if (getter && getter.isReactWarning) {\n return false;\n }\n }\n }\n\n return config.ref !== undefined;\n}\n\nfunction hasValidKey(config) {\n {\n if (hasOwnProperty.call(config, 'key')) {\n var getter = Object.getOwnPropertyDescriptor(config, 'key').get;\n\n if (getter && getter.isReactWarning) {\n return false;\n }\n }\n }\n\n return config.key !== undefined;\n}\n\nfunction warnIfStringRefCannotBeAutoConverted(config, self) {\n {\n if (typeof config.ref === 'string' && ReactCurrentOwner.current && self && ReactCurrentOwner.current.stateNode !== self) {\n var componentName = getComponentNameFromType(ReactCurrentOwner.current.type);\n\n if (!didWarnAboutStringRefs[componentName]) {\n error('Component \"%s\" contains the string ref \"%s\". ' + 'Support for string refs will be removed in a future major release. ' + 'This case cannot be automatically converted to an arrow function. ' + 'We ask you to manually fix this case by using useRef() or createRef() instead. ' + 'Learn more about using refs safely here: ' + 'https://reactjs.org/link/strict-mode-string-ref', getComponentNameFromType(ReactCurrentOwner.current.type), config.ref);\n\n didWarnAboutStringRefs[componentName] = true;\n }\n }\n }\n}\n\nfunction defineKeyPropWarningGetter(props, displayName) {\n {\n var warnAboutAccessingKey = function () {\n if (!specialPropKeyWarningShown) {\n specialPropKeyWarningShown = true;\n\n error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n }\n };\n\n warnAboutAccessingKey.isReactWarning = true;\n Object.defineProperty(props, 'key', {\n get: warnAboutAccessingKey,\n configurable: true\n });\n }\n}\n\nfunction defineRefPropWarningGetter(props, displayName) {\n {\n var warnAboutAccessingRef = function () {\n if (!specialPropRefWarningShown) {\n specialPropRefWarningShown = true;\n\n error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName);\n }\n };\n\n warnAboutAccessingRef.isReactWarning = true;\n Object.defineProperty(props, 'ref', {\n get: warnAboutAccessingRef,\n configurable: true\n });\n }\n}\n/**\n * Factory method to create a new React element. This no longer adheres to\n * the class pattern, so do not use new to call it. Also, instanceof check\n * will not work. Instead test $$typeof field against Symbol.for('react.element') to check\n * if something is a React Element.\n *\n * @param {*} type\n * @param {*} props\n * @param {*} key\n * @param {string|object} ref\n * @param {*} owner\n * @param {*} self A *temporary* helper to detect places where `this` is\n * different from the `owner` when React.createElement is called, so that we\n * can warn. We want to get rid of owner and replace string `ref`s with arrow\n * functions, and as long as `this` and owner are the same, there will be no\n * change in behavior.\n * @param {*} source An annotation object (added by a transpiler or otherwise)\n * indicating filename, line number, and/or other information.\n * @internal\n */\n\n\nvar ReactElement = function (type, key, ref, self, source, owner, props) {\n var element = {\n // This tag allows us to uniquely identify this as a React Element\n $$typeof: REACT_ELEMENT_TYPE,\n // Built-in properties that belong on the element\n type: type,\n key: key,\n ref: ref,\n props: props,\n // Record the component responsible for creating this element.\n _owner: owner\n };\n\n {\n // The validation flag is currently mutative. We put it on\n // an external backing store so that we can freeze the whole object.\n // This can be replaced with a WeakMap once they are implemented in\n // commonly used development environments.\n element._store = {}; // To make comparing ReactElements easier for testing purposes, we make\n // the validation flag non-enumerable (where possible, which should\n // include every environment we run tests in), so the test framework\n // ignores it.\n\n Object.defineProperty(element._store, 'validated', {\n configurable: false,\n enumerable: false,\n writable: true,\n value: false\n }); // self and source are DEV only properties.\n\n Object.defineProperty(element, '_self', {\n configurable: false,\n enumerable: false,\n writable: false,\n value: self\n }); // Two elements created in two different places should be considered\n // equal for testing purposes and therefore we hide it from enumeration.\n\n Object.defineProperty(element, '_source', {\n configurable: false,\n enumerable: false,\n writable: false,\n value: source\n });\n\n if (Object.freeze) {\n Object.freeze(element.props);\n Object.freeze(element);\n }\n }\n\n return element;\n};\n/**\n * https://github.com/reactjs/rfcs/pull/107\n * @param {*} type\n * @param {object} props\n * @param {string} key\n */\n\nfunction jsxDEV(type, config, maybeKey, source, self) {\n {\n var propName; // Reserved names are extracted\n\n var props = {};\n var key = null;\n var ref = null; // Currently, key can be spread in as a prop. This causes a potential\n // issue if key is also explicitly declared (ie. <div {...props} key=\"Hi\" />\n // or <div key=\"Hi\" {...props} /> ). We want to deprecate key spread,\n // but as an intermediary step, we will use jsxDEV for everything except\n // <div {...props} key=\"Hi\" />, because we aren't currently able to tell if\n // key is explicitly declared to be undefined or not.\n\n if (maybeKey !== undefined) {\n {\n checkKeyStringCoercion(maybeKey);\n }\n\n key = '' + maybeKey;\n }\n\n if (hasValidKey(config)) {\n {\n checkKeyStringCoercion(config.key);\n }\n\n key = '' + config.key;\n }\n\n if (hasValidRef(config)) {\n ref = config.ref;\n warnIfStringRefCannotBeAutoConverted(config, self);\n } // Remaining properties are added to a new props object\n\n\n for (propName in config) {\n if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) {\n props[propName] = config[propName];\n }\n } // Resolve default props\n\n\n if (type && type.defaultProps) {\n var defaultProps = type.defaultProps;\n\n for (propName in defaultProps) {\n if (props[propName] === undefined) {\n props[propName] = defaultProps[propName];\n }\n }\n }\n\n if (key || ref) {\n var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type;\n\n if (key) {\n defineKeyPropWarningGetter(props, displayName);\n }\n\n if (ref) {\n defineRefPropWarningGetter(props, displayName);\n }\n }\n\n return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props);\n }\n}\n\nvar ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner;\nvar ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame;\n\nfunction setCurrentlyValidatingElement$1(element) {\n {\n if (element) {\n var owner = element._owner;\n var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null);\n ReactDebugCurrentFrame$1.setExtraStackFrame(stack);\n } else {\n ReactDebugCurrentFrame$1.setExtraStackFrame(null);\n }\n }\n}\n\nvar propTypesMisspellWarningShown;\n\n{\n propTypesMisspellWarningShown = false;\n}\n/**\n * Verifies the object is a ReactElement.\n * See https://reactjs.org/docs/react-api.html#isvalidelement\n * @param {?object} object\n * @return {boolean} True if `object` is a ReactElement.\n * @final\n */\n\n\nfunction isValidElement(object) {\n {\n return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;\n }\n}\n\nfunction getDeclarationErrorAddendum() {\n {\n if (ReactCurrentOwner$1.current) {\n var name = getComponentNameFromType(ReactCurrentOwner$1.current.type);\n\n if (name) {\n return '\\n\\nCheck the render method of `' + name + '`.';\n }\n }\n\n return '';\n }\n}\n\nfunction getSourceInfoErrorAddendum(source) {\n {\n if (source !== undefined) {\n var fileName = source.fileName.replace(/^.*[\\\\\\/]/, '');\n var lineNumber = source.lineNumber;\n return '\\n\\nCheck your code at ' + fileName + ':' + lineNumber + '.';\n }\n\n return '';\n }\n}\n/**\n * Warn if there's no key explicitly set on dynamic arrays of children or\n * object keys are not valid. This allows us to keep track of children between\n * updates.\n */\n\n\nvar ownerHasKeyUseWarning = {};\n\nfunction getCurrentComponentErrorInfo(parentType) {\n {\n var info = getDeclarationErrorAddendum();\n\n if (!info) {\n var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name;\n\n if (parentName) {\n info = \"\\n\\nCheck the top-level render call using <\" + parentName + \">.\";\n }\n }\n\n return info;\n }\n}\n/**\n * Warn if the element doesn't have an explicit key assigned to it.\n * This element is in an array. The array could grow and shrink or be\n * reordered. All children that haven't already been validated are required to\n * have a \"key\" property assigned to it. Error statuses are cached so a warning\n * will only be shown once.\n *\n * @internal\n * @param {ReactElement} element Element that requires a key.\n * @param {*} parentType element's parent's type.\n */\n\n\nfunction validateExplicitKey(element, parentType) {\n {\n if (!element._store || element._store.validated || element.key != null) {\n return;\n }\n\n element._store.validated = true;\n var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);\n\n if (ownerHasKeyUseWarning[currentComponentErrorInfo]) {\n return;\n }\n\n ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a\n // property, it may be the creator of the child that's responsible for\n // assigning it a key.\n\n var childOwner = '';\n\n if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) {\n // Give the component that originally created this child.\n childOwner = \" It was passed a child from \" + getComponentNameFromType(element._owner.type) + \".\";\n }\n\n setCurrentlyValidatingElement$1(element);\n\n error('Each child in a list should have a unique \"key\" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner);\n\n setCurrentlyValidatingElement$1(null);\n }\n}\n/**\n * Ensure that every element either is passed in a static location, in an\n * array with an explicit keys property defined, or in an object literal\n * with valid key property.\n *\n * @internal\n * @param {ReactNode} node Statically passed child of any type.\n * @param {*} parentType node's parent's type.\n */\n\n\nfunction validateChildKeys(node, parentType) {\n {\n if (typeof node !== 'object') {\n return;\n }\n\n if (isArray(node)) {\n for (var i = 0; i < node.length; i++) {\n var child = node[i];\n\n if (isValidElement(child)) {\n validateExplicitKey(child, parentType);\n }\n }\n } else if (isValidElement(node)) {\n // This element was passed in a valid location.\n if (node._store) {\n node._store.validated = true;\n }\n } else if (node) {\n var iteratorFn = getIteratorFn(node);\n\n if (typeof iteratorFn === 'function') {\n // Entry iterators used to provide implicit keys,\n // but now we print a separate warning for them later.\n if (iteratorFn !== node.entries) {\n var iterator = iteratorFn.call(node);\n var step;\n\n while (!(step = iterator.next()).done) {\n if (isValidElement(step.value)) {\n validateExplicitKey(step.value, parentType);\n }\n }\n }\n }\n }\n }\n}\n/**\n * Given an element, validate that its props follow the propTypes definition,\n * provided by the type.\n *\n * @param {ReactElement} element\n */\n\n\nfunction validatePropTypes(element) {\n {\n var type = element.type;\n\n if (type === null || type === undefined || typeof type === 'string') {\n return;\n }\n\n var propTypes;\n\n if (typeof type === 'function') {\n propTypes = type.propTypes;\n } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here.\n // Inner props are checked in the reconciler.\n type.$$typeof === REACT_MEMO_TYPE)) {\n propTypes = type.propTypes;\n } else {\n return;\n }\n\n if (propTypes) {\n // Intentionally inside to avoid triggering lazy initializers:\n var name = getComponentNameFromType(type);\n checkPropTypes(propTypes, element.props, 'prop', name, element);\n } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) {\n propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers:\n\n var _name = getComponentNameFromType(type);\n\n error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown');\n }\n\n if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) {\n error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.');\n }\n }\n}\n/**\n * Given a fragment, validate that it can only be provided with fragment props\n * @param {ReactElement} fragment\n */\n\n\nfunction validateFragmentProps(fragment) {\n {\n var keys = Object.keys(fragment.props);\n\n for (var i = 0; i < keys.length; i++) {\n var key = keys[i];\n\n if (key !== 'children' && key !== 'key') {\n setCurrentlyValidatingElement$1(fragment);\n\n error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key);\n\n setCurrentlyValidatingElement$1(null);\n break;\n }\n }\n\n if (fragment.ref !== null) {\n setCurrentlyValidatingElement$1(fragment);\n\n error('Invalid attribute `ref` supplied to `React.Fragment`.');\n\n setCurrentlyValidatingElement$1(null);\n }\n }\n}\n\nvar didWarnAboutKeySpread = {};\nfunction jsxWithValidation(type, props, key, isStaticChildren, source, self) {\n {\n var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to\n // succeed and there will likely be errors in render.\n\n if (!validType) {\n var info = '';\n\n if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) {\n info += ' You likely forgot to export your component from the file ' + \"it's defined in, or you might have mixed up default and named imports.\";\n }\n\n var sourceInfo = getSourceInfoErrorAddendum(source);\n\n if (sourceInfo) {\n info += sourceInfo;\n } else {\n info += getDeclarationErrorAddendum();\n }\n\n var typeString;\n\n if (type === null) {\n typeString = 'null';\n } else if (isArray(type)) {\n typeString = 'array';\n } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {\n typeString = \"<\" + (getComponentNameFromType(type.type) || 'Unknown') + \" />\";\n info = ' Did you accidentally export a JSX literal instead of a component?';\n } else {\n typeString = typeof type;\n }\n\n error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info);\n }\n\n var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used.\n // TODO: Drop this when these are no longer allowed as the type argument.\n\n if (element == null) {\n return element;\n } // Skip key warning if the type isn't valid since our key validation logic\n // doesn't expect a non-string/function type and can throw confusing errors.\n // We don't want exception behavior to differ between dev and prod.\n // (Rendering will throw with a helpful message and as soon as the type is\n // fixed, the key warnings will appear.)\n\n\n if (validType) {\n var children = props.children;\n\n if (children !== undefined) {\n if (isStaticChildren) {\n if (isArray(children)) {\n for (var i = 0; i < children.length; i++) {\n validateChildKeys(children[i], type);\n }\n\n if (Object.freeze) {\n Object.freeze(children);\n }\n } else {\n error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.');\n }\n } else {\n validateChildKeys(children, type);\n }\n }\n }\n\n {\n if (hasOwnProperty.call(props, 'key')) {\n var componentName = getComponentNameFromType(type);\n var keys = Object.keys(props).filter(function (k) {\n return k !== 'key';\n });\n var beforeExample = keys.length > 0 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}' : '{key: someKey}';\n\n if (!didWarnAboutKeySpread[componentName + beforeExample]) {\n var afterExample = keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}';\n\n error('A props object containing a \"key\" prop is being spread into JSX:\\n' + ' let props = %s;\\n' + ' <%s {...props} />\\n' + 'React keys must be passed directly to JSX without using spread:\\n' + ' let props = %s;\\n' + ' <%s key={someKey} {...props} />', beforeExample, componentName, afterExample, componentName);\n\n didWarnAboutKeySpread[componentName + beforeExample] = true;\n }\n }\n }\n\n if (type === REACT_FRAGMENT_TYPE) {\n validateFragmentProps(element);\n } else {\n validatePropTypes(element);\n }\n\n return element;\n }\n} // These two functions exist to still get child warnings in dev\n// even with the prod transform. This means that jsxDEV is purely\n// opt-in behavior for better messages but that we won't stop\n// giving you warnings if you use production apis.\n\nfunction jsxWithValidationStatic(type, props, key) {\n {\n return jsxWithValidation(type, props, key, true);\n }\n}\nfunction jsxWithValidationDynamic(type, props, key) {\n {\n return jsxWithValidation(type, props, key, false);\n }\n}\n\nvar jsx = jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children.\n// for now we can ship identical prod functions\n\nvar jsxs = jsxWithValidationStatic ;\n\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsx;\nexports.jsxs = jsxs;\n })();\n}\n","import { FormComponentType, ICondition, IConditionalLogic } from '../df-form-controls/df-form-preview-interfaces';\r\n\r\nexport interface IAvailableComponent {\r\n id: string;\r\n label: string;\r\n type: string;\r\n key: string;\r\n}\r\n\r\nexport interface IConditionalEvaluationResult {\r\n shouldShow: boolean;\r\n evaluatedConditions: Array<{\r\n condition: ICondition;\r\n result: boolean;\r\n componentValue: any;\r\n }>;\r\n}\r\n\r\nexport class ConditionalLogicService {\r\n private static instance: ConditionalLogicService;\r\n\r\n private constructor() {}\r\n\r\n public static getInstance(): ConditionalLogicService {\r\n if (!ConditionalLogicService.instance) {\r\n ConditionalLogicService.instance = new ConditionalLogicService();\r\n }\r\n return ConditionalLogicService.instance;\r\n }\r\n\r\n getAvailableComponentsForConditional(\r\n formSchema: FormComponentType[], \r\n excludeComponentId?: string\r\n ): IAvailableComponent[] {\r\n \r\n if (!formSchema || !Array.isArray(formSchema)) {\r\n return [];\r\n }\r\n\r\n const availableComponents = formSchema\r\n .filter(component => !excludeComponentId || component.id !== excludeComponentId)\r\n .map(component => {\r\n const mappedComponent = {\r\n id: component.id,\r\n label: component.basic?.label || component.id,\r\n type: component.name,\r\n key: component.id\r\n };\r\n return mappedComponent;\r\n })\r\n .sort((a, b) => a.label.localeCompare(b.label));\r\n \r\n return availableComponents;\r\n }\r\n\r\n public getApplicableOperators(componentType: string): string[] {\r\n switch (componentType) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'textarea':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'contains',\r\n 'notContains',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'number-input':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'greaterThan',\r\n 'lessThan',\r\n 'greaterThanOrEqual',\r\n 'lessThanOrEqual',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'select':\r\n case 'radio':\r\n case 'segment':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'checkbox':\r\n return [\r\n 'contains',\r\n 'notContains',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n case 'date-picker':\r\n case 'datetime-picker':\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'greaterThan',\r\n 'lessThan',\r\n 'greaterThanOrEqual',\r\n 'lessThanOrEqual',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n\r\n default:\r\n return [\r\n 'equals',\r\n 'notEquals',\r\n 'isEmpty',\r\n 'isNotEmpty'\r\n ];\r\n }\r\n }\r\n\r\n public validateConditionalLogic(\r\n conditional: IConditionalLogic,\r\n formSchema: FormComponentType[]\r\n ): { isValid: boolean; errors: string[] } {\r\n const errors: string[] = [];\r\n\r\n if (!conditional) {\r\n return { isValid: true, errors: [] };\r\n }\r\n\r\n if (!['show', 'hide', 'always'].includes(conditional.action)) {\r\n errors.push('Invalid conditional action');\r\n }\r\n\r\n if (!['all', 'any'].includes(conditional.when)) {\r\n errors.push('Invalid when condition');\r\n }\r\n\r\n if (!conditional.conditions || conditional.conditions.length === 0) {\r\n errors.push('At least one condition is required');\r\n } else {\r\n conditional.conditions.forEach((condition, index) => {\r\n const component = formSchema.find(comp => comp.id === condition.when);\r\n if (!component) {\r\n errors.push(`Condition ${index + 1}: Component not found`);\r\n return;\r\n }\r\n\r\n const applicableOperators = this.getApplicableOperators(component.name);\r\n if (!applicableOperators.includes(condition.operator)) {\r\n errors.push(`Condition ${index + 1}: Operator not applicable for component type`);\r\n }\r\n\r\n if (!this.isValidConditionValue(condition.value, component.name, condition.operator)) {\r\n errors.push(`Condition ${index + 1}: Invalid condition value`);\r\n }\r\n });\r\n }\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors\r\n };\r\n }\r\n\r\n evaluateConditionalLogic(\r\n conditional: IConditionalLogic,\r\n formSchema: FormComponentType[],\r\n formValues: Record<string, any>\r\n ): IConditionalEvaluationResult {\r\n\r\n if (conditional.action === 'always') {\r\n return {\r\n shouldShow: true,\r\n evaluatedConditions: []\r\n };\r\n }\r\n\r\n if (!conditional || !conditional.conditions || conditional.conditions.length === 0) {\r\n return {\r\n shouldShow: true,\r\n evaluatedConditions: []\r\n };\r\n }\r\n\r\n const evaluatedConditions = conditional.conditions.map(condition => {\r\n const componentValue = this.getComponentValue(condition.when, formSchema, formValues);\r\n const result = this.evaluateCondition(condition, componentValue);\r\n \r\n return {\r\n condition,\r\n result,\r\n componentValue\r\n };\r\n });\r\n\r\n const shouldShow = this.determineFinalResult(conditional, evaluatedConditions);\r\n\r\n return {\r\n shouldShow,\r\n evaluatedConditions\r\n };\r\n }\r\n\r\n private getComponentValue(\r\n componentId: string, \r\n formSchema: FormComponentType[], \r\n formValues: Record<string, any>\r\n ): any {\r\n\r\n if (formValues && formValues[componentId] !== undefined) {\r\n return formValues[componentId];\r\n }\r\n\r\n const component = formSchema.find(comp => comp.id === componentId);\r\n if (component && 'defaultValue' in component.basic) {\r\n return component.basic.defaultValue;\r\n }\r\n\r\n return undefined;\r\n }\r\n\r\n private evaluateCondition(condition: ICondition, componentValue: any): boolean {\r\n const { operator, value } = condition;\r\n\r\n if (value === 'checked' || value === 'notChecked') {\r\n return this.evaluateCheckboxCondition(componentValue, value);\r\n }\r\n\r\n switch (operator) {\r\n case 'equals':\r\n return this.isEqual(componentValue, value);\r\n \r\n case 'notEquals':\r\n return !this.isEqual(componentValue, value);\r\n \r\n case 'isEmpty':\r\n return this.isEmpty(componentValue);\r\n \r\n case 'isNotEmpty':\r\n return !this.isEmpty(componentValue);\r\n \r\n case 'contains':\r\n return this.contains(componentValue, value);\r\n \r\n case 'notContains':\r\n return !this.contains(componentValue, value);\r\n \r\n case 'greaterThan':\r\n return this.isGreaterThan(componentValue, value);\r\n \r\n case 'lessThan':\r\n return this.isLessThan(componentValue, value);\r\n \r\n case 'greaterThanOrEqual':\r\n return this.isGreaterThanOrEqual(componentValue, value);\r\n \r\n case 'lessThanOrEqual':\r\n return this.isLessThanOrEqual(componentValue, value);\r\n \r\n default:\r\n return false;\r\n }\r\n }\r\n\r\n private evaluateCheckboxCondition(componentValue: any, expectedValue: string): boolean {\r\n const isChecked = this.isCheckboxChecked(componentValue);\r\n \r\n if (expectedValue === 'checked') {\r\n return isChecked;\r\n } else if (expectedValue === 'notChecked') {\r\n return !isChecked;\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private isCheckboxChecked(componentValue: any): boolean {\r\n if (componentValue === null || componentValue === undefined) {\r\n return false;\r\n }\r\n \r\n if (typeof componentValue === 'boolean') {\r\n return componentValue;\r\n }\r\n \r\n if (typeof componentValue === 'string') {\r\n return componentValue.toLowerCase() === 'true' || componentValue === '1';\r\n }\r\n \r\n if (Array.isArray(componentValue)) {\r\n return componentValue.length > 0;\r\n }\r\n \r\n if (typeof componentValue === 'number') {\r\n return componentValue > 0;\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private determineFinalResult(\r\n conditional: IConditionalLogic, \r\n evaluatedConditions: Array<{ result: boolean }>\r\n ): boolean {\r\n let conditionsMet: boolean;\r\n if (conditional.when === 'all') {\r\n conditionsMet = evaluatedConditions.every(condition => condition.result);\r\n } else if (conditional.when === 'any') {\r\n conditionsMet = evaluatedConditions.some(condition => condition.result);\r\n } else {\r\n conditionsMet = false;\r\n }\r\n \r\n let finalResult: boolean;\r\n if (conditional.action === 'show') {\r\n finalResult = conditionsMet;\r\n } else if (conditional.action === 'hide') {\r\n finalResult = !conditionsMet;\r\n } else if (conditional.action === 'always') {\r\n finalResult = true;\r\n } else {\r\n finalResult = true;\r\n }\r\n \r\n return finalResult;\r\n }\r\n\r\n private isEqual(a: any, b: any): boolean {\r\n if (a === b) return true;\r\n if (a == null || b == null) return false;\r\n \r\n if (Array.isArray(a) && Array.isArray(b)) {\r\n if (a.length !== b.length) return false;\r\n return a.every((val, index) => this.isEqual(val, b[index]));\r\n }\r\n \r\n if (typeof a === 'object' && typeof b === 'object') {\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n return keysA.every(key => this.isEqual(a[key], b[key]));\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private isEmpty(value: any): boolean {\r\n if (value == null || value === undefined) return true;\r\n if (typeof value === 'string') return value.trim() === '';\r\n if (Array.isArray(value)) return value.length === 0;\r\n if (typeof value === 'object') return Object.keys(value).length === 0;\r\n return false;\r\n }\r\n\r\n private contains(container: any, searchValue: any): boolean {\r\n if (container == null || searchValue == null) return false;\r\n \r\n if (typeof container === 'string') {\r\n return container.toLowerCase().includes(String(searchValue).toLowerCase());\r\n }\r\n \r\n if (Array.isArray(container)) {\r\n return container.some(item => this.isEqual(item, searchValue));\r\n }\r\n \r\n return false;\r\n }\r\n\r\n private isGreaterThan(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA > numB;\r\n }\r\n\r\n private isLessThan(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA < numB;\r\n }\r\n\r\n private isGreaterThanOrEqual(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA >= numB;\r\n }\r\n\r\n private isLessThanOrEqual(a: any, b: any): boolean {\r\n const numA = Number(a);\r\n const numB = Number(b);\r\n return !isNaN(numA) && !isNaN(numB) && numA <= numB;\r\n }\r\n\r\n private isValidConditionValue(value: any, componentType: string, operator: string): boolean {\r\n if (value === null || value === undefined) {\r\n return ['isEmpty', 'isNotEmpty'].includes(operator);\r\n }\r\n\r\n switch (componentType) {\r\n case 'number-input':\r\n return !isNaN(Number(value)) || ['isEmpty', 'isNotEmpty'].includes(operator);\r\n\r\n case 'date-picker':\r\n case 'datetime-picker':\r\n return !isNaN(Date.parse(value)) || ['isEmpty', 'isNotEmpty'].includes(operator);\r\n\r\n case 'checkbox':\r\n return Array.isArray(value) || typeof value === 'string' || typeof value === 'number';\r\n\r\n default:\r\n return true;\r\n }\r\n }\r\n\r\n public createDefaultConditionalLogic(): IConditionalLogic {\r\n return {\r\n action: 'show',\r\n when: 'all',\r\n conditions: []\r\n };\r\n }\r\n\r\n public getOperatorDisplayText(operator: string): string {\r\n const operatorTexts: Record<string, string> = {\r\n 'equals': 'Is Equal To',\r\n 'notEquals': 'Is Not Equal To',\r\n 'contains': 'Contains',\r\n 'notContains': 'Does Not Contain',\r\n 'isEmpty': 'Is Empty',\r\n 'isNotEmpty': 'Is Not Empty',\r\n 'greaterThan': 'Is Greater Than',\r\n 'lessThan': 'Is Less Than',\r\n 'greaterThanOrEqual': 'Is Greater Than Or Equal To',\r\n 'lessThanOrEqual': 'Is Less Than Or Equal To'\r\n };\r\n\r\n return operatorTexts[operator] || operator;\r\n }\r\n\r\n public getActionDisplayText(action: string): string {\r\n const actionTexts: Record<string, string> = {\r\n show: 'Show this field when',\r\n hide: 'Hide this field when',\r\n always: 'Always show this field'\r\n };\r\n\r\n return actionTexts[action] || action;\r\n }\r\n\r\n public getConditionalLogicSummary(conditional: IConditionalLogic, formSchema: FormComponentType[]): string {\r\n if (!conditional || conditional.conditions.length === 0) {\r\n return 'No conditions';\r\n }\r\n\r\n if (conditional.action === 'always') {\r\n return 'Always show';\r\n }\r\n\r\n const actionText = this.getActionDisplayText(conditional.action);\r\n const conditionTexts = conditional.conditions.map(condition => {\r\n const component = formSchema.find(comp => comp.id === condition.when);\r\n const componentLabel = component?.basic.label || 'Unknown component';\r\n const operatorText = this.getOperatorDisplayText(condition.operator);\r\n const valueText = this.formatConditionValue(condition.value);\r\n \r\n return `${componentLabel} ${operatorText} ${valueText}`;\r\n });\r\n\r\n const operatorText = conditional.when === 'all' ? ' and ' : ' or ';\r\n return `${actionText} ${conditionTexts.join(operatorText)}`;\r\n }\r\n\r\n private formatConditionValue(value: any): string {\r\n if (value === null || value === undefined) {\r\n return 'empty';\r\n }\r\n \r\n if (Array.isArray(value)) {\r\n return `[${value.join(', ')}]`;\r\n }\r\n \r\n if (typeof value === 'string') {\r\n return `\"${value}\"`;\r\n }\r\n \r\n return String(value);\r\n }\r\n}\r\n\r\nexport const conditionalLogicService = ConditionalLogicService.getInstance();\r\n\r\n","export interface IToast {\r\n id: string;\r\n message: string;\r\n type: 'success' | 'danger' | 'warning' | 'info';\r\n duration?: number;\r\n}\r\n\r\nclass ToastService {\r\n private toasts: IToast[] = [];\r\n private listeners: Array<(toasts: IToast[]) => void> = [];\r\n private defaultDuration = 3000;\r\n private timeouts: Record<string, NodeJS.Timeout> = {};\r\n\r\n private generateId(): string {\r\n return Date.now().toString(36) + Math.random().toString(36).substr(2);\r\n }\r\n\r\n private notifyListeners(): void {\r\n this.listeners.forEach(listener => listener([...this.toasts]));\r\n }\r\n\r\n private addToast(toast: IToast): void {\r\n try {\r\n this.toasts.push(toast);\r\n this.notifyListeners();\r\n\r\n this.timeouts[toast.id] = setTimeout(() => {\r\n this.removeToast(toast.id);\r\n }, toast.duration || this.defaultDuration);\r\n } catch (error) {\r\n console.error('Error displaying toast message:', error);\r\n }\r\n }\r\n\r\n removeToast(id: string): void {\r\n if (this.timeouts[id]) {\r\n clearTimeout(this.timeouts[id]);\r\n delete this.timeouts[id];\r\n }\r\n\r\n this.toasts = this.toasts.filter((toast) => toast.id !== id);\r\n this.notifyListeners();\r\n }\r\n\r\n showSuccess(message: string, duration = 3000): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'success',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n showError(message: string, duration = 5000): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'danger',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n showWarning(message: string, duration?: number): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'warning',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n showInfo(message: string, duration?: number): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type: 'info',\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n show(\r\n message: string,\r\n type: 'success' | 'danger' | 'warning' | 'info' = 'success',\r\n duration?: number,\r\n ): void {\r\n const toast: IToast = {\r\n id: this.generateId(),\r\n message,\r\n type,\r\n duration,\r\n };\r\n this.addToast(toast);\r\n }\r\n\r\n clearAll(): void {\r\n Object.values(this.timeouts).forEach((timeout) => clearTimeout(timeout));\r\n this.timeouts = {};\r\n this.toasts = [];\r\n this.notifyListeners();\r\n }\r\n\r\n subscribe(listener: (toasts: IToast[]) => void): () => void {\r\n this.listeners.push(listener);\r\n return () => {\r\n this.listeners = this.listeners.filter(l => l !== listener);\r\n };\r\n }\r\n\r\n getToasts(): IToast[] {\r\n return [...this.toasts];\r\n }\r\n}\r\n\r\nexport const toastService = new ToastService();\r\n\r\n","import React from 'react';\r\nimport { ErrorMessageProps } from '../df-form-preview-interfaces';\r\n\r\nexport const DfFormErrorMsg: React.FC<ErrorMessageProps> = ({\r\n validationErrors,\r\n fieldId,\r\n touchedFields,\r\n formSubmitted,\r\n properties,\r\n localValidation,\r\n isTouched: localIsTouched,\r\n mode,\r\n}) => {\r\n const getErrorMessage = (): string => {\r\n // Only show error messages in test mode\r\n if (mode !== 'test') {\r\n return '';\r\n }\r\n \r\n // Check if field is touched or form is submitted\r\n const isTouched = localIsTouched || touchedFields[fieldId] || formSubmitted;\r\n \r\n if (!isTouched) {\r\n return '';\r\n }\r\n\r\n // CRITICAL: Prioritize local validation - if local validation is valid, don't show any errors\r\n // This must be checked FIRST before any other error checks\r\n if (localValidation && localValidation.isValid) {\r\n return '';\r\n }\r\n\r\n // Show local validation errors if validation failed\r\n // CRITICAL: Only show errors if validation is actually invalid AND there are error keys\r\n if (localValidation && !localValidation.isValid && Object.keys(localValidation.errors).length > 0) {\r\n const errorKeys = Object.keys(localValidation.errors);\r\n // CRITICAL: Only show error if there's actually an error condition met\r\n // Filter out false/undefined error keys - only show errors that are explicitly true\r\n // Also filter out pattern errors that are false (deleted/cleared)\r\n const actualErrors = errorKeys.filter(key => {\r\n const errorValue = localValidation.errors[key];\r\n // Only include errors that are explicitly true\r\n return errorValue === true;\r\n });\r\n if (actualErrors.length > 0) {\r\n const firstError = actualErrors[0];\r\n // CRITICAL: Don't show custom message if the field is actually valid\r\n // Only show error message if validation is truly invalid\r\n return getDefaultErrorMessage(firstError);\r\n }\r\n }\r\n\r\n // Only check external validation errors if local validation doesn't exist or is not valid\r\n const fieldErrors = validationErrors[fieldId];\r\n if (fieldErrors && typeof fieldErrors === 'string' && fieldErrors.trim() !== '') {\r\n // For date/time components, check if we should use mode-specific message\r\n const componentName = (properties as any).name || '';\r\n const isDateTimeComponent = componentName === 'date-picker' || componentName === 'datetime-picker';\r\n if (isDateTimeComponent && fieldErrors.includes('valid date')) {\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n if (dateTimeMode === 'time') {\r\n return 'Please select a valid time';\r\n } else if (dateTimeMode === 'datetime') {\r\n return 'Please select a valid date and time';\r\n }\r\n }\r\n return fieldErrors;\r\n }\r\n\r\n return '';\r\n };\r\n\r\n const getDefaultErrorMessage = (errorType: string): string => {\r\n const fieldLabel = properties.basic.label || 'This field';\r\n \r\n // CRITICAL: Only use custom validation message if there's actually an error\r\n // Don't show custom message for valid fields\r\n const customMessage = properties.validation?.customValidationMessage;\r\n // Only use custom message if it exists and we have an actual error\r\n if (customMessage && customMessage.trim() !== '') {\r\n return customMessage;\r\n }\r\n \r\n // For date/time components, check dateTimeMode for appropriate error messages\r\n const componentName = (properties as any).name || '';\r\n const isDateTimeComponent = componentName === 'date-picker' || componentName === 'datetime-picker';\r\n const dateTimeMode = isDateTimeComponent ? ((properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date')) : null;\r\n \r\n switch (errorType) {\r\n case 'required':\r\n return `${fieldLabel} is required`;\r\n case 'invalidDate':\r\n // Show mode-specific error messages for date/time components\r\n if (dateTimeMode === 'time') {\r\n return 'Please select a valid time';\r\n } else if (dateTimeMode === 'datetime') {\r\n return 'Please select a valid date and time';\r\n } else if (dateTimeMode === 'date') {\r\n return 'Please select a valid date';\r\n }\r\n return `${fieldLabel} is invalid`;\r\n case 'minLength':\r\n const minLength = properties.validation.minLength;\r\n return `${fieldLabel} must be at least ${minLength} characters long`;\r\n case 'maxLength':\r\n const maxLength = properties.validation.maxLength;\r\n return `${fieldLabel} must be no more than ${maxLength} characters long`;\r\n case 'min':\r\n const min = properties.validation.min;\r\n return `${fieldLabel} must be at least ${min}`;\r\n case 'max':\r\n const max = properties.validation.max;\r\n return `${fieldLabel} must be no more than ${max}`;\r\n case 'lowerLimit':\r\n const numberValidation = properties.validation as any;\r\n const lowerLimit = numberValidation?.lowerLimit;\r\n return `You are under the limit. ${fieldLabel} must be at least ${lowerLimit}`;\r\n case 'upperLimit':\r\n const numberValidationUpper = properties.validation as any;\r\n const upperLimit = numberValidationUpper?.upperLimit;\r\n return `You crossed the limit. ${fieldLabel} must be no more than ${upperLimit}`;\r\n case 'pattern':\r\n return `${fieldLabel} format is invalid`;\r\n case 'email':\r\n return `${fieldLabel} must be a valid email address`;\r\n default:\r\n return `${fieldLabel} is invalid`;\r\n }\r\n };\r\n\r\n const errorMessage = getErrorMessage();\r\n\r\n if (!errorMessage) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"form-error-msg\">\r\n {errorMessage}\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormErrorMsg;\r\n","import React, { useState, useEffect } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { X, AlertTriangle, User, Calendar, MessageSquare } from 'lucide-react';\r\nimport { FormComponentType } from '../df-form-controls/df-form-preview-interfaces';\r\nimport { toastService } from '../services/toast.service';\r\nimport './RaiseIssueModal.scss';\r\n\r\n// Issue status enum\r\nenum EIssueStatus {\r\n OPEN = 'Open',\r\n IN_PROGRESS = 'In-Progress',\r\n REJECTED = 'Rejected',\r\n RESOLVE = 'Resolve'\r\n}\r\n\r\n// Issue interface\r\ninterface IIssue {\r\n _id?: string;\r\n issueNumber?: string;\r\n title?: string;\r\n description?: string;\r\n workOrderNumber?: string;\r\n assetNumber?: string;\r\n formTemplateId?: string;\r\n component?: FormComponentType;\r\n priority?: 'High' | 'Medium' | 'Low';\r\n status?: string;\r\n assignee?: string;\r\n comments?: string;\r\n createdAt?: string;\r\n}\r\n\r\ninterface IRaiseIssueModalProps {\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onSuccess?: (createdIssue?: IIssue) => void;\r\n component?: FormComponentType;\r\n formTemplateId?: string;\r\n notes?: string;\r\n attachments?: File[] | null;\r\n issue?: IIssue | null;\r\n // Optional API callbacks - if not provided, modal will just call onSuccess\r\n onCreateIssue?: (issueData: any, attachments: File[]) => Promise<IIssue>;\r\n onUpdateIssue?: (issueId: string, updateData: any) => Promise<void>;\r\n // Optional user info\r\n user?: {\r\n firstName?: string;\r\n lastName?: string;\r\n };\r\n // Optional available users list\r\n availableUsers?: string[];\r\n}\r\n\r\nexport const RaiseIssueModal: React.FC<IRaiseIssueModalProps> = ({\r\n isOpen,\r\n onClose,\r\n onSuccess,\r\n component,\r\n formTemplateId,\r\n notes = '',\r\n attachments = null,\r\n issue = null,\r\n onCreateIssue,\r\n onUpdateIssue,\r\n user,\r\n availableUsers = [\r\n 'Priya Das',\r\n 'Maria Garcia',\r\n 'John Smith',\r\n 'Sarah Johnson'\r\n ]\r\n}) => {\r\n const [title, setTitle] = useState<string>('');\r\n const [description, setDescription] = useState<string>('');\r\n const [workOrderNumber, setWorkOrderNumber] = useState<string>('');\r\n const [assetNumber, setAssetNumber] = useState<string>('');\r\n const [priority, setPriority] = useState<'High' | 'Medium' | 'Low'>('Medium');\r\n const [status, setStatus] = useState<string>(EIssueStatus.OPEN);\r\n const [assignee, setAssignee] = useState<string>('');\r\n const [comments, setComments] = useState<string>('');\r\n const [isSubmitting, setIsSubmitting] = useState<boolean>(false);\r\n\r\n const isEditMode = !!issue;\r\n\r\n useEffect(() => {\r\n if (isOpen) {\r\n if (issue) {\r\n // Edit mode: populate with issue data\r\n setTitle(issue.title || '');\r\n setDescription(issue.description || '');\r\n setWorkOrderNumber(issue.workOrderNumber || '');\r\n setAssetNumber(issue.assetNumber || '');\r\n setPriority(issue.priority || 'Medium');\r\n // Use enum value or default to OPEN\r\n const issueStatus = issue.status || EIssueStatus.OPEN;\r\n // Normalize to enum values if needed (handle legacy values)\r\n const normalizedStatus = \r\n issueStatus === EIssueStatus.OPEN || issueStatus === EIssueStatus.IN_PROGRESS || issueStatus === EIssueStatus.REJECTED || issueStatus === EIssueStatus.RESOLVE\r\n ? issueStatus\r\n : EIssueStatus.OPEN;\r\n setStatus(normalizedStatus);\r\n setAssignee(issue.assignee || '');\r\n setComments(issue.comments || '');\r\n } else if (component) {\r\n // Create mode: initialize form with component data\r\n const componentLabel = component.basic?.label || 'Component';\r\n setTitle(`${componentLabel} - Issue`);\r\n \r\n // Build description from component value and notes\r\n let desc = `Issue raised for component: ${componentLabel}`;\r\n if (component.basic && 'value' in component.basic && component.basic.value) {\r\n desc += `\\nComponent Value: ${component.basic.value}`;\r\n }\r\n if (notes) {\r\n desc += `\\nNotes: ${notes}`;\r\n }\r\n setDescription(desc);\r\n setComments(notes || '');\r\n }\r\n }\r\n }, [isOpen, component, notes, issue]);\r\n\r\n const updateIssueStatus = async (newStatus: string) => {\r\n if (!issue) return;\r\n\r\n setIsSubmitting(true);\r\n\r\n try {\r\n const updateData = {\r\n title: String(title || '').trim(),\r\n description: String(description || '').trim(),\r\n workOrderNumber: String(workOrderNumber || '').trim() || '',\r\n assetNumber: String(assetNumber || '').trim() || '',\r\n formTemplateId: issue.formTemplateId || '',\r\n component: issue.component || {},\r\n priority,\r\n assignee: String(assignee || '').trim() || undefined,\r\n status: newStatus,\r\n comments: String(comments || '').trim() || ''\r\n };\r\n\r\n if (onUpdateIssue && issue._id) {\r\n await onUpdateIssue(issue._id, updateData);\r\n }\r\n setStatus(newStatus);\r\n \r\n const statusMessages: Record<string, string> = {\r\n [EIssueStatus.IN_PROGRESS]: 'Issue accepted and moved to In-Progress',\r\n [EIssueStatus.RESOLVE]: 'Issue resolved successfully',\r\n [EIssueStatus.REJECTED]: 'Issue rejected'\r\n };\r\n \r\n toastService.showSuccess(statusMessages[newStatus] || 'Issue status updated successfully');\r\n \r\n if (onSuccess) {\r\n onSuccess();\r\n }\r\n onClose();\r\n } catch (error: any) {\r\n const errorMessage = error?.message || error?.error?.message || 'Failed to update issue status. Please try again.';\r\n toastService.showError(errorMessage);\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n const handleAccept = async () => {\r\n await updateIssueStatus(EIssueStatus.IN_PROGRESS);\r\n };\r\n\r\n const handleResolve = async () => {\r\n await updateIssueStatus(EIssueStatus.RESOLVE);\r\n };\r\n\r\n const handleReject = async () => {\r\n await updateIssueStatus(EIssueStatus.REJECTED);\r\n };\r\n\r\n const handleSubmit = async () => {\r\n if (!String(title || '').trim()) {\r\n toastService.showError('Title is required');\r\n return;\r\n }\r\n\r\n if (!String(description || '').trim()) {\r\n toastService.showError('Description is required');\r\n return;\r\n }\r\n\r\n setIsSubmitting(true);\r\n\r\n try {\r\n if (isEditMode && issue) {\r\n // Update existing issue\r\n const updateData = {\r\n title: String(title || '').trim(),\r\n description: String(description || '').trim(),\r\n workOrderNumber: String(workOrderNumber || '').trim() || '',\r\n assetNumber: String(assetNumber || '').trim() || undefined,\r\n formTemplateId: issue.formTemplateId || '',\r\n component: issue.component || {},\r\n priority,\r\n assignee: String(assignee || '').trim() || undefined,\r\n status: status,\r\n comments: String(comments || '').trim() || ''\r\n };\r\n\r\n if (onUpdateIssue && issue._id) {\r\n await onUpdateIssue(issue._id, updateData);\r\n }\r\n toastService.showSuccess('Issue updated successfully');\r\n \r\n if (onSuccess) {\r\n onSuccess();\r\n }\r\n onClose();\r\n } else {\r\n // Create new issue\r\n if (!component) {\r\n toastService.showError('Component is required');\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n \r\n if (!formTemplateId || String(formTemplateId || '').trim() === '') {\r\n toastService.showError('Form template is required');\r\n setIsSubmitting(false);\r\n return;\r\n }\r\n\r\n // Prepare component data for API - include all component properties\r\n const componentData = {\r\n ...component,\r\n basic: {\r\n ...component.basic,\r\n comments: String(notes || '')\r\n }\r\n };\r\n\r\n const issueData = {\r\n title: String(title || '').trim(),\r\n workOrderNumber: String(workOrderNumber || '').trim() || undefined,\r\n assetNumber: String(assetNumber || '').trim() || undefined,\r\n component: componentData,\r\n description: String(description || '').trim(),\r\n formTemplateId,\r\n assignee: String(assignee || '').trim() || undefined,\r\n priority,\r\n status: status,\r\n comments: String(comments || '').trim() || ''\r\n };\r\n\r\n let createdIssue: IIssue | undefined;\r\n if (onCreateIssue) {\r\n createdIssue = await onCreateIssue(issueData, attachments || []);\r\n }\r\n toastService.showSuccess('Issue raised successfully');\r\n \r\n if (onSuccess) {\r\n onSuccess(createdIssue);\r\n }\r\n onClose();\r\n }\r\n } catch (error: any) {\r\n const errorMessage = error?.message || error?.error?.message || (isEditMode ? 'Failed to update issue. Please try again.' : 'Failed to raise issue. Please try again.');\r\n toastService.showError(errorMessage);\r\n } finally {\r\n setIsSubmitting(false);\r\n }\r\n };\r\n\r\n if (!isOpen) {\r\n return null;\r\n }\r\n\r\n const modalContent = (\r\n <div className=\"raise-issue-modal-overlay\" onClick={onClose}>\r\n <div className=\"raise-issue-modal\" onClick={(e) => e.stopPropagation()}>\r\n {/* Header */}\r\n <div className=\"raise-issue-modal-header\">\r\n <div className=\"raise-issue-modal-header-left\">\r\n <AlertTriangle className=\"raise-issue-modal-icon\" size={20} />\r\n <div className=\"raise-issue-modal-header-text\">\r\n <div className=\"raise-issue-modal-title-main\">Issue Details</div>\r\n </div>\r\n </div>\r\n <button\r\n className=\"raise-issue-modal-close\"\r\n onClick={onClose}\r\n aria-label=\"Close\"\r\n >\r\n <X size={18} />\r\n </button>\r\n </div>\r\n\r\n {/* Content */}\r\n <div className=\"raise-issue-modal-content\">\r\n <div className=\"raise-issue-fields-grid\">\r\n {/* Issue Number - Show only in edit mode */}\r\n {isEditMode && issue?.issueNumber && (\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Issue ID</label>\r\n <input\r\n type=\"text\"\r\n className=\"raise-issue-field-input raise-issue-field-readonly\"\r\n value={issue.issueNumber}\r\n readOnly\r\n />\r\n </div>\r\n )}\r\n\r\n {/* Title */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Title <span className=\"raise-issue-required\">*</span></label>\r\n <input\r\n type=\"text\"\r\n className={`raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n placeholder=\"Enter issue title\"\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Work Order */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Work Order <span className=\"raise-issue-required\">*</span></label>\r\n <input\r\n type=\"text\"\r\n className={`raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={workOrderNumber}\r\n onChange={(e) => setWorkOrderNumber(e.target.value)}\r\n placeholder=\"N/A\"\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Asset Number */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Asset Number <span className=\"raise-issue-required\">*</span></label>\r\n <input\r\n type=\"text\"\r\n className={`raise-issue-field-input ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={assetNumber}\r\n onChange={(e) => setAssetNumber(e.target.value)}\r\n placeholder=\"Enter asset number\"\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Raised By */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Raised By</label>\r\n <div className=\"raise-issue-field-value-with-icon\">\r\n <User size={16} />\r\n <span>{user ? `${user.firstName || ''} ${user.lastName || ''}`.trim() || 'User' : 'User'}</span>\r\n </div>\r\n </div>\r\n\r\n {/* Created On */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Created On</label>\r\n <div className=\"raise-issue-field-value-with-icon\">\r\n <Calendar size={16} />\r\n <span>\r\n {isEditMode && issue?.createdAt\r\n ? new Date(issue.createdAt).toLocaleString('en-US', {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n })\r\n : new Date().toLocaleString('en-US', {\r\n year: 'numeric',\r\n month: 'short',\r\n day: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n hour12: true\r\n })}\r\n </span>\r\n </div>\r\n </div>\r\n\r\n {/* Description - Full Width */}\r\n <div className=\"raise-issue-field raise-issue-field-full-width\">\r\n <label className=\"raise-issue-field-label\">Description <span className=\"raise-issue-required\">*</span></label>\r\n <textarea\r\n className={`raise-issue-field-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n placeholder=\"Enter issue description\"\r\n rows={4}\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n\r\n {/* Status */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Status <span className=\"raise-issue-required\">*</span></label>\r\n <select\r\n className={`raise-issue-field-select ${!isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={status}\r\n onChange={(e) => setStatus(e.target.value)}\r\n disabled={!isEditMode}\r\n >\r\n <option value={EIssueStatus.OPEN}>{EIssueStatus.OPEN}</option>\r\n <option value={EIssueStatus.IN_PROGRESS}>{EIssueStatus.IN_PROGRESS}</option>\r\n <option value={EIssueStatus.REJECTED}>{EIssueStatus.REJECTED}</option>\r\n <option value={EIssueStatus.RESOLVE}>{EIssueStatus.RESOLVE}</option>\r\n </select>\r\n </div>\r\n\r\n {/* Assignee */}\r\n <div className=\"raise-issue-field\">\r\n <label className=\"raise-issue-field-label\">Assignee <span className=\"raise-issue-required\">*</span></label>\r\n <select\r\n className=\"raise-issue-field-select\"\r\n value={assignee}\r\n onChange={(e) => setAssignee(e.target.value)}\r\n >\r\n <option value=\"\">Unassigned</option>\r\n {availableUsers.map(userName => (\r\n <option key={userName} value={userName}>\r\n {userName}\r\n </option>\r\n ))}\r\n </select>\r\n </div>\r\n\r\n {/* Priority */}\r\n <div className=\"raise-issue-field raise-issue-field-full-width\">\r\n <label className=\"raise-issue-field-label\">Priority <span className=\"raise-issue-required\">*</span></label>\r\n <div className=\"raise-issue-priority-buttons\">\r\n <button\r\n type=\"button\"\r\n className={`priority-button priority-low ${priority === 'Low' ? 'active' : ''}`}\r\n onClick={() => setPriority('Low')}\r\n >\r\n Low\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`priority-button priority-medium ${priority === 'Medium' ? 'active' : ''}`}\r\n onClick={() => setPriority('Medium')}\r\n >\r\n Medium\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`priority-button priority-high ${priority === 'High' ? 'active' : ''}`}\r\n onClick={() => setPriority('High')}\r\n >\r\n High\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {/* Comments - Full Width */}\r\n <div className=\"raise-issue-field raise-issue-field-full-width\">\r\n <label className=\"raise-issue-field-label-with-icon\">\r\n <MessageSquare size={16} />\r\n <span>Comments</span>\r\n </label>\r\n {!comments && (\r\n <div className=\"raise-issue-no-comments\">No comments yet</div>\r\n )}\r\n <textarea\r\n className={`raise-issue-field-textarea raise-issue-comments-textarea ${isEditMode ? 'raise-issue-field-readonly' : ''}`}\r\n value={comments}\r\n onChange={(e) => setComments(e.target.value)}\r\n placeholder=\"Add a comment...\"\r\n rows={4}\r\n readOnly={isEditMode}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Actions */}\r\n <div className=\"raise-issue-modal-actions\">\r\n <div className=\"raise-issue-modal-actions-buttons\">\r\n {/* Action buttons - only show in edit mode and when status allows actions */}\r\n {isEditMode && issue && (\r\n <>\r\n {status === EIssueStatus.OPEN && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-accept\"\r\n onClick={handleAccept}\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? 'Processing...' : 'Accept'}\r\n </button>\r\n )}\r\n {status === EIssueStatus.IN_PROGRESS && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-resolve\"\r\n onClick={handleResolve}\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? 'Processing...' : 'Resolve'}\r\n </button>\r\n )}\r\n {status === EIssueStatus.OPEN && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-reject\"\r\n onClick={handleReject}\r\n disabled={isSubmitting}\r\n >\r\n {isSubmitting ? 'Processing...' : 'Reject'}\r\n </button>\r\n )}\r\n </>\r\n )}\r\n {!isEditMode && (\r\n <button\r\n className=\"raise-issue-modal-button raise-issue-modal-button-save\"\r\n onClick={handleSubmit}\r\n disabled={isSubmitting || !String(title || '').trim() || !String(description || '').trim()}\r\n >\r\n {isSubmitting ? 'Saving...' : 'Save Changes'}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n\r\n // Render modal using portal to document body for full-page overlay\r\n return createPortal(modalContent, document.body);\r\n};\r\n","import React, { useState, useCallback, useEffect } from 'react';\r\nimport { AlertTriangle, CheckCircle2 } from 'lucide-react';\r\nimport { RaiseIssueModal } from './components/RaiseIssueModal';\r\nimport { toastService } from './services/toast.service';\r\n\r\n// Stub interface for issue (replace with your own)\r\ninterface IIssue {\r\n _id: string;\r\n id?: string;\r\n issueNumber?: string;\r\n title?: string;\r\n description?: string;\r\n status?: string;\r\n createdAt?: string;\r\n component?: any;\r\n formTemplateId?: string;\r\n}\r\nimport './ThresholdAlert.scss';\r\n\r\ninterface IThresholdAlertProps {\r\n component: any;\r\n condition: any;\r\n currentValue: string | number;\r\n thresholdValue: string | number;\r\n formTemplateId?: string;\r\n onDismiss?: () => void;\r\n onIssueRaised?: (conditionId: string) => void;\r\n isIssueRaised?: boolean; // Track if issue has been raised for this condition\r\n compact?: boolean; // Show compact one-liner version for small screens/tables\r\n}\r\n\r\nexport const ThresholdAlert: React.FC<IThresholdAlertProps> = ({\r\n component,\r\n condition,\r\n currentValue,\r\n thresholdValue,\r\n formTemplateId,\r\n onIssueRaised,\r\n isIssueRaised = false,\r\n compact = false\r\n}) => {\r\n const [showRaiseIssueModal, setShowRaiseIssueModal] = useState(false);\r\n const [issue, setIssue] = useState<IIssue | null>(null);\r\n const [isLoadingIssue, setIsLoadingIssue] = useState(false);\r\n const [localIssueRaised, setLocalIssueRaised] = useState(false);\r\n\r\n // Sync local state with prop - if parent says issue is raised, update local state\r\n useEffect(() => {\r\n if (isIssueRaised) {\r\n setLocalIssueRaised(true);\r\n }\r\n }, [isIssueRaised]);\r\n\r\n // Reset local state when condition changes (new condition = new alert)\r\n useEffect(() => {\r\n setLocalIssueRaised(false);\r\n }, [condition?.id]);\r\n\r\n const getOperatorSymbol = (operator: string): string => {\r\n const symbols: Record<string, string> = {\r\n 'greaterThan': '>',\r\n 'lessThan': '<',\r\n 'greaterThanOrEqual': '≥',\r\n 'lessThanOrEqual': '≤',\r\n 'equals': '=',\r\n 'notEquals': '≠'\r\n };\r\n return symbols[operator] || operator;\r\n };\r\n\r\n const getConditionMessage = (): string => {\r\n const operatorSymbol = getOperatorSymbol(condition.operator);\r\n return `${component.basic?.label || 'Value'}: Value ${currentValue} exceeds threshold ${operatorSymbol} ${thresholdValue}`;\r\n };\r\n\r\n const getCompactMessage = (): string => {\r\n const operatorSymbol = getOperatorSymbol(condition.operator);\r\n return `Threshold ${operatorSymbol} ${thresholdValue}`;\r\n };\r\n\r\n const handleRaiseIssueClick = useCallback(async () => {\r\n if (isIssueRaised || localIssueRaised) {\r\n // If we already have the issue stored (from recent creation), use it\r\n if (issue) {\r\n setShowRaiseIssueModal(true);\r\n return;\r\n }\r\n \r\n // Otherwise, fetch the issue data before opening modal\r\n setIsLoadingIssue(true);\r\n try {\r\n // Stub implementation - in a real app, this would fetch from your API\r\n // For now, we'll just open the modal without fetching\r\n // You can replace this with your own issue fetching logic\r\n setIssue(null);\r\n setShowRaiseIssueModal(true);\r\n } catch (error: any) {\r\n console.error('Error fetching issue:', error);\r\n toastService.showError('Failed to load issue details');\r\n } finally {\r\n setIsLoadingIssue(false);\r\n }\r\n } else {\r\n // For new issues, just open the modal\r\n setIssue(null);\r\n setShowRaiseIssueModal(true);\r\n }\r\n }, [isIssueRaised, localIssueRaised, formTemplateId, component, issue]);\r\n\r\n const handleRaiseIssueClose = useCallback(() => {\r\n setShowRaiseIssueModal(false);\r\n // Don't clear issue if it was just created - keep it for viewing\r\n // Only clear if we're not in \"issue raised\" state\r\n if (!isIssueRaised && !localIssueRaised) {\r\n setIssue(null);\r\n }\r\n }, [isIssueRaised, localIssueRaised]);\r\n\r\n const handleRaiseIssueSuccess = useCallback((createdIssue?: IIssue) => {\r\n setShowRaiseIssueModal(false);\r\n // Store the created issue if provided, so we can show it immediately when viewing\r\n if (createdIssue) {\r\n setIssue(createdIssue);\r\n } else {\r\n setIssue(null); // Clear issue state so next view will fetch the new issue\r\n }\r\n // Immediately set local state to hide the alert\r\n setLocalIssueRaised(true);\r\n // Notify parent that issue has been raised for this condition\r\n // Call immediately to ensure state updates\r\n if (onIssueRaised && condition?.id) {\r\n onIssueRaised(condition.id);\r\n }\r\n }, [onIssueRaised, condition]);\r\n\r\n // If issue is raised (either from prop or local state), show only an icon with primary color (like other components)\r\n if (isIssueRaised || localIssueRaised) {\r\n return (\r\n <>\r\n <div className=\"threshold-issue-icon-only\">\r\n <button\r\n type=\"button\"\r\n onClick={handleRaiseIssueClick}\r\n className=\"threshold-issue-icon-button\"\r\n disabled={isLoadingIssue}\r\n title=\"View Raised Issue\"\r\n >\r\n <AlertTriangle className=\"threshold-issue-icon\" size={16} fill=\"currentColor\" />\r\n </button>\r\n </div>\r\n\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={component}\r\n formTemplateId={formTemplateId}\r\n notes=\"\"\r\n attachments={null}\r\n issue={issue}\r\n />\r\n )}\r\n </>\r\n );\r\n }\r\n\r\n // Show compact version for small screens/tables\r\n if (compact) {\r\n return (\r\n <>\r\n <div className=\"threshold-alert threshold-alert-unresolved threshold-alert-compact\">\r\n <div className=\"threshold-alert-border\" />\r\n <div className=\"threshold-alert-content-compact\">\r\n <AlertTriangle className=\"threshold-alert-icon-compact\" size={14} />\r\n <span className=\"threshold-alert-message-compact\">\r\n {getCompactMessage()}\r\n </span>\r\n <button\r\n type=\"button\"\r\n onClick={handleRaiseIssueClick}\r\n className=\"threshold-alert-raise-issue-btn-compact\"\r\n title=\"Raise Issue\"\r\n >\r\n Raise Issue\r\n </button>\r\n </div>\r\n </div>\r\n\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={component}\r\n formTemplateId={formTemplateId}\r\n notes=\"\"\r\n attachments={null}\r\n issue={issue}\r\n />\r\n )}\r\n </>\r\n );\r\n }\r\n\r\n return (\r\n <>\r\n <div className=\"threshold-alert threshold-alert-unresolved\">\r\n <div className=\"threshold-alert-border\" />\r\n <div className=\"threshold-alert-content\">\r\n <div className=\"threshold-alert-header\">\r\n <div className=\"threshold-alert-title-group\">\r\n <AlertTriangle className=\"threshold-alert-icon\" size={20} />\r\n <span className=\"threshold-alert-title\">\r\n Threshold Condition Met - Action Required\r\n </span>\r\n </div>\r\n </div>\r\n \r\n <div className=\"threshold-alert-message\">\r\n {getConditionMessage()}\r\n <span className=\"threshold-alert-warning\"> You must raise an issue before submitting the form.</span>\r\n </div>\r\n\r\n <div className=\"threshold-alert-buttons\">\r\n <button\r\n type=\"button\"\r\n onClick={handleRaiseIssueClick}\r\n className=\"threshold-alert-raise-issue-btn\"\r\n >\r\n Raise Issue Now\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={component}\r\n formTemplateId={formTemplateId}\r\n notes=\"\"\r\n attachments={null}\r\n issue={issue}\r\n />\r\n )}\r\n </>\r\n );\r\n};\r\n\r\n","import React, { useState, useEffect, useCallback, useMemo, useRef } from 'react';\r\nimport { \r\n ITextInputComponent, \r\n INumberInputComponent, \r\n IEmailInputComponent, \r\n TInputComponentType,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\nimport { ThresholdAlert } from '../../ThresholdAlert';\r\n\r\ninterface DfFormInputProps {\r\n id: string;\r\n properties: ITextInputComponent | INumberInputComponent | IEmailInputComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n inputType?: TInputComponentType;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n formTemplateId?: string;\r\n onThresholdIssueRaised?: (conditionId: string) => void;\r\n raisedThresholdIssues?: Set<string>; // Track which threshold issues have been raised\r\n}\r\n\r\nexport const DfFormInput: React.FC<DfFormInputProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n inputType = 'text',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'test',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false,\r\n formTemplateId,\r\n onThresholdIssueRaised,\r\n raisedThresholdIssues = new Set()\r\n}) => {\r\n // Ensure formValue is always a string to prevent [object Object] errors\r\n const getStringValue = (val: any): string => {\r\n if (val === null || val === undefined) return '';\r\n if (typeof val === 'string') return val;\r\n if (typeof val === 'number') return String(val);\r\n if (typeof val === 'boolean') return String(val);\r\n // If it's an object, try to extract a meaningful value or return empty string\r\n if (typeof val === 'object') {\r\n if (Array.isArray(val)) return '';\r\n // Try common object properties\r\n if ('value' in val) return getStringValue(val.value);\r\n if ('label' in val) return getStringValue(val.label);\r\n return '';\r\n }\r\n return String(val || '');\r\n };\r\n\r\n // CRITICAL: Use a ref to track the component's unique ID to prevent value sharing\r\n const componentIdRef = useRef<string>(id);\r\n const inputWrapperRef = useRef<HTMLDivElement>(null);\r\n \r\n // Update ref if ID changes (shouldn't happen, but safety check)\r\n useEffect(() => {\r\n if (id !== componentIdRef.current) {\r\n console.warn(`[DfFormInput] Component ID changed from ${componentIdRef.current} to ${id}`);\r\n componentIdRef.current = id;\r\n }\r\n }, [id]);\r\n \r\n const initialValue = getStringValue(formValue || properties?.basic?.defaultValue || '');\r\n const [value, setValue] = useState<string>(initialValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [isFocused, setIsFocused] = useState<boolean>(false);\r\n const [dismissedAlerts, setDismissedAlerts] = useState<Set<string>>(new Set());\r\n const [previousValue, setPreviousValue] = useState<string>(initialValue);\r\n\r\n // Determine input type based on component name\r\n const getInputType = (): TInputComponentType => {\r\n if (inputType) return inputType;\r\n \r\n const name = properties?.name;\r\n if (name === 'text-input') return 'text';\r\n if (name === 'number-input') return 'number';\r\n if (name === 'email-input') return 'email';\r\n \r\n return 'text';\r\n };\r\n\r\n // Build validation rules\r\n const buildValidationRules = () => {\r\n const rules: any = {};\r\n \r\n if (properties?.validation?.required) {\r\n rules.required = true;\r\n }\r\n \r\n if (getInputType() === 'email') {\r\n rules.email = true;\r\n }\r\n \r\n if (getInputType() === 'text') {\r\n const textValidation = properties.validation as ITextInputComponent['validation'];\r\n if (textValidation?.minLength) rules.minLength = textValidation.minLength;\r\n if (textValidation?.maxLength) rules.maxLength = textValidation.maxLength;\r\n }\r\n \r\n if (getInputType() === 'number') {\r\n const numberValidation = properties.validation as INumberInputComponent['validation'];\r\n if (numberValidation?.min) rules.min = numberValidation.min;\r\n if (numberValidation?.max) rules.max = numberValidation.max;\r\n if (numberValidation?.lowerLimit !== undefined) rules.lowerLimit = numberValidation.lowerLimit;\r\n if (numberValidation?.upperLimit !== undefined) rules.upperLimit = numberValidation.upperLimit;\r\n }\r\n \r\n return rules;\r\n };\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const rules = buildValidationRules();\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (rules.required && (!val || val.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n // Email validation\r\n if (rules.email && val && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/.test(val)) {\r\n errors.email = true;\r\n isValid = false;\r\n }\r\n\r\n // Length validations\r\n if (rules.minLength && val && val.length < rules.minLength) {\r\n errors.minLength = true;\r\n isValid = false;\r\n }\r\n\r\n if (rules.maxLength && val && val.length > rules.maxLength) {\r\n errors.maxLength = true;\r\n isValid = false;\r\n }\r\n\r\n // Number validations\r\n // CRITICAL: Only validate if value is not empty and is a valid number\r\n if (getInputType() === 'number' && val && val.trim() !== '') {\r\n // Remove any whitespace and check if it's a valid number string\r\n const trimmedVal = val.trim();\r\n // CRITICAL FIX: Updated regex to properly accept integers, decimals, and scientific notation\r\n // Pattern: optional minus, digits (required), optional decimal point with digits, optional scientific notation\r\n // This allows: \"33\", \"33.5\", \"-33\", \"33.5e2\", etc.\r\n const isValidNumberFormat = /^-?\\d+(\\.\\d+)?([eE][+-]?\\d+)?$/.test(trimmedVal);\r\n \r\n if (!isValidNumberFormat) {\r\n // Invalid number format - only set pattern error if it's clearly not a number\r\n // Don't set pattern error for partial input during typing (e.g., \"-\", \".\", \"3.\", \"-3.\")\r\n const isPartialInput = /^-?\\.?$/.test(trimmedVal) || /^-?\\d+\\.?$/.test(trimmedVal);\r\n if (trimmedVal.length > 0 && !isPartialInput) {\r\n errors.pattern = true;\r\n isValid = false;\r\n }\r\n } else {\r\n // Valid number format - parse and check min/max/limits\r\n const numValue = parseFloat(trimmedVal);\r\n if (isNaN(numValue)) {\r\n // This shouldn't happen if format is valid, but check anyway\r\n // Only set error if it's not a partial input\r\n const isPartialInput = /^-?\\.?$/.test(trimmedVal) || /^-?\\d+\\.?$/.test(trimmedVal);\r\n if (!isPartialInput) {\r\n errors.pattern = true;\r\n isValid = false;\r\n }\r\n } else {\r\n // Valid number - check min/max/limits only if they are defined\r\n // CRITICAL: First clear any pattern error since format is valid\r\n delete errors.pattern;\r\n \r\n if (rules.min !== undefined && numValue < rules.min) {\r\n errors.min = true;\r\n isValid = false;\r\n }\r\n if (rules.max !== undefined && numValue > rules.max) {\r\n errors.max = true;\r\n isValid = false;\r\n }\r\n if (rules.lowerLimit !== undefined && numValue < rules.lowerLimit) {\r\n errors.lowerLimit = true;\r\n isValid = false;\r\n }\r\n if (rules.upperLimit !== undefined && numValue > rules.upperLimit) {\r\n errors.upperLimit = true;\r\n isValid = false;\r\n }\r\n // CRITICAL: If number is valid and passes all checks, ensure pattern error is cleared\r\n // This ensures pattern error is not set for valid numbers\r\n if (isValid) {\r\n // Explicitly delete pattern error to ensure it's not shown\r\n delete errors.pattern;\r\n }\r\n }\r\n }\r\n } else if (getInputType() === 'number' && val && val.trim() === '') {\r\n // Empty number field - only invalid if required\r\n // Don't set pattern error for empty values\r\n // Explicitly clear pattern error for empty values\r\n delete errors.pattern;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties, getInputType]);\r\n\r\n // Handle value changes\r\n // CRITICAL: Use componentIdRef to ensure we're using the correct component ID\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n // CRITICAL: Use componentIdRef.current to ensure we're using the correct ID\r\n // This prevents ID collisions if the id prop somehow changes\r\n const currentId = componentIdRef.current;\r\n const change: IFormControlChange = {\r\n id: currentId, // Use the ref to ensure correct ID\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n \r\n // Debug: Log value changes to identify issues\r\n if (currentId !== id) {\r\n console.error(`[DfFormInput] ID mismatch in handleValueChange! ref: ${currentId}, prop: ${id}`);\r\n }\r\n \r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField, componentIdRef]);\r\n\r\n // Handle input change\r\n const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = e.target.value;\r\n handleValueChange(newValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n setIsFocused(true);\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsFocused(false);\r\n setIsTouched(true);\r\n \r\n // Always trigger validation on blur in test mode for any field with validation rules\r\n if (mode === 'test' && onValueChange) {\r\n const validation = validateField(value);\r\n const change: IFormControlChange = {\r\n id,\r\n value: value,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n \r\n onValueChange(change);\r\n }\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Reset touched state and value when switching modes\r\n useEffect(() => {\r\n if (mode === 'edit') {\r\n setIsTouched(false);\r\n // Reset value to default value when switching to edit mode\r\n const defaultValue = properties?.basic?.defaultValue || '';\r\n setValue(defaultValue);\r\n } else if (mode === 'test') {\r\n setIsTouched(false);\r\n // Reset value to empty when switching to test mode for fresh start\r\n setValue('');\r\n }\r\n }, [mode, properties?.basic?.defaultValue]);\r\n\r\n // Update value when formValue prop changes (but don't override user input)\r\n // CRITICAL: Only update if formValue is actually for THIS component's ID\r\n // Use componentIdRef to ensure we're checking against the correct component ID\r\n useEffect(() => {\r\n const currentComponentId = componentIdRef.current;\r\n const newValue = getStringValue(formValue || properties?.basic?.defaultValue || '');\r\n \r\n // CRITICAL: Only update if this formValue is actually meant for this component\r\n // Check if formValue matches what should be stored for this component's ID\r\n // This prevents cross-component value syncing when IDs are duplicated\r\n \r\n // Only update if the new value is different and we're not currently focused\r\n // Also, don't override with empty value if user has typed something\r\n // CRITICAL FIX: Don't reset user input when formValue becomes empty\r\n if (newValue !== value && !isFocused && !(newValue === '' && String(value || '').trim() !== '')) {\r\n // Additional check: Only update if formValue is not undefined/null (meaning it's actually set for this component)\r\n // If formValue is undefined, it means this component hasn't been initialized yet, so don't override local state\r\n if (formValue !== undefined && formValue !== null) {\r\n // Double-check: Only update if the ID matches (safety check against ID collisions)\r\n if (currentComponentId === id) {\r\n setValue(newValue);\r\n } else {\r\n console.error(`[DfFormInput] ID mismatch! componentIdRef: ${currentComponentId}, prop id: ${id}`);\r\n }\r\n }\r\n } else if (newValue === '' && String(value || '').trim() !== '' && !isFocused) {\r\n // Don't clear user input\r\n }\r\n }, [formValue, value, isFocused, properties?.basic?.defaultValue, id]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clear value when switching away from test mode\r\n useEffect(() => {\r\n if (mode !== 'test') {\r\n setValue('');\r\n }\r\n }, [mode]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get input classes\r\n const getInputClasses = (): string => {\r\n const base = 'form-control';\r\n \r\n // Only show validation errors in test mode\r\n if (mode === 'test') {\r\n const validation = validateField(value);\r\n const hasLocalError = !validation.isValid && isTouched;\r\n const hasExternalError = validationErrors[id] && (isTouched || formSubmitted);\r\n const error = (hasLocalError || hasExternalError) ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n }\r\n \r\n return `${base} ${className}`.trim();\r\n };\r\n\r\n // Evaluate threshold conditions\r\n const evaluateThresholdCondition = useCallback((condition: any, currentVal: string | number): boolean => {\r\n if (!currentVal || currentVal === '') return false;\r\n \r\n const numValue = typeof currentVal === 'string' ? parseFloat(currentVal) : currentVal;\r\n const thresholdValue = typeof condition.value === 'string' ? parseFloat(condition.value) : condition.value;\r\n \r\n if (isNaN(numValue) || isNaN(thresholdValue)) return false;\r\n\r\n switch (condition.operator) {\r\n case 'greaterThan':\r\n return numValue > thresholdValue;\r\n case 'lessThan':\r\n return numValue < thresholdValue;\r\n case 'greaterThanOrEqual':\r\n return numValue >= thresholdValue;\r\n case 'lessThanOrEqual':\r\n return numValue <= thresholdValue;\r\n case 'equals':\r\n return numValue === thresholdValue;\r\n case 'notEquals':\r\n return numValue !== thresholdValue;\r\n default:\r\n return false;\r\n }\r\n }, []);\r\n\r\n // Get condition conditions and evaluate them\r\n const thresholdConditions = useMemo(() => {\r\n return (properties as any)?.condition?.conditions || [];\r\n }, [(properties as any)?.condition]);\r\n\r\n // Clear dismissed alerts when value changes\r\n useEffect(() => {\r\n if (value !== previousValue) {\r\n setDismissedAlerts(new Set());\r\n setPreviousValue(value);\r\n }\r\n }, [value, previousValue]);\r\n\r\n const activeThresholdCondition = useMemo(() => {\r\n if (mode !== 'test' || !value || value === '') {\r\n return null;\r\n }\r\n \r\n // Check which conditions are currently met\r\n const metConditions = thresholdConditions.filter((condition: any) => \r\n evaluateThresholdCondition(condition, value)\r\n );\r\n \r\n // If no conditions are met, return null\r\n if (metConditions.length === 0) {\r\n return null;\r\n }\r\n \r\n // Find the first condition that is met and not dismissed\r\n // Note: We still return the condition even if an issue is raised, so we can show the indicator\r\n for (const condition of metConditions) {\r\n if (!dismissedAlerts.has(condition.id)) {\r\n return condition;\r\n }\r\n }\r\n \r\n // If all met conditions are dismissed, return null (alert won't show)\r\n return null;\r\n }, [value, thresholdConditions, dismissedAlerts, mode, evaluateThresholdCondition, raisedThresholdIssues]);\r\n\r\n\r\n const handleDismissAlert = useCallback((conditionId: string) => {\r\n setDismissedAlerts(prev => new Set(prev).add(conditionId));\r\n }, []);\r\n\r\n const currentInputType = getInputType();\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <>\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\" ref={inputWrapperRef}>\r\n <input\r\n type={currentInputType}\r\n id={id}\r\n value={value}\r\n onChange={handleInputChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n placeholder={properties.basic.placeholder}\r\n disabled={shouldDisable}\r\n readOnly={readonly || properties?.validation?.readonly}\r\n className={getInputClasses()}\r\n />\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(value)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n\r\n\r\n </div>\r\n </div>\r\n {/* Threshold Alert - Show when condition is met */}\r\n {activeThresholdCondition && mode === 'test' && (() => {\r\n const issueRaised = raisedThresholdIssues?.has(activeThresholdCondition.id) || false;\r\n // Detect if we're inside a table cell or datagrid for compact mode\r\n // Check if parent element is a table cell or datagrid\r\n const isInTable = inputWrapperRef.current?.closest('.table-cell') !== null ||\r\n inputWrapperRef.current?.closest('.cell-content') !== null ||\r\n inputWrapperRef.current?.closest('.datagrid-table-view') !== null ||\r\n inputWrapperRef.current?.closest('.datagrid-list-view') !== null ||\r\n className.includes('table-cell') || \r\n className.includes('cell-content');\r\n return (\r\n <ThresholdAlert\r\n key={`${activeThresholdCondition.id}-${issueRaised}`}\r\n component={properties}\r\n condition={activeThresholdCondition}\r\n currentValue={value}\r\n thresholdValue={activeThresholdCondition.value}\r\n formTemplateId={formTemplateId}\r\n onDismiss={() => handleDismissAlert(activeThresholdCondition.id)}\r\n onIssueRaised={onThresholdIssueRaised}\r\n isIssueRaised={issueRaised}\r\n compact={isInTable}\r\n />\r\n );\r\n })()}\r\n </>\r\n );\r\n};\r\n\r\nexport default DfFormInput;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ITextareaComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormTextareaProps {\r\n id: string;\r\n properties: ITextareaComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormTextarea: React.FC<DfFormTextareaProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [value, setValue] = useState<string>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!val || val.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n // Length validations\r\n if (properties?.validation?.minLength && val && val.length < properties.validation.minLength) {\r\n errors.minLength = true;\r\n isValid = false;\r\n }\r\n\r\n if (properties?.validation?.maxLength && val && val.length > properties.validation.maxLength) {\r\n errors.maxLength = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle textarea change\r\n const handleTextareaChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n const newValue = e.target.value;\r\n handleValueChange(newValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes (only on initial load or when component is reset)\r\n useEffect(() => {\r\n // Only update if the current value is empty (initial state) or if formValue is explicitly set\r\n // This prevents the component from resetting user input when they blur the field\r\n if (value === '' && formValue !== '') {\r\n setValue(formValue);\r\n }\r\n }, [formValue]); // Remove value and isFocused from dependencies to prevent reset on blur\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clear value when switching away from test mode\r\n useEffect(() => {\r\n if (mode !== 'test') {\r\n setValue('');\r\n }\r\n }, [mode]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get textarea classes\r\n const getTextareaClasses = (): string => {\r\n const base = 'form-textarea';\r\n const validation = validateField(value);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n const rows = properties?.validation?.rows || 4;\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <textarea\r\n id={id}\r\n value={value}\r\n onChange={handleTextareaChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n placeholder={properties.basic.placeholder}\r\n disabled={shouldDisable}\r\n readOnly={readonly || properties?.validation?.readonly}\r\n rows={rows}\r\n className={getTextareaClasses()}\r\n />\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(value)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormTextarea;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ISelectComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormSelectProps {\r\n id: string;\r\n properties: ISelectComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string | string[];\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormSelect: React.FC<DfFormSelectProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [selectedValue, setSelectedValue] = useState<string | string[]>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Check if multiple selection is enabled\r\n const isMultiple = properties?.validation?.multiple || false;\r\n\r\n // Validate field\r\n const validateField = useCallback((value: string | string[]): { isValid: boolean; errors: Record<string, boolean> } => {\r\n const errors: Record<string, boolean> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required) {\r\n if (isMultiple) {\r\n if (!Array.isArray(value) || value.length === 0) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n } else {\r\n if (!value || (typeof value === 'string' && value.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n }\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties, isMultiple]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string | string[]) => {\r\n setSelectedValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle select change\r\n const handleSelectChange = (e: React.ChangeEvent<HTMLSelectElement>) => {\r\n if (isMultiple) {\r\n const selectedOptions = Array.from(e.target.selectedOptions, option => option.value);\r\n handleValueChange(selectedOptions);\r\n } else {\r\n handleValueChange(e.target.value);\r\n }\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n if (JSON.stringify(formValue) !== JSON.stringify(selectedValue)) {\r\n setSelectedValue(formValue);\r\n }\r\n }, [formValue, selectedValue]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get select classes\r\n const getSelectClasses = (): string => {\r\n const base = 'form-select';\r\n const validation = validateField(selectedValue);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <select\r\n id={id}\r\n value={isMultiple ? selectedValue as string[] : selectedValue as string}\r\n onChange={handleSelectChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable}\r\n multiple={isMultiple}\r\n className={getSelectClasses()}\r\n >\r\n {!isMultiple && (\r\n <option value=\"\">\r\n {properties.basic.placeholder || 'Select an option'}\r\n </option>\r\n )}\r\n {(properties.options || []).map((option, index) => (\r\n <option \r\n key={index} \r\n value={option.value}\r\n disabled={option.disabled}\r\n >\r\n {option.label}\r\n </option>\r\n ))}\r\n </select>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormSelect;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ICheckboxComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormCheckboxProps {\r\n id: string;\r\n properties: ICheckboxComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string[];\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormCheckbox: React.FC<DfFormCheckboxProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = [],\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n \r\n // Use formValue directly instead of local state to avoid conflicts\r\n const selectedValues = Array.isArray(formValue) ? formValue : [];\r\n\r\n // Validate field\r\n const validateField = useCallback((values: string[]): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && values.length === 0) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValues: string[]) => {\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValues);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValues,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField, selectedValues]);\r\n\r\n // Handle checkbox change\r\n const handleCheckboxChange = (optionValue: string, checked: boolean) => {\r\n \r\n let newValues: string[];\r\n \r\n if (checked) {\r\n newValues = [...selectedValues, optionValue];\r\n } else {\r\n newValues = selectedValues.filter(value => value !== optionValue);\r\n }\r\n \r\n handleValueChange(newValues);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Log formValue changes for debugging\r\n useEffect(() => {\r\n }, [formValue, id, selectedValues]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get layout class for inline/vertical layout\r\n const getLayoutClass = (): string => {\r\n return properties?.basic?.inlineLayout ? 'inline-layout' : 'vertical-layout';\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <>\r\n <div className={`form-group checkbox-group ${getLabelAlignmentClass()} ${getLayoutClass()} ${className}`}>\r\n {!hideLabel && properties.basic.label ? (\r\n <>\r\n <label className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n \r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onChange={(e) => {\r\n handleCheckboxChange(option.value, e.target.checked);\r\n }}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValues)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </>\r\n ) : (\r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"checkbox\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onChange={(e) => {\r\n handleCheckboxChange(option.value, e.target.checked);\r\n }}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValues)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n )}\r\n\r\n </div>\r\n </>\r\n );\r\n};\r\n\r\nexport default DfFormCheckbox;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n IRadioComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormRadioProps {\r\n id: string;\r\n properties: IRadioComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormRadio: React.FC<DfFormRadioProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [selectedValue, setSelectedValue] = useState<string>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((value: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!value || value.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setSelectedValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle radio change\r\n const handleRadioChange = (optionValue: string) => {\r\n handleValueChange(optionValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n if (formValue !== selectedValue) {\r\n setSelectedValue(formValue);\r\n }\r\n }, [formValue, selectedValue]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get layout class for inline/vertical layout\r\n const getLayoutClass = (): string => {\r\n return properties?.basic?.inlineLayout ? 'inline-layout' : 'vertical-layout';\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <>\r\n <div className={`form-group radio-group ${getLabelAlignmentClass()} ${getLayoutClass()} ${className}`}>\r\n {!hideLabel && properties.basic.label ? (\r\n <>\r\n <label className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n \r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"radio\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValue === option.value}\r\n onChange={() => handleRadioChange(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </>\r\n ) : (\r\n <div className=\"input-wrapper\">\r\n <div className={`mt-2 ${properties?.basic?.inlineLayout ? 'inline-options-grid' : 'space-y-2'}`}>\r\n {(properties.options || []).map((option, index) => (\r\n <div key={index} className=\"form-check\">\r\n <input\r\n type=\"radio\"\r\n id={`${id}-${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={selectedValue === option.value}\r\n onChange={() => handleRadioChange(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-check-input\"\r\n />\r\n <label \r\n htmlFor={`${id}-${index}`} \r\n className=\"form-check-label\"\r\n >\r\n {option.label}\r\n </label>\r\n </div>\r\n ))}\r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n )}\r\n\r\n </div>\r\n </>\r\n );\r\n};\r\n\r\nexport default DfFormRadio;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n ISegmentComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\nimport './df-form-segment.scss';\r\n\r\ninterface DfFormSegmentProps {\r\n id: string;\r\n properties: ISegmentComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n showCommentsInPreview?: boolean;\r\n}\r\n\r\nexport const DfFormSegment: React.FC<DfFormSegmentProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [selectedValue, setSelectedValue] = useState<string>(formValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((value: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!value || value.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n\r\n // Handle segment button click\r\n const handleSegmentClick = useCallback((optionValue: string) => {\r\n setSelectedValue(optionValue);\r\n setIsTouched(true);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(optionValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: optionValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors\r\n } as IFormControlChange;\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n if (formValue !== selectedValue) {\r\n setSelectedValue(formValue);\r\n }\r\n }, [formValue, selectedValue]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get segment container class (matching Angular approach)\r\n const getSegmentContainerClass = (): string => {\r\n return properties?.basic?.inlineLayout ? 'inline-layout' : 'grid-layout';\r\n };\r\n\r\n\r\n\r\n\r\n // Get button type for styling (pass/fail) - fallback for backward compatibility\r\n const getButtonType = (optionValue: string): 'pass' | 'fail' => {\r\n const value = optionValue?.toLowerCase();\r\n if (value === 'pass' || value === 'yes') {\r\n return 'pass';\r\n }\r\n if (value === 'fail' || value === 'no') {\r\n return 'fail';\r\n }\r\n return 'pass';\r\n };\r\n\r\n // Get button icon based on option - use custom icon if available, otherwise fallback\r\n const getButtonIcon = (option: any): string => {\r\n if (option?.icon !== undefined && option.icon !== '') {\r\n return option.icon;\r\n }\r\n // Fallback to old logic\r\n const buttonType = getButtonType(option?.value || option);\r\n return buttonType === 'pass' ? '✓' : '×';\r\n };\r\n\r\n // Get button styles based on option - use custom colors if available\r\n const getButtonStyles = (option: any, isSelected: boolean): React.CSSProperties => {\r\n const hasCustomColors = option?.color || option?.backgroundColor;\r\n \r\n if (hasCustomColors) {\r\n return {\r\n color: isSelected ? '#ffffff' : (option.color || '#00814b'),\r\n backgroundColor: isSelected ? (option.color || '#00814b') : (option.backgroundColor || '#34bd4914'),\r\n borderColor: option.color || '#00814b'\r\n };\r\n }\r\n \r\n // Fallback to old logic - no inline styles, use CSS classes\r\n return {};\r\n };\r\n\r\n // Get button class - use custom class if custom colors exist, otherwise use pass/fail\r\n const getButtonClass = (option: any): string => {\r\n const hasCustomColors = option?.color || option?.backgroundColor;\r\n \r\n if (hasCustomColors) {\r\n return 'segment-button-label segment-button-custom';\r\n }\r\n \r\n // Fallback to old logic\r\n const buttonType = getButtonType(option?.value || option);\r\n return `segment-button-label ${buttonType === 'pass' ? 'pass-button' : 'fail-button'}`;\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n return (\r\n <>\r\n <div className={`form-group segment-group ${getLabelAlignmentClass()} ${className}`}>\r\n {!hideLabel && properties.basic.label ? (\r\n <>\r\n <label className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n \r\n <div className=\"form-segment-wrapper\">\r\n <div className={`form-segment-container ${getSegmentContainerClass()}`}>\r\n {(properties.options || []).map((option, index) => {\r\n const isSelected = selectedValue === option.value;\r\n const buttonStyles = getButtonStyles(option, isSelected);\r\n const buttonClass = getButtonClass(option);\r\n const buttonIcon = getButtonIcon(option);\r\n \r\n return (\r\n <div key={index} className={`form-segment-option ${isSelected ? 'selected' : ''}`}>\r\n <input\r\n type=\"radio\"\r\n id={`${id}_option_${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={isSelected}\r\n onChange={() => !shouldDisable && !option.disabled && handleSegmentClick(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-segment-radio\"\r\n />\r\n <label\r\n htmlFor={`${id}_option_${index}`}\r\n className={buttonClass}\r\n style={Object.keys(buttonStyles).length > 0 ? buttonStyles : undefined}\r\n >\r\n {buttonIcon && <span className=\"segment-icon\">{buttonIcon}</span>}\r\n <span className=\"segment-text\">{option.value}</span>\r\n </label>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n\r\n </div>\r\n\r\n </>\r\n ) : (\r\n <div className=\"form-segment-wrapper\">\r\n <div className={`form-segment-container ${getSegmentContainerClass()}`}>\r\n {(properties.options || []).map((option, index) => {\r\n const isSelected = selectedValue === option.value;\r\n const buttonStyles = getButtonStyles(option, isSelected);\r\n const buttonClass = getButtonClass(option);\r\n const buttonIcon = getButtonIcon(option);\r\n \r\n return (\r\n <div key={index} className={`form-segment-option ${isSelected ? 'selected' : ''}`}>\r\n <input\r\n type=\"radio\"\r\n id={`${id}_option_${index}`}\r\n name={id}\r\n value={option.value}\r\n checked={isSelected}\r\n onChange={() => !shouldDisable && !option.disabled && handleSegmentClick(option.value)}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable || option.disabled}\r\n className=\"form-segment-radio\"\r\n />\r\n <label\r\n htmlFor={`${id}_option_${index}`}\r\n className={buttonClass}\r\n style={Object.keys(buttonStyles).length > 0 ? buttonStyles : undefined}\r\n >\r\n {buttonIcon && <span className=\"segment-icon\">{buttonIcon}</span>}\r\n <span className=\"segment-text\">{option.value}</span>\r\n </label>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n \r\n\r\n\r\n\r\n </div>\r\n )}\r\n\r\n \r\n </div>\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(selectedValue)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </>\r\n \r\n );\r\n};\r\n\r\n\r\n\r\nexport default DfFormSegment;\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport { \r\n IDateComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormDateTimeProps {\r\n id: string;\r\n properties: IDateComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormDateTime: React.FC<DfFormDateTimeProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n // Helper function to convert formValue to proper date string format\r\n const convertToDateString = useCallback((val: any): string => {\r\n if (!val) return '';\r\n \r\n // If it's already a string, check if it's a valid date format\r\n if (typeof val === 'string') {\r\n // Check if it's already in yyyy-MM-dd format\r\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(val)) {\r\n return val;\r\n }\r\n // Check if it's in datetime-local format (yyyy-MM-ddTHH:mm)\r\n if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}/.test(val)) {\r\n return val;\r\n }\r\n // Try to parse as date and convert\r\n const date = new Date(val);\r\n if (!isNaN(date.getTime())) {\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n if (dateTimeMode === 'datetime') {\r\n // Format as datetime-local: yyyy-MM-ddTHH:mm\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const day = String(date.getDate()).padStart(2, '0');\r\n const hours = String(date.getHours()).padStart(2, '0');\r\n const minutes = String(date.getMinutes()).padStart(2, '0');\r\n return `${year}-${month}-${day}T${hours}:${minutes}`;\r\n } else if (dateTimeMode === 'time') {\r\n // Format as time: HH:mm\r\n const hours = String(date.getHours()).padStart(2, '0');\r\n const minutes = String(date.getMinutes()).padStart(2, '0');\r\n return `${hours}:${minutes}`;\r\n } else {\r\n // Format as date: yyyy-MM-dd\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0');\r\n const day = String(date.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n }\r\n }\r\n return val; // Return as-is if can't parse\r\n }\r\n \r\n // If it's a Date object\r\n if (val instanceof Date) {\r\n if (isNaN(val.getTime())) return '';\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n if (dateTimeMode === 'datetime') {\r\n const year = val.getFullYear();\r\n const month = String(val.getMonth() + 1).padStart(2, '0');\r\n const day = String(val.getDate()).padStart(2, '0');\r\n const hours = String(val.getHours()).padStart(2, '0');\r\n const minutes = String(val.getMinutes()).padStart(2, '0');\r\n return `${year}-${month}-${day}T${hours}:${minutes}`;\r\n } else if (dateTimeMode === 'time') {\r\n const hours = String(val.getHours()).padStart(2, '0');\r\n const minutes = String(val.getMinutes()).padStart(2, '0');\r\n return `${hours}:${minutes}`;\r\n } else {\r\n const year = val.getFullYear();\r\n const month = String(val.getMonth() + 1).padStart(2, '0');\r\n const day = String(val.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n }\r\n }\r\n \r\n // If it's an object, try to extract date value\r\n if (typeof val === 'object' && val !== null) {\r\n // Try common date object properties\r\n if ('value' in val && val.value) {\r\n return convertToDateString(val.value);\r\n }\r\n if ('date' in val && val.date) {\r\n return convertToDateString(val.date);\r\n }\r\n // Try to parse as ISO string if it has toString\r\n try {\r\n const dateStr = String(val);\r\n const date = new Date(dateStr);\r\n if (!isNaN(date.getTime())) {\r\n return convertToDateString(date);\r\n }\r\n } catch (e) {\r\n // Ignore\r\n }\r\n return '';\r\n }\r\n \r\n return '';\r\n }, [properties]);\r\n\r\n const initialValue = convertToDateString(formValue);\r\n const [value, setValue] = useState<string>(initialValue);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [isFocused, setIsFocused] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Get dateTimeMode to determine validation type\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n const trimmedVal = val ? String(val).trim() : '';\r\n\r\n // Required validation - only check if field is required\r\n if (properties?.validation?.required && (!trimmedVal || trimmedVal === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n\r\n // Only validate format if there's a value (non-required fields can be empty)\r\n if (trimmedVal && trimmedVal !== '') {\r\n if (dateTimeMode === 'time') {\r\n // Validate time format (HH:MM or HH:MM:SS)\r\n // HTML5 time input returns format HH:MM or HH:MM:SS\r\n const timeRegex = /^([0-1][0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/;\r\n if (!timeRegex.test(trimmedVal)) {\r\n errors.invalidDate = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n // Time is valid, no errors\r\n } else if (dateTimeMode === 'datetime') {\r\n // Validate datetime format\r\n const selectedDate = new Date(trimmedVal);\r\n if (isNaN(selectedDate.getTime())) {\r\n errors.invalidDate = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n \r\n // Date range validations for datetime\r\n if (properties?.validation?.minDate) {\r\n const minDate = new Date(properties.validation.minDate);\r\n if (selectedDate < minDate) {\r\n errors.minDate = true;\r\n errors.minDateMessage = `Date and time must be on or after ${minDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n\r\n if (properties?.validation?.maxDate) {\r\n const maxDate = new Date(properties.validation.maxDate);\r\n if (selectedDate > maxDate) {\r\n errors.maxDate = true;\r\n errors.maxDateMessage = `Date and time must be on or before ${maxDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n } else {\r\n // Validate date format (date mode)\r\n const selectedDate = new Date(trimmedVal);\r\n if (isNaN(selectedDate.getTime())) {\r\n errors.invalidDate = true;\r\n isValid = false;\r\n return { isValid, errors };\r\n }\r\n \r\n // Date range validations for date\r\n if (properties?.validation?.minDate) {\r\n const minDate = new Date(properties.validation.minDate);\r\n if (selectedDate < minDate) {\r\n errors.minDate = true;\r\n errors.minDateMessage = `Date must be on or after ${minDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n\r\n if (properties?.validation?.maxDate) {\r\n const maxDate = new Date(properties.validation.maxDate);\r\n if (selectedDate > maxDate) {\r\n errors.maxDate = true;\r\n errors.maxDateMessage = `Date must be on or before ${maxDate.toLocaleDateString()}`;\r\n isValid = false;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setValue(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Handle date change\r\n const handleDateChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = e.target.value;\r\n handleValueChange(newValue);\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n setIsFocused(true);\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsFocused(false);\r\n setIsTouched(true);\r\n \r\n // Validate on blur and notify parent\r\n if (onValueChange) {\r\n const validation = validateField(value);\r\n const change: IFormControlChange = {\r\n id,\r\n value: value,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes\r\n useEffect(() => {\r\n const convertedValue = convertToDateString(formValue);\r\n if (convertedValue !== value && !isFocused) {\r\n setValue(convertedValue);\r\n }\r\n }, [formValue, value, isFocused, convertToDateString]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get date classes\r\n const getDateClasses = (): string => {\r\n const base = 'form-date';\r\n const validation = validateField(value);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n // Determine input type based on dateTimeMode\r\n const componentName = (properties as any).name || '';\r\n const dateTimeMode = (properties.basic as any)?.dateTimeMode || (componentName === 'datetime-picker' ? 'datetime' : 'date');\r\n const getInputType = (): string => {\r\n switch (dateTimeMode) {\r\n case 'time':\r\n return 'time';\r\n case 'datetime':\r\n return 'datetime-local';\r\n case 'date':\r\n default:\r\n return 'date';\r\n }\r\n };\r\n\r\n const inputType = getInputType();\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <input\r\n type={inputType}\r\n id={id}\r\n value={value}\r\n onChange={handleDateChange}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n disabled={shouldDisable}\r\n readOnly={readonly || properties?.validation?.readonly}\r\n min={properties?.validation?.minDate}\r\n max={properties?.validation?.maxDate}\r\n className={getDateClasses()}\r\n />\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(value)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormDateTime;\r\n","import React, { useState, useEffect, useRef, useCallback } from 'react';\r\nimport { \r\n ISignatureComponent,\r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface DfFormSignatureProps {\r\n id: string;\r\n properties: ISignatureComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: string;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormSignature: React.FC<DfFormSignatureProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = '',\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'preview',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const canvasRef = useRef<HTMLCanvasElement>(null);\r\n const [isDrawing, setIsDrawing] = useState<boolean>(false);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [signatureData, setSignatureData] = useState<string>(formValue);\r\n const [isSaving, setIsSaving] = useState<boolean>(false);\r\n\r\n // Validate field\r\n const validateField = useCallback((val: string): { isValid: boolean; errors: Record<string, any> } => {\r\n const errors: Record<string, any> = {};\r\n let isValid = true;\r\n\r\n // Required validation\r\n if (properties?.validation?.required && (!val || val.trim() === '')) {\r\n errors.required = true;\r\n isValid = false;\r\n }\r\n\r\n return { isValid, errors };\r\n }, [properties]);\r\n\r\n // Handle value changes\r\n const handleValueChange = useCallback((newValue: string) => {\r\n setSignatureData(newValue);\r\n \r\n if (onValueChange) {\r\n const validation = validateField(newValue);\r\n const change: IFormControlChange = {\r\n id,\r\n value: newValue,\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, onValueChange, validateField]);\r\n\r\n // Get theme-aware colors\r\n const getThemeColors = useCallback(() => {\r\n const isDarkMode = document.documentElement.classList.contains('dark') || \r\n document.documentElement.getAttribute('data-theme') === 'dark';\r\n \r\n // Get CSS variable values\r\n const computedStyle = getComputedStyle(document.documentElement);\r\n let backgroundColor = computedStyle.getPropertyValue('--df-color-fb-input-bg').trim();\r\n \r\n // If CSS variable is not available or empty, use fallback\r\n if (!backgroundColor) {\r\n backgroundColor = isDarkMode ? '#2c2e34' : '#ffffff';\r\n }\r\n \r\n const strokeColor = isDarkMode ? '#ffffff' : '#000000';\r\n \r\n return {\r\n strokeColor,\r\n backgroundColor\r\n };\r\n }, []);\r\n\r\n // Load signature from data URL\r\n const loadSignature = useCallback((dataURL: string) => {\r\n if (!dataURL) { \r\n return;\r\n }\r\n \r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n const img = new Image();\r\n img.onload = () => {\r\n // Clear canvas\r\n ctx.clearRect(0, 0, canvas.width, canvas.height);\r\n \r\n // Set background\r\n const colors = getThemeColors();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n \r\n // Calculate scaling to fit the signature properly\r\n const canvasAspectRatio = canvas.width / canvas.height;\r\n const imgAspectRatio = img.width / img.height;\r\n \r\n let drawWidth = canvas.width;\r\n let drawHeight = canvas.height;\r\n let drawX = 0;\r\n let drawY = 0;\r\n \r\n if (imgAspectRatio > canvasAspectRatio) {\r\n // Image is wider than canvas\r\n drawHeight = canvas.width / imgAspectRatio;\r\n drawY = (canvas.height - drawHeight) / 2;\r\n } else {\r\n // Image is taller than canvas\r\n drawWidth = canvas.height * imgAspectRatio;\r\n drawX = (canvas.width - drawWidth) / 2;\r\n }\r\n \r\n // Draw the signature image with proper scaling\r\n ctx.drawImage(img, drawX, drawY, drawWidth, drawHeight);\r\n };\r\n \r\n img.onerror = (error) => {\r\n console.error('DfFormSignature: error loading image', {\r\n id,\r\n error,\r\n dataURL: dataURL.substring(0, 50) + '...'\r\n });\r\n };\r\n \r\n img.src = dataURL;\r\n }, [getThemeColors, id]);\r\n\r\n // Initialize canvas\r\n const initializeCanvas = useCallback(() => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n // Get the display size\r\n const rect = canvas.getBoundingClientRect();\r\n \r\n // Set canvas size to match display size\r\n canvas.width = rect.width;\r\n canvas.height = rect.height;\r\n \r\n // Ensure canvas is properly sized\r\n canvas.style.width = rect.width + 'px';\r\n canvas.style.height = rect.height + 'px';\r\n \r\n const colors = getThemeColors();\r\n \r\n // Set drawing styles\r\n ctx.strokeStyle = colors.strokeColor;\r\n ctx.lineWidth = 2;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n \r\n // Set background only if canvas is empty\r\n if (!signatureData) {\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, canvas.width, canvas.height);\r\n } else {\r\n loadSignature(signatureData);\r\n }\r\n }, [signatureData, getThemeColors, loadSignature]);\r\n\r\n // Handle viewport changes and device view switches\r\n const handleViewportChange = useCallback(() => {\r\n // Small delay to ensure DOM has updated after viewport change\r\n setTimeout(() => {\r\n initializeCanvas();\r\n }, 100);\r\n }, [initializeCanvas]);\r\n\r\n // Listen for viewport changes and device view switches\r\n useEffect(() => {\r\n // Listen for window resize events\r\n const handleResize = () => {\r\n handleViewportChange();\r\n };\r\n\r\n // Listen for device view changes by observing class changes on the form canvas container\r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && \r\n (mutation.attributeName === 'class')) {\r\n const target = mutation.target as HTMLElement;\r\n // Check if the class change is related to device view switching\r\n if (target.classList.contains('form-canvas-container') && \r\n (target.classList.contains('mobile-view') || \r\n target.classList.contains('tablet-view') || \r\n target.classList.contains('desktop-view'))) {\r\n handleViewportChange();\r\n }\r\n }\r\n });\r\n });\r\n\r\n // Start observing the document for class changes\r\n observer.observe(document.body, {\r\n attributes: true,\r\n attributeFilter: ['class'],\r\n subtree: true\r\n });\r\n\r\n // Add resize listener\r\n window.addEventListener('resize', handleResize);\r\n\r\n // Cleanup\r\n return () => {\r\n observer.disconnect();\r\n window.removeEventListener('resize', handleResize);\r\n };\r\n }, [handleViewportChange]);\r\n\r\n\r\n // Get accurate coordinates relative to canvas\r\n const getCanvasCoordinates = useCallback((e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) return { x: 0, y: 0 };\r\n \r\n const rect = canvas.getBoundingClientRect();\r\n const scaleX = canvas.width / rect.width;\r\n const scaleY = canvas.height / rect.height;\r\n \r\n const clientX = e.type.includes('mouse') \r\n ? (e as React.MouseEvent).clientX\r\n : (e as React.TouchEvent).touches[0].clientX;\r\n const clientY = e.type.includes('mouse')\r\n ? (e as React.MouseEvent).clientY\r\n : (e as React.TouchEvent).touches[0].clientY;\r\n \r\n return {\r\n x: (clientX - rect.left) * scaleX,\r\n y: (clientY - rect.top) * scaleY\r\n };\r\n }, []);\r\n\r\n // Start drawing\r\n const startDrawing = (e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\r\n if (readonly || disabled || properties?.validation?.readonly) return;\r\n \r\n // Check if the click is on the clear button area\r\n const target = e.target as HTMLElement;\r\n if (target.closest('.clear-signature-btn')) {\r\n return; // Don't start drawing if clicking on the clear button\r\n }\r\n \r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n setIsDrawing(true);\r\n setIsTouched(true);\r\n \r\n const canvas = canvasRef.current;\r\n if (!canvas) return;\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n \r\n const { x, y } = getCanvasCoordinates(e);\r\n \r\n // Set drawing styles\r\n const colors = getThemeColors();\r\n ctx.strokeStyle = colors.strokeColor;\r\n ctx.lineWidth = 2;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n \r\n ctx.beginPath();\r\n ctx.moveTo(x, y);\r\n };\r\n\r\n // Draw\r\n const draw = (e: React.MouseEvent<HTMLCanvasElement> | React.TouchEvent<HTMLCanvasElement>) => {\r\n if (!isDrawing) return;\r\n \r\n e.preventDefault();\r\n e.stopPropagation();\r\n \r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n const { x, y } = getCanvasCoordinates(e);\r\n\r\n ctx.lineTo(x, y);\r\n ctx.stroke();\r\n };\r\n\r\n // Check if canvas has content\r\n const hasCanvasContent = (canvas: HTMLCanvasElement): boolean => {\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return false;\r\n \r\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);\r\n const data = imageData.data;\r\n \r\n // Check if any pixel is not white (has content)\r\n for (let i = 0; i < data.length; i += 4) {\r\n const r = data[i];\r\n const g = data[i + 1];\r\n const b = data[i + 2];\r\n const a = data[i + 3];\r\n \r\n // If pixel is not white or transparent, canvas has content\r\n if (a > 0 && (r < 255 || g < 255 || b < 255)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n };\r\n\r\n // Stop drawing\r\n const stopDrawing = () => {\r\n if (!isDrawing) return;\r\n \r\n setIsDrawing(false);\r\n setIsSaving(true); // Set saving flag\r\n \r\n // Convert canvas to data URL\r\n const canvas = canvasRef.current;\r\n if (canvas) {\r\n // Check if canvas has content before saving\r\n hasCanvasContent(canvas);\r\n \r\n const dataURL = canvas.toDataURL('image/png');\r\n \r\n setSignatureData(dataURL);\r\n handleValueChange(dataURL);\r\n \r\n // Clear saving flag after a short delay\r\n setTimeout(() => {\r\n setIsSaving(false);\r\n }, 100);\r\n } else {\r\n setIsSaving(false);\r\n }\r\n };\r\n\r\n // Clear signature\r\n const clearSignature = (e?: React.MouseEvent) => {\r\n e?.preventDefault();\r\n e?.stopPropagation();\r\n\r\n const canvas = canvasRef.current;\r\n if (!canvas) {\r\n return;\r\n }\r\n \r\n // Get the display dimensions\r\n const rect = canvas.getBoundingClientRect();\r\n \r\n // Reset canvas dimensions to force a complete clear\r\n canvas.width = rect.width;\r\n canvas.height = rect.height;\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) {\r\n return;\r\n }\r\n \r\n // Set theme-aware background\r\n const colors = getThemeColors();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n \r\n // Reset drawing styles\r\n ctx.strokeStyle = colors.strokeColor;\r\n ctx.lineWidth = 2;\r\n ctx.lineCap = 'round';\r\n ctx.lineJoin = 'round';\r\n \r\n // Update state\r\n setSignatureData('');\r\n handleValueChange('');\r\n };\r\n\r\n\r\n // Update canvas colors when theme changes\r\n const updateCanvasColors = useCallback(() => {\r\n const canvas = canvasRef.current;\r\n if (!canvas) return;\r\n \r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n \r\n const colors = getThemeColors();\r\n \r\n // Update stroke color\r\n ctx.strokeStyle = colors.strokeColor;\r\n \r\n // If canvas is empty, update background color\r\n if (!signatureData) {\r\n const rect = canvas.getBoundingClientRect();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n } else {\r\n // If there's signature data, we need to redraw with new background\r\n // Save the current signature data\r\n const currentSignature = signatureData;\r\n \r\n // Clear and redraw with new background\r\n const rect = canvas.getBoundingClientRect();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n \r\n // Reload the signature with new background\r\n if (currentSignature) {\r\n loadSignature(currentSignature);\r\n }\r\n }\r\n }, [getThemeColors, signatureData, loadSignature]);\r\n\r\n // Listen for theme changes and update canvas colors\r\n useEffect(() => {\r\n const handleThemeChange = () => {\r\n updateCanvasColors();\r\n };\r\n\r\n // Listen for class changes on document element\r\n const observer = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation.type === 'attributes' && \r\n (mutation.attributeName === 'class' || mutation.attributeName === 'data-theme')) {\r\n handleThemeChange();\r\n }\r\n });\r\n });\r\n\r\n observer.observe(document.documentElement, {\r\n attributes: true,\r\n attributeFilter: ['class', 'data-theme']\r\n });\r\n\r\n return () => {\r\n observer.disconnect();\r\n };\r\n }, [updateCanvasColors]);\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Update value when formValue prop changes (but don't override user input)\r\n useEffect(() => {\r\n // Only update if the formValue is different and we're not currently drawing or saving\r\n // Also, don't reset if the user has drawn something (signatureData is not empty)\r\n // CRITICAL FIX: Don't reload signature if we're currently saving (prevents flicker)\r\n if (formValue !== signatureData && !isDrawing && !isSaving && (signatureData === '' || formValue !== '')) {\r\n // Additional check: don't reload if the formValue is the same as current signatureData\r\n if (formValue === signatureData) {\r\n return;\r\n }\r\n setSignatureData(formValue);\r\n if (formValue) {\r\n loadSignature(formValue);\r\n }\r\n } else if (formValue === '' && signatureData !== '' && !isDrawing && !isSaving) {\r\n } else if (isSaving) {\r\n }\r\n }, [formValue, signatureData, isDrawing, isSaving]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clear signature when switching away from test mode\r\n useEffect(() => {\r\n if (mode !== 'test') {\r\n setSignatureData('');\r\n // Clear the canvas as well\r\n const canvas = canvasRef.current;\r\n if (canvas) {\r\n const ctx = canvas.getContext('2d');\r\n if (ctx) {\r\n const rect = canvas.getBoundingClientRect();\r\n canvas.width = rect.width;\r\n canvas.height = rect.height;\r\n const colors = getThemeColors();\r\n ctx.fillStyle = colors.backgroundColor;\r\n ctx.fillRect(0, 0, rect.width, rect.height);\r\n }\r\n }\r\n }\r\n }, [mode]);\r\n\r\n // Initialize canvas on mount and when mode changes\r\n useEffect(() => {\r\n initializeCanvas();\r\n }, [mode]); // Only reinitialize when mode changes, not when signatureData changes\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get signature classes\r\n const getSignatureClasses = (): string => {\r\n const base = 'form-signature';\r\n const validation = validateField(signatureData);\r\n const error = !validation.isValid && isTouched ? 'is-invalid' : '';\r\n return `${base} ${error} ${className}`.trim();\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && properties.basic.label && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic.label}\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"input-wrapper\">\r\n <div className=\"signature-container\" style={{ \r\n position: 'relative',\r\n width: '100%',\r\n maxWidth: '100%',\r\n overflow: 'hidden'\r\n }}>\r\n <canvas\r\n ref={canvasRef}\r\n id={id}\r\n className={getSignatureClasses()}\r\n onMouseDown={startDrawing}\r\n onMouseMove={draw}\r\n onMouseUp={stopDrawing}\r\n onMouseLeave={stopDrawing}\r\n onTouchStart={startDrawing}\r\n onTouchMove={draw}\r\n onTouchEnd={stopDrawing}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n style={{\r\n width: '100%',\r\n height: '150px',\r\n border: '2px solid var(--df-color-primary-border)',\r\n borderRadius: '6px',\r\n cursor: shouldDisable ? 'not-allowed' : 'crosshair',\r\n backgroundColor: 'var(--df-color-fb-input-bg)',\r\n touchAction: 'none', // Prevent scrolling when drawing on mobile\r\n userSelect: 'none' // Prevent text selection\r\n }}\r\n />\r\n \r\n {!shouldDisable && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => clearSignature(e)}\r\n className=\"clear-signature-btn\"\r\n style={{\r\n position: 'absolute',\r\n bottom: '8px',\r\n right: '8px',\r\n padding: '4px 8px',\r\n backgroundColor: 'var(--df-color-error-primary)',\r\n color: 'white',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n fontSize: '0.75rem',\r\n fontWeight: '500',\r\n zIndex: 10,\r\n transition: 'all 0.2s ease',\r\n minWidth: '60px',\r\n minHeight: '28px'\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = 'var(--df-color-error-dark, #dc2626)';\r\n e.currentTarget.style.transform = 'scale(1.05)';\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = 'var(--df-color-error-primary)';\r\n e.currentTarget.style.transform = 'scale(1)';\r\n }}\r\n >\r\n Clear\r\n </button>\r\n )}\r\n </div>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateField(signatureData)}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormSignature;\r\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { \r\n IFileUploadComponent, \r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\n\r\ninterface IFileDataObject {\r\n name?: string;\r\n fileName?: string;\r\n type?: string;\r\n fileType?: string;\r\n mimeType?: string;\r\n size?: number;\r\n fileSize?: number;\r\n url?: string;\r\n path?: string;\r\n data?: string;\r\n}\r\n\r\ninterface DfFormFileUploadProps {\r\n id: string;\r\n properties: IFileUploadComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: File[] | FileList | IFileDataObject[] | string[] | null;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\ninterface IFilePreview {\r\n file: File;\r\n id: string;\r\n preview?: string;\r\n size: number;\r\n type: string;\r\n name: string;\r\n}\r\n\r\nexport const DfFormFileUpload: React.FC<DfFormFileUploadProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = null,\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'test',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [files, setFiles] = useState<IFilePreview[]>([]);\r\n const [isDragOver, setIsDragOver] = useState<boolean>(false);\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n // Convert FileList or File[] to IFilePreview[]\r\n const convertToFilePreviews = useCallback((fileList: FileList | File[] | IFileDataObject[] | string[] | null): IFilePreview[] => {\r\n if (!fileList) return [];\r\n \r\n const fileArray = Array.isArray(fileList) ? fileList : Array.from(fileList);\r\n const results: IFilePreview[] = [];\r\n \r\n fileArray.forEach((file, index) => {\r\n // CRITICAL: Handle API data structure where file is an object with name, type, size, data, url\r\n if (file && typeof file === 'object' && !(file instanceof File) && !(file instanceof Blob)) {\r\n const fileObj = file as any;\r\n // Check if it's an API file object with data/url properties\r\n if (fileObj.data || fileObj.url || (fileObj.name && fileObj.type)) {\r\n const fileName = fileObj.name || fileObj.fileName || `file-${index}`;\r\n const fileSize = fileObj.size || fileObj.fileSize || 0;\r\n const fileType = fileObj.type || fileObj.fileType || fileObj.mimeType || '';\r\n \r\n // CRITICAL: Handle base64 data from API\r\n let preview: string | undefined;\r\n if (fileObj.url) {\r\n // Use URL if available (may be data URI)\r\n preview = fileObj.url;\r\n } else if (fileObj.data) {\r\n // Handle base64 data\r\n const fileData = fileObj.data;\r\n if (typeof fileData === 'string') {\r\n if (fileData.startsWith('data:')) {\r\n preview = fileData;\r\n } else {\r\n // Base64 string without prefix - add data URI prefix\r\n const cleanedData = fileData.replace(/\\s/g, '');\r\n if (/^[A-Za-z0-9+/=]+$/.test(cleanedData) && cleanedData.length > 10) {\r\n // Detect image type from base64 or use provided type\r\n let detectedType = fileType;\r\n if (!detectedType) {\r\n if (cleanedData.startsWith('/9j/') || cleanedData.startsWith('iVBORw0KGgoAAAANSUhEUgAA')) {\r\n detectedType = 'image/jpeg';\r\n } else if (cleanedData.startsWith('iVBORw0KGgo')) {\r\n detectedType = 'image/png';\r\n } else if (cleanedData.startsWith('R0lGOD')) {\r\n detectedType = 'image/gif';\r\n } else if (cleanedData.startsWith('UklGR')) {\r\n detectedType = 'image/webp';\r\n } else {\r\n detectedType = 'image/png'; // Default\r\n }\r\n }\r\n preview = `data:${detectedType};base64,${cleanedData}`;\r\n } else {\r\n preview = fileData; // Might be a URL\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Create a minimal File object for the interface\r\n const fileInstance = new File([], fileName, { type: fileType });\r\n \r\n results.push({\r\n file: fileInstance,\r\n id: `${id}-file-${index}`,\r\n size: fileSize,\r\n type: fileType,\r\n name: fileName,\r\n preview\r\n });\r\n \r\n return; // Skip to next file\r\n }\r\n }\r\n // Check if file is actually a File object\r\n const isFileObject = (file as any) instanceof File || (file as any) instanceof Blob;\r\n \r\n // If it's a string (URL), create a mock File-like object for display\r\n let preview: string | undefined;\r\n let fileSize = 0;\r\n let fileType = '';\r\n let fileName = '';\r\n let fileObj: File;\r\n \r\n if (isFileObject) {\r\n // It's a real File/Blob object\r\n const fileInstance = file as File;\r\n fileSize = fileInstance.size || 0;\r\n fileType = fileInstance.type || '';\r\n fileName = fileInstance.name || `file-${index}`;\r\n fileObj = fileInstance;\r\n \r\n // Create object URL only for image files\r\n if (fileType.startsWith('image/')) {\r\n try {\r\n preview = URL.createObjectURL(fileInstance);\r\n } catch (error) {\r\n console.error('Error creating object URL:', error);\r\n preview = undefined;\r\n }\r\n }\r\n } else if (typeof file === 'string') {\r\n // It's a string (URL or base64)\r\n const fileString = file as string;\r\n \r\n // CRITICAL: Handle base64 strings that might not have the data: prefix\r\n // Check if it's a base64 string (starts with common base64 patterns or is long base64-like string)\r\n // Also check for base64 strings that might have been encoded differently\r\n const cleanedString = fileString.replace(/\\s/g, '');\r\n const isBase64String = cleanedString.length > 50 && \r\n /^[A-Za-z0-9+/=]+$/.test(cleanedString) && \r\n !fileString.startsWith('http') && \r\n !fileString.startsWith('https') &&\r\n !fileString.startsWith('data:') &&\r\n !fileString.startsWith('blob:') &&\r\n !fileString.startsWith('/');\r\n \r\n // If it's a base64 string without prefix, add the data URI prefix\r\n let processedFileString = fileString;\r\n if (isBase64String) {\r\n // Try to detect image type from base64 patterns\r\n // JPEG: starts with /9j/\r\n // PNG: starts with iVBORw0KGgo\r\n // GIF: starts with R0lGOD\r\n // WebP: starts with UklGR\r\n let imageType = 'image/png'; // Default to PNG\r\n if (cleanedString.startsWith('/9j/') || cleanedString.startsWith('iVBORw0KGgoAAAANSUhEUgAA')) {\r\n imageType = 'image/jpeg';\r\n } else if (cleanedString.startsWith('iVBORw0KGgo')) {\r\n imageType = 'image/png';\r\n } else if (cleanedString.startsWith('R0lGOD')) {\r\n imageType = 'image/gif';\r\n } else if (cleanedString.startsWith('UklGR')) {\r\n imageType = 'image/webp';\r\n }\r\n processedFileString = `data:${imageType};base64,${cleanedString}`;\r\n }\r\n \r\n // Try to extract filename from URL\r\n let extractedFileName = '';\r\n if (processedFileString.startsWith('data:')) {\r\n // For data URIs, try to extract filename from the data URI itself if available\r\n // Format: data:image/png;base64,... or data:image/png;filename=example.png;base64,...\r\n const filenameMatch = processedFileString.match(/filename=([^;]+)/i);\r\n if (filenameMatch) {\r\n extractedFileName = decodeURIComponent(filenameMatch[1]);\r\n } else {\r\n // Fallback: use a generic name based on type\r\n const typeMatch = processedFileString.match(/data:([^;]+)/);\r\n if (typeMatch) {\r\n const mimeType = typeMatch[1];\r\n const extension = mimeType.includes('image') ? (mimeType.includes('jpeg') ? 'jpg' : 'png') : \r\n mimeType.includes('pdf') ? 'pdf' :\r\n mimeType.includes('word') ? 'doc' :\r\n mimeType.includes('excel') ? 'xls' : 'file';\r\n extractedFileName = `file-${index + 1}.${extension}`;\r\n } else {\r\n extractedFileName = `file-${index + 1}`;\r\n }\r\n }\r\n } else if (processedFileString.startsWith('http://') || processedFileString.startsWith('https://') || processedFileString.startsWith('blob:')) {\r\n // Extract filename from URL path\r\n try {\r\n const url = new URL(fileString);\r\n const pathname = url.pathname;\r\n const urlFileName = pathname.split('/').pop() || '';\r\n if (urlFileName && urlFileName.includes('.')) {\r\n extractedFileName = decodeURIComponent(urlFileName);\r\n } else {\r\n // Try to get from query params or use index\r\n const queryFileName = url.searchParams.get('filename') || url.searchParams.get('name');\r\n extractedFileName = queryFileName ? decodeURIComponent(queryFileName) : `file-${index + 1}`;\r\n }\r\n } catch (e) {\r\n // If URL parsing fails, try simple extraction\r\n const lastSlash = fileString.lastIndexOf('/');\r\n const lastPart = lastSlash >= 0 ? fileString.substring(lastSlash + 1) : fileString;\r\n const questionMark = lastPart.indexOf('?');\r\n const fileNamePart = questionMark >= 0 ? lastPart.substring(0, questionMark) : lastPart;\r\n if (fileNamePart && fileNamePart.includes('.')) {\r\n extractedFileName = decodeURIComponent(fileNamePart);\r\n } else {\r\n extractedFileName = `file-${index + 1}`;\r\n }\r\n }\r\n } else {\r\n extractedFileName = `file-${index + 1}`;\r\n }\r\n \r\n fileName = extractedFileName || `file-${index + 1}`;\r\n \r\n // Extract file type from data URI (use processedFileString)\r\n if (processedFileString.startsWith('data:')) {\r\n const semicolonIndex = processedFileString.indexOf(';');\r\n if (semicolonIndex > 5) {\r\n fileType = processedFileString.substring(5, semicolonIndex);\r\n } else {\r\n fileType = 'application/octet-stream';\r\n }\r\n } else {\r\n // Try to infer from file extension or default to image/png for URLs\r\n const extensionMatch = processedFileString.match(/\\.(jpg|jpeg|png|gif|webp|svg|pdf|doc|docx|xls|xlsx|zip|rar)$/i) || \r\n fileName.match(/\\.(jpg|jpeg|png|gif|webp|svg|pdf|doc|docx|xls|xlsx|zip|rar)$/i);\r\n if (extensionMatch) {\r\n const ext = extensionMatch[1].toLowerCase();\r\n const mimeTypes: Record<string, string> = {\r\n jpg: 'image/jpeg',\r\n jpeg: 'image/jpeg',\r\n png: 'image/png',\r\n gif: 'image/gif',\r\n webp: 'image/webp',\r\n svg: 'image/svg+xml',\r\n pdf: 'application/pdf',\r\n doc: 'application/msword',\r\n docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',\r\n xls: 'application/vnd.ms-excel',\r\n xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\r\n zip: 'application/zip',\r\n rar: 'application/x-rar-compressed'\r\n };\r\n fileType = mimeTypes[ext] || 'application/octet-stream';\r\n } else {\r\n // If it's a base64 string, default to image type\r\n fileType = isBase64String ? 'image/png' : 'application/octet-stream';\r\n }\r\n }\r\n \r\n // Use the processed string as preview if it's an image URL/data URI\r\n if (processedFileString.startsWith('data:image') || processedFileString.startsWith('http://') || processedFileString.startsWith('https://') || processedFileString.startsWith('blob:')) {\r\n preview = processedFileString;\r\n }\r\n \r\n // Create a minimal File object for the interface\r\n fileObj = new File([], fileName, { type: fileType });\r\n } else if (file && typeof file === 'object') {\r\n // It might be an object with file properties (from API response)\r\n const fileObject = file as any;\r\n fileName = fileObject.name || fileObject.fileName || `file-${index}`;\r\n fileSize = fileObject.size || fileObject.fileSize || 0;\r\n fileType = fileObject.type || fileObject.fileType || fileObject.mimeType || '';\r\n \r\n // Check if there's a URL or path property\r\n if (fileObject.url || fileObject.path) {\r\n preview = fileObject.url || fileObject.path;\r\n } else if (fileType.startsWith('image/') && fileObject.data) {\r\n // Handle base64 data\r\n const fileData = fileObject.data;\r\n if (typeof fileData === 'string') {\r\n if (fileData.startsWith('data:')) {\r\n preview = fileData;\r\n } else {\r\n // Check if it's a base64 string without prefix\r\n const cleanedData = fileData.replace(/\\s/g, '');\r\n if (/^[A-Za-z0-9+/=]+$/.test(cleanedData) && cleanedData.length > 50) {\r\n preview = `data:${fileType};base64,${cleanedData}`;\r\n } else {\r\n preview = fileData; // Might be a URL\r\n }\r\n }\r\n } else {\r\n preview = undefined;\r\n }\r\n }\r\n \r\n // Create a minimal File object for the interface\r\n fileObj = new File([], fileName, { type: fileType });\r\n } else {\r\n // Unknown format, skip\r\n return;\r\n }\r\n \r\n results.push({\r\n file: fileObj,\r\n id: `${id}-file-${index}`,\r\n size: fileSize,\r\n type: fileType,\r\n name: fileName,\r\n preview\r\n });\r\n });\r\n \r\n return results;\r\n }, [id]);\r\n\r\n // Validate files - disabled for file upload component\r\n const validateFiles = useCallback((): { isValid: boolean; errors: Record<string, any> } => {\r\n // Always return valid since we're not maintaining validation\r\n return { isValid: true, errors: {} };\r\n }, []);\r\n\r\n // Handle file selection\r\n const handleFileSelect = useCallback((selectedFiles: FileList | File[]) => {\r\n if (readonly || disabled) return;\r\n\r\n const newFiles = convertToFilePreviews(selectedFiles);\r\n // If files already exist, always append new files (for \"add more\" functionality)\r\n // If no files exist, replace (regardless of multiple setting)\r\n const shouldAppend = files.length > 0;\r\n const allFiles = shouldAppend ? [...files, ...newFiles] : newFiles;\r\n \r\n // Apply max files limit\r\n const maxFiles = properties?.validation?.maxFiles || Infinity;\r\n const limitedFiles = allFiles.slice(0, maxFiles);\r\n \r\n setFiles(limitedFiles);\r\n setIsTouched(true);\r\n \r\n if (onValueChange) {\r\n const validation = validateFiles();\r\n const change: IFormControlChange = {\r\n id,\r\n value: limitedFiles.map(f => f.file),\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n }, [files, properties, readonly, disabled, onValueChange, validateFiles, convertToFilePreviews, id]);\r\n\r\n // Handle drag events\r\n const handleDragOver = (e: React.DragEvent) => {\r\n e.preventDefault();\r\n if (!readonly && !disabled) {\r\n setIsDragOver(true);\r\n }\r\n };\r\n\r\n const handleDragLeave = (e: React.DragEvent) => {\r\n e.preventDefault();\r\n setIsDragOver(false);\r\n };\r\n\r\n const handleDrop = (e: React.DragEvent) => {\r\n e.preventDefault();\r\n setIsDragOver(false);\r\n \r\n if (readonly || disabled) return;\r\n \r\n const droppedFiles = e.dataTransfer.files;\r\n if (droppedFiles.length > 0) {\r\n handleFileSelect(droppedFiles);\r\n }\r\n };\r\n\r\n // Handle file input change\r\n const handleFileInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {\r\n const selectedFiles = e.target.files;\r\n if (selectedFiles && selectedFiles.length > 0) {\r\n handleFileSelect(selectedFiles);\r\n // Reset input value to allow selecting the same file again\r\n e.target.value = '';\r\n }\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n \r\n if (mode === 'test' && onValueChange) {\r\n const validation = validateFiles();\r\n const change: IFormControlChange = {\r\n id,\r\n value: files.map(f => f.file),\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Remove file\r\n const removeFile = (fileId: string) => {\r\n if (readonly || disabled) return;\r\n \r\n const updatedFiles = files.filter(f => f.id !== fileId);\r\n setFiles(updatedFiles);\r\n setIsTouched(true);\r\n \r\n if (onValueChange) {\r\n const validation = validateFiles();\r\n const change: IFormControlChange = {\r\n id,\r\n value: updatedFiles.map(f => f.file),\r\n isValid: validation.isValid,\r\n errors: validation.errors,\r\n };\r\n onValueChange(change);\r\n }\r\n };\r\n\r\n // Format file size\r\n const formatFileSize = (bytes: number): string => {\r\n if (bytes === 0) return '0 Bytes';\r\n const k = 1024;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB'];\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];\r\n };\r\n\r\n // Get file icon based on type\r\n const getFileIcon = (fileType: string): string => {\r\n if (fileType.startsWith('image/')) return '🖼️';\r\n if (fileType.startsWith('video/')) return '🎥';\r\n if (fileType.startsWith('audio/')) return '🎵';\r\n if (fileType.includes('pdf')) return '📄';\r\n if (fileType.includes('word') || fileType.includes('document')) return '📝';\r\n if (fileType.includes('excel') || fileType.includes('spreadsheet')) return '📊';\r\n if (fileType.includes('zip') || fileType.includes('rar')) return '📦';\r\n return '📁';\r\n };\r\n\r\n // Update touched fields\r\n useEffect(() => {\r\n if (isTouched) {\r\n touchedFields[id] = true;\r\n }\r\n }, [isTouched, id, touchedFields]);\r\n\r\n // Reset touched state when switching modes, but preserve files\r\n useEffect(() => {\r\n if (mode === 'edit') {\r\n setIsTouched(false);\r\n // Don't clear files - let formValue prop handle the state\r\n } else if (mode === 'test') {\r\n setIsTouched(false);\r\n // Don't clear files - let formValue prop handle the state\r\n }\r\n }, [mode]);\r\n\r\n // Update value when formValue prop changes or on mount\r\n // CRITICAL: This must run whenever formValue changes to display API images\r\n useEffect(() => {\r\n // CRITICAL: Always convert formValue, even if it's null/undefined (will return empty array)\r\n // Use a ref to track previous formValue to detect actual changes\r\n const newFiles = convertToFilePreviews(formValue);\r\n \r\n // CRITICAL: Check if formValue actually changed or if it's the first load with data\r\n // This ensures base64 data from API is properly displayed\r\n const hasFormValue = formValue !== null && formValue !== undefined && \r\n ((Array.isArray(formValue) && formValue.length > 0) ||\r\n (typeof formValue === 'string' && String(formValue).trim() !== '') ||\r\n (typeof formValue === 'object' && !Array.isArray(formValue) && Object.keys(formValue).length > 0));\r\n \r\n // Always update if formValue has data, or if files array is empty and formValue exists\r\n if (hasFormValue || (files.length === 0 && formValue !== null && formValue !== undefined)) {\r\n // Force update to ensure API images are displayed\r\n setFiles(newFiles);\r\n } else if (formValue === null || formValue === undefined || \r\n (Array.isArray(formValue) && formValue.length === 0)) {\r\n // Clear files if formValue is explicitly null/empty\r\n if (files.length > 0) {\r\n setFiles([]);\r\n }\r\n }\r\n }, [formValue, convertToFilePreviews, files.length]);\r\n\r\n // Mark as touched when form is submitted\r\n useEffect(() => {\r\n if (formSubmitted) {\r\n setIsTouched(true);\r\n }\r\n }, [formSubmitted]);\r\n\r\n // Clean up object URLs (only for blob URLs, not data URIs or http URLs)\r\n useEffect(() => {\r\n return () => {\r\n files.forEach(file => {\r\n if (file.preview && file.preview.startsWith('blob:')) {\r\n try {\r\n URL.revokeObjectURL(file.preview);\r\n } catch (error) {\r\n console.error('Error revoking object URL:', error);\r\n }\r\n }\r\n });\r\n };\r\n }, [files]);\r\n\r\n // Get label alignment class\r\n const getLabelAlignmentClass = (): string => {\r\n const alignment = properties?.styles?.labelAlignment;\r\n return alignment === 'left' ? 'label-left' : 'label-top';\r\n };\r\n\r\n // Get upload area classes\r\n const getUploadAreaClasses = (): string => {\r\n const base = 'file-upload-area';\r\n const dragOverClass = isDragOver ? 'drag-over' : '';\r\n const readonlyClass = readonly ? 'readonly' : '';\r\n const disabledClass = disabled ? 'disabled' : '';\r\n \r\n // No validation logic - always return base classes\r\n return `${base} ${dragOverClass} ${readonlyClass} ${disabledClass} ${className}`.trim();\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n const isMultiple = properties?.validation?.multiple || false;\r\n const acceptTypes = properties?.validation?.accept || '*/*';\r\n const maxFiles = properties?.validation?.maxFiles || Infinity;\r\n const canAddMoreFiles = files.length < maxFiles && (isMultiple || maxFiles > 1);\r\n const isEditMode = mode === 'edit';\r\n const isPreviewOrTestMode = mode === 'preview' || mode === 'test';\r\n\r\n // Filter image files for preview/test mode display\r\n const imageFiles = files.filter(file => file.type.startsWith('image/'));\r\n const nonImageFiles = files.filter(file => !file.type.startsWith('image/'));\r\n const hasImages = imageFiles.length > 0;\r\n const shouldShowImageDisplay = isPreviewOrTestMode && hasImages;\r\n\r\n // Handle add more files button click\r\n const handleAddMoreFiles = (e: React.MouseEvent<HTMLButtonElement>) => {\r\n e.stopPropagation();\r\n if (!shouldDisable && fileInputRef.current && isEditMode) {\r\n // Reset input value to allow selecting the same file again\r\n fileInputRef.current.value = '';\r\n fileInputRef.current.click();\r\n }\r\n };\r\n\r\n // Render image display for preview/test mode\r\n if (shouldShowImageDisplay) {\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic?.label || 'Attachments'}\r\n {properties.validation?.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"file-upload-wrapper\">\r\n <div className=\"file-image-display\">\r\n {imageFiles.map((file) => (\r\n <div key={file.id} className=\"file-image-container\">\r\n {file.preview && (\r\n <img \r\n src={file.preview} \r\n alt={file.name} \r\n className=\"file-image-preview\"\r\n />\r\n )}\r\n <div className=\"file-image-info\">\r\n <div className=\"file-name\" title={file.name}>{file.name}</div>\r\n <div className=\"file-size\">{formatFileSize(file.size)}</div>\r\n </div>\r\n </div>\r\n ))}\r\n {nonImageFiles.length > 0 && (\r\n <div className=\"file-other-files\">\r\n <div className=\"file-other-files-label\">Other Files:</div>\r\n {nonImageFiles.map((file) => (\r\n <div key={file.id} className=\"file-item-minimal\">\r\n <div className=\"file-icon\">{getFileIcon(file.type)}</div>\r\n <div className=\"file-info\">\r\n <div className=\"file-name\" title={file.name}>{file.name}</div>\r\n <div className=\"file-size\">{formatFileSize(file.size)}</div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateFiles()}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className={`form-group ${getLabelAlignmentClass()}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {properties.basic?.label || 'Attachments'}\r\n {properties.validation?.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </label>\r\n )}\r\n\r\n <div className=\"file-upload-wrapper\">\r\n <div\r\n className={getUploadAreaClasses()}\r\n onDragOver={handleDragOver}\r\n onDragLeave={handleDragLeave}\r\n onDrop={handleDrop}\r\n onClick={(e) => {\r\n // Only trigger file picker in edit mode when no files exist and not clicking on file items\r\n const target = e.target as HTMLElement;\r\n const isClickOnFileItem = target.closest('.file-item') !== null;\r\n const isClickOnRemoveButton = target.closest('.file-remove') !== null;\r\n \r\n if (isEditMode && !shouldDisable && files.length === 0 && !isClickOnFileItem && !isClickOnRemoveButton) {\r\n fileInputRef.current?.click();\r\n }\r\n }}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n tabIndex={shouldDisable ? -1 : 0}\r\n >\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n id={id}\r\n multiple={isMultiple}\r\n accept={acceptTypes}\r\n onChange={handleFileInputChange}\r\n disabled={shouldDisable}\r\n style={{ display: 'none' }}\r\n />\r\n \r\n {files.length === 0 ? (\r\n <div \r\n className=\"upload-placeholder\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n if (isEditMode && !shouldDisable) {\r\n fileInputRef.current?.click();\r\n }\r\n }}\r\n >\r\n <div className=\"upload-icon\">📁</div>\r\n <div className=\"upload-text\">\r\n {/* <p>Drop files here or click to browse</p> */}\r\n {properties.basic.placeholder && (\r\n <p className=\"upload-hint\">{properties.basic.placeholder}</p>\r\n )}\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"file-list\">\r\n {files.map((file) => (\r\n <div key={file.id} className=\"file-item\">\r\n <div className=\"file-preview\">\r\n {file.preview ? (\r\n <img src={file.preview} alt={file.name} className=\"file-image\" />\r\n ) : (\r\n <div className=\"file-icon\">{getFileIcon(file.type)}</div>\r\n )}\r\n </div>\r\n <div className=\"file-info\">\r\n <div className=\"file-name\" title={file.name}>{file.name}</div>\r\n <div className=\"file-size\">{formatFileSize(file.size)}</div>\r\n </div>\r\n {isEditMode && !shouldDisable && (\r\n <button\r\n type=\"button\"\r\n className=\"file-remove\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n removeFile(file.id);\r\n }}\r\n aria-label={`Remove ${file.name}`}\r\n >\r\n ✕\r\n </button>\r\n )}\r\n </div>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n\r\n {files.length > 0 && canAddMoreFiles && !shouldDisable && isEditMode && (\r\n <button\r\n type=\"button\"\r\n className=\"file-add-more\"\r\n onClick={handleAddMoreFiles}\r\n aria-label=\"Add more files\"\r\n >\r\n <svg\r\n className=\"file-add-icon\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n strokeWidth=\"2\"\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n >\r\n <path d=\"M12 5v14M5 12h14\" />\r\n </svg>\r\n <span className=\"file-add-text\">Add More Files</span>\r\n </button>\r\n )}\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={validateFiles()}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormFileUpload;\r\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { \r\n ILocationComponent, \r\n IFormControlChange,\r\n IFormValidationErrors\r\n} from '../df-form-preview-interfaces';\r\nimport { DfFormErrorMsg } from '../df-form-error-msg';\r\nimport { MapPin, Navigation, X, Loader2 } from 'lucide-react';\r\n\r\ninterface DfFormLocationProps {\r\n id: string;\r\n properties: ILocationComponent;\r\n validationErrors?: IFormValidationErrors;\r\n formValue?: ILocationData | null;\r\n readonly?: boolean;\r\n disabled?: boolean;\r\n touchedFields?: Record<string, boolean>;\r\n formSubmitted?: boolean;\r\n mode?: 'edit' | 'preview' | 'test';\r\n onValueChange?: (change: IFormControlChange) => void;\r\n onBlur?: () => void;\r\n onFocus?: () => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\ninterface ILocationData {\r\n latitude: number;\r\n longitude: number;\r\n accuracy?: number;\r\n timestamp?: number;\r\n address?: string;\r\n placeName?: string;\r\n city?: string;\r\n country?: string;\r\n}\r\n\r\ninterface IMapMarker {\r\n lat: number;\r\n lng: number;\r\n isCurrentLocation?: boolean;\r\n}\r\n\r\nexport const DfFormLocation: React.FC<DfFormLocationProps> = ({\r\n id,\r\n properties,\r\n validationErrors = {},\r\n formValue = null,\r\n readonly = false,\r\n disabled = false,\r\n touchedFields = {},\r\n formSubmitted = false,\r\n mode = 'test',\r\n onValueChange,\r\n onBlur,\r\n onFocus,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [locationData, setLocationData] = useState<ILocationData | null>(formValue);\r\n const [isLoading, setIsLoading] = useState<boolean>(false);\r\n const [error, setError] = useState<string>('');\r\n const [isTouched, setIsTouched] = useState<boolean>(false);\r\n const [showMap, setShowMap] = useState<boolean>(false);\r\n const [mapCenter, setMapCenter] = useState<{ lat: number; lng: number }>({ lat: 40.7128, lng: -74.0060 });\r\n const [mapMarker, setMapMarker] = useState<IMapMarker | null>(null);\r\n const [mapZoom, setMapZoom] = useState<number>(10);\r\n const [searchQuery, setSearchQuery] = useState<string>('');\r\n const [isSearching, setIsSearching] = useState<boolean>(false);\r\n const mapRef = useRef<HTMLDivElement>(null);\r\n const [isDragging, setIsDragging] = useState<boolean>(false);\r\n const [dragStart, setDragStart] = useState<{ x: number; y: number } | null>(null);\r\n const [isReverseGeocoding, setIsReverseGeocoding] = useState<boolean>(false);\r\n\r\n // Update location data when formValue prop changes\r\n // CRITICAL: Only update if formValue is actually provided (not default/cached)\r\n useEffect(() => {\r\n if (formValue && formValue.latitude && formValue.longitude) {\r\n // Only set location if it's a valid location (not default coordinates)\r\n // Check if it's not the default New York coordinates\r\n const isDefaultLocation = formValue.latitude === 40.7128 && formValue.longitude === -74.0060;\r\n if (!isDefaultLocation) {\r\n setLocationData(formValue);\r\n setMapMarker({\r\n lat: formValue.latitude,\r\n lng: formValue.longitude,\r\n isCurrentLocation: false\r\n });\r\n setMapCenter({ lat: formValue.latitude, lng: formValue.longitude });\r\n }\r\n } else {\r\n // Only clear if formValue is explicitly null/undefined, not if it's missing\r\n if (formValue === null || formValue === undefined) {\r\n setLocationData(null);\r\n setMapMarker(null);\r\n }\r\n }\r\n }, [formValue]);\r\n\r\n // Initialize map with default center (New York)\r\n useEffect(() => {\r\n if (showMap && mapCenter.lat === 40.7128 && mapCenter.lng === -74.0060) {\r\n // Map is already initialized with default center\r\n }\r\n }, [showMap, mapCenter]);\r\n\r\n // Close map and reset map-related state when component becomes disabled (e.g., switching to edit mode)\r\n useEffect(() => {\r\n if (readonly || disabled) {\r\n // Close map if component is disabled/readonly (edit/preview mode)\r\n if (showMap) {\r\n setShowMap(false);\r\n }\r\n // Reset search query and dragging state\r\n if (searchQuery) {\r\n setSearchQuery('');\r\n }\r\n if (isDragging) {\r\n setIsDragging(false);\r\n setDragStart(null);\r\n }\r\n }\r\n }, [readonly, disabled]);\r\n\r\n // Reverse geocoding to get address details\r\n const reverseGeocode = useCallback(async (lat: number, lng: number) => {\r\n setIsReverseGeocoding(true);\r\n try {\r\n const response = await fetch(\r\n `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&addressdetails=1&zoom=18`\r\n );\r\n const data = await response.json();\r\n \r\n if (data && data.address) {\r\n const address = data.address;\r\n return {\r\n placeName: data.display_name || '',\r\n city: address.city || address.town || address.village || address.municipality || '',\r\n country: address.country || ''\r\n };\r\n }\r\n } catch (err) {\r\n console.error('Reverse geocoding failed:', err);\r\n } finally {\r\n setIsReverseGeocoding(false);\r\n }\r\n return { placeName: '', city: '', country: '' };\r\n }, []);\r\n\r\n // Update location data with reverse geocoding\r\n const updateLocationWithAddress = useCallback(async (lat: number, lng: number, existingData?: Partial<ILocationData>) => {\r\n const addressData = await reverseGeocode(lat, lng);\r\n const location: ILocationData = {\r\n latitude: lat,\r\n longitude: lng,\r\n timestamp: Date.now(),\r\n placeName: addressData.placeName,\r\n city: addressData.city,\r\n country: addressData.country,\r\n address: addressData.placeName,\r\n ...existingData\r\n };\r\n \r\n setLocationData(location);\r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: false\r\n });\r\n setIsTouched(true);\r\n\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: location,\r\n isValid: true,\r\n errors: {},\r\n };\r\n onValueChange(change);\r\n }\r\n }, [reverseGeocode, id, onValueChange]);\r\n\r\n // Get current location using geolocation API\r\n // CRITICAL: Support both mobile (Capacitor) and web browsers\r\n const getCurrentLocation = useCallback(async () => {\r\n if (readonly || disabled) return;\r\n\r\n setIsLoading(true);\r\n setError('');\r\n\r\n // Check if we're in a Capacitor/Ionic environment (mobile app)\r\n const isCapacitor = typeof (window as any).Capacitor !== 'undefined';\r\n \r\n if (isCapacitor) {\r\n try {\r\n // Use Capacitor Geolocation plugin for mobile devices\r\n const { Geolocation } = (window as any).Capacitor.Plugins;\r\n \r\n if (Geolocation) {\r\n try {\r\n // Request permissions first (required for mobile)\r\n const permissionStatus = await Geolocation.requestPermissions();\r\n \r\n if (permissionStatus.location !== 'granted') {\r\n setIsLoading(false);\r\n setError('Location permission is required. Please enable location access in your device settings.');\r\n return;\r\n }\r\n \r\n // Get position using Capacitor Geolocation\r\n const position = await Geolocation.getCurrentPosition({\r\n enableHighAccuracy: properties.validation?.enableHighAccuracy ?? true,\r\n timeout: properties.validation?.timeout ?? 10000,\r\n maximumAge: properties.validation?.maximumAge ?? 300000\r\n });\r\n \r\n const lat = position.coords.latitude;\r\n const lng = position.coords.longitude;\r\n \r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: true\r\n });\r\n setMapCenter({ lat, lng });\r\n setIsTouched(true);\r\n \r\n // Update location with reverse geocoding\r\n await updateLocationWithAddress(lat, lng, {\r\n accuracy: position.coords.accuracy,\r\n timestamp: Date.now()\r\n });\r\n \r\n setIsLoading(false);\r\n setError(''); // Clear any previous errors\r\n return; // Success - exit early\r\n } catch (capError: any) {\r\n setIsLoading(false);\r\n // Handle Capacitor-specific errors\r\n if (capError.message?.includes('permission') || capError.message?.includes('denied')) {\r\n setError('Location permission is required. Please enable location access in your device settings.');\r\n } else if (capError.message?.includes('timeout')) {\r\n setError('Location request timed out. Please try again.');\r\n } else {\r\n setError('Unable to retrieve your location. Please try again.');\r\n }\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n // Capacitor not properly initialized, fall through to web geolocation\r\n console.warn('Capacitor Geolocation not available, falling back to web geolocation');\r\n }\r\n }\r\n\r\n // Fallback to standard web geolocation API (for browsers)\r\n if (!navigator.geolocation) {\r\n setIsLoading(false);\r\n setError('Geolocation is not supported by this browser.');\r\n return;\r\n }\r\n\r\n const options: PositionOptions = {\r\n enableHighAccuracy: properties.validation?.enableHighAccuracy ?? true,\r\n timeout: properties.validation?.timeout ?? 10000,\r\n maximumAge: properties.validation?.maximumAge ?? 300000 // 5 minutes\r\n };\r\n\r\n navigator.geolocation.getCurrentPosition(\r\n async (position) => {\r\n const lat = position.coords.latitude;\r\n const lng = position.coords.longitude;\r\n \r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: true\r\n });\r\n setMapCenter({ lat, lng });\r\n setIsTouched(true);\r\n \r\n // Update location with reverse geocoding\r\n await updateLocationWithAddress(lat, lng, {\r\n accuracy: position.coords.accuracy,\r\n timestamp: position.timestamp\r\n });\r\n \r\n setIsLoading(false);\r\n setError(''); // Clear any previous errors\r\n },\r\n (error) => {\r\n setIsLoading(false);\r\n let errorMessage = 'Unable to retrieve your location.';\r\n \r\n switch (error.code) {\r\n case error.PERMISSION_DENIED:\r\n errorMessage = 'Location access denied by user. Please enable location access in your browser/device settings.';\r\n break;\r\n case error.POSITION_UNAVAILABLE:\r\n errorMessage = 'Location information is unavailable.';\r\n break;\r\n case error.TIMEOUT:\r\n errorMessage = 'Location request timed out. Please try again.';\r\n break;\r\n }\r\n \r\n setError(errorMessage);\r\n },\r\n options\r\n );\r\n }, [readonly, disabled, properties, updateLocationWithAddress]);\r\n\r\n // Clear location data\r\n const clearLocation = useCallback(() => {\r\n if (readonly || disabled) return;\r\n\r\n setLocationData(null);\r\n setMapMarker(null);\r\n setError('');\r\n setIsTouched(true);\r\n\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: null,\r\n isValid: true,\r\n errors: {},\r\n };\r\n onValueChange(change);\r\n }\r\n }, [readonly, disabled, id, onValueChange]);\r\n\r\n // Toggle map visibility\r\n const toggleMap = useCallback(() => {\r\n if (readonly || disabled) return;\r\n setShowMap(!showMap);\r\n }, [readonly, disabled, showMap]);\r\n\r\n // Convert pixel coordinates to lat/lng using proper Web Mercator projection\r\n const pixelToLatLng = useCallback((x: number, y: number, center: { lat: number; lng: number }, zoom: number, width: number, height: number) => {\r\n // Calculate pixel offset from center\r\n const offsetX = x - width / 2;\r\n const offsetY = y - height / 2;\r\n \r\n // Convert to meters (approximate)\r\n const metersPerPixel = (156543.03392 * Math.cos(center.lat * Math.PI / 180)) / Math.pow(2, zoom);\r\n const metersX = offsetX * metersPerPixel;\r\n const metersY = offsetY * metersPerPixel;\r\n \r\n // Convert meters to lat/lng\r\n const lat = center.lat + (metersY / 111320);\r\n const lng = center.lng + (metersX / (111320 * Math.cos(center.lat * Math.PI / 180)));\r\n \r\n return { lat, lng };\r\n }, []);\r\n\r\n // Handle map mouse down (start drag)\r\n const handleMapMouseDown = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\r\n if (readonly || disabled || !mapRef.current) return;\r\n if (event.button !== 0) return; // Only handle left mouse button\r\n \r\n setIsDragging(true);\r\n setDragStart({ x: event.clientX, y: event.clientY });\r\n event.preventDefault();\r\n }, [readonly, disabled]);\r\n\r\n // Handle map mouse move (during drag)\r\n const handleMapMouseMove = useCallback((event: React.MouseEvent<HTMLDivElement>) => {\r\n if (!isDragging || !dragStart || !mapRef.current) return;\r\n \r\n const deltaX = event.clientX - dragStart.x;\r\n const deltaY = event.clientY - dragStart.y;\r\n \r\n // Convert pixel offset to lat/lng offset\r\n const metersPerPixel = (156543.03392 * Math.cos(mapCenter.lat * Math.PI / 180)) / Math.pow(2, mapZoom);\r\n const latOffset = -(deltaY * metersPerPixel) / 111320;\r\n const lngOffset = (deltaX * metersPerPixel) / (111320 * Math.cos(mapCenter.lat * Math.PI / 180));\r\n \r\n setMapCenter({\r\n lat: mapCenter.lat + latOffset,\r\n lng: mapCenter.lng + lngOffset\r\n });\r\n \r\n setDragStart({ x: event.clientX, y: event.clientY });\r\n }, [isDragging, dragStart, mapCenter, mapZoom]);\r\n\r\n // Handle map mouse up (end drag or click)\r\n const handleMapMouseUp = useCallback(async (event: React.MouseEvent<HTMLDivElement>) => {\r\n if (!mapRef.current) return;\r\n \r\n if (isDragging && dragStart) {\r\n // Check if it was a drag (moved more than 5 pixels)\r\n const deltaX = Math.abs(event.clientX - dragStart.x);\r\n const deltaY = Math.abs(event.clientY - dragStart.y);\r\n \r\n if (deltaX > 5 || deltaY > 5) {\r\n // It was a drag, just update the center\r\n setIsDragging(false);\r\n setDragStart(null);\r\n return;\r\n }\r\n }\r\n \r\n // It was a click, select location\r\n if (readonly || disabled) {\r\n setIsDragging(false);\r\n setDragStart(null);\r\n return;\r\n }\r\n \r\n const rect = mapRef.current.getBoundingClientRect();\r\n const x = event.clientX - rect.left;\r\n const y = event.clientY - rect.top;\r\n \r\n const { lat, lng } = pixelToLatLng(x, y, mapCenter, mapZoom, rect.width, rect.height);\r\n \r\n // Update location with reverse geocoding\r\n await updateLocationWithAddress(lat, lng);\r\n \r\n setIsDragging(false);\r\n setDragStart(null);\r\n }, [readonly, disabled, mapRef, mapCenter, mapZoom, pixelToLatLng, updateLocationWithAddress, isDragging, dragStart]);\r\n\r\n // Search for location using Nominatim API (OpenStreetMap)\r\n const searchLocation = useCallback(async (query: string) => {\r\n if (!query.trim() || readonly || disabled) return;\r\n\r\n setIsSearching(true);\r\n setError('');\r\n\r\n try {\r\n const response = await fetch(\r\n `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(query)}&limit=5&addressdetails=1`\r\n );\r\n const results = await response.json();\r\n\r\n if (results && results.length > 0) {\r\n const firstResult = results[0];\r\n const lat = parseFloat(firstResult.lat);\r\n const lng = parseFloat(firstResult.lon);\r\n\r\n // Extract address components\r\n const address = firstResult.address || {};\r\n const location: ILocationData = {\r\n latitude: lat,\r\n longitude: lng,\r\n address: firstResult.display_name,\r\n placeName: firstResult.display_name,\r\n city: address.city || address.town || address.village || address.municipality || '',\r\n country: address.country || '',\r\n timestamp: Date.now()\r\n };\r\n\r\n setLocationData(location);\r\n setMapMarker({\r\n lat: lat,\r\n lng: lng,\r\n isCurrentLocation: false\r\n });\r\n setMapCenter({ lat, lng });\r\n setIsTouched(true);\r\n\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: location,\r\n isValid: true,\r\n errors: {},\r\n };\r\n onValueChange(change);\r\n }\r\n } else {\r\n setError('No locations found for your search.');\r\n }\r\n } catch (err) {\r\n setError('Failed to search for location. Please try again.');\r\n } finally {\r\n setIsSearching(false);\r\n }\r\n }, [readonly, disabled, id, onValueChange]);\r\n\r\n // Handle search input change\r\n const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setSearchQuery(event.target.value);\r\n };\r\n\r\n // Handle search form submission\r\n const handleSearchSubmit = (event: React.FormEvent) => {\r\n event.preventDefault();\r\n if (searchQuery.trim()) {\r\n searchLocation(searchQuery);\r\n }\r\n };\r\n\r\n // Handle focus\r\n const handleFocus = () => {\r\n if (onFocus) {\r\n onFocus();\r\n }\r\n };\r\n\r\n // Handle blur\r\n const handleBlur = () => {\r\n setIsTouched(true);\r\n \r\n if (onBlur) {\r\n onBlur();\r\n }\r\n };\r\n\r\n // Format coordinates for display\r\n const formatCoordinates = (lat: number | undefined, lng: number | undefined): string => {\r\n if (lat === undefined || lng === undefined || isNaN(lat) || isNaN(lng)) {\r\n return '';\r\n }\r\n return `${Number(lat).toFixed(6)}, ${Number(lng).toFixed(6)}`;\r\n };\r\n\r\n // Format accuracy for display\r\n const formatAccuracy = (accuracy?: number): string => {\r\n if (!accuracy) return '';\r\n return `±${Math.round(accuracy)}m`;\r\n };\r\n\r\n const shouldDisable = disabled || readonly || properties?.validation?.readonly;\r\n const label = properties?.basic?.label || 'Location';\r\n const description = properties?.basic?.description || '';\r\n\r\n return (\r\n <div className={`form-group ${hideLabel ? 'no-label' : ''} ${className}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"form-label\">\r\n {label}\r\n {properties?.validation?.required && <span className=\"required-indicator\">*</span>}\r\n </label>\r\n )}\r\n\r\n {description && (\r\n <div className=\"form-group-description\">\r\n {description}\r\n </div>\r\n )}\r\n\r\n <div className=\"location-wrapper\">\r\n {/* Hide buttons when readonly and location data exists (submission view) */}\r\n {!(readonly && locationData) && (\r\n <div className=\"location-controls\">\r\n <button\r\n type=\"button\"\r\n className={`location-btn ${isLoading ? 'loading' : ''}`}\r\n onClick={getCurrentLocation}\r\n disabled={shouldDisable || isLoading}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n tabIndex={shouldDisable ? -1 : 0}\r\n >\r\n {isLoading ? (\r\n <>\r\n <Loader2 size={16} className=\"loading-spinner\" />\r\n Getting Location...\r\n </>\r\n ) : (\r\n <>\r\n <Navigation size={16} />\r\n Get Current Location\r\n </>\r\n )}\r\n </button>\r\n\r\n <button\r\n type=\"button\"\r\n className=\"location-btn secondary\"\r\n onClick={toggleMap}\r\n disabled={shouldDisable}\r\n onFocus={handleFocus}\r\n onBlur={handleBlur}\r\n tabIndex={shouldDisable ? -1 : 0}\r\n >\r\n <MapPin size={16} />\r\n {showMap ? 'Hide Map' : 'Choose on Map'}\r\n </button>\r\n </div>\r\n )}\r\n\r\n {locationData && (\r\n <div className=\"location-display\">\r\n {/* Hide clear button when readonly (submission view) */}\r\n {!readonly && (\r\n <button\r\n type=\"button\"\r\n className=\"location-clear-btn\"\r\n onClick={clearLocation}\r\n disabled={shouldDisable}\r\n title=\"Clear location\"\r\n >\r\n <X size={16} />\r\n </button>\r\n )}\r\n {locationData.placeName && (\r\n <div className=\"location-place-name\">\r\n <strong>Place:</strong> {locationData.placeName}\r\n </div>\r\n )}\r\n {(locationData.city || locationData.country) && (\r\n <div className=\"location-address\">\r\n <strong>Address:</strong> {[locationData.city, locationData.country].filter(Boolean).join(', ')}\r\n </div>\r\n )}\r\n <div className=\"location-coordinates\">\r\n <strong>Coordinates:</strong> {formatCoordinates(locationData.latitude, locationData.longitude)}\r\n </div>\r\n {locationData.accuracy && (\r\n <div className=\"location-accuracy\">\r\n <strong>Accuracy:</strong> {formatAccuracy(locationData.accuracy)}\r\n </div>\r\n )}\r\n {locationData.timestamp && (\r\n <div className=\"location-timestamp\">\r\n <strong>Captured:</strong> {new Date(locationData.timestamp).toLocaleString()}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Hide map when readonly (submission view) */}\r\n {showMap && !readonly && (\r\n <div className=\"location-map-container\">\r\n <div className=\"location-map-header\">\r\n <h4>Select Location on Map</h4>\r\n <p>Search for a place or click on the map to select a location</p>\r\n </div>\r\n \r\n {/* Search functionality */}\r\n <div className=\"location-search\">\r\n <form onSubmit={handleSearchSubmit} className=\"search-form\">\r\n <div className=\"search-input-group\">\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={handleSearchChange}\r\n placeholder=\"Search for a place (e.g., New York, Paris, Tokyo)\"\r\n className=\"search-input\"\r\n disabled={shouldDisable || isSearching}\r\n />\r\n <button\r\n type=\"submit\"\r\n className=\"search-btn\"\r\n disabled={shouldDisable || isSearching || !searchQuery.trim()}\r\n >\r\n {isSearching ? (\r\n <Loader2 size={16} className=\"loading-spinner\" />\r\n ) : (\r\n 'Search'\r\n )}\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n\r\n {/* Map container */}\r\n <div \r\n ref={mapRef}\r\n className={`location-map ${isDragging ? 'dragging' : ''}`}\r\n onMouseDown={handleMapMouseDown}\r\n onMouseMove={handleMapMouseMove}\r\n onMouseUp={handleMapMouseUp}\r\n onMouseLeave={() => {\r\n setIsDragging(false);\r\n setDragStart(null);\r\n }}\r\n style={{\r\n position: 'relative',\r\n height: '400px',\r\n border: '2px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n cursor: isDragging ? 'grabbing' : 'grab',\r\n background: `url(https://tile.openstreetmap.org/${mapZoom}/${Math.floor((mapCenter.lng + 180) / 360 * Math.pow(2, mapZoom))}/${Math.floor((1 - Math.log(Math.tan(mapCenter.lat * Math.PI / 180) + 1 / Math.cos(mapCenter.lat * Math.PI / 180)) / Math.PI) / 2 * Math.pow(2, mapZoom))}.png) center/cover no-repeat`,\r\n userSelect: 'none'\r\n }}\r\n >\r\n {/* Map marker */}\r\n {mapMarker && (\r\n <div\r\n className={`map-marker ${mapMarker.isCurrentLocation ? 'current-location' : 'selected-location'}`}\r\n style={{\r\n position: 'absolute',\r\n left: '50%',\r\n top: '50%',\r\n transform: 'translate(-50%, -100%)',\r\n zIndex: 10\r\n }}\r\n >\r\n <MapPin size={24} />\r\n </div>\r\n )}\r\n \r\n {/* Map center indicator */}\r\n <div\r\n className=\"map-center-indicator\"\r\n style={{\r\n position: 'absolute',\r\n left: '50%',\r\n top: '50%',\r\n transform: 'translate(-50%, -50%)',\r\n width: '4px',\r\n height: '4px',\r\n backgroundColor: 'var(--df-color-primary)',\r\n borderRadius: '50%',\r\n zIndex: 5\r\n }}\r\n />\r\n\r\n {/* Map controls */}\r\n <div className=\"map-controls\">\r\n <button\r\n type=\"button\"\r\n className=\"map-zoom-btn\"\r\n onClick={() => setMapZoom(prev => Math.min(18, prev + 1))}\r\n disabled={mapZoom >= 18}\r\n >\r\n +\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"map-zoom-btn\"\r\n onClick={() => setMapZoom(prev => Math.max(1, prev - 1))}\r\n disabled={mapZoom <= 1}\r\n >\r\n −\r\n </button>\r\n </div>\r\n </div>\r\n \r\n <div className=\"location-map-instructions\">\r\n <p><strong>Instructions:</strong></p>\r\n <ul>\r\n <li>Search for a place using the search box above</li>\r\n <li>Click anywhere on the map to select a location</li>\r\n <li>Drag the map to pan around</li>\r\n <li>Use the zoom buttons (+/−) to zoom in/out</li>\r\n <li>Use \"Get Current Location\" to automatically detect your position</li>\r\n </ul>\r\n </div>\r\n \r\n {isReverseGeocoding && (\r\n <div className=\"location-loading\">\r\n <Loader2 size={16} className=\"loading-spinner\" />\r\n <span>Loading address details...</span>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {error && (\r\n <div className=\"location-error\">\r\n {error}\r\n </div>\r\n )}\r\n </div>\r\n\r\n <DfFormErrorMsg\r\n validationErrors={validationErrors}\r\n fieldId={id}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n properties={properties}\r\n localValidation={{ isValid: true, errors: {} }}\r\n isTouched={isTouched}\r\n mode={mode}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormLocation;\r\n","import React from 'react';\r\nimport { IHeadingComponent } from '../df-form-preview-interfaces';\r\n\r\ninterface DfFormHeadingProps {\r\n id: string;\r\n properties: IHeadingComponent;\r\n mode?: 'edit' | 'preview' | 'test';\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormHeading: React.FC<DfFormHeadingProps> = ({\r\n id,\r\n properties,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const level = (properties.styles as any)?.level ?? properties.basic.level ?? 1;\r\n const text = properties.basic.label;\r\n \r\n // Get heading classes\r\n const getHeadingClasses = (): string => {\r\n const base = 'form-heading';\r\n const levelClass = `h${level}`;\r\n const alignment = properties?.styles?.textAlign ? `text-${properties.styles.textAlign}` : '';\r\n return `${base} ${levelClass} ${alignment} ${className}`.trim();\r\n };\r\n\r\n // Get inline styles\r\n const getInlineStyles = (): React.CSSProperties => {\r\n const styles: React.CSSProperties = {};\r\n \r\n if (properties?.styles?.fontSize) {\r\n styles.fontSize = properties.styles.fontSize;\r\n }\r\n \r\n if (properties?.styles?.color) {\r\n styles.color = properties.styles.color;\r\n }\r\n \r\n return styles;\r\n };\r\n\r\n // Render the appropriate heading element\r\n const renderHeading = () => {\r\n const headingProps = {\r\n id,\r\n className: getHeadingClasses(),\r\n style: getInlineStyles(),\r\n };\r\n\r\n switch (level) {\r\n case 1:\r\n return <h1 {...headingProps}>{text}</h1>;\r\n case 2:\r\n return <h2 {...headingProps}>{text}</h2>;\r\n case 3:\r\n return <h3 {...headingProps}>{text}</h3>;\r\n case 4:\r\n return <h4 {...headingProps}>{text}</h4>;\r\n case 5:\r\n return <h5 {...headingProps}>{text}</h5>;\r\n case 6:\r\n return <h6 {...headingProps}>{text}</h6>;\r\n default:\r\n return <h1 {...headingProps}>{text}</h1>;\r\n }\r\n };\r\n\r\n // If hideLabel is true, don't render the heading\r\n if (hideLabel) {\r\n return null;\r\n }\r\n \r\n return renderHeading();\r\n};\r\n\r\nexport default DfFormHeading;\r\n","import React, { useState, useEffect, useCallback, useRef } from 'react';\r\nimport { Bold, Italic, Image, List, ListOrdered } from 'lucide-react';\r\nimport { \r\n IInstructionComponent, \r\n IFormControlChange\r\n} from '../df-form-preview-interfaces';\r\n\r\ninterface DfFormInstructionProps {\r\n id: string;\r\n properties: IInstructionComponent;\r\n mode?: 'edit' | 'preview' | 'test';\r\n formValue?: any; // Add formValue prop to receive data from formValues\r\n onValueChange?: (change: IFormControlChange) => void;\r\n className?: string;\r\n hideLabel?: boolean;\r\n}\r\n\r\nexport const DfFormInstruction: React.FC<DfFormInstructionProps> = ({\r\n id,\r\n properties,\r\n mode = 'preview',\r\n formValue,\r\n onValueChange,\r\n className = '',\r\n hideLabel = false\r\n}) => {\r\n const [htmlContent, setHtmlContent] = useState<string>('');\r\n const [listStyle, setListStyle] = useState<'none' | 'numbers' | 'bullets' | 'alpha'>(\r\n properties.validation?.listStyle || 'numbers'\r\n );\r\n const [selectedColor, setSelectedColor] = useState<string>('#000000');\r\n const editorRef = useRef<HTMLDivElement>(null);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const isUserInputRef = useRef(false);\r\n const isEditable = mode === 'edit';\r\n\r\n // Track previous properties to detect actual changes\r\n const prevPropsRef = useRef<{ instructions: string[]; listStyle: string; formValue: any }>({ \r\n instructions: [], \r\n listStyle: 'numbers',\r\n formValue: undefined\r\n });\r\n const prevModeRef = useRef<string>(mode);\r\n \r\n // Initialize content from properties - update when properties change or mode changes\r\n useEffect(() => {\r\n // CRITICAL: Check formValue first (from API/formValues), then fallback to properties\r\n // Handle different data formats for instructions\r\n let propsInstructions: string[] = [];\r\n let propsListStyle: 'none' | 'numbers' | 'bullets' | 'alpha' = 'numbers';\r\n \r\n // Priority 1: Check formValue (from API response or formValues state)\r\n if (formValue !== undefined && formValue !== null) {\r\n if (typeof formValue === 'object' && formValue.instructions) {\r\n // If formValue is an object with instructions property\r\n if (Array.isArray(formValue.instructions)) {\r\n propsInstructions = formValue.instructions;\r\n } else if (typeof formValue.instructions === 'string') {\r\n propsInstructions = [formValue.instructions];\r\n }\r\n // Check for listStyle in formValue\r\n if (formValue.listStyle) {\r\n propsListStyle = formValue.listStyle;\r\n }\r\n } else if (Array.isArray(formValue)) {\r\n propsInstructions = formValue;\r\n } else if (typeof formValue === 'string') {\r\n propsInstructions = [formValue];\r\n }\r\n }\r\n \r\n // Priority 2: Check properties.basic.value (API data structure)\r\n if (propsInstructions.length === 0 && properties.basic?.value) {\r\n const basicValue = properties.basic.value as any;\r\n if (basicValue && typeof basicValue === 'object' && !Array.isArray(basicValue) && basicValue.instructions) {\r\n // API structure: basic.value.instructions\r\n if (Array.isArray(basicValue.instructions)) {\r\n propsInstructions = basicValue.instructions;\r\n } else if (typeof basicValue.instructions === 'string') {\r\n propsInstructions = [basicValue.instructions];\r\n }\r\n // Get listStyle from basic.value.listStyle\r\n if (basicValue.listStyle && typeof basicValue.listStyle === 'string') {\r\n propsListStyle = basicValue.listStyle as 'none' | 'numbers' | 'bullets' | 'alpha';\r\n }\r\n } else if (Array.isArray(basicValue)) {\r\n propsInstructions = basicValue;\r\n } else if (typeof basicValue === 'string') {\r\n propsInstructions = [basicValue];\r\n }\r\n }\r\n \r\n // Priority 3: Fallback to properties.basic.instructions if formValue is empty\r\n if (propsInstructions.length === 0 && properties.basic?.instructions) {\r\n if (Array.isArray(properties.basic.instructions)) {\r\n propsInstructions = properties.basic.instructions;\r\n } else if (typeof properties.basic.instructions === 'string') {\r\n // If it's a string, try to parse it or use it as single instruction\r\n propsInstructions = [properties.basic.instructions];\r\n }\r\n }\r\n \r\n // Get listStyle from validation or basic.value\r\n if (!propsListStyle || propsListStyle === 'numbers') {\r\n propsListStyle = properties.validation?.listStyle || \r\n (properties.basic?.value as any)?.listStyle || \r\n 'numbers';\r\n }\r\n \r\n // Check if properties have actually changed\r\n const propsChanged = \r\n JSON.stringify(propsInstructions) !== JSON.stringify(prevPropsRef.current.instructions) ||\r\n propsListStyle !== prevPropsRef.current.listStyle;\r\n \r\n // Check if mode changed (e.g., switching from preview to edit)\r\n const modeChanged = mode !== prevModeRef.current;\r\n \r\n // CRITICAL: Check if formValue actually changed (for API data)\r\n // Use deep comparison to detect changes\r\n const formValueChanged = JSON.stringify(formValue) !== JSON.stringify(prevPropsRef.current.formValue);\r\n \r\n // CRITICAL: Also check if formValue was previously empty/null and now has data\r\n const formValueWasEmpty = !prevPropsRef.current.formValue || \r\n (Array.isArray(prevPropsRef.current.formValue) && prevPropsRef.current.formValue.length === 0) ||\r\n (typeof prevPropsRef.current.formValue === 'string' && prevPropsRef.current.formValue.trim() === '');\r\n const formValueNowHasData = formValue !== undefined && formValue !== null && \r\n ((Array.isArray(formValue) && formValue.length > 0) ||\r\n (typeof formValue === 'string' && formValue.trim() !== '') ||\r\n (typeof formValue === 'object' && Object.keys(formValue).length > 0));\r\n const formValueJustLoaded = formValueWasEmpty && formValueNowHasData;\r\n \r\n // Update if properties changed, mode changed, formValue changed (API data), or formValue just loaded\r\n if (propsChanged || modeChanged || formValueChanged || formValueJustLoaded) {\r\n // CRITICAL: Decode URL-encoded HTML strings (e.g., \\u003Cul\\u003E -> <ul>)\r\n const decodeHtml = (str: string): string => {\r\n if (typeof str !== 'string') return str;\r\n // Decode Unicode escape sequences\r\n return str.replace(/\\\\u([0-9a-fA-F]{4})/g, (match, code) => {\r\n return String.fromCharCode(parseInt(code, 16));\r\n });\r\n };\r\n \r\n // Decode all instruction strings\r\n const decodedInstructions = propsInstructions.map(inst => {\r\n if (typeof inst === 'string') {\r\n return decodeHtml(inst);\r\n }\r\n return inst;\r\n });\r\n \r\n const hasHtml = decodedInstructions.some(inst => typeof inst === 'string' && /<[^>]+>/.test(inst));\r\n let expectedContent = '';\r\n \r\n if (decodedInstructions.length > 0) {\r\n if (hasHtml) {\r\n // Already has HTML - just join and use as is\r\n expectedContent = decodedInstructions.join('');\r\n } else {\r\n const listTag = propsListStyle === 'numbers' ? 'ol' : propsListStyle === 'bullets' ? 'ul' : 'div';\r\n const listItems = decodedInstructions\r\n .filter(inst => inst && typeof inst === 'string')\r\n .map(inst => `<li>${inst.replace(/\\n/g, '<br>')}</li>`)\r\n .join('');\r\n \r\n if (listTag === 'div') {\r\n expectedContent = decodedInstructions\r\n .filter(inst => inst && typeof inst === 'string')\r\n .map(inst => `<div>${inst.replace(/\\n/g, '<br>')}</div>`)\r\n .join('');\r\n } else {\r\n expectedContent = `<${listTag}>${listItems}</${listTag}>`;\r\n }\r\n }\r\n }\r\n \r\n // Update state\r\n setListStyle(propsListStyle);\r\n setHtmlContent(expectedContent);\r\n \r\n // Update editor content when switching to edit mode or when properties change\r\n if (isEditable && editorRef.current) {\r\n // When switching to edit mode, always load from properties\r\n // When properties change, update if content is different\r\n if (modeChanged || (propsChanged && editorRef.current.innerHTML.trim() !== expectedContent.trim())) {\r\n editorRef.current.innerHTML = expectedContent;\r\n }\r\n }\r\n \r\n // Update previous refs\r\n prevPropsRef.current = { \r\n instructions: propsInstructions, \r\n listStyle: propsListStyle,\r\n formValue: formValue\r\n };\r\n prevModeRef.current = mode;\r\n }\r\n }, [formValue, properties.basic?.instructions, properties.validation?.listStyle, mode, isEditable]);\r\n\r\n // Sync htmlContent to editor when it changes (but not on user input)\r\n // This is mainly for when properties change externally\r\n useEffect(() => {\r\n if (isEditable && editorRef.current) {\r\n const currentEditorContent = editorRef.current.innerHTML.trim();\r\n const htmlContentTrimmed = htmlContent.trim();\r\n \r\n // Only update if content is different and it's not from user input\r\n if (htmlContentTrimmed !== currentEditorContent && !isUserInputRef.current) {\r\n editorRef.current.innerHTML = htmlContent;\r\n }\r\n }\r\n \r\n // Reset user input flag after a delay to allow for property updates\r\n if (isUserInputRef.current) {\r\n const timeout = setTimeout(() => {\r\n isUserInputRef.current = false;\r\n }, 200);\r\n return () => clearTimeout(timeout);\r\n }\r\n }, [htmlContent, isEditable]);\r\n\r\n // Handle content change - always save when content changes\r\n const handleContentChange = useCallback(() => {\r\n if (!editorRef.current) return;\r\n \r\n isUserInputRef.current = true;\r\n const content = editorRef.current.innerHTML.trim();\r\n \r\n // Always save the current content, even if it appears unchanged\r\n // This ensures data is persisted when user types and saves quickly\r\n const htmlInstructions = content ? [content] : [];\r\n \r\n // Always call onValueChange to ensure data is saved to field state\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: {\r\n instructions: htmlInstructions,\r\n listStyle\r\n },\r\n isValid: true,\r\n errors: {}\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n // Update state only if content actually changed (to avoid unnecessary re-renders)\r\n if (content !== htmlContent) {\r\n setHtmlContent(content);\r\n }\r\n }, [id, listStyle, onValueChange, htmlContent]);\r\n\r\n // Save on blur to ensure data is persisted when user leaves the editor\r\n const handleBlur = useCallback(() => {\r\n if (!editorRef.current) return;\r\n \r\n const content = editorRef.current.innerHTML.trim();\r\n const htmlInstructions = content ? [content] : [];\r\n \r\n // Always save on blur to ensure persistence\r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: {\r\n instructions: htmlInstructions,\r\n listStyle\r\n },\r\n isValid: true,\r\n errors: {}\r\n };\r\n onValueChange(change);\r\n }\r\n \r\n // Update state to match\r\n setHtmlContent(content);\r\n isUserInputRef.current = false;\r\n }, [id, listStyle, onValueChange]);\r\n\r\n // Format text command\r\n const executeCommand = useCallback((command: string, value?: string) => {\r\n document.execCommand(command, false, value);\r\n editorRef.current?.focus();\r\n handleContentChange();\r\n }, [handleContentChange]);\r\n\r\n // Handle bold\r\n const handleBold = useCallback(() => {\r\n executeCommand('bold');\r\n }, [executeCommand]);\r\n\r\n // Handle italic\r\n const handleItalic = useCallback(() => {\r\n executeCommand('italic');\r\n }, [executeCommand]);\r\n\r\n // Handle color\r\n const handleColorChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const color = e.target.value;\r\n setSelectedColor(color);\r\n executeCommand('foreColor', color);\r\n }, [executeCommand]);\r\n\r\n // Handle list style change\r\n const handleListStyleChange = useCallback((style: 'none' | 'numbers' | 'bullets' | 'alpha') => {\r\n setListStyle(style);\r\n \r\n if (!editorRef.current) return;\r\n \r\n // Save current selection\r\n const selection = window.getSelection();\r\n const range = selection && selection.rangeCount > 0 ? selection.getRangeAt(0) : null;\r\n \r\n // Get current content\r\n let currentContent = editorRef.current.innerHTML;\r\n \r\n // Convert existing lists to the new format\r\n if (style === 'numbers') {\r\n // Convert ul to ol\r\n currentContent = currentContent.replace(/<ul>/gi, '<ol>').replace(/<\\/ul>/gi, '</ol>');\r\n // If no list exists, wrap content in ol\r\n if (!currentContent.includes('<ol>') && !currentContent.includes('<ul>')) {\r\n const lines = currentContent.split(/<br\\s*\\/?>/i).filter(line => line.trim());\r\n if (lines.length > 0) {\r\n currentContent = '<ol>' + lines.map(line => `<li>${line}</li>`).join('') + '</ol>';\r\n }\r\n }\r\n } else if (style === 'bullets') {\r\n // Convert ol to ul\r\n currentContent = currentContent.replace(/<ol>/gi, '<ul>').replace(/<\\/ol>/gi, '</ul>');\r\n // If no list exists, wrap content in ul\r\n if (!currentContent.includes('<ol>') && !currentContent.includes('<ul>')) {\r\n const lines = currentContent.split(/<br\\s*\\/?>/i).filter(line => line.trim());\r\n if (lines.length > 0) {\r\n currentContent = '<ul>' + lines.map(line => `<li>${line}</li>`).join('') + '</ul>';\r\n }\r\n }\r\n } else {\r\n // Remove list formatting\r\n currentContent = currentContent.replace(/<\\/?[ou]l>/gi, '').replace(/<li>/gi, '<div>').replace(/<\\/li>/gi, '</div>');\r\n }\r\n \r\n // Update editor content\r\n editorRef.current.innerHTML = currentContent;\r\n setHtmlContent(currentContent);\r\n \r\n // Restore selection if possible\r\n if (range && selection) {\r\n try {\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n } catch (e) {\r\n // Ignore selection errors\r\n }\r\n }\r\n \r\n // Trigger change\r\n handleContentChange();\r\n \r\n if (onValueChange) {\r\n const change: IFormControlChange = {\r\n id,\r\n value: {\r\n instructions: currentContent ? [currentContent] : [],\r\n listStyle: style\r\n },\r\n isValid: true,\r\n errors: {}\r\n };\r\n onValueChange(change);\r\n }\r\n }, [id, handleContentChange, onValueChange]);\r\n\r\n // Handle image upload\r\n const handleImageUpload = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const file = e.target.files?.[0];\r\n if (!file || !file.type.startsWith('image/')) return;\r\n \r\n const reader = new FileReader();\r\n reader.onload = (event) => {\r\n const imageUrl = event.target?.result as string;\r\n if (imageUrl && editorRef.current) {\r\n // Insert image at cursor position\r\n const img = document.createElement('img');\r\n img.src = imageUrl;\r\n img.style.maxWidth = '100%';\r\n img.style.height = 'auto';\r\n \r\n const selection = window.getSelection();\r\n if (selection && selection.rangeCount > 0) {\r\n const range = selection.getRangeAt(0);\r\n range.deleteContents();\r\n range.insertNode(img);\r\n } else {\r\n editorRef.current.appendChild(img);\r\n }\r\n \r\n handleContentChange();\r\n }\r\n };\r\n reader.readAsDataURL(file);\r\n \r\n // Reset file input\r\n if (fileInputRef.current) {\r\n fileInputRef.current.value = '';\r\n }\r\n }, [handleContentChange]);\r\n\r\n // Handle paste events to clean up pasted content\r\n const handlePaste = useCallback((e: React.ClipboardEvent) => {\r\n e.preventDefault();\r\n const text = e.clipboardData.getData('text/plain');\r\n const selection = window.getSelection();\r\n \r\n if (selection && selection.rangeCount > 0) {\r\n const range = selection.getRangeAt(0);\r\n range.deleteContents();\r\n const textNode = document.createTextNode(text);\r\n range.insertNode(textNode);\r\n range.setStartAfter(textNode);\r\n range.collapse(true);\r\n selection.removeAllRanges();\r\n selection.addRange(range);\r\n }\r\n \r\n handleContentChange();\r\n }, [handleContentChange]);\r\n\r\n // Check if command is active\r\n const isCommandActive = useCallback((command: string): boolean => {\r\n return document.queryCommandState(command);\r\n }, []);\r\n\r\n return (\r\n <div className={`form-group instruction-group ${className}`}>\r\n {!hideLabel && (\r\n <label htmlFor={id} className=\"instruction-label\">\r\n {'Instructions'}\r\n </label>\r\n )}\r\n\r\n {/* Rich Text Editor - Only show in edit mode */}\r\n {isEditable ? (\r\n <div className=\"instruction-rich-editor\">\r\n {/* Toolbar */}\r\n <div className=\"instruction-toolbar\">\r\n <div className=\"toolbar-group\">\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${isCommandActive('bold') ? 'active' : ''}`}\r\n onClick={handleBold}\r\n title=\"Bold\"\r\n aria-label=\"Bold\"\r\n >\r\n <Bold size={16} />\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${isCommandActive('italic') ? 'active' : ''}`}\r\n onClick={handleItalic}\r\n title=\"Italic\"\r\n aria-label=\"Italic\"\r\n >\r\n <Italic size={16} />\r\n </button>\r\n </div>\r\n \r\n <div className=\"toolbar-separator\" />\r\n \r\n <div className=\"toolbar-group\">\r\n <div className=\"color-picker-wrapper\">\r\n <input\r\n type=\"color\"\r\n value={selectedColor}\r\n onChange={handleColorChange}\r\n className=\"color-picker-input\"\r\n title=\"Text Color\"\r\n />\r\n <label className=\"color-picker-label\" title=\"Text Color\">\r\n <span style={{ color: selectedColor }}>A</span>\r\n </label>\r\n </div>\r\n </div>\r\n \r\n <div className=\"toolbar-separator\" />\r\n \r\n <div className=\"toolbar-group\">\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${listStyle === 'bullets' ? 'active' : ''}`}\r\n onClick={() => handleListStyleChange('bullets')}\r\n title=\"Bullet List\"\r\n aria-label=\"Bullet List\"\r\n >\r\n <List size={16} />\r\n </button>\r\n <button\r\n type=\"button\"\r\n className={`toolbar-btn ${listStyle === 'numbers' ? 'active' : ''}`}\r\n onClick={() => handleListStyleChange('numbers')}\r\n title=\"Numbered List\"\r\n aria-label=\"Numbered List\"\r\n >\r\n <ListOrdered size={16} />\r\n </button>\r\n </div>\r\n \r\n <div className=\"toolbar-separator\" />\r\n \r\n <div className=\"toolbar-group\">\r\n <button\r\n type=\"button\"\r\n className=\"toolbar-btn\"\r\n onClick={() => fileInputRef.current?.click()}\r\n title=\"Insert Image\"\r\n aria-label=\"Insert Image\"\r\n >\r\n <Image size={16} />\r\n </button>\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n accept=\"image/*\"\r\n onChange={handleImageUpload}\r\n style={{ display: 'none' }}\r\n />\r\n </div>\r\n </div>\r\n\r\n {/* Editor */}\r\n <div\r\n ref={editorRef}\r\n contentEditable\r\n className=\"instruction-editor-content\"\r\n onInput={handleContentChange}\r\n onBlur={handleBlur}\r\n onPaste={handlePaste}\r\n data-placeholder=\"Enter instructions (press Enter for a new line)...\"\r\n suppressContentEditableWarning\r\n />\r\n </div>\r\n ) : (\r\n /* Preview Mode - Show formatted content */\r\n <div className={`instruction-preview-wrapper ${listStyle === 'numbers' ? 'instruction-list-numbers' : listStyle === 'bullets' ? 'instruction-list-bullets' : ''}`}>\r\n {htmlContent ? (\r\n <div \r\n className=\"instruction-preview-content\"\r\n dangerouslySetInnerHTML={{ __html: htmlContent }}\r\n />\r\n ) : (\r\n <div className=\"instruction-empty\">\r\n <p>No instructions provided</p>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormInstruction;\r\n\r\n","import React, { useState, useCallback, useEffect, useRef } from 'react';\r\nimport { MessageSquare, Paperclip, Mail, AlertCircle, X, Check, ChevronDown, ChevronUp } from 'lucide-react';\r\nimport { FormComponentType as TFormComponent } from './df-form-controls/df-form-preview-interfaces';\r\nimport { RaiseIssueModal } from './components/RaiseIssueModal';\r\nimport './ComponentActionFeatures.scss';\r\n\r\n// Attachment Thumbnails Component\r\nconst AttachmentThumbnails: React.FC<{\r\n attachments: File[] | null;\r\n onRemove: (index: number) => void;\r\n}> = ({ attachments, onRemove }) => {\r\n const [objectUrls, setObjectUrls] = useState<Map<number, string>>(new Map());\r\n\r\n useEffect(() => {\r\n if (!attachments) {\r\n // Cleanup all URLs\r\n setObjectUrls(prev => {\r\n prev.forEach(url => URL.revokeObjectURL(url));\r\n return new Map();\r\n });\r\n return;\r\n }\r\n\r\n const newUrls = new Map<number, string>();\r\n attachments.forEach((file, index) => {\r\n if (file.type.startsWith('image/')) {\r\n const url = URL.createObjectURL(file);\r\n newUrls.set(index, url);\r\n }\r\n });\r\n\r\n // Cleanup old URLs that are no longer needed\r\n setObjectUrls(prev => {\r\n prev.forEach((url, index) => {\r\n if (!newUrls.has(index)) {\r\n URL.revokeObjectURL(url);\r\n }\r\n });\r\n return newUrls;\r\n });\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n newUrls.forEach(url => URL.revokeObjectURL(url));\r\n };\r\n }, [attachments]);\r\n\r\n if (!attachments || attachments.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"attachment-thumbnails-container\">\r\n {attachments.map((file, index) => {\r\n const isImage = file.type.startsWith('image/');\r\n const objectUrl = objectUrls.get(index);\r\n \r\n return (\r\n <div key={index} className=\"attachment-thumbnail\">\r\n {isImage && objectUrl ? (\r\n <>\r\n <img src={objectUrl} alt={file.name} />\r\n <button\r\n type=\"button\"\r\n className=\"thumbnail-remove-btn\"\r\n onClick={() => onRemove(index)}\r\n title=\"Remove attachment\"\r\n >\r\n <X size={14} />\r\n </button>\r\n </>\r\n ) : (\r\n <>\r\n <div className=\"file-icon-placeholder\">\r\n <Paperclip size={20} />\r\n </div>\r\n <span className=\"file-name\">{file.name}</span>\r\n <button\r\n type=\"button\"\r\n className=\"thumbnail-remove-btn\"\r\n onClick={() => onRemove(index)}\r\n title=\"Remove attachment\"\r\n >\r\n <X size={14} />\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n\r\ninterface IComponentActionFeaturesProps {\r\n component: TFormComponent;\r\n mode: 'edit' | 'preview' | 'test';\r\n formTemplateId?: string;\r\n formValue?: any;\r\n onNotesChange?: (notes: string) => void;\r\n onAttachmentChange?: (files: File[] | null) => void;\r\n notes?: string;\r\n attachments?: File[] | null;\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void;\r\n onThresholdIssueRaised?: (conditionId: string) => void;\r\n onBasicPropertyActionCompletion?: (action: 'notes' | 'attachments' | 'email' | 'issue', completed: boolean) => void;\r\n}\r\n\r\nexport const ComponentActionFeatures: React.FC<IComponentActionFeaturesProps> = ({\r\n component,\r\n mode,\r\n formTemplateId,\r\n formValue,\r\n onNotesChange,\r\n onAttachmentChange,\r\n notes = '',\r\n attachments = null,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onBasicPropertyActionCompletion\r\n}) => {\r\n const [localNotes, setLocalNotes] = useState<string>(notes || '');\r\n const [localAttachments, setLocalAttachments] = useState<File[] | null>(attachments || null);\r\n const [showNotesInput, setShowNotesInput] = useState<boolean>(false);\r\n const [showRaiseIssueModal, setShowRaiseIssueModal] = useState<boolean>(false);\r\n const [emailSent, setEmailSent] = useState<boolean>(false);\r\n const [issueRaised, setIssueRaised] = useState<boolean>(false);\r\n const [actionsExpanded, setActionsExpanded] = useState<boolean>(false);\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const previousFormValueRef = useRef<any>(formValue);\r\n const notesInitializedRef = useRef<boolean>(false);\r\n const attachmentsInitializedRef = useRef<boolean>(false);\r\n\r\n // Initialize local state from props on mount\r\n useEffect(() => {\r\n if (!notesInitializedRef.current && notes !== undefined && notes !== null) {\r\n const notesStr = typeof notes === 'string' ? notes : String(notes || '');\r\n setLocalNotes(notesStr);\r\n notesInitializedRef.current = true;\r\n }\r\n }, [notes]);\r\n\r\n useEffect(() => {\r\n if (!attachmentsInitializedRef.current && attachments !== undefined) {\r\n setLocalAttachments(attachments);\r\n attachmentsInitializedRef.current = true;\r\n }\r\n }, [attachments]);\r\n\r\n // Sync local state with props when they change (but don't override if user is actively editing or has local data)\r\n useEffect(() => {\r\n if (notesInitializedRef.current && !showNotesInput && notes !== undefined && notes !== null) {\r\n const notesStr = typeof notes === 'string' ? notes : String(notes || '');\r\n // Only sync if local notes are empty or props have a different value\r\n // Also check if notes prop matches localNotes to avoid unnecessary updates\r\n if ((!localNotes || String(localNotes || '').trim() === '') && notesStr && notesStr.trim() !== '') {\r\n // Only update if local is empty and prop has value\r\n setLocalNotes(notesStr);\r\n } else if (notesStr && notesStr.trim() !== '' && notesStr !== localNotes) {\r\n // Only update if prop has a different non-empty value\r\n setLocalNotes(notesStr);\r\n }\r\n }\r\n }, [notes, showNotesInput, localNotes]);\r\n\r\n useEffect(() => {\r\n if (attachmentsInitializedRef.current && attachments !== undefined) {\r\n // Only sync if local attachments are null or props have different attachments\r\n if (!localAttachments || (attachments && attachments.length > 0 && attachments !== localAttachments)) {\r\n setLocalAttachments(attachments);\r\n }\r\n }\r\n }, [attachments, localAttachments]);\r\n\r\n // Reset state when formValue changes for option-based components only\r\n // For ALL other components (input, textarea, date, signature, location, etc.), preserve notes and attachments\r\n useEffect(() => {\r\n const isOptionBasedComponent = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');\r\n \r\n // Only reset for option-based components when the selected option actually changes\r\n if (isOptionBasedComponent) {\r\n const previousValue = previousFormValueRef.current;\r\n const currentValue = formValue;\r\n \r\n // Check if the value actually changed (not just initialized)\r\n // For checkbox, compare arrays properly\r\n let valueChanged = false;\r\n if (component.name === 'checkbox') {\r\n const prevArray = Array.isArray(previousValue) ? previousValue : (previousValue ? [previousValue] : []);\r\n const currArray = Array.isArray(currentValue) ? currentValue : (currentValue ? [currentValue] : []);\r\n valueChanged = JSON.stringify(prevArray.sort()) !== JSON.stringify(currArray.sort());\r\n } else {\r\n valueChanged = previousValue !== currentValue && previousValue !== undefined;\r\n }\r\n \r\n if (valueChanged) {\r\n // Only reset action states, but preserve notes and attachments if they exist in props\r\n setEmailSent(false);\r\n setIssueRaised(false);\r\n setShowRaiseIssueModal(false);\r\n setShowNotesInput(false);\r\n setActionsExpanded(false);\r\n \r\n // For option-based components, notes/attachments should be preserved per option\r\n // Only reset if props don't have them AND we're switching to a different option\r\n // Check if notes exist in props first\r\n const notesStr = typeof notes === 'string' ? notes : String(notes || '');\r\n if (!notesStr || notesStr.trim() === '') {\r\n // Only clear if we're switching options and there are no saved notes\r\n setLocalNotes('');\r\n } else {\r\n // Keep the notes from props\r\n setLocalNotes(notesStr);\r\n }\r\n \r\n if (!attachments || attachments.length === 0) {\r\n setLocalAttachments(null);\r\n } else {\r\n // Keep the attachments from props\r\n setLocalAttachments(attachments);\r\n }\r\n }\r\n \r\n previousFormValueRef.current = currentValue;\r\n }\r\n // For ALL non-option-based components (input, textarea, date, signature, location, etc.),\r\n // NEVER reset notes/attachments when form value changes - they should persist\r\n // Just update the ref to track value changes for future comparisons\r\n if (!isOptionBasedComponent) {\r\n previousFormValueRef.current = formValue;\r\n }\r\n }, [formValue, component.name, notes, attachments]);\r\n\r\n // Helper function to evaluate threshold conditions\r\n const evaluateThresholdCondition = useCallback((condition: any, value: any): boolean => {\r\n const { operator, value: conditionValue } = condition;\r\n const stringValue = String(value).toLowerCase();\r\n const stringConditionValue = String(conditionValue).toLowerCase();\r\n\r\n switch (operator) {\r\n case 'equals':\r\n return stringValue === stringConditionValue || String(value) === String(conditionValue);\r\n case 'notEquals':\r\n return stringValue !== stringConditionValue && String(value) !== String(conditionValue);\r\n case 'greaterThan':\r\n return Number(value) > Number(conditionValue);\r\n case 'lessThan':\r\n return Number(value) < Number(conditionValue);\r\n case 'greaterThanOrEqual':\r\n return Number(value) >= Number(conditionValue);\r\n case 'lessThanOrEqual':\r\n return Number(value) <= Number(conditionValue);\r\n default:\r\n return false;\r\n }\r\n }, []);\r\n\r\n // Find active threshold condition(s) for this component\r\n const getActiveThresholdConditions = useCallback((): any[] => {\r\n const hasValidFormValue = formValue !== undefined && \r\n formValue !== null && \r\n formValue !== '' && \r\n !(Array.isArray(formValue) && formValue.length === 0);\r\n if (!hasValidFormValue) return [];\r\n const condition = (component as any).condition;\r\n if (!condition || !condition.conditions || condition.conditions.length === 0) return [];\r\n \r\n const activeConditions: any[] = [];\r\n \r\n if (component.name === 'checkbox' && Array.isArray(formValue)) {\r\n formValue.forEach((value: any) => {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, value)\r\n );\r\n if (matchingCondition && !activeConditions.find(c => c.id === matchingCondition.id)) {\r\n activeConditions.push(matchingCondition);\r\n }\r\n });\r\n } else {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, formValue)\r\n );\r\n if (matchingCondition) {\r\n activeConditions.push(matchingCondition);\r\n }\r\n }\r\n \r\n return activeConditions;\r\n }, [component, formValue, evaluateThresholdCondition]);\r\n\r\n const handleNotesChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {\r\n const value = e.target.value;\r\n setLocalNotes(value);\r\n if (onNotesChange) {\r\n onNotesChange(value);\r\n }\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n const isCompleted = String(value || '').trim().length > 0;\r\n activeConditions.forEach(condition => {\r\n if (condition.enableNotes === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'notes', isCompleted);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('notes', isCompleted);\r\n }\r\n }, [onNotesChange, getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleNotesSave = useCallback(() => {\r\n // Save notes and close input - always save even if empty\r\n if (onNotesChange) {\r\n const notesStr = typeof localNotes === 'string' ? localNotes : String(localNotes || '');\r\n // Call the callback to persist notes\r\n onNotesChange(notesStr);\r\n // Use setTimeout to ensure the callback completes before closing\r\n // This prevents the sync effect from overwriting the saved notes\r\n setTimeout(() => {\r\n setShowNotesInput(false);\r\n }, 0);\r\n } else {\r\n // If no callback, just close immediately\r\n setShowNotesInput(false);\r\n }\r\n }, [localNotes, onNotesChange]);\r\n\r\n const handleNotesBlur = useCallback(() => {\r\n // Save notes when blurring\r\n handleNotesSave();\r\n }, [handleNotesSave]);\r\n\r\n const handleNotesKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {\r\n // Save on Ctrl+Enter or Cmd+Enter\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {\r\n e.preventDefault();\r\n handleNotesSave();\r\n }\r\n }, [handleNotesSave]);\r\n\r\n const handleNotesIconClick = useCallback(() => {\r\n setShowNotesInput(true);\r\n }, []);\r\n\r\n const handleNotesSummaryClick = useCallback(() => {\r\n setShowNotesInput(true);\r\n }, []);\r\n\r\n const handleAttachmentIconClick = useCallback(() => {\r\n fileInputRef.current?.click();\r\n }, []);\r\n\r\n const handleFileChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = e.target.files;\r\n if (files && files.length > 0) {\r\n const fileArray = Array.from(files);\r\n setLocalAttachments(fileArray);\r\n if (onAttachmentChange) {\r\n onAttachmentChange(fileArray);\r\n }\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableAttachment === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'attachments', true);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('attachments', true);\r\n }\r\n }\r\n // Reset input so same file can be selected again\r\n if (fileInputRef.current) {\r\n fileInputRef.current.value = '';\r\n }\r\n }, [onAttachmentChange, getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleRemoveAttachment = useCallback((index: number) => {\r\n if (localAttachments) {\r\n const newAttachments = localAttachments.filter((_, i) => i !== index);\r\n if (newAttachments.length === 0) {\r\n setLocalAttachments(null);\r\n if (onAttachmentChange) {\r\n onAttachmentChange(null);\r\n }\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableAttachment === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'attachments', false);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('attachments', false);\r\n }\r\n } else {\r\n setLocalAttachments(newAttachments);\r\n if (onAttachmentChange) {\r\n onAttachmentChange(newAttachments);\r\n }\r\n }\r\n }\r\n }, [localAttachments, onAttachmentChange, getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleSendEmailClick = useCallback(() => {\r\n // Immediately send email\r\n setEmailSent(true);\r\n \r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableSendEmail === true && onThresholdActionCompletion) {\r\n onThresholdActionCompletion(condition.id, 'email', true);\r\n }\r\n });\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n if (!hasComponentThresholdConditions && onBasicPropertyActionCompletion) {\r\n onBasicPropertyActionCompletion('email', true);\r\n }\r\n \r\n // TODO: Call send email API when available\r\n setTimeout(() => {\r\n setEmailSent(false);\r\n }, 3000);\r\n }, [getActiveThresholdConditions, onThresholdActionCompletion, component, onBasicPropertyActionCompletion]);\r\n\r\n const handleRaiseIssueClick = useCallback(() => {\r\n setShowRaiseIssueModal(true);\r\n }, []);\r\n\r\n const handleRaiseIssueClose = useCallback(() => {\r\n setShowRaiseIssueModal(false);\r\n }, []);\r\n\r\n const handleRaiseIssueSuccess = useCallback(() => {\r\n setShowRaiseIssueModal(false);\r\n setIssueRaised(true);\r\n \r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n \r\n if (hasComponentThresholdConditions) {\r\n // For threshold conditions, notify each active condition that issue was raised\r\n const activeConditions = getActiveThresholdConditions();\r\n activeConditions.forEach(condition => {\r\n if (condition.enableRaiseIssue === true && onThresholdIssueRaised) {\r\n onThresholdIssueRaised(condition.id);\r\n }\r\n });\r\n } else if (onBasicPropertyActionCompletion) {\r\n // For basic property actions (no threshold conditions)\r\n onBasicPropertyActionCompletion('issue', true);\r\n }\r\n }, [component, onBasicPropertyActionCompletion, getActiveThresholdConditions, onThresholdIssueRaised]);\r\n\r\n // Only show in test mode\r\n if (mode !== 'test') {\r\n return null;\r\n }\r\n\r\n // Check if this is an option-based component\r\n const isOptionBasedComponent = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');\r\n const componentOptions = (component as any).basic?.options || (component as any).options || [];\r\n\r\n let enableNotes = false;\r\n let enableAttachment = false;\r\n let enableRaiseIssue = false;\r\n let enableSendEmail = false;\r\n let selectedOption: any = null;\r\n\r\n const hasValidFormValue = formValue !== undefined && \r\n formValue !== null && \r\n formValue !== '' && \r\n !(Array.isArray(formValue) && formValue.length === 0);\r\n\r\n const condition = (component as any).condition;\r\n const hasThresholdConditions = condition && condition.conditions && condition.conditions.length > 0;\r\n \r\n if (hasThresholdConditions && hasValidFormValue) {\r\n if (component.name === 'checkbox' && Array.isArray(formValue)) {\r\n const selectedValues = formValue;\r\n for (const value of selectedValues) {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, value)\r\n );\r\n if (matchingCondition) {\r\n enableNotes = enableNotes || (matchingCondition.enableNotes === true);\r\n enableAttachment = enableAttachment || (matchingCondition.enableAttachment === true);\r\n enableRaiseIssue = enableRaiseIssue || (matchingCondition.enableRaiseIssue === true);\r\n enableSendEmail = enableSendEmail || (matchingCondition.enableSendEmail === true);\r\n }\r\n }\r\n } else if (isOptionBasedComponent) {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, formValue)\r\n );\r\n if (matchingCondition) {\r\n enableNotes = matchingCondition.enableNotes === true;\r\n enableAttachment = matchingCondition.enableAttachment === true;\r\n enableRaiseIssue = matchingCondition.enableRaiseIssue === true;\r\n enableSendEmail = matchingCondition.enableSendEmail === true;\r\n }\r\n } else {\r\n const matchingCondition = condition.conditions.find((cond: any) => \r\n evaluateThresholdCondition(cond, formValue)\r\n );\r\n if (matchingCondition) {\r\n enableNotes = matchingCondition.enableNotes === true;\r\n enableAttachment = matchingCondition.enableAttachment === true;\r\n enableRaiseIssue = matchingCondition.enableRaiseIssue === true;\r\n enableSendEmail = matchingCondition.enableSendEmail === true;\r\n }\r\n }\r\n }\r\n\r\n if (!hasThresholdConditions) {\r\n // First, get component-level actions as fallback\r\n const componentBasic = component.basic as any;\r\n const componentLevelNotes = componentBasic?.enableNotes === true;\r\n const componentLevelAttachment = componentBasic?.enableAttachment === true;\r\n const componentLevelRaiseIssue = componentBasic?.enableRaiseIssue === true;\r\n const componentLevelSendEmail = componentBasic?.enableSendEmail === true;\r\n \r\n if (isOptionBasedComponent) {\r\n if (hasValidFormValue) {\r\n // Value is selected, check option-level actions\r\n if (component.name === 'checkbox') {\r\n const selectedValues = Array.isArray(formValue) ? formValue : [formValue];\r\n selectedValues.forEach((value: any) => {\r\n const option = componentOptions.find((opt: any) => {\r\n if (!opt || !opt.value) return false;\r\n if (opt.value === value) return true;\r\n if (String(opt.value) === String(value)) return true;\r\n if (opt.label === value || String(opt.label) === String(value)) return true;\r\n return false;\r\n });\r\n if (option) {\r\n // Check if option has actions enabled\r\n enableNotes = enableNotes || (option.enableNotes === true);\r\n enableAttachment = enableAttachment || (option.enableAttachment === true);\r\n enableRaiseIssue = enableRaiseIssue || (option.enableRaiseIssue === true);\r\n enableSendEmail = enableSendEmail || (option.enableSendEmail === true);\r\n if (!selectedOption) {\r\n selectedOption = option;\r\n }\r\n }\r\n });\r\n // Always include component-level actions as fallback\r\n enableNotes = enableNotes || componentLevelNotes;\r\n enableAttachment = enableAttachment || componentLevelAttachment;\r\n enableRaiseIssue = enableRaiseIssue || componentLevelRaiseIssue;\r\n enableSendEmail = enableSendEmail || componentLevelSendEmail;\r\n } else {\r\n selectedOption = componentOptions.find((opt: any) => {\r\n if (!opt || !opt.value) return false;\r\n if (opt.value === formValue) return true;\r\n if (String(opt.value) === String(formValue)) return true;\r\n if (opt.label === formValue || String(opt.label) === String(formValue)) return true;\r\n return false;\r\n });\r\n if (selectedOption) {\r\n const optionNotes = selectedOption.enableNotes === true;\r\n const optionAttachment = selectedOption.enableAttachment === true;\r\n const optionRaiseIssue = selectedOption.enableRaiseIssue === true;\r\n const optionSendEmail = selectedOption.enableSendEmail === true;\r\n \r\n // Use option-level actions if set, otherwise fallback to component-level\r\n enableNotes = optionNotes || componentLevelNotes;\r\n enableAttachment = optionAttachment || componentLevelAttachment;\r\n enableRaiseIssue = optionRaiseIssue || componentLevelRaiseIssue;\r\n enableSendEmail = optionSendEmail || componentLevelSendEmail;\r\n } else {\r\n // No option found, use component-level actions\r\n enableNotes = componentLevelNotes;\r\n enableAttachment = componentLevelAttachment;\r\n enableRaiseIssue = componentLevelRaiseIssue;\r\n enableSendEmail = componentLevelSendEmail;\r\n }\r\n }\r\n } else {\r\n // No value selected, but still show component-level actions if enabled\r\n enableNotes = componentLevelNotes;\r\n enableAttachment = componentLevelAttachment;\r\n enableRaiseIssue = componentLevelRaiseIssue;\r\n enableSendEmail = componentLevelSendEmail;\r\n }\r\n } else {\r\n // Not an option-based component, use component-level actions\r\n enableNotes = componentLevelNotes;\r\n enableAttachment = componentLevelAttachment;\r\n enableRaiseIssue = componentLevelRaiseIssue;\r\n enableSendEmail = componentLevelSendEmail;\r\n }\r\n }\r\n\r\n if (!enableNotes && !enableAttachment && !enableRaiseIssue && !enableSendEmail) {\r\n return null;\r\n }\r\n\r\n const activeConditions = getActiveThresholdConditions();\r\n const componentCondition = (component as any).condition;\r\n const hasComponentThresholdConditions = componentCondition && componentCondition.conditions && componentCondition.conditions.length > 0;\r\n \r\n const isNotesMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableNotes === true) \r\n : false;\r\n const isAttachmentsMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableAttachment === true) \r\n : false;\r\n const isSendEmailMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableSendEmail === true) \r\n : false;\r\n const isRaiseIssueMandatory = hasComponentThresholdConditions \r\n ? activeConditions.some(c => c.enableRaiseIssue === true) \r\n : false;\r\n\r\n const hasNotes = String(localNotes || '').trim().length > 0;\r\n const hasAttachments = localAttachments && localAttachments.length > 0;\r\n const attachmentCount = localAttachments ? localAttachments.length : 0;\r\n\r\n return (\r\n <>\r\n <div className=\"component-action-features\">\r\n {/* Icon Toolbar */}\r\n <div className=\"action-icons-toolbar\">\r\n {enableNotes && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${hasNotes ? 'active' : ''} ${isNotesMandatory ? 'mandatory' : ''}`}\r\n onClick={handleNotesIconClick}\r\n title=\"Add Notes\"\r\n >\r\n <MessageSquare size={14} fill={hasNotes ? 'currentColor' : 'none'} />\r\n {isNotesMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {enableAttachment && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${hasAttachments ? 'active' : ''} ${isAttachmentsMandatory ? 'mandatory' : ''}`}\r\n onClick={handleAttachmentIconClick}\r\n title=\"Add Attachment\"\r\n >\r\n <Paperclip size={14} fill={hasAttachments ? 'currentColor' : 'none'} />\r\n {attachmentCount > 0 && <span className=\"attachment-count-badge\">{attachmentCount}</span>}\r\n {isAttachmentsMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {enableSendEmail && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${emailSent ? 'active sent' : ''} ${isSendEmailMandatory ? 'mandatory' : ''}`}\r\n onClick={handleSendEmailClick}\r\n disabled={emailSent}\r\n title=\"Send Email\"\r\n >\r\n {emailSent ? (\r\n <>\r\n <Check size={14} />\r\n </>\r\n ) : (\r\n <Mail size={14} fill={emailSent ? 'currentColor' : 'none'} />\r\n )}\r\n {isSendEmailMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {enableRaiseIssue && (\r\n <button\r\n type=\"button\"\r\n className={`action-icon-button ${issueRaised ? 'active' : ''} ${isRaiseIssueMandatory ? 'mandatory' : ''}`}\r\n onClick={handleRaiseIssueClick}\r\n title=\"Raise an Issue\"\r\n >\r\n <AlertCircle size={14} fill={issueRaised ? 'currentColor' : 'none'} />\r\n {isRaiseIssueMandatory && <span className=\"mandatory-indicator\">*</span>}\r\n </button>\r\n )}\r\n\r\n {/* Accordion Toggle Button - Show if there are notes or attachments */}\r\n {((hasNotes && enableNotes) || (hasAttachments && enableAttachment)) && (\r\n <button\r\n type=\"button\"\r\n className=\"action-icon-button accordion-toggle\"\r\n onClick={() => setActionsExpanded(!actionsExpanded)}\r\n title={actionsExpanded ? 'Collapse' : 'Expand'}\r\n >\r\n {actionsExpanded ? <ChevronUp size={14} /> : <ChevronDown size={14} />}\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Notes Input Overlay */}\r\n {showNotesInput && enableNotes && (\r\n <div className=\"notes-input-overlay\">\r\n <textarea\r\n className=\"action-notes-textarea\"\r\n value={localNotes}\r\n onChange={handleNotesChange}\r\n onBlur={handleNotesBlur}\r\n onKeyDown={handleNotesKeyDown}\r\n placeholder=\"Explain which protocols were not followed (Press Ctrl+Enter to save)\"\r\n rows={4}\r\n autoFocus\r\n />\r\n <div className=\"notes-input-actions\">\r\n <button\r\n type=\"button\"\r\n className=\"notes-save-button\"\r\n onClick={handleNotesSave}\r\n title=\"Save notes (Ctrl+Enter)\"\r\n >\r\n Save\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"notes-cancel-button\"\r\n onClick={() => {\r\n setShowNotesInput(false);\r\n }}\r\n title=\"Cancel\"\r\n >\r\n Cancel\r\n </button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Notes and Attachments Content - Controlled by Accordion */}\r\n {actionsExpanded && (\r\n <div className=\"actions-content\">\r\n {/* Notes Summary */}\r\n {!showNotesInput && hasNotes && enableNotes && (\r\n <div className=\"notes-summary-section\">\r\n <div className=\"notes-full-text\" onClick={handleNotesSummaryClick}>\r\n <span className=\"notes-label\">Notes:</span> {localNotes}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Attachment Thumbnails */}\r\n {hasAttachments && enableAttachment && (\r\n <div className=\"attachments-section\">\r\n <AttachmentThumbnails\r\n attachments={localAttachments}\r\n onRemove={handleRemoveAttachment}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Hidden File Input */}\r\n {enableAttachment && (\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n multiple\r\n accept=\"image/*,.pdf\"\r\n onChange={handleFileChange}\r\n style={{ display: 'none' }}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Raise Issue Modal */}\r\n {showRaiseIssueModal && (\r\n <RaiseIssueModal\r\n isOpen={showRaiseIssueModal}\r\n onClose={handleRaiseIssueClose}\r\n onSuccess={handleRaiseIssueSuccess}\r\n component={selectedOption ? {\r\n ...component,\r\n basic: {\r\n ...(component.basic as any),\r\n label: `${(component.basic as any)?.label || 'Component'} - ${selectedOption.label || selectedOption.value}`,\r\n value: selectedOption.value || (component.basic as any)?.value || ''\r\n } as any\r\n } : component}\r\n formTemplateId={formTemplateId || ''}\r\n notes={localNotes}\r\n attachments={localAttachments}\r\n />\r\n )}\r\n </>\r\n );\r\n};\r\n","import React from 'react';\r\nimport { Paperclip } from 'lucide-react';\r\nimport { FormComponentType as TFormComponent } from '../df-form-controls/df-form-preview-interfaces';\r\nimport './ComponentSubmissionActions.scss';\r\n\r\ninterface IComponentSubmissionActionsProps {\r\n component: TFormComponent;\r\n}\r\n\r\ninterface IAttachmentData {\r\n name: string;\r\n type: string;\r\n size: number;\r\n data: string;\r\n}\r\n\r\n// Attachment Thumbnails Component for Submission View\r\nconst SubmissionAttachmentThumbnails: React.FC<{\r\n attachments: IAttachmentData[];\r\n}> = ({ attachments }) => {\r\n // Convert base64 data to data URI for display\r\n const getImageSrc = (attachment: IAttachmentData): string => {\r\n if (!attachment.data) return '';\r\n \r\n // If already a data URI, return as is\r\n if (attachment.data.startsWith('data:')) {\r\n return attachment.data;\r\n }\r\n \r\n // Convert base64 to data URI\r\n const mimeType = attachment.type || 'image/png';\r\n return `data:${mimeType};base64,${attachment.data}`;\r\n };\r\n\r\n if (!attachments || attachments.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"attachment-thumbnails-container\">\r\n {attachments.map((attachment, index) => {\r\n const isImage = attachment.type?.startsWith('image/') || false;\r\n const imageSrc = isImage ? getImageSrc(attachment) : '';\r\n \r\n return (\r\n <div key={index} className=\"attachment-thumbnail\">\r\n {isImage && imageSrc ? (\r\n <img src={imageSrc} alt={attachment.name || `Attachment ${index + 1}`} />\r\n ) : (\r\n <div className=\"file-icon-placeholder\">\r\n <Paperclip size={20} />\r\n <span className=\"file-name\">{attachment.name || `File ${index + 1}`}</span>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n\r\nexport const ComponentSubmissionActions: React.FC<IComponentSubmissionActionsProps> = ({\r\n component\r\n}) => {\r\n // Extract notes and attachments from component.basic\r\n const notes = (component as any).basic?.notes || '';\r\n const attachments = ((component as any).basic?.attachments || []) as IAttachmentData[];\r\n\r\n const hasNotes = notes && notes.trim().length > 0;\r\n const hasAttachments = attachments && attachments.length > 0;\r\n\r\n // Don't render if there are no notes or attachments\r\n if (!hasNotes && !hasAttachments) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div className=\"component-submission-actions\">\r\n {/* Notes and Attachments Content - Always visible */}\r\n <div className=\"actions-content\">\r\n {/* Notes Summary */}\r\n {hasNotes && (\r\n <div className=\"notes-summary-section\">\r\n <div className=\"notes-full-text\">\r\n <span className=\"notes-label\">Notes:</span> {notes}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {/* Attachment Thumbnails */}\r\n {hasAttachments && (\r\n <div className=\"attachments-section\">\r\n <SubmissionAttachmentThumbnails attachments={attachments} />\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n","import React, { useState, useCallback, useEffect } from 'react'\r\nimport { useDroppable } from '@dnd-kit/core'\r\nimport { useSortable, SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { ChevronDown, ChevronRight, GripVertical, Edit, Trash2 } from 'lucide-react'\r\nimport { ISectionComponent, FormComponentType, IFormControlChange } from '../df-form-preview-interfaces'\r\n\r\n// Import form control components for rendering children\r\nimport { DfFormInput } from '../df-form-input'\r\nimport { DfFormTextarea } from '../df-form-textarea'\r\nimport { DfFormSelect } from '../df-form-select'\r\nimport { DfFormCheckbox } from '../df-form-checkbox'\r\nimport { DfFormRadio } from '../df-form-radio'\r\nimport { DfFormDateTime } from '../df-form-date-time'\r\nimport { DfFormSignature } from '../df-form-signature'\r\nimport { DfFormHeading } from '../df-form-heading'\r\nimport { ComponentActionFeatures } from '../../ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from '../../components/ComponentSubmissionActions'\r\n\r\ninterface DfFormSectionProps {\r\n id: string\r\n properties: ISectionComponent\r\n validationErrors?: Record<string, any>\r\n formValue?: any\r\n formData?: Record<string, any>\r\n readonly?: boolean\r\n disabled?: boolean\r\n touchedFields?: Record<string, boolean>\r\n formSubmitted?: boolean\r\n mode?: 'edit' | 'preview' | 'test'\r\n onValueChange?: (change: IFormControlChange) => void\r\n onBlur?: () => void\r\n onFocus?: () => void\r\n onSelect?: () => void\r\n isSelected?: boolean\r\n className?: string\r\n // Section-specific props\r\n onSectionSelect?: (section: ISectionComponent) => void\r\n onSectionDelete?: (sectionId: string) => void\r\n onChildrenChange?: (children: FormComponentType[]) => void\r\n onChildSelect?: (child: FormComponentType) => void\r\n onChildDelete?: (childId: string) => void\r\n selectedChild?: FormComponentType | null\r\n renderFormComponent?: (field: FormComponentType) => React.ReactNode\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\n// Draggable child component for items inside the section\r\ninterface DraggableChildProps {\r\n child: FormComponentType\r\n selectedChild: FormComponentType | null\r\n mode: 'edit' | 'preview' | 'test'\r\n onChildSelect: (child: FormComponentType) => void\r\n onChildDelete: (child: FormComponentType, event: React.MouseEvent) => void\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n isOverlay?: boolean\r\n isChildrenEditMode?: boolean\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst DraggableChild: React.FC<DraggableChildProps> = ({\r\n child,\r\n selectedChild,\r\n mode,\r\n onChildSelect,\r\n onChildDelete,\r\n renderFormComponent,\r\n isOverlay = false,\r\n isChildrenEditMode = false,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const formValue = formData[child.id];\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = mode === 'preview' && (\r\n ((child as any).basic?.notes && (child as any).basic.notes.trim().length > 0) ||\r\n ((child as any).basic?.attachments && Array.isArray((child as any).basic.attachments) && (child as any).basic.attachments.length > 0)\r\n );\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n isSorting,\r\n } = useSortable({\r\n id: child.id,\r\n disabled: isOverlay || mode !== 'edit',\r\n })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n // opacity: isDragging ? 0.3 : 1,\r\n zIndex: isDragging ? 1000 : 'auto',\r\n }\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n style={style}\r\n className={`form-component section-child ${selectedChild?.id === child.id ? 'selected' : ''} ${isDragging ? 'dragging' : ''} ${isSorting ? 'sorting' : ''} ${isChildrenEditMode ? 'children-edit-active' : ''}`}\r\n onClick={() => !isDragging && onChildSelect(child)}\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {/* Drag Handle - Show in edit mode or when children edit mode is active */}\r\n {(mode === 'edit' || isChildrenEditMode) && (\r\n <div \r\n className=\"child-drag-handle\" \r\n {...listeners} \r\n {...attributes}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n >\r\n <GripVertical size={14} />\r\n </div>\r\n )}\r\n \r\n {/* Child Content */}\r\n <div className=\"form-component-content section-child-content\">\r\n {/* Child Actions - Show in edit mode or when children edit mode is active */}\r\n {(mode === 'edit' || isChildrenEditMode) && (\r\n <div className=\"component-actions child-actions\">\r\n <button\r\n className=\"btn edit-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onChildSelect(child)\r\n }}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n title=\"Edit properties\"\r\n >\r\n <Edit size={12} />\r\n </button>\r\n <button\r\n className=\"btn delete-btn\"\r\n onClick={(e) => onChildDelete(child, e)}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n title=\"Delete component\"\r\n >\r\n <Trash2 size={12} />\r\n </button>\r\n </div>\r\n )}\r\n\r\n <div className=\"component-preview child-preview\">\r\n {renderFormComponent(child)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(child.name) && (\r\n <ComponentActionFeatures\r\n component={child as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(child.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(child.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={child as any}\r\n />\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport const DfFormSection: React.FC<DfFormSectionProps> = ({\r\n id,\r\n properties,\r\n mode = 'edit',\r\n formData = {},\r\n onValueChange,\r\n onSelect,\r\n isSelected = false,\r\n className = '',\r\n onSectionSelect,\r\n onChildSelect,\r\n onChildDelete,\r\n selectedChild,\r\n renderFormComponent,\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const [isCollapsed, setIsCollapsed] = useState(properties.basic.collapsed)\r\n const [isEditingTitle, setIsEditingTitle] = useState(false)\r\n const [isEditingDescription, setIsEditingDescription] = useState(false)\r\n const [sectionTitle, setSectionTitle] = useState(properties.basic.label)\r\n const [sectionDescription, setSectionDescription] = useState(properties.basic.description)\r\n const [children, setChildren] = useState<FormComponentType[]>(properties.children || [])\r\n const [isChildrenEditMode, setIsChildrenEditMode] = useState(false)\r\n\r\n // Sync children with properties changes\r\n useEffect(() => {\r\n setChildren(properties.children || [])\r\n }, [properties.children])\r\n\r\n // Sync basic props (label, description) with incoming properties updates\r\n useEffect(() => {\r\n setSectionTitle(properties.basic.label)\r\n setSectionDescription(properties.basic.description)\r\n }, [properties.basic.label, properties.basic.description])\r\n\r\n // Make the section a drop target - Only in edit mode\r\n const { setNodeRef, isOver } = useDroppable({\r\n id: `section-${id}`,\r\n disabled: mode !== 'edit'\r\n })\r\n\r\n // Decide visibility after all hooks are called to keep hooks order stable\r\n const shouldHideInCurrentMode = (mode === 'preview' || mode === 'test') && (!(properties.children && properties.children.length > 0))\r\n\r\n // Handle section title change\r\n const handleTitleChange = useCallback((newTitle: string) => {\r\n setSectionTitle(newTitle)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, label: newTitle } }\r\n })\r\n }, [id, properties, onValueChange])\r\n\r\n // Handle section description change\r\n const handleDescriptionChange = useCallback((newDescription: string) => {\r\n setSectionDescription(newDescription)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, description: newDescription } }\r\n })\r\n }, [id, properties, onValueChange])\r\n\r\n // Handle child selection\r\n const handleChildSelect = useCallback((child: FormComponentType) => {\r\n onChildSelect?.(child)\r\n }, [onChildSelect])\r\n\r\n // Handle child deletion\r\n const handleChildDelete = useCallback((child: FormComponentType, event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n \r\n // Update local children state immediately for responsive UI\r\n const newChildren = children.filter(c => c.id !== child.id)\r\n setChildren(newChildren)\r\n \r\n // Notify parent component - this will trigger the useEffect to sync\r\n onChildDelete?.(child.id)\r\n }, [onChildDelete, children, id])\r\n\r\n // Handle section selection\r\n const handleSectionSelect = useCallback(() => {\r\n onSectionSelect?.(properties)\r\n onSelect?.()\r\n }, [onSectionSelect, onSelect, properties])\r\n\r\n // Handle section double-click to activate children edit mode\r\n const handleSectionDoubleClick = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n if (mode === 'edit' && children.length > 0) {\r\n setIsChildrenEditMode(!isChildrenEditMode)\r\n }\r\n }, [mode, children.length, isChildrenEditMode])\r\n\r\n // Toggle collapse state\r\n const toggleCollapse = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n setIsCollapsed(!isCollapsed)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, collapsed: !isCollapsed } }\r\n })\r\n }, [isCollapsed, id, properties, onValueChange])\r\n\r\n // Use the provided render function or fallback to default\r\n const renderComponent = renderFormComponent || useCallback((field: FormComponentType) => {\r\n const commonProps = {\r\n id: field.id,\r\n properties: field,\r\n validationErrors: {},\r\n formValue: formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : ''), // CRITICAL: Always get formValue from formData in package\r\n touchedFields: {},\r\n formSubmitted: false,\r\n mode,\r\n onValueChange: onValueChange, // Pass the parent's onValueChange to child components\r\n onBlur: () => {},\r\n onFocus: () => {}\r\n }\r\n\r\n switch (field.name) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'number-input':\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={field as any}\r\n inputType={field.name === 'text-input' ? 'text' : \r\n field.name === 'number-input' ? 'number' : 'email'}\r\n readonly={false} // CRITICAL: Always editable in package\r\n disabled={false} // CRITICAL: Never disabled in package\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={field as any} readonly={false} disabled={false} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} disabled={false} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} formValue={[]} disabled={false} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} readonly={false} disabled={false} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={field as any} />\r\n \r\n case 'heading':\r\n return <DfFormHeading {...commonProps} properties={field as any} />\r\n \r\n default:\r\n return (\r\n <div className=\"form-group\">\r\n <div className=\"form-group-label\">\r\n Unsupported Component: {field.name}\r\n </div>\r\n </div>\r\n )\r\n }\r\n }, [mode, onValueChange, formData])\r\n\r\n if (shouldHideInCurrentMode) {\r\n return null\r\n }\r\n\r\n // Filter out dimension-related styles for sections as they should be flexible containers\r\n const sectionStyles = {\r\n backgroundColor: properties.styles?.backgroundColor || 'var(--df-color-fb-container)',\r\n borderColor: properties.styles?.borderColor || 'var(--df-color-fb-border)',\r\n borderWidth: properties.styles?.borderWidth || '2px',\r\n borderRadius: properties.styles?.borderRadius || '8px',\r\n padding: properties.styles?.padding || '16px',\r\n margin: properties.styles?.margin || '16px 0',\r\n // Explicitly exclude dimension properties\r\n // width, height, minWidth, maxWidth, minHeight, maxHeight should not be applied\r\n };\r\n\r\n return (\r\n <div \r\n ref={setNodeRef}\r\n className={`df-form-section ${isSelected ? 'selected' : ''} ${isOver ? 'drag-over' : ''} ${className}`}\r\n style={sectionStyles}\r\n >\r\n {/* Section Header */}\r\n <div \r\n className={`section-header ${isChildrenEditMode ? 'children-edit-mode' : ''}`}\r\n onClick={handleSectionSelect}\r\n onDoubleClick={handleSectionDoubleClick}\r\n >\r\n <div className=\"section-header-content\">\r\n {/* Section Title with inline collapse icon */}\r\n <div className=\"section-title\">\r\n {/* Left side: collapse icon in all modes */}\r\n <span\r\n className=\"section-toggle\"\r\n title={isCollapsed ? 'Expand section' : 'Collapse section'}\r\n role=\"button\"\r\n tabIndex={0}\r\n onClick={(e) => { e.stopPropagation(); toggleCollapse(e) }}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggleCollapse(e as any) } }}\r\n style={{ marginRight: '8px', display: 'inline-flex', alignItems: 'center' }}\r\n >\r\n {isCollapsed ? <ChevronRight size={18} /> : <ChevronDown size={18} />}\r\n </span>\r\n\r\n {mode === 'edit' && isEditingTitle ? (\r\n <input\r\n type=\"text\"\r\n value={sectionTitle}\r\n onChange={(e) => setSectionTitle(e.target.value)}\r\n onBlur={() => {\r\n setIsEditingTitle(false)\r\n handleTitleChange(sectionTitle)\r\n }}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n setIsEditingTitle(false)\r\n handleTitleChange(sectionTitle)\r\n }\r\n }}\r\n className=\"section-title-input\"\r\n autoFocus\r\n />\r\n ) : (\r\n <h3 \r\n className=\"section-title-text\"\r\n onDoubleClick={() => mode === 'edit' && setIsEditingTitle(true)}\r\n style={{ display: 'inline', margin: 0 }}\r\n >\r\n {sectionTitle || 'Untitled Section'}\r\n </h3>\r\n )}\r\n </div>\r\n\r\n </div>\r\n \r\n {/* Section Description (below header) */}\r\n {(sectionDescription || mode === 'edit') && (\r\n <div className=\"section-description\">\r\n {mode === 'edit' && isEditingDescription ? (\r\n <textarea\r\n value={sectionDescription}\r\n onChange={(e) => setSectionDescription(e.target.value)}\r\n onBlur={() => {\r\n setIsEditingDescription(false)\r\n handleDescriptionChange(sectionDescription)\r\n }}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter' && e.ctrlKey) {\r\n setIsEditingDescription(false)\r\n handleDescriptionChange(sectionDescription)\r\n }\r\n }}\r\n className=\"section-description-input\"\r\n placeholder=\"Section description (optional)\"\r\n autoFocus\r\n />\r\n ) : (\r\n <p \r\n className=\"section-description-text\"\r\n onDoubleClick={() => mode === 'edit' && setIsEditingDescription(true)}\r\n >\r\n {sectionDescription || 'Section description'}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n\r\n \r\n </div>\r\n\r\n {/* Section Content */}\r\n {!isCollapsed && (\r\n <div \r\n className={`section-content ${isOver ? 'drag-over' : ''} ${children.length === 0 ? 'empty' : 'has-children'}`}\r\n onClick={(e) => {\r\n // Only select section if clicking on the background, not on child components\r\n if (e.target === e.currentTarget) {\r\n handleSectionSelect()\r\n }\r\n }}\r\n >\r\n <SortableContext items={children.map(c => c.id)} strategy={verticalListSortingStrategy}>\r\n {children.length === 0 ? (\r\n <div \r\n className=\"section-empty-state\" \r\n onClick={handleSectionSelect}\r\n style={{\r\n textAlign: 'center',\r\n color: '#6b7280',\r\n fontSize: '14px',\r\n padding: '40px 20px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n gap: '8px',\r\n cursor: 'pointer',\r\n border: '2px dotted #d1d5db',\r\n borderRadius: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n transition: 'all 0.3s ease',\r\n margin: '16px 0'\r\n }}\r\n >\r\n {/* <div style={{ fontSize: '24px', opacity: 0.5 }}>📋</div> */}\r\n <div style={{ \r\n fontWeight: '500',\r\n color: isOver ? '#3b82f6' : '#374151'\r\n }}>\r\n {isOver ? 'Drop components here' : 'Empty Section'}\r\n </div>\r\n <div style={{ \r\n fontSize: '12px',\r\n color: '#9ca3af'\r\n }}>\r\n Drag and drop components here to create your section\r\n </div>\r\n </div>\r\n ) : (\r\n children.map((child) => (\r\n <DraggableChild\r\n key={child.id}\r\n child={child}\r\n selectedChild={selectedChild || null}\r\n mode={mode}\r\n onChildSelect={handleChildSelect}\r\n onChildDelete={handleChildDelete}\r\n renderFormComponent={renderComponent}\r\n isChildrenEditMode={isChildrenEditMode}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n />\r\n ))\r\n )}\r\n </SortableContext>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormSection\r\n","import React, { useState, useCallback, useEffect, useRef } from 'react'\r\nimport { useDroppable } from '@dnd-kit/core'\r\nimport { useSortable, SortableContext, horizontalListSortingStrategy } from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { ChevronDown, ChevronRight, GripVertical, Edit, Trash2, Grid } from 'lucide-react'\r\nimport { IDataGridComponent, FormComponentType, IFormControlChange, DataGridEntry } from '../df-form-preview-interfaces'\r\nimport './df-form-grid.scss'\r\n\r\n// Import form control components for rendering children\r\nimport { DfFormInput } from '../df-form-input'\r\nimport { DfFormTextarea } from '../df-form-textarea'\r\nimport { DfFormSelect } from '../df-form-select'\r\nimport { DfFormCheckbox } from '../df-form-checkbox'\r\nimport { DfFormRadio } from '../df-form-radio'\r\nimport { DfFormDateTime } from '../df-form-date-time'\r\nimport { DfFormSignature } from '../df-form-signature'\r\nimport { DfFormHeading } from '../df-form-heading'\r\nimport { DfFormInstruction } from '../df-form-instruction'\r\nimport { ComponentActionFeatures } from '../../ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from '../../components/ComponentSubmissionActions'\r\n\r\ninterface DfFormDataGridProps {\r\n id: string\r\n properties: IDataGridComponent\r\n validationErrors?: Record<string, any>\r\n formValue?: any\r\n formData?: Record<string, any>\r\n readonly?: boolean\r\n disabled?: boolean\r\n touchedFields?: Record<string, boolean>\r\n formSubmitted?: boolean\r\n mode?: 'edit' | 'preview' | 'test'\r\n onValueChange?: (change: IFormControlChange) => void\r\n onBlur?: () => void\r\n onFocus?: () => void\r\n onSelect?: () => void\r\n isSelected?: boolean\r\n className?: string\r\n // DataGrid-specific props\r\n onDataGridSelect?: (dataGrid: IDataGridComponent) => void\r\n onDataGridDelete?: (dataGridId: string) => void\r\n onEntryChange?: (entryIndex: number, components: FormComponentType[]) => void\r\n onComponentSelect?: (component: FormComponentType) => void\r\n onComponentDelete?: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n selectedComponent?: FormComponentType | null\r\n renderFormComponent?: (field: FormComponentType, hideLabel?: boolean) => React.ReactNode\r\n // Additional props for consistency with other components\r\n onDataGridUpdate?: (dataGridId: string, updates: Partial<IDataGridComponent>) => void\r\n onEntryAdd?: () => void\r\n onEntryRemove?: (entryIndex: number) => void\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\n// Draggable component for items inside grid entries\r\ninterface DraggableGridComponentProps {\r\n component: FormComponentType\r\n selectedComponent: FormComponentType | null\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n isOverlay?: boolean\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst DraggableGridComponent: React.FC<DraggableGridComponentProps> = ({\r\n component,\r\n selectedComponent,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n renderFormComponent,\r\n isOverlay = false,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const formValue = formData[component.id];\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = mode === 'preview' && (\r\n ((component as any).basic?.notes && (component as any).basic.notes.trim().length > 0) ||\r\n ((component as any).basic?.attachments && Array.isArray((component as any).basic.attachments) && (component as any).basic.attachments.length > 0)\r\n );\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n isSorting,\r\n } = useSortable({\r\n id: component.id,\r\n disabled: isOverlay,\r\n })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.3 : 1,\r\n zIndex: isDragging ? 1000 : 'auto',\r\n }\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n style={{\r\n ...style,\r\n border: selectedComponent?.id === component.id ? '2px solid #3b82f6' : '1px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n padding: '12px',\r\n position: 'relative',\r\n minHeight: '80px',\r\n transition: 'all 0.2s ease',\r\n boxShadow: selectedComponent?.id === component.id ? '0 4px 12px rgba(59, 130, 246, 0.15)' : '0 1px 3px rgba(0, 0, 0, 0.1)',\r\n cursor: 'pointer'\r\n }}\r\n className={`form-component grid-component ${selectedComponent?.id === component.id ? 'selected' : ''} ${isDragging ? 'dragging' : ''} ${isSorting ? 'sorting' : ''}`}\r\n onClick={() => !isDragging && onComponentSelect(component)}\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {/* Drag Handle - Only visible in edit mode */}\r\n {mode === 'edit' && (\r\n <div \r\n className=\"component-drag-handle\" \r\n {...listeners} \r\n {...attributes}\r\n onClick={(e) => e.stopPropagation()}\r\n style={{ \r\n position: 'absolute',\r\n top: '50%',\r\n left: '4px',\r\n transform: 'translateY(-50%)',\r\n padding: '4px',\r\n backgroundColor: '#f3f4f6',\r\n borderRadius: '4px',\r\n cursor: 'grab',\r\n opacity: 1,\r\n zIndex: 10,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center'\r\n }}\r\n >\r\n <GripVertical size={12} color=\"var(--df-color-text-light)\" />\r\n </div>\r\n )}\r\n\r\n {/* Component Content */}\r\n <div \r\n className=\"component-content\"\r\n style={{\r\n paddingTop: mode === 'edit' ? '24px' : '0',\r\n paddingLeft: mode === 'edit' ? '28px' : '0',\r\n minHeight: '60px'\r\n }}\r\n >\r\n {renderFormComponent(component)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(component.name) && (\r\n <ComponentActionFeatures\r\n component={component as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(component.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(component.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={component as any}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Action Buttons */}\r\n {mode === 'edit' && (\r\n <div \r\n className=\"component-actions\" \r\n style={{ \r\n position: 'absolute',\r\n top: '4px',\r\n right: '4px',\r\n display: 'flex',\r\n gap: '4px',\r\n opacity: 1,\r\n zIndex: 10\r\n }}\r\n >\r\n {/* Edit Button */}\r\n {onComponentEdit && (\r\n <button\r\n className=\"component-edit-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentEdit(component)\r\n }}\r\n type=\"button\"\r\n title=\"Edit Component\"\r\n style={{\r\n padding: '4px',\r\n backgroundColor: '#3b82f6',\r\n color: '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease'\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = '#2563eb'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = '#3b82f6'\r\n }}\r\n >\r\n <Edit size={12} />\r\n </button>\r\n )}\r\n \r\n {/* Delete Button */}\r\n <button\r\n className=\"component-delete-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentDelete(component, e)\r\n }}\r\n type=\"button\"\r\n title=\"Delete Component\"\r\n style={{\r\n padding: '4px',\r\n backgroundColor: '#ef4444',\r\n color: '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n cursor: 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease'\r\n }}\r\n onMouseEnter={(e) => {\r\n e.currentTarget.style.backgroundColor = '#dc2626'\r\n }}\r\n onMouseLeave={(e) => {\r\n e.currentTarget.style.backgroundColor = '#ef4444'\r\n }}\r\n >\r\n <Trash2 size={12} />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Simple Grid Drop Zone Component\r\ninterface GridDropZoneProps {\r\n gridComponents: FormComponentType[]\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n selectedComponent: FormComponentType | null\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n gridId: string // Add unique grid ID prop\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst GridDropZone: React.FC<GridDropZoneProps> = ({\r\n gridComponents,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n onComponentUpdate,\r\n selectedComponent,\r\n renderFormComponent,\r\n gridId,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const { setNodeRef, isOver } = useDroppable({\r\n id: `grid-drop-zone-${gridId}`,\r\n disabled: mode !== 'edit'\r\n })\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n className=\"grid-drop-zone\"\r\n style={{\r\n border: isOver ? '2px dashed #3b82f6' : '2px dashed #d1d5db',\r\n borderRadius: '8px',\r\n padding: '16px',\r\n backgroundColor: isOver ? 'var(--df-color-primary-light)' : 'var(--df-color-fb-container)',\r\n minHeight: '120px',\r\n transition: 'all 0.2s ease',\r\n position: 'relative'\r\n }}\r\n >\r\n {gridComponents.length > 0 ? (\r\n <>\r\n <SortableContext items={gridComponents.map(c => c.id)} strategy={horizontalListSortingStrategy}>\r\n <div style={{ \r\n display: 'flex',\r\n flexDirection: 'row',\r\n flexWrap: 'nowrap',\r\n gap: '12px',\r\n alignItems: 'start',\r\n marginBottom: gridComponents.length > 0 ? '12px' : '0',\r\n overflowX: 'auto',\r\n width: '100%'\r\n }}>\r\n {gridComponents.map((component) => (\r\n <div key={component.id} style={{ flex: '1 1 0', minWidth: '200px', maxWidth: '100%' }}>\r\n <DraggableGridComponent\r\n component={component}\r\n selectedComponent={selectedComponent}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect}\r\n onComponentDelete={onComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n onComponentUpdate={onComponentUpdate}\r\n renderFormComponent={renderFormComponent}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n </SortableContext>\r\n \r\n {/* Additional Drop Zone for More Components */}\r\n <div style={{\r\n border: isOver ? '2px dashed #3b82f6' : '1px dashed var(--df-color-fb-border)',\r\n borderRadius: '6px',\r\n padding: '12px',\r\n backgroundColor: isOver ? 'var(--df-color-primary-light)' : 'var(--df-color-fb-container)',\r\n textAlign: 'center',\r\n color: 'var(--df-color-text-light)',\r\n fontSize: '12px',\r\n transition: 'all 0.2s ease',\r\n minHeight: '40px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center'\r\n }}>\r\n {isOver ? (\r\n <span style={{ color: '#3b82f6', fontWeight: '500' }}>\r\n Drop component here to add to grid\r\n </span>\r\n ) : (\r\n <span>\r\n + Drop more components here\r\n </span>\r\n )}\r\n </div>\r\n </>\r\n ) : (\r\n <div style={{ \r\n textAlign: 'center', \r\n color: 'var(--df-color-text-light)', \r\n fontSize: '14px',\r\n padding: '40px 20px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n alignItems: 'center',\r\n gap: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n border: '1px dashed var(--df-color-fb-border)',\r\n borderRadius: '8px'\r\n }}>\r\n {/* <div style={{ \r\n fontSize: '24px',\r\n opacity: 0.5\r\n }}>\r\n 📋\r\n </div> */}\r\n <div style={{ \r\n fontWeight: '500',\r\n color: isOver ? 'var(--df-color-primary)' : 'var(--df-color-text-dark)'\r\n }}>\r\n {isOver ? 'Drop components here' : 'Empty DataGrid'}\r\n </div>\r\n <div style={{ \r\n fontSize: '12px',\r\n color: '#9ca3af'\r\n }}>\r\n Drag and drop components here to create your grid\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Table View Component for Preview/Test Mode\r\ninterface TableViewProps {\r\n templateComponents: FormComponentType[]\r\n dataEntries: any[]\r\n renderFormComponent: (field: FormComponentType, hideLabel?: boolean) => React.ReactNode\r\n renderComponent?: (field: FormComponentType, hideLabel?: boolean) => React.ReactNode\r\n mode?: 'edit' | 'preview' | 'test'\r\n allowAddRemoveEntries?: boolean\r\n addAnotherText?: string\r\n removeText?: string\r\n maxEntries?: number\r\n minEntries?: number\r\n displayAsGrid?: boolean\r\n onAddEntry?: () => void\r\n onRemoveEntry?: (entryIndex: number) => void\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n datagridId?: string // Add datagrid ID prop\r\n}\r\n\r\nconst TableView: React.FC<TableViewProps> = ({\r\n templateComponents,\r\n dataEntries,\r\n renderFormComponent,\r\n renderComponent: internalRenderComponent,\r\n mode = 'preview',\r\n allowAddRemoveEntries = true,\r\n addAnotherText = 'Add Another',\r\n removeText = 'Remove',\r\n maxEntries = 10,\r\n minEntries = 1,\r\n displayAsGrid = true,\r\n onAddEntry,\r\n onRemoveEntry,\r\n formData: _formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange,\r\n datagridId = '' // Add datagrid ID with default\r\n}) => {\r\n\r\n if (templateComponents.length === 0) {\r\n return (\r\n <div style={{ \r\n textAlign: 'center', \r\n padding: '40px', \r\n color: 'var(--df-color-text-light)',\r\n border: '1px dashed #d1d5db',\r\n borderRadius: '8px',\r\n backgroundColor: 'var(--df-color-fb-container)'\r\n }}>\r\n No components defined. Add components to see the {displayAsGrid ? 'table' : 'list'} view.\r\n </div>\r\n )\r\n }\r\n\r\n // Render as Grid/Table View\r\n if (displayAsGrid) {\r\n return (\r\n <div className=\"datagrid-table-view\" style={{ \r\n border: '1px solid var(--df-color-fb-border)', \r\n borderRadius: '8px',\r\n overflow: 'hidden',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n maxWidth: '100%'\r\n }}>\r\n {/* Scroll Indicator */}\r\n <div style={{\r\n position: 'absolute',\r\n top: '8px',\r\n right: '8px',\r\n zIndex: 10,\r\n fontSize: '12px',\r\n color: 'var(--df-color-text-light)',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n padding: '4px 8px',\r\n borderRadius: '4px',\r\n border: '1px solid var(--df-color-fb-border)',\r\n opacity: templateComponents.length > 4 ? 1 : 0,\r\n transition: 'opacity 0.2s ease'\r\n }}>\r\n ← Scroll →\r\n </div>\r\n\r\n {/* Horizontal Scrollable Container */}\r\n <div \r\n className=\"table-scroll-container\"\r\n style={{\r\n overflowX: 'auto',\r\n overflowY: 'hidden',\r\n maxWidth: '100%',\r\n scrollbarWidth: 'thin',\r\n scrollbarColor: 'var(--df-color-fb-border) var(--df-color-fb-icon-bg)',\r\n position: 'relative'\r\n }}\r\n >\r\n {/* Table Headers */}\r\n <div className=\"table-headers\" style={{\r\n display: 'grid',\r\n gridTemplateColumns: `repeat(${templateComponents.length}, minmax(150px, 1fr))`,\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n borderBottom: '2px solid var(--df-color-fb-border)',\r\n minWidth: `${templateComponents.length * 150}px`\r\n }}>\r\n {templateComponents.map((component, index) => (\r\n <div key={`header-${component.id}`} style={{\r\n padding: '12px 16px',\r\n fontWeight: '600',\r\n color: 'var(--df-color-text-dark)',\r\n borderRight: index < templateComponents.length - 1 ? '1px solid var(--df-color-fb-border)' : 'none',\r\n fontSize: '14px',\r\n minWidth: '150px',\r\n whiteSpace: 'nowrap',\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis'\r\n }}>\r\n {component.basic?.label || `Column ${index + 1}`}\r\n </div>\r\n ))}\r\n </div>\r\n \r\n {/* Table Rows */}\r\n {dataEntries.length > 0 ? (\r\n dataEntries.map((entry, entryIndex) => (\r\n <div key={entry.id} className=\"table-row\" style={{\r\n display: 'grid',\r\n gridTemplateColumns: `repeat(${templateComponents.length}, minmax(150px, 1fr))`,\r\n borderBottom: entryIndex < dataEntries.length - 1 ? '1px solid var(--df-color-fb-border)' : 'none',\r\n backgroundColor: entryIndex % 2 === 0 ? 'var(--df-color-fb-container)' : 'var(--df-color-fb-bg)',\r\n position: 'relative',\r\n minWidth: `${templateComponents.length * 150}px`,\r\n isolation: 'isolate' // Create new stacking context for buttons\r\n }}>\r\n {templateComponents.map((templateComponent, componentIndex) => {\r\n // Find the corresponding component in this entry by position/index, not by name/label\r\n // This ensures each template component maps to the correct entry component\r\n let entryComponent = entry.components?.[componentIndex]\r\n \r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = templateComponent.id || `component-${componentIndex}`;\r\n const expectedUniqueId = `${baseComponentId}-entry-${datagridId}-${entryIndex}-${componentIndex}`;\r\n \r\n // If no component found at this index, create one from the template\r\n if (!entryComponent) {\r\n entryComponent = {\r\n ...templateComponent,\r\n id: expectedUniqueId,\r\n basic: {\r\n ...templateComponent.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear any default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n } else {\r\n // CRITICAL: Ensure the component has the correct unique ID\r\n // If the ID doesn't match the expected pattern, update it\r\n if (entryComponent.id !== expectedUniqueId) {\r\n entryComponent = {\r\n ...entryComponent,\r\n id: expectedUniqueId, // Update to the correct unique ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n } else {\r\n // Preserve the original ID if it's already correct\r\n entryComponent = {\r\n ...entryComponent,\r\n id: entryComponent.id, // Keep the original ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n }\r\n }\r\n \r\n return (\r\n <div key={`${entry.id}-${componentIndex}`} style={{\r\n padding: '12px 16px',\r\n borderRight: componentIndex < templateComponents.length - 1 ? '1px solid var(--df-color-fb-border)' : 'none',\r\n minHeight: '60px',\r\n minWidth: '150px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n overflow: 'visible', // CRITICAL: Allow buttons to be visible\r\n position: 'relative',\r\n zIndex: 1\r\n }}>\r\n <div style={{\r\n width: '100%',\r\n minWidth: '120px',\r\n overflow: 'hidden',\r\n position: 'relative',\r\n zIndex: 1\r\n }}>\r\n {/* Use internal renderComponent if available, otherwise use renderFormComponent from parent */}\r\n {/* This ensures each entry component gets its own isolated form value using unique IDs */}\r\n {internalRenderComponent ? internalRenderComponent(entryComponent, true) : renderFormComponent(entryComponent, true)}\r\n </div>\r\n </div>\r\n )\r\n })}\r\n \r\n {/* Remove button for each row when more than 1 entry exists */}\r\n {allowAddRemoveEntries && dataEntries.length > minEntries && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length <= minEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onRemoveEntry) {\r\n try {\r\n onRemoveEntry(entryIndex);\r\n } catch (error) {\r\n console.error('Error removing entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length <= minEntries}\r\n style={{\r\n position: 'absolute',\r\n top: '8px',\r\n right: '8px',\r\n padding: '4px 8px',\r\n backgroundColor: dataEntries.length <= minEntries ? '#f3f4f6' : '#ef4444',\r\n color: dataEntries.length <= minEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length <= minEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '4px',\r\n zIndex: 1000,\r\n minWidth: '24px',\r\n height: '24px',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto' // CRITICAL: Ensure button can receive clicks\r\n }}\r\n title={removeText}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#dc2626';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#ef4444';\r\n }\r\n }}\r\n >\r\n <span style={{ fontSize: '14px' }}>×</span>\r\n </button>\r\n )}\r\n </div>\r\n ))\r\n ) : (\r\n <div style={{\r\n padding: '40px',\r\n textAlign: 'center',\r\n color: 'var(--df-color-text-light)',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n borderTop: '1px solid var(--df-color-fb-border)'\r\n }}>\r\n No data entries. {allowAddRemoveEntries ? 'Click \"Add Another\" to add entries.' : 'Use the properties panel to add entries.'}\r\n </div>\r\n )}\r\n\r\n </div>\r\n\r\n {/* Add Another button - Moved outside scrollable container */}\r\n {/* CRITICAL: Always show in package (no mode check) - all functionality enabled */}\r\n {allowAddRemoveEntries && (\r\n <div style={{\r\n padding: '16px',\r\n backgroundColor: 'var(--df-color-fb-bg)',\r\n borderTop: '1px solid var(--df-color-fb-border)',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n position: 'sticky',\r\n bottom: 0,\r\n zIndex: 5\r\n }}>\r\n <button\r\n type=\"button\" // CRITICAL: Prevent form submission/navigation\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length >= maxEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onAddEntry) {\r\n try {\r\n onAddEntry();\r\n } catch (error) {\r\n console.error('Error adding entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length >= maxEntries}\r\n style={{\r\n padding: '8px 16px',\r\n backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',\r\n color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '6px',\r\n fontSize: '14px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length >= maxEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '6px',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto', // CRITICAL: Ensure button can receive clicks\r\n zIndex: 1000 // CRITICAL: Ensure button is above other elements\r\n }}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#059669';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#10b981';\r\n }\r\n }}\r\n >\r\n <span style={{ fontSize: '16px' }}>+</span>\r\n {addAnotherText}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n }\r\n\r\n // Render as List/Card View\r\n return (\r\n <div className=\"datagrid-list-view\" style={{ \r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '12px',\r\n backgroundColor: 'var(--df-color-fb-container)'\r\n }}>\r\n {dataEntries.length > 0 ? (\r\n dataEntries.map((entry, entryIndex) => (\r\n <div key={entry.id} className=\"list-entry\" style={{\r\n border: '1px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n padding: '16px',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n position: 'relative',\r\n transition: 'all 0.2s ease'\r\n }}>\r\n {/* Entry Header */}\r\n <div style={{\r\n display: 'flex',\r\n justifyContent: 'space-between',\r\n alignItems: 'center',\r\n marginBottom: '12px',\r\n paddingBottom: '8px',\r\n borderBottom: '1px solid var(--df-color-fb-border)'\r\n }}>\r\n <span style={{\r\n fontWeight: '600',\r\n color: 'var(--df-color-text-dark)',\r\n fontSize: '14px'\r\n }}>\r\n Entry #{entryIndex + 1}\r\n </span>\r\n \r\n {/* Remove button for each entry when more than 1 entry exists */}\r\n {allowAddRemoveEntries && dataEntries.length > 1 && (\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length <= minEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onRemoveEntry) {\r\n try {\r\n onRemoveEntry(entryIndex);\r\n } catch (error) {\r\n console.error('Error removing entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length <= minEntries}\r\n style={{\r\n padding: '4px 8px',\r\n backgroundColor: dataEntries.length <= minEntries ? '#f3f4f6' : '#ef4444',\r\n color: dataEntries.length <= minEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '4px',\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length <= minEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '4px',\r\n minWidth: '24px',\r\n height: '24px',\r\n justifyContent: 'center',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto', // CRITICAL: Ensure button can receive clicks\r\n zIndex: 1000 // CRITICAL: Ensure button is above other elements\r\n }}\r\n title={removeText}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#dc2626';\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length > minEntries) {\r\n e.currentTarget.style.backgroundColor = '#ef4444';\r\n }\r\n }}\r\n >\r\n <span style={{ fontSize: '14px' }}>×</span>\r\n </button>\r\n )}\r\n </div>\r\n\r\n {/* Entry Fields */}\r\n <div style={{\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))',\r\n gap: '16px'\r\n }}>\r\n {templateComponents.map((templateComponent, componentIndex) => {\r\n // Find the corresponding component in this entry by index first, then by name+label\r\n let entryComponent = entry.components?.[componentIndex]\r\n \r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = templateComponent.id || `component-${componentIndex}`;\r\n const expectedUniqueId = `${baseComponentId}-entry-${datagridId}-${entryIndex}-${componentIndex}`;\r\n \r\n // If no component at this index, try to find by name+label\r\n if (!entryComponent) {\r\n entryComponent = entry.components?.find((comp: any) => \r\n comp.name === templateComponent.name && \r\n comp.basic?.label === templateComponent.basic?.label\r\n )\r\n }\r\n \r\n // If no matching component found, use the template component\r\n if (!entryComponent) {\r\n entryComponent = {\r\n ...templateComponent,\r\n id: expectedUniqueId,\r\n basic: {\r\n ...templateComponent.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear any default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n } else {\r\n // CRITICAL: Ensure the component has the correct unique ID\r\n // If the ID doesn't match the expected pattern, update it\r\n if (entryComponent.id !== expectedUniqueId) {\r\n entryComponent = {\r\n ...entryComponent,\r\n id: expectedUniqueId, // Update to the correct unique ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n } else {\r\n // Preserve the original ID if it's already correct\r\n entryComponent = {\r\n ...entryComponent,\r\n id: entryComponent.id, // Keep the original ID\r\n basic: {\r\n ...entryComponent.basic,\r\n showLabel: false // Hide label in datagrid cells\r\n }\r\n }\r\n }\r\n }\r\n \r\n return (\r\n <div key={`${entry.id}-${componentIndex}`} style={{\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '4px'\r\n }}>\r\n <label style={{\r\n fontSize: '12px',\r\n fontWeight: '500',\r\n color: 'var(--df-color-text-light)',\r\n textTransform: 'uppercase',\r\n letterSpacing: '0.05em'\r\n }}>\r\n {templateComponent.basic?.label || `Field ${componentIndex + 1}`}\r\n </label>\r\n <div style={{\r\n minHeight: '40px',\r\n display: 'flex',\r\n alignItems: 'center',\r\n flexDirection: 'column',\r\n width: '100%'\r\n }}>\r\n {/* Use internal renderComponent if available, otherwise use renderFormComponent from parent */}\r\n {/* This ensures each entry component gets its own isolated form value using unique IDs */}\r\n {internalRenderComponent ? internalRenderComponent(entryComponent) : renderFormComponent(entryComponent)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(entryComponent.name) && (\r\n <ComponentActionFeatures\r\n component={entryComponent as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={_formData[entryComponent.id]}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(entryComponent.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(entryComponent.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {mode === 'preview' && (\r\n (() => {\r\n const hasSubmissionData = (\r\n ((entryComponent as any).basic?.notes && (entryComponent as any).basic.notes.trim().length > 0) ||\r\n ((entryComponent as any).basic?.attachments && Array.isArray((entryComponent as any).basic.attachments) && (entryComponent as any).basic.attachments.length > 0)\r\n );\r\n return hasSubmissionData ? (\r\n <ComponentSubmissionActions\r\n component={entryComponent as any}\r\n />\r\n ) : null;\r\n })()\r\n )}\r\n </div>\r\n </div>\r\n )\r\n })}\r\n </div>\r\n </div>\r\n ))\r\n ) : (\r\n <div style={{\r\n padding: '40px',\r\n textAlign: 'center',\r\n color: 'var(--df-color-text-light)',\r\n backgroundColor: 'var(--df-color-fb-container)',\r\n border: '1px dashed #d1d5db',\r\n borderRadius: '8px'\r\n }}>\r\n No data entries. {allowAddRemoveEntries ? 'Click \"Add Another\" to add entries.' : 'Use the properties panel to add entries.'}\r\n </div>\r\n )}\r\n\r\n {/* Add Another button below the list for test mode */}\r\n {mode === 'test' && allowAddRemoveEntries && (\r\n <div style={{\r\n padding: '16px',\r\n backgroundColor: '#f8f9fa',\r\n border: '1px solid var(--df-color-fb-border)',\r\n borderRadius: '8px',\r\n display: 'flex',\r\n justifyContent: 'center'\r\n }}>\r\n <button\r\n type=\"button\" // CRITICAL: Prevent form submission/navigation\r\n onClick={(e) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // CRITICAL: Check if button is disabled before calling handler\r\n if (dataEntries.length >= maxEntries) {\r\n return;\r\n }\r\n // CRITICAL: Call the handler if it exists\r\n if (onAddEntry) {\r\n try {\r\n onAddEntry();\r\n } catch (error) {\r\n console.error('Error adding entry:', error);\r\n }\r\n }\r\n }}\r\n disabled={dataEntries.length >= maxEntries}\r\n style={{\r\n padding: '8px 16px',\r\n backgroundColor: dataEntries.length >= maxEntries ? '#f3f4f6' : '#10b981',\r\n color: dataEntries.length >= maxEntries ? '#9ca3af' : '#ffffff',\r\n border: 'none',\r\n borderRadius: '6px',\r\n fontSize: '14px',\r\n fontWeight: '500',\r\n cursor: dataEntries.length >= maxEntries ? 'not-allowed' : 'pointer',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: '8px',\r\n transition: 'all 0.2s ease',\r\n pointerEvents: 'auto', // CRITICAL: Ensure button can receive clicks\r\n zIndex: 1000 // CRITICAL: Ensure button is above other elements\r\n }}\r\n onMouseEnter={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#059669'\r\n }\r\n }}\r\n onMouseLeave={(e) => {\r\n if (dataEntries.length < maxEntries) {\r\n e.currentTarget.style.backgroundColor = '#10b981'\r\n }\r\n }}\r\n >\r\n <span>+</span>\r\n {addAnotherText}\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n\r\nexport const DfFormDataGrid: React.FC<DfFormDataGridProps> = ({\r\n id,\r\n properties,\r\n mode = 'edit',\r\n formData = {},\r\n validationErrors = {},\r\n touchedFields = {},\r\n formSubmitted = false,\r\n onValueChange,\r\n onSelect,\r\n isSelected = false,\r\n className = '',\r\n onDataGridSelect,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n onComponentUpdate,\r\n selectedComponent,\r\n renderFormComponent,\r\n onEntryAdd,\r\n onEntryRemove,\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const [isCollapsed, setIsCollapsed] = useState(false)\r\n const hasInitialized = useRef(false)\r\n\r\n // Get all components in the grid\r\n let gridComponents = properties.templateComponents || []\r\n const dataEntries = properties.entries || []\r\n \r\n \r\n // Fallback: If no template components but we have entries, extract template from first entry\r\n if (gridComponents.length === 0 && dataEntries.length > 0 && dataEntries[0].components) {\r\n gridComponents = dataEntries[0].components.map((comp: any) => ({\r\n ...comp,\r\n id: comp.id?.replace(/-entry-\\d+$/, '') || comp.id, // Remove entry suffix for template\r\n basic: {\r\n ...comp.basic,\r\n showLabel: true // Show labels in template\r\n }\r\n }))\r\n }\r\n\r\n // Initialize template components if empty (only in edit mode)\r\n useEffect(() => {\r\n if (mode === 'edit' && !properties.templateComponents && onValueChange && hasInitialized.current) {\r\n const newValue = { \r\n ...properties, \r\n templateComponents: []\r\n }\r\n // Only call onValueChange if the data actually changed\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n hasInitialized.current = true\r\n }, [properties.templateComponents, id, onValueChange, properties, mode])\r\n\r\n // Sync template components with existing entries and create initial entry if needed\r\n useEffect(() => {\r\n if (gridComponents.length > 0) {\r\n // In test mode, ensure we have at least one entry if entries are empty\r\n if (mode === 'test' && dataEntries.length === 0 && hasInitialized.current) {\r\n const firstEntry = {\r\n id: `entry-${id}-0`,\r\n index: 0,\r\n components: gridComponents.map((comp, componentIndex) => {\r\n const baseComponentId = comp.id || `component-${componentIndex}`;\r\n return {\r\n ...comp,\r\n id: `${baseComponentId}-entry-${id}-0-${componentIndex}`,\r\n basic: {\r\n ...comp.basic,\r\n showLabel: false,\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n };\r\n }),\r\n styles: {}\r\n }\r\n \r\n if (onValueChange) {\r\n const newValue = { ...properties, entries: [firstEntry] }\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n return\r\n }\r\n \r\n // Only run this effect if we're in edit mode and there are actual changes needed\r\n if (mode !== 'edit' || !hasInitialized.current) {\r\n return // Don't run sync logic in preview mode or on first render\r\n }\r\n \r\n \r\n // Force update entries that don't have proper unique IDs\r\n const needsIdUpdate = dataEntries.some(entry => \r\n entry.components?.some((comp: any, index: number) => {\r\n const expectedId = `${gridComponents[index]?.id}-entry-${entry.index}-${index}`\r\n return comp.id !== expectedId\r\n })\r\n )\r\n \r\n if (needsIdUpdate && onValueChange) {\r\n const updatedEntries = dataEntries.map(entry => ({\r\n ...entry,\r\n components: entry.components?.map((comp: any, index: number) => ({\r\n ...comp,\r\n id: `${gridComponents[index]?.id}-entry-${entry.index}-${index}`\r\n })) || []\r\n }))\r\n \r\n // Only call onValueChange if the data actually changed\r\n const newValue = { ...properties, entries: updatedEntries }\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n return // Exit early to avoid double processing\r\n }\r\n // If no entries exist, create the first entry (only in edit mode, test mode handled above)\r\n if (dataEntries.length === 0 && mode === 'edit') {\r\n const firstEntry = {\r\n id: `entry-${id}-0`,\r\n index: 0,\r\n components: gridComponents.map((comp, componentIndex) => {\r\n const baseComponentId = comp.id || `component-${componentIndex}`;\r\n return {\r\n ...comp,\r\n id: `${baseComponentId}-entry-${id}-0-${componentIndex}`,\r\n basic: {\r\n ...comp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n };\r\n }),\r\n styles: {}\r\n }\r\n\r\n if (onValueChange) {\r\n const newValue = { ...properties, entries: [firstEntry] }\r\n // Only call onValueChange if the data actually changed\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n } else if (dataEntries.length > 0) {\r\n // Update existing entries to include all template components and sync their properties\r\n const needsUpdate = dataEntries.some(entry => {\r\n // Check if entry is missing any template components or if existing components need updates\r\n return gridComponents.some((templateComp, componentIndex) => {\r\n const existingComponent = entry.components?.[componentIndex]\r\n \r\n if (!existingComponent) {\r\n return true // Missing component at this index\r\n }\r\n \r\n // Check if component has proper unique ID\r\n const expectedId = `${templateComp.id}-entry-${entry.index}-${componentIndex}`\r\n const hasProperId = existingComponent.id === expectedId\r\n \r\n // Check if existing component needs to be updated with new template properties\r\n // Compare key properties that should be synced\r\n const needsPropertyUpdate = \r\n JSON.stringify((existingComponent.basic as any)?.options) !== JSON.stringify((templateComp.basic as any)?.options) ||\r\n (existingComponent.basic as any)?.placeholder !== (templateComp.basic as any)?.placeholder ||\r\n (existingComponent.basic as any)?.defaultValue !== (templateComp.basic as any)?.defaultValue ||\r\n (existingComponent.basic as any)?.label !== (templateComp.basic as any)?.label ||\r\n existingComponent.validation?.required !== templateComp.validation?.required\r\n return !hasProperId || needsPropertyUpdate\r\n })\r\n })\r\n\r\n if (needsUpdate && onValueChange) {\r\n const updatedEntries = dataEntries.map(entry => {\r\n // Use index-based matching to ensure each template component maps to the correct entry component\r\n const updatedComponents = gridComponents.map((templateComp, componentIndex) => {\r\n // Find existing component by index first\r\n let existingComponent: FormComponentType | undefined = entry.components?.[componentIndex]\r\n \r\n // If no component at this index, try to find by name+label (for backward compatibility)\r\n if (!existingComponent) {\r\n existingComponent = entry.components?.find((comp: any) => \r\n comp.name === templateComp.name && \r\n comp.basic?.label === templateComp.basic?.label\r\n ) as FormComponentType | undefined\r\n }\r\n \r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = templateComp.id || `component-${componentIndex}`;\r\n const uniqueId = `${baseComponentId}-entry-${id}-${entry.index}-${componentIndex}`\r\n \r\n if (existingComponent) {\r\n // Update existing component with new template properties while ensuring unique ID\r\n // CRITICAL: Don't preserve value from basic - form values should come from formData\r\n const updatedComponent = {\r\n ...templateComp,\r\n id: uniqueId, // Always use the unique ID pattern\r\n basic: {\r\n ...templateComp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n\r\n return updatedComponent\r\n } else {\r\n // Create new component based on template\r\n const newComponent = {\r\n ...templateComp,\r\n id: uniqueId,\r\n basic: {\r\n ...templateComp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n }\r\n \r\n return newComponent\r\n }\r\n })\r\n\r\n return {\r\n ...entry,\r\n components: updatedComponents\r\n }\r\n })\r\n\r\n const newValue = { ...properties, entries: updatedEntries }\r\n // Only call onValueChange if the data actually changed\r\n if (JSON.stringify(newValue) !== JSON.stringify(properties)) {\r\n onValueChange({\r\n id,\r\n value: newValue\r\n })\r\n }\r\n }\r\n }\r\n }\r\n }, [gridComponents, dataEntries, id, onValueChange, properties, mode, properties.templateComponents])\r\n\r\n const handleDataGridClick = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n onSelect?.()\r\n onDataGridSelect?.(properties)\r\n }, [onSelect, onDataGridSelect, properties])\r\n\r\n const toggleCollapse = (event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n setIsCollapsed(!isCollapsed)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...properties.basic, collapsed: !isCollapsed } }\r\n })\r\n }\r\n\r\n const handleComponentDelete = useCallback((component: FormComponentType, event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n \r\n // Call the parent's component delete handler first\r\n if (onComponentDelete) {\r\n onComponentDelete(component, event)\r\n }\r\n \r\n // Remove from grid template components\r\n const updatedComponents = gridComponents.filter(comp => comp.id !== component.id)\r\n \r\n // Remove from all existing entries by matching component name and label\r\n const updatedEntries = dataEntries.map(entry => ({\r\n ...entry,\r\n components: entry.components?.filter((entryComp: any) => \r\n !(entryComp.name === component.name && entryComp.basic?.label === component.basic?.label)\r\n ) || []\r\n }))\r\n \r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { \r\n ...properties, \r\n templateComponents: updatedComponents,\r\n entries: updatedEntries\r\n }\r\n })\r\n }\r\n }, [onComponentDelete, properties, onValueChange, id, gridComponents, dataEntries])\r\n\r\n const handleComponentUpdate = useCallback((componentId: string, updates: Partial<FormComponentType>) => {\r\n // Call the parent's component update handler first\r\n if (onComponentUpdate) {\r\n onComponentUpdate(componentId, updates)\r\n }\r\n \r\n // Update the component in grid template components\r\n const updatedComponents = gridComponents.map(comp => \r\n comp.id === componentId ? { ...comp, ...updates } : comp\r\n )\r\n \r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, templateComponents: updatedComponents }\r\n })\r\n }\r\n }, [onComponentUpdate, properties, onValueChange, id, gridComponents])\r\n\r\n // Handle component value change for form data updates (test mode)\r\n const handleComponentValueChange = useCallback((change: IFormControlChange) => {\r\n if (mode === 'test') {\r\n // In test mode, update form data through the parent's onValueChange\r\n // This allows the form data to be updated for interactive components\r\n if (onValueChange) {\r\n onValueChange({\r\n id: change.id,\r\n value: change.value\r\n })\r\n }\r\n }\r\n // CRITICAL: Always handle value changes in package (like test mode)\r\n }, [onValueChange])\r\n\r\n const handleAddEntry = useCallback(() => {\r\n // CRITICAL: Always use the latest properties.entries to ensure we're working with current state\r\n const currentEntries = properties.entries || [];\r\n const newEntryIndex = currentEntries.length;\r\n // CRITICAL: Use a unique entry ID that includes the datagrid ID to prevent conflicts\r\n const newEntryId = `entry-${id}-${newEntryIndex}`;\r\n \r\n const newEntry: DataGridEntry = {\r\n id: newEntryId,\r\n index: newEntryIndex,\r\n components: gridComponents.map((comp, componentIndex) => {\r\n // CRITICAL: Generate unique ID that includes datagrid ID, entry index, and component index\r\n // This ensures no ID collisions across different datagrids or entries\r\n const baseComponentId = comp.id || `component-${componentIndex}`;\r\n const uniqueComponentId = `${baseComponentId}-entry-${id}-${newEntryIndex}-${componentIndex}`;\r\n \r\n return {\r\n ...comp,\r\n id: uniqueComponentId, // Make each component unique per entry and position\r\n basic: {\r\n ...comp.basic,\r\n showLabel: false, // Hide label in datagrid cells\r\n // Clear any default values to prevent value sharing\r\n defaultValue: undefined,\r\n value: undefined\r\n }\r\n };\r\n }) as FormComponentType[],\r\n styles: {}\r\n }\r\n \r\n const updatedEntries = [...currentEntries, newEntry]\r\n \r\n // CRITICAL: Update via onValueChange first to update internal state\r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, entries: updatedEntries }\r\n })\r\n }\r\n \r\n // CRITICAL: Call onEntryAdd immediately (matching main app behavior)\r\n // The parent's onEntryAdd will sync formComponents with the updated entries\r\n onEntryAdd?.()\r\n }, [properties, onValueChange, id, onEntryAdd, gridComponents])\r\n\r\n const handleRemoveEntry = useCallback((entryIndex: number) => {\r\n const updatedEntries = properties.entries\r\n .filter((_, index) => index !== entryIndex)\r\n .map((entry, index) => ({ ...entry, index, id: `entry-${id}-${index}` }))\r\n \r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, entries: updatedEntries }\r\n })\r\n }\r\n }, [properties, onValueChange, id, onEntryRemove])\r\n\r\n\r\n // Use our own render function to ensure proper onComponentUpdate handling\r\n const renderComponent = useCallback((field: FormComponentType, hideLabel: boolean = false) => {\r\n // CRITICAL: Always get formValue from formData in package (like test mode)\r\n // This ensures each entry component gets its own value, not shared with other entries or sections\r\n const formValue = formData[field.id] || ('defaultValue' in field.basic ? field.basic.defaultValue || '' : '')\r\n \r\n const commonProps = {\r\n id: field.id, // Use the unique ID from the field\r\n properties: field,\r\n validationErrors: validationErrors || {},\r\n formValue: formValue, // This uses the unique ID to get the correct value\r\n touchedFields: touchedFields || {},\r\n formSubmitted: formSubmitted || false,\r\n mode,\r\n hideLabel,\r\n onValueChange: handleComponentValueChange, // This will update formData using the unique ID\r\n onBlur: () => {},\r\n onFocus: () => {}\r\n }\r\n\r\n switch (field.name) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'number-input':\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={field as any}\r\n inputType={field.name === 'text-input' ? 'text' : \r\n field.name === 'number-input' ? 'number' : 'email'}\r\n readonly={false} // CRITICAL: Always editable in package\r\n disabled={false} // CRITICAL: Never disabled in package\r\n hideLabel={hideLabel}\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={field as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} formValue={[]} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...field,\r\n options: (field as any).basic?.options || []\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={field as any} readonly={false} disabled={false} hideLabel={hideLabel} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={field as any} hideLabel={hideLabel} />\r\n \r\n case 'heading':\r\n return <DfFormHeading {...commonProps} properties={field as any} hideLabel={hideLabel} />\r\n \r\n case 'instructions':\r\n return <DfFormInstruction {...commonProps} properties={field as any} hideLabel={hideLabel} />\r\n \r\n default:\r\n return <div className=\"unknown-component\">Unknown component: {field.name}</div>\r\n }\r\n }, [mode, handleComponentValueChange, formData, validationErrors, touchedFields, formSubmitted])\r\n\r\n const gridStyle = {\r\n backgroundColor: properties.styles.backgroundColor || 'var(--df-color-fb-container)',\r\n borderColor: properties.styles.borderColor || 'var(--df-color-fb-border)',\r\n borderWidth: properties.styles.borderWidth || '2px',\r\n borderRadius: properties.styles.borderRadius || '8px',\r\n padding: properties.styles.padding || '16px',\r\n margin: properties.styles.margin || '16px 0'\r\n }\r\n\r\n // Always render the grid - let GridDropZone handle empty state\r\n\r\n return (\r\n <div\r\n className={`form-group df-form-datagrid ${isSelected ? 'selected' : ''} ${className}`}\r\n onClick={handleDataGridClick}\r\n style={gridStyle}\r\n >\r\n {/* Grid Header */}\r\n <div className=\"grid-header\">\r\n <div className=\"grid-title\" onClick={toggleCollapse}>\r\n <div className=\"title-content\" style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>\r\n {isCollapsed ? <ChevronRight size={16} /> : <ChevronDown size={16} />}\r\n <Grid size={16} />\r\n <span className=\"grid-label\" style={{ fontWeight: '600' }}>{properties.basic.label}</span>\r\n {properties.validation.required && (\r\n <span className=\"required-indicator\" style={{ color: '#ef4444' }}>*</span>\r\n )}\r\n </div>\r\n </div>\r\n \r\n </div>\r\n\r\n {/* Grid Description */}\r\n {properties.basic.description && !isCollapsed && (\r\n <div className=\"grid-description\" style={{ marginTop: '8px', color: 'var(--df-color-text-light)', fontSize: '14px' }}>\r\n {properties.basic.description}\r\n </div>\r\n )}\r\n\r\n {/* Grid Content */}\r\n {!isCollapsed && (\r\n <div className=\"grid-content\" style={{ marginTop: '16px' }}>\r\n {mode === 'edit' ? (\r\n <GridDropZone\r\n gridComponents={gridComponents}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect || (() => {})}\r\n onComponentDelete={handleComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n onComponentUpdate={handleComponentUpdate}\r\n selectedComponent={selectedComponent || null}\r\n renderFormComponent={renderFormComponent || renderComponent}\r\n gridId={id}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n ) : (\r\n /* Table View for Preview/Test Mode */\r\n <TableView\r\n templateComponents={gridComponents}\r\n dataEntries={dataEntries}\r\n renderFormComponent={renderFormComponent || renderComponent}\r\n mode={mode}\r\n allowAddRemoveEntries={properties.datagrid?.allowAddRemoveEntries ?? true}\r\n addAnotherText={properties.datagrid?.addAnotherText ?? 'Add Entry'}\r\n removeText={properties.datagrid?.removeText ?? 'Remove'}\r\n maxEntries={properties.datagrid?.maxEntries ?? 10}\r\n minEntries={properties.datagrid?.minEntries ?? 1}\r\n displayAsGrid={properties.datagrid?.displayAsGrid ?? true}\r\n onAddEntry={onEntryAdd ? onEntryAdd : handleAddEntry}\r\n onRemoveEntry={onEntryRemove ? onEntryRemove : handleRemoveEntry}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n datagridId={id}\r\n />\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormDataGrid","import React, { useState, useEffect, useCallback, useRef } from 'react'\r\nimport { \r\n FormComponentType, \r\n IFormControlChange, \r\n IFormValidationErrors\r\n} from './df-form-controls/df-form-preview-interfaces'\r\nimport { conditionalLogicService } from './services/conditionalLogicService'\r\nimport { FormComponentType as TFormComponent } from './df-form-controls/df-form-preview-interfaces'\r\nimport { toastService } from './services/toast.service'\r\n\r\n// Import form control components\r\nimport { DfFormInput } from './df-form-controls/df-form-input'\r\nimport { DfFormTextarea } from './df-form-controls/df-form-textarea'\r\nimport { DfFormSelect } from './df-form-controls/df-form-select'\r\nimport { DfFormCheckbox } from './df-form-controls/df-form-checkbox'\r\nimport { DfFormRadio } from './df-form-controls/df-form-radio'\r\nimport { DfFormSegment } from './df-form-controls/df-form-segment'\r\nimport { DfFormDateTime } from './df-form-controls/df-form-date-time'\r\nimport { DfFormSignature } from './df-form-controls/df-form-signature'\r\nimport { DfFormFileUpload } from './df-form-controls/df-form-file-upload'\r\nimport { DfFormLocation } from './df-form-controls/df-form-location'\r\nimport { DfFormHeading } from './df-form-controls/df-form-heading'\r\nimport { DfFormInstruction } from './df-form-controls/df-form-instruction'\r\nimport { DfFormSection } from './df-form-controls/df-form-section/df-form-section'\r\nimport { DfFormDataGrid } from './df-form-controls/df-form-grid/df-form-grid'\r\nimport { ComponentActionFeatures } from './ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from './components/ComponentSubmissionActions'\r\n\r\n// Import styles\r\nimport './DfFormPreview.scss'\r\n\r\n// Dynamic imports to avoid circular dependencies\r\nconst DfFormTable = React.lazy(() => import('./df-form-controls/df-form-table/df-form-table'))\r\n\r\nexport type DeviceType = 'desktop' | 'tablet' | 'mobile'\r\n\r\nexport interface DfFormPreviewProps {\r\n formComponents: FormComponentType[]\r\n formData?: any\r\n currentDevice?: DeviceType\r\n isPreviewMode?: boolean\r\n initialFormData?: FormComponentType[]\r\n onSubmit?: (formData: FormComponentType[]) => void\r\n onFormDataChange?: (formData: FormComponentType[]) => void\r\n formTitle?: string\r\n formDescription?: string\r\n formTemplateId?: string\r\n // Optional component management props for edit mode\r\n onComponentSelect?: (component: FormComponentType) => void\r\n onComponentDelete?: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n onComponentUpdate?: (componentId: string, updates: Partial<FormComponentType>) => void\r\n selectedComponent?: FormComponentType | null\r\n}\r\n\r\nexport const DfFormPreview: React.FC<DfFormPreviewProps> = ({\r\n formComponents = [],\r\n currentDevice = 'desktop',\r\n isPreviewMode = false,\r\n initialFormData = [],\r\n onSubmit,\r\n onFormDataChange,\r\n formTitle,\r\n formDescription,\r\n formTemplateId,\r\n // Add component management props for edit mode\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n onComponentUpdate,\r\n selectedComponent\r\n}) => {\r\n // Form state\r\n const [formValues, setFormValues] = useState<Record<string, any>>({})\r\n const [validationErrors, setValidationErrors] = useState<IFormValidationErrors>({})\r\n const [formSubmitted, setFormSubmitted] = useState(false)\r\n const [touchedFields, setTouchedFields] = useState<Record<string, boolean>>({})\r\n const [componentVisibility, setComponentVisibility] = useState<Record<string, boolean>>({})\r\n // Track raised issues for threshold conditions (Set of condition IDs)\r\n const [raisedThresholdIssues, setRaisedThresholdIssues] = useState<Set<string>>(new Set())\r\n // Track threshold action completions: Map<conditionId, { notesCompleted, attachmentsCompleted, emailSent }>\r\n const [thresholdActionCompletions, setThresholdActionCompletions] = useState<Map<string, { notesCompleted: boolean; attachmentsCompleted: boolean; emailSent: boolean }>>(new Map())\r\n // Track threshold validation state for submit button\r\n const [thresholdValidationState, setThresholdValidationState] = useState<{ isValid: boolean; errorMessage?: string }>({ isValid: true })\r\n\r\n // Initialize form state\r\n useEffect(() => {\r\n initializeFormState()\r\n }, [formComponents, initialFormData])\r\n\r\n // Recursive function to initialize values from nested components\r\n const initializeComponentValues = (components: any[], values: Record<string, any>) => {\r\n components.forEach(component => {\r\n if (component.id) {\r\n // Always initialize component in form state, even with empty values\r\n // This ensures that value changes are tracked properly\r\n if ('value' in component.basic && component.basic.value !== undefined) {\r\n values[component.id] = component.basic.value\r\n }\r\n // Fallback to defaultValue if no value\r\n else if ('defaultValue' in component.basic && component.basic.defaultValue !== undefined) {\r\n values[component.id] = component.basic.defaultValue\r\n }\r\n // If neither value nor defaultValue exists, initialize with appropriate default based on component type\r\n else {\r\n // For checkbox and multi-select components, initialize with empty array\r\n if (component.name === 'checkbox' || component.name === 'select') {\r\n values[component.id] = []\r\n } else {\r\n // For other components, initialize with empty string\r\n values[component.id] = ''\r\n }\r\n }\r\n }\r\n\r\n // Handle nested components in table cells\r\n if (component.cells && Array.isArray(component.cells)) {\r\n component.cells.forEach((row: any[], _rowIndex: number) => {\r\n if (Array.isArray(row)) {\r\n row.forEach((cell: any, _cellIndex: number) => {\r\n if (cell && cell.components && Array.isArray(cell.components)) {\r\n initializeComponentValues(cell.components, values)\r\n }\r\n })\r\n }\r\n })\r\n }\r\n\r\n // Handle nested components in datagrid entries\r\n if (component.entries && Array.isArray(component.entries)) {\r\n component.entries.forEach((entry: any, _entryIndex: number) => {\r\n if (entry && entry.components && Array.isArray(entry.components)) {\r\n initializeComponentValues(entry.components, values)\r\n }\r\n })\r\n }\r\n \r\n // Handle file component - initialize with file data if present\r\n if (component.name === 'file' && component.basic) {\r\n const fileData = (component.basic as any).files || (component.basic as any).attachments || (component.basic as any).value;\r\n if (fileData) {\r\n values[component.id] = fileData;\r\n }\r\n }\r\n \r\n // Handle instructions component - ensure instructions array exists and initialize formValue\r\n if (component.name === 'instructions' && component.basic) {\r\n if (!(component.basic as any).instructions) {\r\n // Initialize empty instructions array if not present\r\n (component.basic as any).instructions = [];\r\n }\r\n // CRITICAL: Initialize formValue for instructions from API data\r\n // Check if component has value from API (could be in basic.value, basic.instructions, or formData)\r\n const instructionValue = (component.basic as any).value || (component.basic as any).instructions;\r\n if (instructionValue) {\r\n // Store instruction data in formValues so it can be passed to DfFormInstruction\r\n values[component.id] = instructionValue;\r\n }\r\n }\r\n\r\n // Handle nested components in section children\r\n if (component.children && Array.isArray(component.children)) {\r\n initializeComponentValues(component.children, values)\r\n }\r\n })\r\n }\r\n\r\n const initializeFormState = useCallback(() => {\r\n const initialValues: Record<string, any> = {}\r\n const seenIds = new Set<string>();\r\n \r\n // Validate component IDs for uniqueness\r\n const validateComponentIds = (components: any[]): void => {\r\n components.forEach(component => {\r\n if (component.id) {\r\n if (seenIds.has(component.id)) {\r\n console.error(`[DfFormPreview] Duplicate component ID detected: ${component.id}. Component:`, component);\r\n // Generate a unique ID for duplicate\r\n component.id = `${component.id}-duplicate-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\r\n console.warn(`[DfFormPreview] Generated new unique ID: ${component.id}`);\r\n }\r\n seenIds.add(component.id);\r\n }\r\n \r\n // Recursively validate nested components\r\n if (component.children && Array.isArray(component.children)) {\r\n validateComponentIds(component.children);\r\n }\r\n if (component.cells && Array.isArray(component.cells)) {\r\n component.cells.forEach((row: any[]) => {\r\n if (Array.isArray(row)) {\r\n row.forEach((cell: any) => {\r\n if (cell && cell.components && Array.isArray(cell.components)) {\r\n validateComponentIds(cell.components);\r\n }\r\n });\r\n }\r\n });\r\n }\r\n if (component.entries && Array.isArray(component.entries)) {\r\n component.entries.forEach((entry: any) => {\r\n if (entry && entry.components && Array.isArray(entry.components)) {\r\n validateComponentIds(entry.components);\r\n }\r\n });\r\n }\r\n });\r\n };\r\n \r\n // Validate all component IDs for uniqueness\r\n if (formComponents && formComponents.length > 0) {\r\n validateComponentIds(formComponents);\r\n }\r\n if (initialFormData && initialFormData.length > 0) {\r\n validateComponentIds(initialFormData);\r\n }\r\n \r\n // Initialize form values from initial data\r\n if (initialFormData && initialFormData.length > 0) {\r\n initializeComponentValues(initialFormData, initialValues)\r\n }\r\n \r\n // Initialize form values from form components (for submitted data)\r\n if (formComponents && formComponents.length > 0) {\r\n initializeComponentValues(formComponents, initialValues)\r\n }\r\n setFormValues(initialValues)\r\n\r\n // Evaluate initial conditional logic\r\n evaluateConditionalLogic()\r\n }, [initialFormData, formComponents])\r\n\r\n // Recursive function to evaluate conditional logic for nested components\r\n const evaluateComponentConditionalLogic = (components: any[], visibility: Record<string, boolean>) => {\r\n components.forEach(component => {\r\n if (component.id) {\r\n // Skip conditional logic for table and datagrid components - they are always visible\r\n if (component.name === 'table' || component.name === 'datagrid') {\r\n visibility[component.id] = true\r\n } else if (component.conditional) {\r\n // Use the proper conditional logic service\r\n const result = conditionalLogicService.evaluateConditionalLogic(\r\n component.conditional,\r\n formComponents,\r\n formValues\r\n )\r\n visibility[component.id] = result.shouldShow\r\n } else {\r\n // No conditional logic means always show\r\n visibility[component.id] = true\r\n }\r\n }\r\n\r\n // Handle nested components in table cells\r\n if (component.cells && Array.isArray(component.cells)) {\r\n component.cells.forEach((row: any[]) => {\r\n row.forEach((cell: any) => {\r\n if (cell.components && Array.isArray(cell.components)) {\r\n evaluateComponentConditionalLogic(cell.components, visibility)\r\n }\r\n })\r\n })\r\n }\r\n\r\n // Handle nested components in datagrid entries\r\n if (component.entries && Array.isArray(component.entries)) {\r\n component.entries.forEach((entry: any) => {\r\n if (entry.components && Array.isArray(entry.components)) {\r\n evaluateComponentConditionalLogic(entry.components, visibility)\r\n }\r\n })\r\n }\r\n\r\n // Handle nested components in section children\r\n if (component.children && Array.isArray(component.children)) {\r\n evaluateComponentConditionalLogic(component.children, visibility)\r\n }\r\n })\r\n }\r\n\r\n // Evaluate conditional logic for all components\r\n const evaluateConditionalLogic = useCallback(() => {\r\n const visibility: Record<string, boolean> = {}\r\n \r\n if (formComponents && formComponents.length > 0) {\r\n evaluateComponentConditionalLogic(formComponents, visibility)\r\n }\r\n \r\n setComponentVisibility(visibility)\r\n }, [formComponents, formValues])\r\n\r\n // Check if a component should be visible based on conditional logic\r\n const shouldShowComponent = useCallback((componentId: string): boolean => {\r\n // Find the component to check its type\r\n const component = formComponents.find(comp => comp.id === componentId)\r\n \r\n // Table and datagrid components are always visible (no conditional logic)\r\n if (component && (component.name === 'table' || component.name === 'datagrid')) {\r\n return true\r\n }\r\n \r\n const isVisible = componentVisibility[componentId] !== false\r\n return isVisible\r\n }, [componentVisibility, formComponents])\r\n\r\n // Handle form value changes and re-evaluate conditional logic\r\n const onFormValueChange = useCallback((change: IFormControlChange) => {\r\n // CRITICAL: Validate that change.id is valid and unique\r\n if (!change.id || typeof change.id !== 'string' || change.id.trim() === '') {\r\n console.error('[DfFormPreview] Invalid component ID in onFormValueChange:', change);\r\n return;\r\n }\r\n \r\n // CRITICAL: Check if multiple components share this ID (ID collision detection)\r\n const componentsWithSameId = formComponents.filter(comp => comp.id === change.id);\r\n if (componentsWithSameId.length > 1) {\r\n console.error(`[DfFormPreview] ID COLLISION DETECTED! Multiple components share ID \"${change.id}\":`, \r\n componentsWithSameId.map(c => ({ id: c.id, name: c.name, label: c.basic?.label })));\r\n // Don't update - this would cause all components with this ID to get the same value\r\n return;\r\n }\r\n \r\n // Debug: Log value changes to identify ID collisions\r\n const existingValue = formValues[change.id];\r\n if (existingValue !== undefined && existingValue !== change.value) {\r\n console.log('[DfFormPreview] Updating form value:', {\r\n id: change.id,\r\n oldValue: existingValue,\r\n newValue: change.value\r\n });\r\n }\r\n \r\n const newFormValues = {\r\n ...formValues,\r\n [change.id]: change.value\r\n }\r\n setFormValues(newFormValues)\r\n \r\n // Clear raised issues for this component when value changes\r\n // This ensures that if threshold condition changes, user must raise issue again\r\n const component = formComponents.find(comp => comp.id === change.id);\r\n if (component) {\r\n const threshold = (component as any)?.threshold;\r\n if (threshold && threshold.conditions && threshold.conditions.length > 0) {\r\n setRaisedThresholdIssues(prev => {\r\n const newSet = new Set(prev);\r\n threshold.conditions.forEach((condition: any) => {\r\n newSet.delete(condition.id);\r\n });\r\n return newSet;\r\n });\r\n }\r\n }\r\n \r\n // Recursive function to update component values\r\n const updateComponentValue = (components: FormComponentType[]): FormComponentType[] => {\r\n return components.map(component => {\r\n if (component.id === change.id) {\r\n if ('defaultValue' in component.basic) {\r\n return {\r\n ...component,\r\n basic: {\r\n ...component.basic,\r\n value: change.value ?? component.basic.defaultValue,\r\n defaultValue: change.value\r\n }\r\n } as FormComponentType\r\n }\r\n }\r\n \r\n // Recursively update nested components\r\n if (component.name === 'section' && (component as any).children) {\r\n return {\r\n ...component,\r\n children: updateComponentValue((component as any).children)\r\n } as FormComponentType\r\n }\r\n \r\n if (component.name === 'table' && (component as any).cells) {\r\n return {\r\n ...component,\r\n cells: (component as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n const updatedCell = { ...cell };\r\n if (updatedCell.components) {\r\n updatedCell.components = updateComponentValue(updatedCell.components);\r\n }\r\n return updatedCell;\r\n })\r\n )\r\n } as FormComponentType\r\n }\r\n \r\n if (component.name === 'datagrid' && (component as any).entries) {\r\n return {\r\n ...component,\r\n entries: (component as any).entries.map((entry: any) => {\r\n const updatedEntry = { ...entry };\r\n if (updatedEntry.components) {\r\n updatedEntry.components = updateComponentValue(updatedEntry.components);\r\n }\r\n return updatedEntry;\r\n })\r\n } as FormComponentType\r\n }\r\n \r\n return component\r\n })\r\n }\r\n \r\n // Update form components\r\n const updatedComponents = updateComponentValue(formComponents)\r\n \r\n onFormDataChange?.(updatedComponents)\r\n \r\n // Clear validation errors when user starts typing and re-validate\r\n if (validationErrors[change.id]) {\r\n setValidationErrors(prev => ({\r\n ...prev,\r\n [change.id]: ''\r\n }))\r\n }\r\n \r\n // Re-validate the field after value change (only in test mode)\r\n if (!isPreviewMode) {\r\n setTimeout(() => {\r\n validateField(change.id)\r\n }, 100)\r\n }\r\n \r\n // Re-evaluate conditional logic with new form values\r\n setTimeout(() => {\r\n const visibility: Record<string, boolean> = {}\r\n \r\n formComponents.forEach(component => {\r\n // Skip conditional logic for table and datagrid components - they are always visible\r\n if (component.name === 'table' || component.name === 'datagrid') {\r\n visibility[component.id] = true\r\n } else if (component.conditional) {\r\n const result = conditionalLogicService.evaluateConditionalLogic(\r\n component.conditional,\r\n formComponents,\r\n newFormValues\r\n )\r\n visibility[component.id] = result.shouldShow\r\n } else {\r\n visibility[component.id] = true\r\n }\r\n })\r\n \r\n setComponentVisibility(visibility)\r\n }, 0)\r\n }, [formComponents, formValues, validationErrors, onFormDataChange])\r\n\r\n // Recursive function to find a component by ID in nested structures\r\n const findComponentById = useCallback((components: FormComponentType[], fieldId: string): FormComponentType | null => {\r\n for (const comp of components) {\r\n if (comp.id === fieldId) {\r\n return comp\r\n }\r\n \r\n // Check nested components in sections\r\n if (comp.name === 'section' && (comp as any).children) {\r\n const found = findComponentById((comp as any).children, fieldId)\r\n if (found) return found\r\n }\r\n \r\n // Check nested components in table cells\r\n if (comp.name === 'table' && (comp as any).cells) {\r\n for (const row of (comp as any).cells) {\r\n for (const cell of row) {\r\n if (cell.components) {\r\n const found = findComponentById(cell.components, fieldId)\r\n if (found) return found\r\n }\r\n }\r\n }\r\n }\r\n \r\n // Check nested components in datagrid entries\r\n if (comp.name === 'datagrid' && (comp as any).entries) {\r\n for (const entry of (comp as any).entries) {\r\n if (entry.components) {\r\n const found = findComponentById(entry.components, fieldId)\r\n if (found) return found\r\n }\r\n }\r\n }\r\n }\r\n return null\r\n }, [])\r\n\r\n // Validate individual field\r\n const validateField = useCallback((fieldId: string) => {\r\n // Only validate in test mode\r\n if (isPreviewMode) return\r\n \r\n // Find component recursively (handles nested components)\r\n const component = findComponentById(formComponents, fieldId)\r\n if (!component) return\r\n\r\n // Get current value from form values (real-time input)\r\n const currentValue = formValues[fieldId] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n\r\n let errorMessage = ''\r\n\r\n // Check for required validation\r\n if (component.validation.required && !hasValue) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} is required`\r\n }\r\n // Check for email validation\r\n else if (component.name === 'email-input' && hasValue && !/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/.test(currentValue)) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be a valid email`\r\n }\r\n // Check for minLength validation\r\n else if (component.validation.minLength && hasValue && currentValue.length < component.validation.minLength) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be at least ${component.validation.minLength} characters`\r\n }\r\n // Check for maxLength validation\r\n else if (component.validation.maxLength && hasValue && currentValue.length > component.validation.maxLength) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be no more than ${component.validation.maxLength} characters`\r\n }\r\n // Check for number validations\r\n else if (component.name === 'number-input' && hasValue) {\r\n const numValue = parseFloat(String(currentValue))\r\n if (isNaN(numValue)) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be a valid number`\r\n } else {\r\n const numberValidation = component.validation as any\r\n // CRITICAL: Check min/max first, then lowerLimit/upperLimit\r\n // Only show error if validation actually fails\r\n if (numberValidation.min !== undefined && numValue < numberValidation.min) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be at least ${numberValidation.min}`\r\n } else if (numberValidation.max !== undefined && numValue > numberValidation.max) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `${fieldLabel} must be no more than ${numberValidation.max}`\r\n } else if (numberValidation.lowerLimit !== undefined && numValue < numberValidation.lowerLimit) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `You are under the limit. ${fieldLabel} must be at least ${numberValidation.lowerLimit}`\r\n } else if (numberValidation.upperLimit !== undefined && numValue > numberValidation.upperLimit) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n errorMessage = customMessage || `You crossed the limit. ${fieldLabel} must be no more than ${numberValidation.upperLimit}`\r\n }\r\n // If no validation errors, errorMessage remains empty (valid)\r\n }\r\n }\r\n \r\n // Always set the error message (empty string if valid) to clear previous errors\r\n setValidationErrors(prev => ({\r\n ...prev,\r\n [fieldId]: errorMessage\r\n }))\r\n }, [formComponents, isPreviewMode, formValues, findComponentById])\r\n\r\n // Handle form control blur\r\n const onFormControlBlur = useCallback((fieldId: string) => {\r\n setTouchedFields(prev => ({\r\n ...prev,\r\n [fieldId]: true\r\n }))\r\n // Validate field on blur (only in test mode)\r\n if (!isPreviewMode) {\r\n // Use setTimeout to ensure formValues are updated\r\n setTimeout(() => {\r\n validateField(fieldId)\r\n }, 0)\r\n }\r\n }, [isPreviewMode, validateField])\r\n\r\n // Handle form control focus\r\n const onFormControlFocus = useCallback((fieldId: string) => {\r\n // Clear validation errors when field is focused\r\n if (validationErrors[fieldId]) {\r\n setValidationErrors(prev => ({\r\n ...prev,\r\n [fieldId]: ''\r\n }))\r\n }\r\n }, [validationErrors])\r\n\r\n // Disabled automatic validation to let DfFormInput handle its own validation\r\n // This prevents conflicts between external and local validation\r\n // useEffect(() => {\r\n // if (!isPreviewMode && Object.keys(formValues).length > 0) {\r\n // // Validate all form components when form values change (but not on initial load)\r\n // formComponents.forEach(component => {\r\n // validateField(component.id)\r\n // })\r\n // }\r\n // }, [formValues, validateField, isPreviewMode, formComponents])\r\n\r\n // Enhanced form validity check\r\n const isFormValid = useCallback((): boolean => {\r\n return formComponents.every(component => {\r\n // Use real-time form values instead of component values\r\n const currentValue = formValues[component.id] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n \r\n if (component.validation.required && !hasValue) {\r\n return false\r\n }\r\n return true\r\n })\r\n }, [formComponents, formValues])\r\n\r\n // Evaluate threshold condition (handles both numeric and string values)\r\n const evaluateThresholdCondition = useCallback((condition: any, currentVal: string | number | string[]): boolean => {\r\n // Handle array values (for checkbox)\r\n if (Array.isArray(currentVal)) {\r\n return currentVal.some(val => evaluateThresholdCondition(condition, val));\r\n }\r\n \r\n if (currentVal === undefined || currentVal === null || currentVal === '') return false;\r\n \r\n // Try numeric comparison first\r\n const numValue = typeof currentVal === 'string' ? parseFloat(currentVal) : currentVal;\r\n const thresholdValue = typeof condition.value === 'string' ? parseFloat(condition.value) : condition.value;\r\n \r\n // If both are valid numbers, use numeric comparison\r\n if (!isNaN(numValue) && !isNaN(thresholdValue)) {\r\n switch (condition.operator) {\r\n case 'greaterThan':\r\n return numValue > thresholdValue;\r\n case 'lessThan':\r\n return numValue < thresholdValue;\r\n case 'greaterThanOrEqual':\r\n return numValue >= thresholdValue;\r\n case 'lessThanOrEqual':\r\n return numValue <= thresholdValue;\r\n case 'equals':\r\n return numValue === thresholdValue;\r\n case 'notEquals':\r\n return numValue !== thresholdValue;\r\n default:\r\n return false;\r\n }\r\n }\r\n \r\n // For string comparison (checkbox, radio, select, segment)\r\n const stringValue = String(currentVal).toLowerCase();\r\n const stringConditionValue = String(condition.value).toLowerCase();\r\n \r\n switch (condition.operator) {\r\n case 'equals':\r\n return stringValue === stringConditionValue || String(currentVal) === String(condition.value);\r\n case 'notEquals':\r\n return stringValue !== stringConditionValue && String(currentVal) !== String(condition.value);\r\n case 'greaterThan':\r\n case 'lessThan':\r\n case 'greaterThanOrEqual':\r\n case 'lessThanOrEqual':\r\n // For string values, these operators don't make sense, return false\r\n return false;\r\n default:\r\n return false;\r\n }\r\n }, []);\r\n\r\n // Get all met threshold conditions that require issue to be raised\r\n const getMetThresholdConditions = useCallback((): Array<{ componentId: string; condition: any; componentLabel: string }> => {\r\n if (isPreviewMode) return [];\r\n \r\n const metConditions: Array<{ componentId: string; condition: any; componentLabel: string }> = [];\r\n \r\n formComponents.forEach(component => {\r\n const condition = (component as any)?.condition;\r\n if (!condition || !condition.conditions || condition.conditions.length === 0) {\r\n return;\r\n }\r\n \r\n const currentValue = formValues[component.id];\r\n // Check if value is valid (not undefined, null, empty string, or empty array)\r\n const hasValidValue = currentValue !== undefined && \r\n currentValue !== null && \r\n currentValue !== '' && \r\n !(Array.isArray(currentValue) && currentValue.length === 0);\r\n \r\n if (!hasValidValue) {\r\n return;\r\n }\r\n \r\n condition.conditions.forEach((cond: any) => {\r\n // All met threshold conditions require raising an issue (mandatory)\r\n if (evaluateThresholdCondition(cond, currentValue)) {\r\n metConditions.push({\r\n componentId: component.id,\r\n condition: cond,\r\n componentLabel: component.basic?.label || 'Field'\r\n });\r\n }\r\n });\r\n });\r\n \r\n return metConditions;\r\n }, [formComponents, formValues, isPreviewMode, evaluateThresholdCondition]);\r\n\r\n // Validate threshold conditions - check if all met conditions have all mandatory actions completed\r\n const validateThresholdConditions = useCallback((): { isValid: boolean; errorMessage?: string } => {\r\n if (isPreviewMode) return { isValid: true };\r\n \r\n const metConditions = getMetThresholdConditions();\r\n \r\n if (metConditions.length === 0) {\r\n return { isValid: true };\r\n }\r\n \r\n // Check each met condition for all mandatory actions\r\n for (const { condition, componentLabel } of metConditions) {\r\n const completions = thresholdActionCompletions.get(condition.id) || { notesCompleted: false, attachmentsCompleted: false, emailSent: false };\r\n const missingActions: string[] = [];\r\n \r\n // Check if raise issue is required and completed\r\n if (condition.enableRaiseIssue === true && !raisedThresholdIssues.has(condition.id)) {\r\n missingActions.push('raise an issue');\r\n }\r\n \r\n // Check if notes are required and completed\r\n if (condition.enableNotes === true && !completions.notesCompleted) {\r\n missingActions.push('add notes');\r\n }\r\n \r\n // Check if attachments are required and completed\r\n if (condition.enableAttachment === true && !completions.attachmentsCompleted) {\r\n missingActions.push('add attachments');\r\n }\r\n \r\n // Check if send email is required and completed\r\n if (condition.enableSendEmail === true && !completions.emailSent) {\r\n missingActions.push('send email');\r\n }\r\n \r\n if (missingActions.length > 0) {\r\n const actionsText = missingActions.length === 1 \r\n ? missingActions[0] \r\n : missingActions.slice(0, -1).join(', ') + ' and ' + missingActions[missingActions.length - 1];\r\n return {\r\n isValid: false,\r\n errorMessage: `Please ${actionsText} for the threshold condition met in \"${componentLabel}\". You cannot submit the form until all required actions are completed.`\r\n };\r\n }\r\n }\r\n \r\n return { isValid: true };\r\n }, [isPreviewMode, getMetThresholdConditions, raisedThresholdIssues, thresholdActionCompletions]);\r\n\r\n // Callback to mark threshold issue as raised\r\n const handleThresholdIssueRaised = useCallback((conditionId: string) => {\r\n if (conditionId) {\r\n setRaisedThresholdIssues(prev => {\r\n const newSet = new Set(prev);\r\n newSet.add(conditionId);\r\n return newSet;\r\n });\r\n }\r\n }, []);\r\n\r\n // Callback to update threshold action completions\r\n const handleThresholdActionCompletion = useCallback((conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => {\r\n if (conditionId) {\r\n setThresholdActionCompletions(prev => {\r\n const newMap = new Map(prev);\r\n const current = newMap.get(conditionId) || { notesCompleted: false, attachmentsCompleted: false, emailSent: false };\r\n if (action === 'notes') {\r\n newMap.set(conditionId, { ...current, notesCompleted: completed });\r\n } else if (action === 'attachments') {\r\n newMap.set(conditionId, { ...current, attachmentsCompleted: completed });\r\n } else if (action === 'email') {\r\n newMap.set(conditionId, { ...current, emailSent: completed });\r\n }\r\n return newMap;\r\n });\r\n }\r\n }, []);\r\n\r\n // Update threshold validation state when form values, raised issues, or action completions change\r\n useEffect(() => {\r\n if (!isPreviewMode) {\r\n const validation = validateThresholdConditions();\r\n setThresholdValidationState(validation);\r\n }\r\n }, [formValues, raisedThresholdIssues, thresholdActionCompletions, isPreviewMode, validateThresholdConditions]);\r\n\r\n // Validate all fields\r\n const validateAllFields = useCallback((): boolean => {\r\n // Only validate in test mode\r\n if (isPreviewMode) return true\r\n \r\n let isValid = true\r\n setFormSubmitted(true)\r\n const errors: IFormValidationErrors = {}\r\n\r\n formComponents.forEach(component => {\r\n // Use real-time form values instead of component values\r\n const currentValue = formValues[component.id] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n\r\n if (component.validation.required && !hasValue) {\r\n const customMessage = component.validation.customValidationMessage\r\n const fieldLabel = component.basic.label || 'This field'\r\n const errorMessage = customMessage || `${fieldLabel} is required`\r\n errors[component.id] = errorMessage\r\n isValid = false\r\n } else {\r\n errors[component.id] = ''\r\n }\r\n\r\n setTouchedFields(prev => ({\r\n ...prev,\r\n [component.id]: true\r\n }))\r\n })\r\n\r\n setValidationErrors(errors)\r\n return isValid\r\n }, [formComponents, isPreviewMode, formValues])\r\n\r\n // Handle form submission\r\n const handleSubmit = useCallback(() => {\r\n setFormSubmitted(true)\r\n\r\n if (!validateAllFields()) {\r\n // Focus on the first invalid field\r\n const firstErrorField = formComponents.find(comp => {\r\n const currentValue = formValues[comp.id] || ''\r\n \r\n // Check if field has a value\r\n let hasValue = false\r\n \r\n if (Array.isArray(currentValue)) {\r\n // For array values (checkbox, multi-select), check if array has items\r\n hasValue = currentValue.length > 0\r\n } else if (typeof currentValue === 'string') {\r\n // For string values, check if not empty after trimming\r\n hasValue = currentValue.trim() !== ''\r\n } else {\r\n // For other types, check if not null/undefined\r\n hasValue = currentValue !== null && currentValue !== undefined\r\n }\r\n \r\n return comp.validation.required && !hasValue\r\n })\r\n if (firstErrorField) {\r\n const errorElement = document.getElementById(firstErrorField.id)\r\n if (errorElement) {\r\n errorElement.focus()\r\n }\r\n }\r\n return\r\n }\r\n\r\n // Validate threshold conditions - ensure all met conditions have issues raised\r\n const thresholdValidation = validateThresholdConditions();\r\n if (!thresholdValidation.isValid) {\r\n // Show error message\r\n if (thresholdValidation.errorMessage) {\r\n toastService.showError(thresholdValidation.errorMessage);\r\n }\r\n // Focus on the first component with unmet threshold condition\r\n const metConditions = getMetThresholdConditions();\r\n const firstUnmet = metConditions.find(\r\n ({ condition }) => !raisedThresholdIssues.has(condition.id)\r\n );\r\n if (firstUnmet) {\r\n const errorElement = document.getElementById(firstUnmet.componentId);\r\n if (errorElement) {\r\n errorElement.scrollIntoView({ behavior: 'smooth', block: 'center' });\r\n }\r\n }\r\n return;\r\n }\r\n\r\n // Recursive function to update component values from form state\r\n const updateComponentValues = (components: FormComponentType[]): FormComponentType[] => {\r\n return components.map(component => {\r\n const userValue = formValues[component.id]\r\n let finalValue = userValue\r\n \r\n // Debug: Log all form values to see what's being tracked\r\n if (component.name === 'text-input' && component.basic?.label === 'New text input') {\r\n }\r\n \r\n if (finalValue === undefined) {\r\n if ('value' in component.basic && component.basic.value !== undefined) {\r\n finalValue = component.basic.value\r\n } else if ('defaultValue' in component.basic && component.basic.defaultValue !== undefined) {\r\n finalValue = component.basic.defaultValue\r\n } else {\r\n finalValue = ''\r\n }\r\n }\r\n\r\n // Debug table cell components\r\n if (component.name === 'text-input' && component.basic?.label === 'New text input') {\r\n }\r\n\r\n const updatedComponent = {\r\n ...component,\r\n basic: {\r\n ...component.basic,\r\n value: finalValue,\r\n defaultValue: finalValue\r\n }\r\n } as FormComponentType\r\n\r\n // Recursively update nested components\r\n if (updatedComponent.name === 'section' && (updatedComponent as any).children) {\r\n (updatedComponent as any).children = updateComponentValues((updatedComponent as any).children);\r\n }\r\n \r\n if (updatedComponent.name === 'table' && (updatedComponent as any).cells) {\r\n (updatedComponent as any).cells = (updatedComponent as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n const updatedCell = { ...cell };\r\n if (updatedCell.components) {\r\n updatedCell.components = updateComponentValues(updatedCell.components);\r\n }\r\n return updatedCell;\r\n })\r\n );\r\n }\r\n \r\n if (updatedComponent.name === 'datagrid' && (updatedComponent as any).entries) {\r\n (updatedComponent as any).entries = (updatedComponent as any).entries.map((entry: any) => {\r\n const updatedEntry = { ...entry };\r\n if (updatedEntry.components) {\r\n updatedEntry.components = updateComponentValues(updatedEntry.components);\r\n }\r\n return updatedEntry;\r\n });\r\n }\r\n\r\n return updatedComponent;\r\n });\r\n };\r\n\r\n // Prepare final form data\r\n const finalFormData = updateComponentValues(formComponents)\r\n\r\n onSubmit?.(finalFormData)\r\n }, [formComponents, formValues, validateAllFields, onSubmit])\r\n\r\n // Get preview classes\r\n const getPreviewClasses = useCallback(() => {\r\n return {\r\n [`device-${currentDevice}`]: true,\r\n readonly: isPreviewMode\r\n }\r\n }, [currentDevice, isPreviewMode])\r\n\r\n // Render form component based on type\r\n // CRITICAL: Use a ref to cache generated IDs so they don't change on re-render\r\n // This prevents ID regeneration which causes component remounting and state loss\r\n const componentIdCacheRef = useRef<Map<string, string>>(new Map());\r\n const componentCounterRef = useRef<number>(0);\r\n \r\n const renderFormComponent = (component: FormComponentType) => {\r\n // CRITICAL: Ensure component has a valid unique ID\r\n // NEVER regenerate IDs - always use existing or cached ID\r\n let finalComponentId: string;\r\n \r\n if (component.id && typeof component.id === 'string' && component.id.trim() !== '') {\r\n // Component already has an ID - use it (most common case)\r\n finalComponentId = component.id;\r\n } else {\r\n // Component is missing an ID - need to generate and cache it\r\n // Create a stable cache key using component properties that don't change\r\n const label = (component.basic as any)?.label || '';\r\n const name = component.name || 'unknown';\r\n // Use a combination that's stable across renders\r\n const cacheKey = `${name}-${label}`;\r\n \r\n // Check if we've already generated an ID for a component with these properties\r\n let cachedId = componentIdCacheRef.current.get(cacheKey);\r\n \r\n if (!cachedId) {\r\n // Generate a new ID only once and cache it permanently\r\n // Use a counter to ensure uniqueness even if multiple components have same name+label\r\n componentCounterRef.current += 1;\r\n cachedId = `generated-${name}-${componentCounterRef.current}-${Math.random().toString(36).substr(2, 9)}`;\r\n componentIdCacheRef.current.set(cacheKey, cachedId);\r\n console.warn('[DfFormPreview] Generated and cached ID for component:', cachedId, 'key:', cacheKey);\r\n }\r\n \r\n finalComponentId = cachedId;\r\n \r\n // Create a new component object with the cached ID (don't mutate original)\r\n component = {\r\n ...component,\r\n id: finalComponentId\r\n };\r\n }\r\n \r\n // CRITICAL: Use the finalComponentId we determined above\r\n const componentId = finalComponentId;\r\n const formValue = formValues[componentId]\r\n \r\n // Debug: Log if formValue is being shared incorrectly\r\n if (formValue !== undefined) {\r\n // Check if this value is being used by multiple components\r\n const componentsWithSameValue = formComponents.filter(comp => \r\n comp.id !== componentId && formValues[comp.id] === formValue\r\n );\r\n if (componentsWithSameValue.length > 0) {\r\n console.warn(`[DfFormPreview] Component ${componentId} shares form value with other components:`, \r\n componentsWithSameValue.map(c => c.id));\r\n }\r\n }\r\n \r\n const commonProps = {\r\n id: componentId, // Use the validated component ID\r\n validationErrors,\r\n formValue: formValue, // This should be unique per component ID\r\n touchedFields,\r\n formSubmitted,\r\n mode: 'test' as 'preview' | 'test', // CRITICAL: Always use 'test' mode in package - all functionality enabled\r\n readonly: false, // CRITICAL: Always allow editing in package\r\n onValueChange: onFormValueChange, // This will use change.id which should match componentId\r\n onBlur: () => onFormControlBlur(componentId),\r\n onFocus: () => onFormControlFocus(componentId)\r\n }\r\n\r\n switch (component.name) {\r\n case 'text-input':\r\n case 'number-input':\r\n case 'email-input':\r\n // Regular text/email/number input\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={component as any}\r\n inputType={component.name === 'text-input' ? 'text' : \r\n component.name === 'number-input' ? 'number' : 'email'}\r\n formTemplateId={formTemplateId}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n raisedThresholdIssues={raisedThresholdIssues}\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={component as any} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} />\r\n \r\n case 'segment':\r\n // Map basic.options to top-level options for segment component\r\n const segmentProps = {\r\n ...component,\r\n options: (component as any).basic?.options || [],\r\n basic: {\r\n ...component.basic,\r\n comments: (component as any).basic?.comments || ''\r\n }\r\n }\r\n return <DfFormSegment {...commonProps} properties={segmentProps as any} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={component as any} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={component as any} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={component as any} />\r\n \r\n case 'heading':\r\n return (\r\n <DfFormHeading\r\n {...commonProps}\r\n properties={component as any}\r\n />\r\n )\r\n \r\n case 'instructions':\r\n // CRITICAL: Pass formValue to instructions component so it can display API data\r\n // Also check component.basic.value for API data structure\r\n const instructionFormValue = formValue || \r\n (component.basic as any)?.value || \r\n null;\r\n return (\r\n <DfFormInstruction\r\n {...commonProps}\r\n properties={component as any}\r\n formValue={instructionFormValue}\r\n />\r\n )\r\n \r\n case 'location':\r\n return <DfFormLocation {...commonProps} properties={component as any} />\r\n \r\n case 'section':\r\n return (\r\n <DfFormSection\r\n {...commonProps}\r\n properties={component as any}\r\n formData={formValues}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n renderFormComponent={(field: FormComponentType) => {\r\n // Ensure the nested component gets the proper form value\r\n // const fieldValue = formValues[field.id] || (field.basic as any)?.value || (field.basic as any)?.defaultValue || ''\r\n return renderFormComponent(field)\r\n }}\r\n />\r\n )\r\n \r\n case 'table':\r\n\r\n return (\r\n <React.Suspense fallback={<div>Loading table...</div>}>\r\n <DfFormTable \r\n {...commonProps} \r\n properties={component as any}\r\n formData={formValues}\r\n formTemplateId={formTemplateId}\r\n mode={commonProps.mode}\r\n validationErrors={validationErrors}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n onNotesChange={(componentId: string, notes: string) => {\r\n // Handle notes change for table cell components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).cells) {\r\n const updatedCells = (comp as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n if (cell.components) {\r\n const updatedCellComponents = cell.components.map((cellComp: any) => {\r\n if (cellComp.id === componentId) {\r\n return {\r\n ...cellComp,\r\n basic: {\r\n ...cellComp.basic,\r\n notes\r\n }\r\n }\r\n }\r\n return cellComp\r\n })\r\n return { ...cell, components: updatedCellComponents }\r\n }\r\n return cell\r\n })\r\n )\r\n return { ...comp, cells: updatedCells }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n onAttachmentChange={(componentId: string, attachments: File[] | null) => {\r\n // Handle attachment change for table cell components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).cells) {\r\n const updatedCells = (comp as any).cells.map((row: any[]) =>\r\n row.map((cell: any) => {\r\n if (cell.components) {\r\n const updatedCellComponents = cell.components.map((cellComp: any) => {\r\n if (cellComp.id === componentId) {\r\n return {\r\n ...cellComp,\r\n basic: {\r\n ...cellComp.basic,\r\n attachments: attachments || []\r\n }\r\n }\r\n }\r\n return cellComp\r\n })\r\n return { ...cell, components: updatedCellComponents }\r\n }\r\n return cell\r\n })\r\n )\r\n return { ...comp, cells: updatedCells }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n renderFormComponent={(field: FormComponentType) => {\r\n // CRITICAL: Pass the field to renderFormComponent which has access to latest formValues\r\n // renderFormComponent uses formValues[field.id] internally, so it will get the correct value\r\n return renderFormComponent(field)\r\n }}\r\n />\r\n </React.Suspense>\r\n )\r\n \r\n case 'datagrid':\r\n return (\r\n <DfFormDataGrid\r\n {...commonProps}\r\n properties={component as any}\r\n formData={formValues}\r\n formTemplateId={formTemplateId}\r\n mode={commonProps.mode}\r\n validationErrors={validationErrors}\r\n touchedFields={touchedFields}\r\n formSubmitted={formSubmitted}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n onComponentSelect={onComponentSelect}\r\n onComponentDelete={onComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n onComponentUpdate={onComponentUpdate}\r\n selectedComponent={selectedComponent}\r\n onValueChange={(change: IFormControlChange) => {\r\n // Handle datagrid value changes (entries updates)\r\n if (change.id === component.id && change.value && typeof change.value === 'object' && 'entries' in change.value) {\r\n // Update formComponents with new entries structure\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n ...change.value\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n // Also update formValues for nested components\r\n if (change.value.entries && Array.isArray(change.value.entries)) {\r\n change.value.entries.forEach((entry: any) => {\r\n if (entry.components && Array.isArray(entry.components)) {\r\n entry.components.forEach((nestedComp: any) => {\r\n const nestedValue = formValues[nestedComp.id];\r\n if (nestedValue !== undefined) {\r\n // Value already exists, keep it\r\n } else {\r\n // Initialize with defaultValue if available\r\n const defaultValue = nestedComp.basic?.defaultValue;\r\n if (defaultValue !== undefined) {\r\n setFormValues(prev => ({\r\n ...prev,\r\n [nestedComp.id]: defaultValue\r\n }))\r\n }\r\n }\r\n })\r\n }\r\n })\r\n }\r\n } else {\r\n // For nested component value changes, use the regular handler\r\n onFormValueChange(change)\r\n }\r\n }}\r\n onEntryAdd={() => {\r\n // CRITICAL: Entry has already been added via onValueChange in DfFormDataGrid\r\n // Get the updated component from formComponents (which should have been updated by onValueChange)\r\n const currentComponent = formComponents.find(comp => comp.id === component.id);\r\n if (currentComponent && (currentComponent as any).entries) {\r\n // Entry should already be in the component via onValueChange\r\n // Just ensure formComponents is in sync (no-op if already synced)\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n // Ensure entries are properly structured\r\n return {\r\n ...comp,\r\n entries: (comp as any).entries || []\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n } else {\r\n // Fallback: If component doesn't have entries yet, try to get from formValues\r\n setTimeout(() => {\r\n const datagridValue = formValues[component.id];\r\n if (datagridValue && typeof datagridValue === 'object' && 'entries' in datagridValue) {\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n entries: datagridValue.entries\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }\r\n }, 100)\r\n }\r\n }}\r\n onEntryRemove={(entryIndex: number) => {\r\n // Handle entry remove - update form components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).entries) {\r\n const currentEntries = (comp as any).entries || []\r\n const updatedEntries = currentEntries\r\n .filter((_: any, index: number) => index !== entryIndex)\r\n .map((entry: any, index: number) => ({\r\n ...entry,\r\n index,\r\n id: `entry-${comp.id}-${index}`,\r\n components: entry.components?.map((comp: any, compIndex: number) => {\r\n const templateComp = ((comp as any).templateComponents || [])[compIndex]\r\n return {\r\n ...comp,\r\n id: templateComp ? `${templateComp.id}-entry-${index}-${compIndex}` : comp.id\r\n }\r\n }) || []\r\n }))\r\n return {\r\n ...comp,\r\n entries: updatedEntries\r\n }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n onNotesChange={(componentId: string, notes: string) => {\r\n // Handle notes change for datagrid entry components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).entries) {\r\n const updatedEntries = (comp as any).entries.map((entry: any) => {\r\n if (entry.components) {\r\n const updatedComponents = entry.components.map((entryComp: any) => {\r\n if (entryComp.id === componentId) {\r\n return {\r\n ...entryComp,\r\n basic: {\r\n ...entryComp.basic,\r\n notes\r\n }\r\n }\r\n }\r\n return entryComp\r\n })\r\n return { ...entry, components: updatedComponents }\r\n }\r\n return entry\r\n })\r\n return { ...comp, entries: updatedEntries }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n onAttachmentChange={(componentId: string, attachments: File[] | null) => {\r\n // Handle attachment change for datagrid entry components\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id && (comp as any).entries) {\r\n const updatedEntries = (comp as any).entries.map((entry: any) => {\r\n if (entry.components) {\r\n const updatedComponents = entry.components.map((entryComp: any) => {\r\n if (entryComp.id === componentId) {\r\n return {\r\n ...entryComp,\r\n basic: {\r\n ...entryComp.basic,\r\n attachments: attachments || []\r\n }\r\n }\r\n }\r\n return entryComp\r\n })\r\n return { ...entry, components: updatedComponents }\r\n }\r\n return entry\r\n })\r\n return { ...comp, entries: updatedEntries }\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents)\r\n }}\r\n renderFormComponent={(field: FormComponentType) => {\r\n // Ensure the nested component gets the proper form value\r\n return renderFormComponent(field)\r\n }}\r\n />\r\n )\r\n \r\n case 'file':\r\n // Get file value from formValues, or from component basic properties\r\n // CRITICAL: Check basic.value first (API data structure), then formValue\r\n const fileFormValue = formValue || \r\n (component.basic as any)?.value || \r\n (component.basic as any)?.files || \r\n (component.basic as any)?.attachments || \r\n null;\r\n return (\r\n <DfFormFileUpload \r\n {...commonProps} \r\n properties={component as any}\r\n formValue={fileFormValue}\r\n />\r\n )\r\n \r\n \r\n default:\r\n return (\r\n <div className=\"form-group\">\r\n <div className=\"form-group-label\">\r\n Unsupported Component: {component.name}\r\n </div>\r\n </div>\r\n )\r\n }\r\n }\r\n\r\n return (\r\n <div className=\"form-preview-container\">\r\n <div className=\"form-preview-wrapper\">\r\n <div className={`form-preview ${Object.entries(getPreviewClasses()).map(([key, value]: [string, boolean]) => value ? key : '').join(' ')}`}>\r\n {/* Form Canvas Header - You can implement this separately */}\r\n <div className=\"form-canvas-header\">\r\n {/* <FormCanvasHeader \r\n formData={formData}\r\n disableSaveDraft={false}\r\n disableCancel={false}\r\n disableSubmit={false}\r\n showTags={false}\r\n /> */}\r\n </div>\r\n\r\n {formComponents.length === 0 ? (\r\n <div className=\"empty-state\">\r\n <div className=\"empty-state-card\">\r\n <div className=\"empty-state-preview-area\">\r\n <span className=\"empty-state-placeholder\">\r\n Add components to see the form preview\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n ) : (\r\n <form className=\"form-preview-form\" onSubmit={(e) => { e.preventDefault(); handleSubmit(); }}>\r\n {/* Form Title and Description */}\r\n {(formTitle || formDescription) && (\r\n <div className=\"form-header\">\r\n {formTitle && (\r\n <h1 className=\"form-title\">{formTitle}</h1>\r\n )}\r\n {formDescription && (\r\n <p className=\"form-description\">{formDescription}</p>\r\n )}\r\n </div>\r\n )}\r\n\r\n {formComponents.map((component) => {\r\n const basic = component.basic as any;\r\n const formValue = formValues[component.id];\r\n const isOptionBased = ['select', 'radio', 'checkbox', 'segment'].includes(component.name || '');\r\n const componentOptions = (component as any).options || basic?.options || [];\r\n \r\n // Get column class from component styles\r\n const getColumnClass = (): string => {\r\n const column = (component as any)?.styles?.column;\r\n // Section and table components should always be full width\r\n if (component.name === 'section' || component.name === 'table' || component.name === 'datagrid') {\r\n return 'col-12';\r\n }\r\n // Map column value to class name\r\n if (column === 3) return 'col-3';\r\n if (column === 6) return 'col-6';\r\n if (column === 9) return 'col-9';\r\n if (column === 12) return 'col-12';\r\n // Default to full width if no column specified\r\n return 'col-12';\r\n };\r\n \r\n const columnClass = getColumnClass();\r\n \r\n // Check if component or selected option has action features\r\n let hasActionFeatures = false;\r\n if (!isPreviewMode) {\r\n if (isOptionBased && formValue !== undefined && formValue !== null && formValue !== '') {\r\n if (component.name === 'checkbox') {\r\n const selectedValues = Array.isArray(formValue) ? formValue : [formValue];\r\n hasActionFeatures = selectedValues.some((value: string) => {\r\n const option = componentOptions.find((opt: any) => opt.value === value);\r\n return option && (option.enableNotes || option.enableAttachment || option.enableRaiseIssue || option.enableSendEmail);\r\n });\r\n } else {\r\n const selectedOption = componentOptions.find((opt: any) => opt.value === formValue);\r\n hasActionFeatures = selectedOption && (selectedOption.enableNotes || selectedOption.enableAttachment || selectedOption.enableRaiseIssue || selectedOption.enableSendEmail);\r\n }\r\n } else {\r\n hasActionFeatures = basic?.enableNotes || basic?.enableAttachment || basic?.enableRaiseIssue || basic?.enableSendEmail;\r\n }\r\n }\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = isPreviewMode && (\r\n ((component as any).basic?.notes && (component as any).basic.notes.trim().length > 0) ||\r\n ((component as any).basic?.attachments && Array.isArray((component as any).basic.attachments) && (component as any).basic.attachments.length > 0)\r\n );\r\n\r\n return (\r\n <div \r\n key={component.id} \r\n className={`form-group ${columnClass} ${hasActionFeatures || hasSubmissionData ? 'has-action-features' : ''}`}\r\n style={{ display: shouldShowComponent(component.id) ? 'block' : 'none' }}\r\n >\r\n {renderFormComponent(component)}\r\n {/* Action Features - Only show in test mode, exclude certain component types */}\r\n {!isPreviewMode && !['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(component.name) && (\r\n <ComponentActionFeatures\r\n component={component as any}\r\n mode={isPreviewMode ? 'preview' : 'test'}\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={handleThresholdActionCompletion}\r\n onThresholdIssueRaised={handleThresholdIssueRaised}\r\n onNotesChange={(notes: string) => {\r\n // Handle notes change for regular components - update component.basic.notes\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n basic: {\r\n ...comp.basic,\r\n notes: notes || ''\r\n } as any\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents as FormComponentType[])\r\n }}\r\n onAttachmentChange={(attachments: File[] | null) => {\r\n // Handle attachment change for regular components - update component.basic.attachments\r\n const updatedComponents = formComponents.map(comp => {\r\n if (comp.id === component.id) {\r\n return {\r\n ...comp,\r\n basic: {\r\n ...comp.basic,\r\n attachments: attachments || []\r\n } as any\r\n } as FormComponentType\r\n }\r\n return comp\r\n })\r\n onFormDataChange?.(updatedComponents as FormComponentType[])\r\n }}\r\n notes={(component as any).basic?.notes || ''}\r\n attachments={(component as any).basic?.attachments || null}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {isPreviewMode && hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={component as any}\r\n />\r\n )}\r\n </div>\r\n );\r\n })}\r\n \r\n {!isPreviewMode && (\r\n <div className=\"form-actions\">\r\n <button\r\n type=\"submit\"\r\n disabled={!isFormValid() || !thresholdValidationState.isValid}\r\n className=\"form-submit-button\"\r\n title={!thresholdValidationState.isValid ? thresholdValidationState.errorMessage : ''}\r\n >\r\n Submit\r\n </button>\r\n </div>\r\n )}\r\n </form>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormPreview\r\n","import React, { useState, useEffect, useCallback } from 'react';\r\nimport './df-form-comments.scss';\r\n\r\ninterface DfFormCommentsProps {\r\n comment?: string;\r\n onSave?: (comment: string) => void;\r\n placeholder?: string;\r\n className?: string;\r\n disabled?: boolean;\r\n}\r\n\r\nexport const DfFormComments: React.FC<DfFormCommentsProps> = ({\r\n comment = '',\r\n onSave,\r\n placeholder = 'Enter your reason...',\r\n className = '',\r\n disabled = false\r\n}) => {\r\n const [isExpanded, setIsExpanded] = useState<boolean>(true);\r\n const [currentComment, setCurrentComment] = useState<string>(comment);\r\n const [hasChanges, setHasChanges] = useState<boolean>(false);\r\n\r\n // Update local state when comment prop changes\r\n useEffect(() => {\r\n setCurrentComment(comment);\r\n setHasChanges(false);\r\n }, [comment]);\r\n\r\n // Handle input changes\r\n const handleInputChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {\r\n const newValue = event.target.value;\r\n setCurrentComment(newValue);\r\n setHasChanges(newValue !== comment);\r\n }, [comment]);\r\n\r\n // Handle input blur with auto-save\r\n const handleInputBlur = useCallback(() => {\r\n if (hasChanges && onSave && !disabled) {\r\n onSave(currentComment);\r\n setHasChanges(false);\r\n }\r\n }, [hasChanges, onSave, currentComment, disabled]);\r\n\r\n // Handle input focus\r\n const handleInputFocus = useCallback(() => {\r\n // Focus handler if needed\r\n }, []);\r\n\r\n // Toggle comments section\r\n const toggleComments = useCallback(() => {\r\n if (!disabled) {\r\n setIsExpanded(!isExpanded);\r\n }\r\n }, [isExpanded, disabled]);\r\n\r\n\r\n return (\r\n <div className={`df-form-comments ${className}`}>\r\n <div className=\"df-form-comments__header\">\r\n <h3 className=\"df-form-comments__title\">Comments</h3>\r\n <button\r\n className=\"df-form-comments__toggle\"\r\n type=\"button\"\r\n onClick={toggleComments}\r\n aria-expanded={isExpanded}\r\n aria-label=\"Toggle comments section\"\r\n disabled={disabled}\r\n >\r\n {isExpanded ? (\r\n <span className=\"df-form-comments__toggle-icon\">▼</span>\r\n ) : (\r\n <span className=\"df-form-comments__toggle-icon\">▶</span>\r\n )}\r\n </button>\r\n </div>\r\n\r\n <div className={`df-form-comments__content ${isExpanded ? 'df-form-comments__content--expanded' : ''}`}>\r\n <div className=\"df-form-comments__input-container\">\r\n <div className=\"df-form-comments__input-line\">\r\n <input\r\n type=\"text\"\r\n id=\"comment-input\"\r\n className=\"df-form-comments__input\"\r\n value={currentComment}\r\n onChange={handleInputChange}\r\n onBlur={handleInputBlur}\r\n onFocus={handleInputFocus}\r\n placeholder={placeholder}\r\n disabled={disabled}\r\n />\r\n </div>\r\n \r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\nexport default DfFormComments;\r\n","import React, { useState, useCallback, useEffect, useRef, useMemo } from 'react'\r\nimport { useDroppable } from '@dnd-kit/core'\r\nimport { useSortable, SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable'\r\nimport { CSS } from '@dnd-kit/utilities'\r\nimport { ChevronDown, ChevronRight, GripVertical, Edit, Trash2, Table } from 'lucide-react'\r\nimport { ITableComponent, FormComponentType, IFormControlChange, TableCell } from '../df-form-preview-interfaces'\r\nimport { v4 as uuidv4 } from 'uuid'\r\nimport './df-form-table.scss'\r\n\r\n// Import form control components for rendering children\r\nimport { DfFormInput } from '../df-form-input'\r\nimport { DfFormTextarea } from '../df-form-textarea'\r\nimport { DfFormSelect } from '../df-form-select'\r\nimport { DfFormCheckbox } from '../df-form-checkbox'\r\nimport { DfFormRadio } from '../df-form-radio'\r\nimport { DfFormDateTime } from '../df-form-date-time'\r\nimport { DfFormSignature } from '../df-form-signature'\r\nimport { DfFormHeading } from '../df-form-heading'\r\nimport { ComponentActionFeatures } from '../../ComponentActionFeatures'\r\nimport { ComponentSubmissionActions } from '../../components/ComponentSubmissionActions'\r\n\r\n// Function to ensure table cell components have proper IDs\r\nconst ensureComponentHasId = (component: FormComponentType): FormComponentType => {\r\n if (!component.id) {\r\n return {\r\n ...component,\r\n id: uuidv4()\r\n }\r\n }\r\n return component\r\n}\r\n\r\ninterface DfFormTableProps {\r\n id: string\r\n properties: ITableComponent\r\n validationErrors?: Record<string, any>\r\n formValue?: any\r\n formData?: Record<string, any>\r\n readonly?: boolean\r\n disabled?: boolean\r\n touchedFields?: Record<string, boolean>\r\n formSubmitted?: boolean\r\n mode?: 'edit' | 'preview' | 'test'\r\n onValueChange?: (change: IFormControlChange) => void\r\n onBlur?: () => void\r\n onFocus?: () => void\r\n onSelect?: () => void\r\n isSelected?: boolean\r\n className?: string\r\n // Table-specific props\r\n onTableSelect?: (table: ITableComponent) => void\r\n onTableDelete?: (tableId: string) => void\r\n onCellChange?: (row: number, column: number, components: FormComponentType[]) => void\r\n onComponentSelect?: (component: FormComponentType) => void\r\n onComponentDelete?: (componentId: string) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n selectedComponent?: FormComponentType | null\r\n renderFormComponent?: (field: FormComponentType) => React.ReactNode\r\n // Additional props for consistency with section component\r\n onTableUpdate?: (tableId: string, updates: Partial<ITableComponent>) => void\r\n onCellAdd?: (row: number, column: number) => void\r\n onCellRemove?: (row: number, column: number) => void\r\n onRowAdd?: () => void\r\n onRowRemove?: (rowIndex: number) => void\r\n onColumnAdd?: () => void\r\n onColumnRemove?: (columnIndex: number) => void\r\n // Props for action features\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\n// Simple component for preview mode (no drag handles or action buttons)\r\ninterface SimpleTableComponentProps {\r\n component: FormComponentType\r\n mode: 'edit' | 'preview' | 'test'\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst SimpleTableComponent: React.FC<SimpleTableComponentProps> = ({\r\n component,\r\n mode,\r\n renderFormComponent,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const formValue = formData[component.id]\r\n \r\n // Check if component has notes or attachments for submission view\r\n const hasSubmissionData = mode === 'preview' && (\r\n ((component as any).basic?.notes && (component as any).basic.notes.trim().length > 0) ||\r\n ((component as any).basic?.attachments && Array.isArray((component as any).basic.attachments) && (component as any).basic.attachments.length > 0)\r\n );\r\n \r\n return (\r\n <div className=\"simple-table-component\">\r\n {renderFormComponent(component)}\r\n {/* Action Features - Only show in test mode for nested components, exclude certain component types */}\r\n {!['section', 'table', 'heading', 'file', 'instructions', 'signature', 'location', 'datagrid'].includes(component.name) && (\r\n <ComponentActionFeatures\r\n component={component as any}\r\n mode=\"test\"\r\n formTemplateId={formTemplateId}\r\n formValue={formValue}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange ? (notes) => onNotesChange(component.id, notes) : undefined}\r\n onAttachmentChange={onAttachmentChange ? (attachments) => onAttachmentChange(component.id, attachments) : undefined}\r\n />\r\n )}\r\n {/* Submission Actions - Show in preview mode when there are notes or attachments */}\r\n {hasSubmissionData && (\r\n <ComponentSubmissionActions\r\n component={component as any}\r\n />\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Draggable component for items inside table cells\r\ninterface DraggableTableComponentProps {\r\n component: FormComponentType\r\n selectedComponent: FormComponentType | null\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n isOverlay?: boolean\r\n}\r\n\r\nconst DraggableTableComponent: React.FC<DraggableTableComponentProps> = ({\r\n component,\r\n selectedComponent,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n renderFormComponent,\r\n isOverlay = false,\r\n}) => {\r\n const {\r\n attributes,\r\n listeners,\r\n setNodeRef,\r\n transform,\r\n transition,\r\n isDragging,\r\n isSorting,\r\n } = useSortable({\r\n id: component.id,\r\n disabled: isOverlay, // Only disable when it's an overlay, allow dragging in edit mode\r\n })\r\n\r\n const style = {\r\n transform: CSS.Transform.toString(transform),\r\n transition,\r\n opacity: isDragging ? 0.3 : 1,\r\n zIndex: isDragging ? 1000 : 'auto',\r\n }\r\n\r\n return (\r\n <div\r\n ref={setNodeRef}\r\n style={style}\r\n className={`form-component table-component ${selectedComponent?.id === component.id ? 'selected' : ''} ${isDragging ? 'dragging' : ''} ${isSorting ? 'sorting' : ''}`}\r\n onClick={() => !isDragging && onComponentSelect(component)}\r\n role=\"button\"\r\n tabIndex={0}\r\n >\r\n {/* Drag Handle - Only visible in edit mode */}\r\n {mode === 'edit' && (\r\n <div \r\n className=\"component-drag-handle\" \r\n {...listeners} \r\n {...attributes}\r\n onClick={(e) => e.stopPropagation()}\r\n style={{ opacity: 1 }}\r\n >\r\n <GripVertical size={14} />\r\n </div>\r\n )}\r\n\r\n {/* Component Content */}\r\n <div className=\"component-content\">\r\n {renderFormComponent(component)}\r\n </div>\r\n\r\n {/* Action Buttons - Only show in edit mode */}\r\n {mode === 'edit' && (\r\n <div className=\"component-actions\" style={{ opacity: 1 }}>\r\n {/* Edit Button */}\r\n {onComponentEdit && (\r\n <button\r\n className=\"component-edit-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentEdit(component)\r\n }}\r\n type=\"button\"\r\n title=\"Edit Component\"\r\n >\r\n <Edit size={12} />\r\n </button>\r\n )}\r\n \r\n {/* Delete Button */}\r\n <button\r\n className=\"component-delete-btn\"\r\n onClick={(e) => {\r\n e.stopPropagation()\r\n onComponentDelete(component, e)\r\n }}\r\n type=\"button\"\r\n title=\"Delete Component\"\r\n >\r\n <Trash2 size={12} />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\n// Table Cell Component\r\ninterface TableCellComponentProps {\r\n cell: TableCell\r\n mode: 'edit' | 'preview' | 'test'\r\n onComponentSelect: (component: FormComponentType) => void\r\n onComponentDelete: (component: FormComponentType, event: React.MouseEvent) => void\r\n onComponentEdit?: (component: FormComponentType) => void\r\n selectedComponent: FormComponentType | null\r\n renderFormComponent: (field: FormComponentType) => React.ReactNode\r\n formData?: Record<string, any>\r\n formTemplateId?: string\r\n onThresholdActionCompletion?: (conditionId: string, action: 'notes' | 'attachments' | 'email', completed: boolean) => void\r\n onThresholdIssueRaised?: (conditionId: string) => void\r\n tableId: string\r\n onNotesChange?: (componentId: string, notes: string) => void\r\n onAttachmentChange?: (componentId: string, attachments: File[] | null) => void\r\n}\r\n\r\nconst TableCellComponent: React.FC<TableCellComponentProps> = ({\r\n cell,\r\n mode,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n selectedComponent,\r\n renderFormComponent,\r\n formData = {},\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n tableId,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const dropZoneId = `table-cell-${tableId}-${cell.row}-${cell.column}`\r\n \r\n const { setNodeRef, isOver } = useDroppable({\r\n id: dropZoneId,\r\n disabled: mode !== 'edit',\r\n data: {\r\n type: 'table-cell',\r\n tableId: tableId,\r\n cell: cell,\r\n row: cell.row,\r\n column: cell.column\r\n }\r\n })\r\n\r\n // In preview/test mode, show empty cells as transparent spaces to maintain positioning\r\n // Don't hide them completely to preserve the table structure\r\n\r\n const cellStyle = {\r\n ...cell.styles,\r\n backgroundColor: isOver ? 'var(--df-color-primary-light)' : cell.styles?.backgroundColor || 'transparent',\r\n minHeight: cell.styles?.minHeight || (mode === 'preview' || mode === 'test') ? '40px' : '60px',\r\n padding: cell.styles?.padding || (mode === 'preview' || mode === 'test') ? '8px' : '8px',\r\n border: (mode === 'preview' || mode === 'test') ? 'none' : \r\n (isOver ? '2px dashed var(--df-color-primary)' : cell.styles?.borderColor ? `1px solid ${cell.styles.borderColor}` : '1px solid var(--df-color-fb-border)'),\r\n borderRadius: (mode === 'preview' || mode === 'test') ? '0' : '4px',\r\n position: 'relative' as const,\r\n verticalAlign: cell.styles?.verticalAlign || 'top'\r\n }\r\n\r\n return (\r\n <td\r\n ref={setNodeRef}\r\n style={cellStyle}\r\n className={`table-cell ${isOver ? 'drag-over' : ''}`}\r\n >\r\n <div className=\"cell-content\">\r\n {cell.components && Array.isArray(cell.components) && cell.components.length > 0 ? (\r\n mode === 'edit' ? (\r\n <SortableContext items={cell.components.map(c => c.id || uuidv4())} strategy={verticalListSortingStrategy}>\r\n {cell.components.map((component) => {\r\n const componentWithId = ensureComponentHasId(component)\r\n return (\r\n <DraggableTableComponent\r\n key={componentWithId.id}\r\n component={componentWithId}\r\n selectedComponent={selectedComponent}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect}\r\n onComponentDelete={onComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n renderFormComponent={renderFormComponent}\r\n />\r\n )\r\n })}\r\n </SortableContext>\r\n ) : (\r\n // In preview/test mode, use simple components without drag handles\r\n // CRITICAL: Use component.id directly as key - don't regenerate IDs on every render\r\n cell.components.map((component) => {\r\n // Only ensure ID if it's truly missing - don't regenerate existing IDs\r\n const componentWithId = component.id ? component : ensureComponentHasId(component);\r\n return (\r\n <SimpleTableComponent\r\n key={componentWithId.id}\r\n component={componentWithId}\r\n mode={mode}\r\n renderFormComponent={renderFormComponent}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n )\r\n })\r\n )\r\n ) : (\r\n // Only show drop zone content in edit mode\r\n mode === 'edit' ? (\r\n <div className=\"empty-cell-placeholder\">\r\n <div className=\"cell-info\">\r\n <span className=\"drop-zone-text\">Drag and Drop a form component</span>\r\n <span className=\"cell-coordinates\">Cell ({cell.row + 1}, {cell.column + 1})</span>\r\n </div>\r\n </div>\r\n ) : (\r\n // In preview/test mode, show empty cell as transparent space to maintain positioning\r\n <div style={{ \r\n minHeight: '20px', \r\n backgroundColor: 'transparent',\r\n visibility: 'hidden' // Hide content but maintain space\r\n }}>\r\n \r\n </div>\r\n )\r\n )}\r\n </div>\r\n </td>\r\n )\r\n}\r\n\r\nexport const DfFormTable: React.FC<DfFormTableProps> = ({\r\n id,\r\n properties,\r\n mode = 'edit',\r\n formData = {},\r\n validationErrors = {},\r\n touchedFields = {},\r\n formSubmitted = false,\r\n onValueChange,\r\n onSelect,\r\n isSelected = false,\r\n className = '',\r\n onTableSelect,\r\n onComponentSelect,\r\n onComponentDelete,\r\n onComponentEdit,\r\n selectedComponent,\r\n renderFormComponent,\r\n formTemplateId,\r\n onThresholdActionCompletion,\r\n onThresholdIssueRaised,\r\n onNotesChange,\r\n onAttachmentChange\r\n}) => {\r\n const [isCollapsed, setIsCollapsed] = useState(false) // Always start expanded to show drop zones\r\n\r\n // Check if table has any components in any cells\r\n const hasAnyComponents = properties.cells?.some(row => \r\n row.some(cell => cell.components && cell.components.length > 0)\r\n ) || false\r\n\r\n // Initialize and update table cells when rows/columns change\r\n // CRITICAL: Skip cell initialization updates to prevent flickering when user types\r\n useEffect(() => {\r\n // Skip updates to prevent flickering - cells are already initialized\r\n return;\r\n \r\n // Get rows and columns from table properties (where they're actually stored)\r\n const currentRows = properties.table?.rows || properties.basic?.rows || 3\r\n const currentColumns = properties.table?.columns || properties.basic?.columns || 3\r\n const currentCells = properties.cells || []\r\n \r\n // Check if we need to update the table structure\r\n const needsUpdate = currentCells.length === 0 || \r\n currentCells.length !== currentRows || \r\n (currentCells.length > 0 && currentCells[0].length !== currentColumns)\r\n \r\n if (needsUpdate) {\r\n const newCells: TableCell[][] = []\r\n \r\n for (let row = 0; row < currentRows; row++) {\r\n const rowCells: TableCell[] = []\r\n for (let col = 0; col < currentColumns; col++) {\r\n const cellId = `cell-${row}-${col}`\r\n \r\n // Try to preserve existing components if the cell exists\r\n let existingComponents: FormComponentType[] = []\r\n if (currentCells[row] && currentCells[row][col]) {\r\n existingComponents = (currentCells[row][col].components || []).map(ensureComponentHasId)\r\n }\r\n \r\n rowCells.push({\r\n id: cellId,\r\n row,\r\n column: col,\r\n components: existingComponents,\r\n styles: {}\r\n })\r\n }\r\n newCells.push(rowCells)\r\n }\r\n \r\n onValueChange?.({\r\n id,\r\n value: { ...properties, cells: newCells }\r\n })\r\n }\r\n }, [properties.table?.rows, properties.table?.columns, properties.basic?.rows, properties.basic?.columns, properties.cells, id, onValueChange]) // Watch for rows/columns changes\r\n\r\n const handleTableClick = useCallback((event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n onSelect?.()\r\n onTableSelect?.(properties)\r\n }, [onSelect, onTableSelect, properties])\r\n\r\n const toggleCollapse = (event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n setIsCollapsed(!isCollapsed)\r\n onValueChange?.({\r\n id,\r\n value: { ...properties, basic: { ...(properties.basic || {}), collapsed: !isCollapsed } }\r\n })\r\n }\r\n\r\n\r\n const handleComponentDelete = useCallback((component: FormComponentType, event: React.MouseEvent) => {\r\n event.stopPropagation()\r\n\r\n // Find and remove the component from the table cell\r\n const updatedCells = properties.cells.map(row => \r\n row.map(cell => {\r\n if (cell.components && cell.components.some(comp => comp.id === component.id)) { \r\n const filteredComponents = cell.components.filter(comp => comp.id !== component.id)\r\n \r\n return {\r\n ...cell,\r\n components: filteredComponents\r\n }\r\n }\r\n return cell\r\n })\r\n )\r\n \r\n // Update the table with the modified cells\r\n if (onValueChange) {\r\n onValueChange({\r\n id,\r\n value: { ...properties, cells: updatedCells }\r\n })\r\n } else {\r\n }\r\n \r\n // Don't call parent delete handler for table cell components\r\n // The parent delete handler is for deleting entire fields, not components within table cells\r\n }, [onComponentDelete, properties, onValueChange, id])\r\n\r\n // CRITICAL FIX: Ensure all table cell components have proper IDs with table and cell position\r\n // Use useMemo to prevent ID regeneration on every render\r\n const cellsWithIds = useMemo(() => {\r\n if (!properties.cells) return [];\r\n \r\n return properties.cells.map((row: any[], rowIndex: number) => \r\n row.map((cell: any, cellIndex: number) => ({\r\n ...cell,\r\n components: (cell.components && Array.isArray(cell.components)) \r\n ? cell.components.map((comp: any, compIndex: number) => {\r\n // CRITICAL: Only generate ID if it's missing - never regenerate existing IDs\r\n // This prevents component remounting and losing input state\r\n if (comp.id && typeof comp.id === 'string' && comp.id.trim() !== '') {\r\n // ID already exists - keep it as is\r\n return comp;\r\n }\r\n \r\n // Generate unique ID that includes table ID, row, cell, and component index\r\n // This ensures no conflicts with other components\r\n const uniqueId = `${comp.name || 'component'}-table-${id}-row-${rowIndex}-cell-${cellIndex}-comp-${compIndex}`;\r\n return {\r\n ...comp,\r\n id: uniqueId\r\n }\r\n })\r\n : []\r\n }))\r\n )\r\n }, [properties.cells, id]) // Only recalculate if cells or table ID changes\r\n \r\n // CRITICAL FIX: Update the parent component with the cells that have proper IDs\r\n // Skip this in package to prevent flickering - cells are managed by parent\r\n // useEffect(() => {\r\n // // Disabled to prevent flickering when user types\r\n // }, [])\r\n \r\n // CRITICAL: Create a stable renderComponent that doesn't recreate on every render\r\n // Match main app implementation - directly access formData from closure\r\n const renderComponent = renderFormComponent || useCallback((field: FormComponentType) => {\r\n // CRITICAL: Only ensure ID if it's missing - don't regenerate existing IDs\r\n // This prevents component remounting and losing input state\r\n const componentWithId = field.id ? field : ensureComponentHasId(field)\r\n \r\n // Get form value - directly access formData from closure (matches main app)\r\n const formValue = formData[componentWithId.id] || ('defaultValue' in componentWithId.basic ? componentWithId.basic.defaultValue || '' : '');\r\n \r\n const commonProps = {\r\n id: componentWithId.id,\r\n properties: componentWithId,\r\n validationErrors: {},\r\n formValue: formValue,\r\n touchedFields: {},\r\n formSubmitted: false,\r\n mode,\r\n onValueChange: (change: IFormControlChange) => {\r\n // Forward the change to parent's onValueChange to update formValues\r\n onValueChange?.(change)\r\n },\r\n onBlur: () => {},\r\n onFocus: () => {}\r\n }\r\n\r\n switch (componentWithId.name) {\r\n case 'text-input':\r\n case 'email-input':\r\n case 'number-input':\r\n return (\r\n <DfFormInput\r\n {...commonProps}\r\n properties={componentWithId as any}\r\n inputType={componentWithId.name === 'text-input' ? 'text' : \r\n componentWithId.name === 'number-input' ? 'number' : 'email'}\r\n readonly={false} // CRITICAL: Always editable in package\r\n disabled={false} // CRITICAL: Never disabled in package\r\n />\r\n )\r\n \r\n case 'textarea':\r\n return <DfFormTextarea {...commonProps} properties={componentWithId as any} readonly={false} disabled={false} />\r\n \r\n case 'select':\r\n // Map basic.options to top-level options for select component\r\n const selectProps = {\r\n ...componentWithId,\r\n options: (componentWithId as any).basic?.options || []\r\n }\r\n return <DfFormSelect {...commonProps} properties={selectProps as any} disabled={false} />\r\n \r\n case 'checkbox':\r\n // Map basic.options to top-level options for checkbox component\r\n const checkboxProps = {\r\n ...componentWithId,\r\n options: (componentWithId as any).basic?.options || []\r\n }\r\n return <DfFormCheckbox {...commonProps} properties={checkboxProps as any} formValue={[]} disabled={false} />\r\n \r\n case 'radio':\r\n // Map basic.options to top-level options for radio component\r\n const radioProps = {\r\n ...componentWithId,\r\n options: (componentWithId as any).basic?.options || []\r\n }\r\n return <DfFormRadio {...commonProps} properties={radioProps as any} readonly={false} disabled={false} />\r\n \r\n case 'date':\r\n case 'date-picker':\r\n return <DfFormDateTime {...commonProps} properties={componentWithId as any} readonly={false} disabled={false} />\r\n \r\n case 'datetime-picker':\r\n return <DfFormDateTime {...commonProps} properties={componentWithId as any} readonly={false} disabled={false} />\r\n \r\n case 'signature':\r\n return <DfFormSignature {...commonProps} properties={componentWithId as any} />\r\n \r\n case 'heading':\r\n return <DfFormHeading {...commonProps} properties={componentWithId as any} />\r\n \r\n default:\r\n return <div className=\"unknown-component\">Unknown component: {componentWithId.name}</div>\r\n }\r\n }, [renderFormComponent, mode, formData, onValueChange]) // Include renderFormComponent, formData and onValueChange to ensure latest values are used\r\n\r\n const tableStyle = {\r\n backgroundColor: properties.styles?.backgroundColor || 'var(--df-color-fb-container)',\r\n borderColor: properties.styles?.borderColor || 'var(--df-color-fb-border)',\r\n borderWidth: properties.styles?.borderWidth || '2px',\r\n borderRadius: properties.styles?.borderRadius || '8px',\r\n padding: properties.styles?.padding || '16px',\r\n margin: properties.styles?.margin || '16px 0'\r\n }\r\n\r\n const tableElementStyle: React.CSSProperties = {\r\n width: '100%',\r\n minWidth: '600px', // Ensure minimum width to trigger horizontal scroll\r\n borderCollapse: (mode === 'preview' || mode === 'test') ? 'separate' : 'collapse',\r\n tableLayout: 'fixed',\r\n border: (mode === 'preview' || mode === 'test') ? '1px solid var(--df-color-fb-border)' : 'none'\r\n }\r\n\r\n // Don't render the table if it has no components and we're in preview mode\r\n // Test mode should always show tables so users can interact with them\r\n if (!hasAnyComponents && mode === 'preview') {\r\n return null\r\n }\r\n\r\n\r\n return (\r\n <div\r\n className={`form-group df-form-table ${isSelected ? 'selected' : ''} ${mode === 'preview' ? 'preview-mode' : mode === 'test' ? 'test-mode' : ''} ${className}`}\r\n onClick={handleTableClick}\r\n style={tableStyle}\r\n >\r\n {/* Table Header */}\r\n <div className=\"table-header\">\r\n <div className=\"table-title\" onClick={toggleCollapse}>\r\n <div className=\"title-content\">\r\n {isCollapsed ? <ChevronRight size={16} /> : <ChevronDown size={16} />}\r\n <Table size={16} />\r\n <span className=\"table-label\">{properties.basic?.label || 'Table'}</span>\r\n {properties.validation?.required && (\r\n <span className=\"required-indicator\">*</span>\r\n )}\r\n </div>\r\n </div>\r\n \r\n \r\n </div>\r\n\r\n {/* Table Description */}\r\n {properties.basic?.description && !isCollapsed && (\r\n <div className=\"table-description\">\r\n {properties.basic.description}\r\n </div>\r\n )}\r\n\r\n {/* Table Content */}\r\n {!isCollapsed && (\r\n <div className=\"table-content\">\r\n {(() => {\r\n return null\r\n })()}\r\n <table style={tableElementStyle}>\r\n {/* Column Headers */}\r\n {properties.table?.displayAsTable && (mode === 'edit' || properties.table?.showColumns) && (\r\n <thead>\r\n <tr className=\"table-header-row\">\r\n {Array.from({ length: properties.table?.columns || properties.basic?.columns || 3 }, (_, colIndex) => {\r\n // Parse column names from the comma-separated string\r\n const columnNames = properties.table?.columnNames?.split(',').map(name => name.trim()) || []\r\n const columnName = columnNames[colIndex] || `Column ${colIndex + 1}`\r\n \r\n return (\r\n <th \r\n key={`header-${colIndex}`}\r\n className=\"table-header-cell\"\r\n style={{\r\n backgroundColor: properties.styles.headerBackgroundColor || (mode === 'preview' || mode === 'test') ? 'var(--df-color-fb-container)' : 'var(--df-color-fb-container)',\r\n color: properties.styles.headerTextColor || 'var(--df-color-text-dark)',\r\n padding: '12px',\r\n border: (mode === 'preview' || mode === 'test') ? '1px solid var(--df-color-fb-border)' : '1px solid var(--df-color-fb-border)',\r\n fontWeight: '600',\r\n fontSize: '14px',\r\n textAlign: 'center'\r\n }}\r\n >\r\n {columnName}\r\n </th>\r\n )\r\n })}\r\n </tr>\r\n </thead>\r\n )}\r\n <tbody>\r\n {cellsWithIds.map((row, rowIndex) => (\r\n <tr \r\n key={rowIndex}\r\n className=\"table-row\"\r\n >\r\n {row.map((cell) => (\r\n <TableCellComponent\r\n key={cell.id}\r\n cell={cell}\r\n mode={mode}\r\n onComponentSelect={onComponentSelect || (() => {})}\r\n onComponentDelete={handleComponentDelete}\r\n onComponentEdit={onComponentEdit}\r\n selectedComponent={selectedComponent || null}\r\n renderFormComponent={renderComponent}\r\n formData={formData}\r\n formTemplateId={formTemplateId}\r\n onThresholdActionCompletion={onThresholdActionCompletion}\r\n onThresholdIssueRaised={onThresholdIssueRaised}\r\n tableId={id}\r\n onNotesChange={onNotesChange}\r\n onAttachmentChange={onAttachmentChange}\r\n />\r\n ))}\r\n </tr>\r\n ))}\r\n </tbody>\r\n </table>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n\r\nexport default DfFormTable","// Form Builder Schema Model - Package version\r\n// Defines enums and base types for form component configurations\r\n\r\nimport { FormComponentType, IConditionalLogic, ICondition } from '../df-form-controls/df-form-preview-interfaces';\r\n\r\n// Re-export types from interfaces\r\nexport type { FormComponentType, IConditionalLogic, ICondition };\r\n\r\nexport type TComponentCategory = 'Basic' | 'Advanced' | 'Layout' | 'Custom';\r\n\r\nexport type TBasicComponentName =\r\n | 'text-input'\r\n | 'number-input'\r\n | 'email-input'\r\n | 'textarea'\r\n | 'select'\r\n | 'checkbox'\r\n | 'radio'\r\n | 'segment'\r\n | 'date-picker'\r\n | 'datetime-picker'\r\n | 'info'\r\n | 'signature'\r\n | 'heading'\r\n | 'instructions'\r\n | 'section'\r\n | 'table'\r\n | 'datagrid'\r\n | 'file'\r\n | 'location';\r\n\r\nexport type TComponentName = TBasicComponentName;\r\n\r\nexport enum ELabelAlignment {\r\n Top = 'top',\r\n Left = 'left',\r\n}\r\n\r\nexport interface IOption {\r\n label: string;\r\n value: string;\r\n selected?: boolean;\r\n enableNotes?: boolean;\r\n enableAttachment?: boolean;\r\n enableRaiseIssue?: boolean;\r\n enableSendEmail?: boolean;\r\n color?: string;\r\n backgroundColor?: string;\r\n icon?: string;\r\n}\r\n\r\nexport type TCheckboxValue = string | string[];\r\n\r\nexport interface IBaseProps {\r\n label: string;\r\n value: string;\r\n defaultValue: string | number;\r\n placeholder?: string;\r\n options?: any[];\r\n description?: string;\r\n collapsed?: boolean;\r\n valid?: boolean;\r\n enableNotes?: boolean;\r\n enableAttachment?: boolean;\r\n enableRaiseIssue?: boolean;\r\n enableSendEmail?: boolean;\r\n}\r\n\r\nexport interface IBaseValidationProps {\r\n required: boolean;\r\n customValidationMessage: string;\r\n readonly: boolean;\r\n}\r\n\r\nexport interface IBaseStyleProps {\r\n labelAlignment: ELabelAlignment;\r\n width?: number;\r\n height?: number;\r\n minWidth?: number;\r\n maxWidth?: number;\r\n minHeight?: number;\r\n maxHeight?: number;\r\n column?: number;\r\n backgroundColor?: string;\r\n borderColor?: string;\r\n borderWidth?: string;\r\n borderRadius?: string;\r\n padding?: string;\r\n margin?: string;\r\n}\r\n\r\nexport type TInputComponentType = 'text' | 'number' | 'email';\r\n\r\nexport interface IBaseInputComponent {\r\n inputType: TInputComponentType;\r\n}\r\n\r\nexport interface IBaseComponent {\r\n id: string;\r\n _id: string;\r\n name: TComponentName;\r\n category: TComponentCategory;\r\n basic: IBaseProps;\r\n validation: IBaseValidationProps;\r\n styles: IBaseStyleProps;\r\n position: number;\r\n options: any[];\r\n conditional: IConditionalLogic;\r\n}\r\n\r\n// Type alias for compatibility\r\nexport type TFormComponent = FormComponentType;\r\n\r\n"],"names":["process","env","NODE_ENV","jsxRuntimeModule","exports","f","require$$0","k","Symbol","for","l","m","Object","prototype","hasOwnProperty","n","__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED","ReactCurrentOwner","p","key","ref","__self","__source","q","c","a","g","b","d","e","h","call","defaultProps","$$typeof","type","props","_owner","current","reactJsxRuntime_production_min","jsx","jsxs","REACT_MODULE_REFERENCE","React","REACT_ELEMENT_TYPE","REACT_PORTAL_TYPE","REACT_FRAGMENT_TYPE","REACT_STRICT_MODE_TYPE","REACT_PROFILER_TYPE","REACT_PROVIDER_TYPE","REACT_CONTEXT_TYPE","REACT_FORWARD_REF_TYPE","REACT_SUSPENSE_TYPE","REACT_SUSPENSE_LIST_TYPE","REACT_MEMO_TYPE","REACT_LAZY_TYPE","REACT_OFFSCREEN_TYPE","MAYBE_ITERATOR_SYMBOL","iterator","ReactSharedInternals","error","format","_len2","arguments","length","args","Array","_key2","level","stack","ReactDebugCurrentFrame","getStackAddendum","concat","argsWithFormat","map","item","String","unshift","Function","apply","console","printWarning","getContextName","displayName","getComponentNameFromType","tag","name","_context","outerType","innerType","wrapperName","functionName","getWrappedName","render","outerName","lazyComponent","payload","_payload","init","_init","x","prevLog","prevInfo","prevWarn","prevError","prevGroup","prevGroupCollapsed","prevGroupEnd","assign","disabledDepth","disabledLog","__reactDisabledLog","prefix","ReactCurrentDispatcher","describeBuiltInComponentFrame","source","ownerFn","undefined","Error","match","trim","componentFrameCache","reentry","PossiblyWeakMap","WeakMap","Map","describeNativeComponentFrame","fn","construct","control","frame","get","previousDispatcher","previousPrepareStackTrace","prepareStackTrace","log","info","warn","group","groupCollapsed","groupEnd","configurable","enumerable","value","writable","defineProperties","disableLogs","Fake","defineProperty","set","Reflect","sample","sampleLines","split","controlLines","s","_frame","replace","includes","reenableLogs","syntheticFrame","describeUnknownElementTypeFrameInDEV","isReactComponent","loggedTypeFailures","setCurrentlyValidatingElement","element","owner","_source","setExtraStackFrame","isArrayImpl","isArray","testStringCoercion","checkKeyStringCoercion","willCoercionThrow","toStringTag","constructor","typeName","specialPropKeyWarningShown","specialPropRefWarningShown","didWarnAboutStringRefs","RESERVED_PROPS","jsxDEV","config","maybeKey","self","propName","getter","getOwnPropertyDescriptor","isReactWarning","hasValidKey","hasValidRef","stateNode","componentName","warnIfStringRefCannotBeAutoConverted","warnAboutAccessingKey","defineKeyPropWarningGetter","warnAboutAccessingRef","defineRefPropWarningGetter","_store","freeze","ReactElement","propTypesMisspellWarningShown","ReactCurrentOwner$1","ReactDebugCurrentFrame$1","setCurrentlyValidatingElement$1","isValidElement","object","getDeclarationErrorAddendum","ownerHasKeyUseWarning","validateExplicitKey","parentType","validated","currentComponentErrorInfo","parentName","getCurrentComponentErrorInfo","childOwner","validateChildKeys","node","i","child","iteratorFn","maybeIterable","maybeIterator","getIteratorFn","entries","step","next","done","validatePropTypes","propTypes","typeSpecs","values","location","has","bind","typeSpecName","error$1","err","ex","message","checkPropTypes","PropTypes","getDefaultProps","isReactClassApproved","didWarnAboutKeySpread","jsxWithValidation","isStaticChildren","validType","getModuleId","isValidElementType","keys","typeString","sourceInfo","fileName","lineNumber","getSourceInfoErrorAddendum","children","filter","beforeExample","join","fragment","validateFragmentProps","reactJsxRuntime_development","Fragment","ConditionalLogicService","getInstance","instance","getAvailableComponentsForConditional","formSchema","excludeComponentId","component","id","label","basic","sort","localeCompare","getApplicableOperators","componentType","validateConditionalLogic","conditional","errors","action","push","when","conditions","forEach","condition","index","find","comp","this","operator","isValidConditionValue","isValid","evaluateConditionalLogic","formValues","shouldShow","evaluatedConditions","componentValue","getComponentValue","result","evaluateCondition","determineFinalResult","componentId","defaultValue","evaluateCheckboxCondition","isEqual","isEmpty","contains","isGreaterThan","isLessThan","isGreaterThanOrEqual","isLessThanOrEqual","expectedValue","isChecked","isCheckboxChecked","toLowerCase","conditionsMet","finalResult","every","some","val","keysA","keysB","container","searchValue","numA","Number","numB","isNaN","Date","parse","createDefaultConditionalLogic","getOperatorDisplayText","equals","notEquals","notContains","isNotEmpty","greaterThan","lessThan","greaterThanOrEqual","lessThanOrEqual","getActionDisplayText","show","hide","always","getConditionalLogicSummary","actionText","conditionTexts","formatConditionValue","operatorText","conditionalLogicService","toastService","toasts","listeners","defaultDuration","timeouts","generateId","now","toString","Math","random","substr","notifyListeners","listener","addToast","toast","setTimeout","removeToast","duration","clearTimeout","showSuccess","showError","showWarning","showInfo","clearAll","timeout","subscribe","getToasts","DfFormErrorMsg","validationErrors","fieldId","touchedFields","formSubmitted","properties","localValidation","isTouched","localIsTouched","mode","getDefaultErrorMessage","errorType","fieldLabel","customMessage","validation","customValidationMessage","dateTimeMode","minLength","maxLength","min","max","numberValidation","lowerLimit","numberValidationUpper","upperLimit","errorMessage","actualErrors","firstError","fieldErrors","getErrorMessage","_jsx","className","EIssueStatus","RaiseIssueModal","isOpen","onClose","onSuccess","formTemplateId","notes","attachments","issue","onCreateIssue","onUpdateIssue","user","availableUsers","title","setTitle","useState","description","setDescription","workOrderNumber","setWorkOrderNumber","assetNumber","setAssetNumber","priority","setPriority","status","setStatus","OPEN","assignee","setAssignee","comments","setComments","isSubmitting","setIsSubmitting","isEditMode","useEffect","issueStatus","normalizedStatus","IN_PROGRESS","REJECTED","RESOLVE","componentLabel","desc","updateIssueStatus","async","newStatus","updateData","_id","statusMessages","modalContent","onClick","_jsxs","stopPropagation","AlertTriangle","size","X","issueNumber","readOnly","onChange","target","placeholder","User","firstName","lastName","Calendar","createdAt","toLocaleString","year","month","day","hour","minute","hour12","rows","disabled","userName","MessageSquare","_Fragment","componentData","issueData","createdIssue","createPortal","document","body","ThresholdAlert","currentValue","thresholdValue","onIssueRaised","isIssueRaised","compact","showRaiseIssueModal","setShowRaiseIssueModal","setIssue","isLoadingIssue","setIsLoadingIssue","localIssueRaised","setLocalIssueRaised","getOperatorSymbol","handleRaiseIssueClick","useCallback","handleRaiseIssueClose","handleRaiseIssueSuccess","fill","operatorSymbol","getConditionMessage","DfFormInput","formValue","inputType","readonly","onValueChange","onBlur","onFocus","hideLabel","onThresholdIssueRaised","raisedThresholdIssues","Set","getStringValue","componentIdRef","useRef","inputWrapperRef","initialValue","setValue","setIsTouched","isFocused","setIsFocused","dismissedAlerts","setDismissedAlerts","previousValue","setPreviousValue","getInputType","validateField","rules","required","email","textValidation","buildValidationRules","test","trimmedVal","numValue","parseFloat","pattern","isPartialInput","handleValueChange","newValue","currentId","change","currentComponentId","evaluateThresholdCondition","currentVal","thresholdConditions","useMemo","activeThresholdCondition","metConditions","handleDismissAlert","conditionId","prev","add","currentInputType","shouldDisable","alignment","styles","labelAlignment","getLabelAlignmentClass","htmlFor","base","hasLocalError","hasExternalError","getInputClasses","issueRaised","isInTable","closest","onDismiss","DfFormTextarea","DfFormSelect","selectedValue","setSelectedValue","isMultiple","multiple","JSON","stringify","selectedOptions","from","option","options","DfFormCheckbox","selectedValues","newValues","handleCheckboxChange","optionValue","checked","handleFocus","handleBlur","inlineLayout","DfFormRadio","handleRadioChange","DfFormSegment","handleSegmentClick","getSegmentContainerClass","getButtonType","getButtonIcon","icon","getButtonStyles","isSelected","color","backgroundColor","borderColor","getButtonClass","buttonStyles","buttonClass","buttonIcon","style","DfFormDateTime","convertToDateString","date","getTime","getFullYear","getMonth","padStart","getDate","getHours","getMinutes","dateStr","invalidDate","selectedDate","minDate","minDateMessage","toLocaleDateString","maxDate","maxDateMessage","convertedValue","DfFormSignature","canvasRef","isDrawing","setIsDrawing","signatureData","setSignatureData","isSaving","setIsSaving","getThemeColors","isDarkMode","documentElement","classList","getAttribute","getComputedStyle","getPropertyValue","strokeColor","loadSignature","dataURL","canvas","ctx","getContext","img","Image","onload","clearRect","width","height","colors","fillStyle","fillRect","canvasAspectRatio","imgAspectRatio","drawWidth","drawHeight","drawX","drawY","drawImage","onerror","substring","src","initializeCanvas","rect","getBoundingClientRect","strokeStyle","lineWidth","lineCap","lineJoin","handleViewportChange","handleResize","observer","MutationObserver","mutations","mutation","attributeName","observe","attributes","attributeFilter","subtree","window","addEventListener","disconnect","removeEventListener","getCanvasCoordinates","y","scaleX","scaleY","clientX","touches","clientY","left","top","startDrawing","preventDefault","beginPath","moveTo","draw","lineTo","stroke","stopDrawing","data","getImageData","r","hasCanvasContent","toDataURL","updateCanvasColors","currentSignature","position","maxWidth","overflow","onMouseDown","onMouseMove","onMouseUp","onMouseLeave","onTouchStart","onTouchMove","onTouchEnd","border","borderRadius","cursor","touchAction","userSelect","clearSignature","bottom","right","padding","fontSize","fontWeight","zIndex","transition","minWidth","minHeight","onMouseEnter","currentTarget","transform","DfFormFileUpload","files","setFiles","isDragOver","setIsDragOver","fileInputRef","convertToFilePreviews","fileList","fileArray","results","file","File","Blob","fileObj","url","fileSize","fileType","mimeType","preview","fileData","startsWith","cleanedData","detectedType","fileInstance","URL","createObjectURL","fileString","cleanedString","isBase64String","processedFileString","imageType","extractedFileName","filenameMatch","decodeURIComponent","typeMatch","urlFileName","pathname","pop","queryFileName","searchParams","lastSlash","lastIndexOf","lastPart","questionMark","indexOf","fileNamePart","semicolonIndex","extensionMatch","jpg","jpeg","png","gif","webp","svg","pdf","doc","docx","xls","xlsx","zip","rar","fileObject","path","validateFiles","handleFileSelect","selectedFiles","newFiles","allFiles","maxFiles","Infinity","limitedFiles","slice","formatFileSize","bytes","floor","pow","toFixed","getFileIcon","revokeObjectURL","acceptTypes","accept","canAddMoreFiles","isPreviewOrTestMode","imageFiles","nonImageFiles","hasImages","alt","onDragOver","onDragLeave","onDrop","droppedFiles","dataTransfer","isClickOnFileItem","isClickOnRemoveButton","click","tabIndex","display","fileId","updatedFiles","removeFile","viewBox","strokeWidth","strokeLinecap","strokeLinejoin","DfFormLocation","locationData","setLocationData","isLoading","setIsLoading","setError","showMap","setShowMap","mapCenter","setMapCenter","lat","lng","mapMarker","setMapMarker","mapZoom","setMapZoom","searchQuery","setSearchQuery","isSearching","setIsSearching","mapRef","isDragging","setIsDragging","dragStart","setDragStart","isReverseGeocoding","setIsReverseGeocoding","latitude","longitude","isCurrentLocation","reverseGeocode","response","fetch","json","address","placeName","display_name","city","town","village","municipality","country","updateLocationWithAddress","existingData","addressData","timestamp","getCurrentLocation","Capacitor","Geolocation","Plugins","requestPermissions","getCurrentPosition","enableHighAccuracy","maximumAge","coords","accuracy","capError","navigator","geolocation","code","PERMISSION_DENIED","POSITION_UNAVAILABLE","TIMEOUT","clearLocation","toggleMap","pixelToLatLng","center","zoom","offsetX","offsetY","metersPerPixel","cos","PI","metersX","metersY","handleMapMouseDown","event","button","handleMapMouseMove","deltaX","deltaY","latOffset","lngOffset","handleMapMouseUp","abs","searchLocation","query","encodeURIComponent","firstResult","lon","Loader2","Navigation","MapPin","Boolean","round","onSubmit","background","tan","DfFormHeading","text","getInlineStyles","headingProps","textAlign","renderHeading","DfFormInstruction","htmlContent","setHtmlContent","listStyle","setListStyle","selectedColor","setSelectedColor","editorRef","isUserInputRef","isEditable","prevPropsRef","instructions","prevModeRef","propsInstructions","propsListStyle","basicValue","propsChanged","modeChanged","formValueChanged","formValueWasEmpty","formValueNowHasData","decodeHtml","str","fromCharCode","parseInt","decodedInstructions","inst","hasHtml","expectedContent","listTag","listItems","innerHTML","currentEditorContent","handleContentChange","content","executeCommand","command","execCommand","focus","handleBold","handleItalic","handleColorChange","handleListStyleChange","selection","getSelection","range","rangeCount","getRangeAt","currentContent","lines","line","removeAllRanges","addRange","handleImageUpload","reader","FileReader","imageUrl","createElement","deleteContents","insertNode","appendChild","readAsDataURL","handlePaste","clipboardData","getData","textNode","createTextNode","setStartAfter","collapse","isCommandActive","queryCommandState","Bold","Italic","List","ListOrdered","contentEditable","onInput","onPaste","suppressContentEditableWarning","dangerouslySetInnerHTML","__html","AttachmentThumbnails","onRemove","objectUrls","setObjectUrls","newUrls","isImage","objectUrl","Paperclip","ComponentActionFeatures","onNotesChange","onAttachmentChange","onThresholdActionCompletion","onBasicPropertyActionCompletion","localNotes","setLocalNotes","localAttachments","setLocalAttachments","showNotesInput","setShowNotesInput","emailSent","setEmailSent","setIssueRaised","actionsExpanded","setActionsExpanded","previousFormValueRef","notesInitializedRef","attachmentsInitializedRef","notesStr","isOptionBasedComponent","valueChanged","prevArray","currArray","conditionValue","stringValue","stringConditionValue","getActiveThresholdConditions","activeConditions","matchingCondition","cond","handleNotesChange","isCompleted","enableNotes","componentCondition","handleNotesSave","handleNotesBlur","handleNotesKeyDown","ctrlKey","metaKey","handleNotesIconClick","handleNotesSummaryClick","handleAttachmentIconClick","handleFileChange","enableAttachment","handleRemoveAttachment","newAttachments","_","handleSendEmailClick","enableSendEmail","enableRaiseIssue","componentOptions","selectedOption","hasValidFormValue","hasThresholdConditions","componentBasic","componentLevelNotes","componentLevelAttachment","componentLevelRaiseIssue","componentLevelSendEmail","opt","optionNotes","optionAttachment","optionRaiseIssue","optionSendEmail","hasComponentThresholdConditions","isNotesMandatory","isAttachmentsMandatory","isSendEmailMandatory","isRaiseIssueMandatory","hasNotes","hasAttachments","attachmentCount","Check","Mail","AlertCircle","ChevronUp","ChevronDown","onKeyDown","autoFocus","SubmissionAttachmentThumbnails","attachment","imageSrc","getImageSrc","ComponentSubmissionActions","DraggableChild","selectedChild","onChildSelect","onChildDelete","renderFormComponent","isOverlay","isChildrenEditMode","formData","hasSubmissionData","setNodeRef","isSorting","useSortable","CSS","Transform","role","GripVertical","Edit","Trash2","DfFormSection","onSelect","onSectionSelect","isCollapsed","setIsCollapsed","collapsed","isEditingTitle","setIsEditingTitle","isEditingDescription","setIsEditingDescription","sectionTitle","setSectionTitle","sectionDescription","setSectionDescription","setChildren","setIsChildrenEditMode","isOver","useDroppable","shouldHideInCurrentMode","handleTitleChange","newTitle","handleDescriptionChange","newDescription","handleChildSelect","handleChildDelete","newChildren","handleSectionSelect","handleSectionDoubleClick","toggleCollapse","renderComponent","field","commonProps","selectProps","checkboxProps","radioProps","sectionStyles","borderWidth","margin","onDoubleClick","marginRight","alignItems","ChevronRight","SortableContext","items","strategy","verticalListSortingStrategy","flexDirection","gap","DraggableGridComponent","selectedComponent","onComponentSelect","onComponentDelete","onComponentEdit","opacity","boxShadow","justifyContent","paddingTop","paddingLeft","GridDropZone","gridComponents","onComponentUpdate","gridId","horizontalListSortingStrategy","flexWrap","marginBottom","overflowX","flex","TableView","templateComponents","dataEntries","internalRenderComponent","allowAddRemoveEntries","addAnotherText","removeText","maxEntries","minEntries","displayAsGrid","onAddEntry","onRemoveEntry","_formData","datagridId","overflowY","scrollbarWidth","scrollbarColor","gridTemplateColumns","borderBottom","borderRight","whiteSpace","textOverflow","entry","entryIndex","isolation","templateComponent","componentIndex","entryComponent","components","expectedUniqueId","showLabel","pointerEvents","borderTop","paddingBottom","textTransform","letterSpacing","DfFormDataGrid","onDataGridSelect","onEntryAdd","onEntryRemove","hasInitialized","firstEntry","baseComponentId","expectedId","updatedEntries","templateComp","existingComponent","hasProperId","needsPropertyUpdate","updatedComponents","uniqueId","handleDataGridClick","handleComponentDelete","entryComp","handleComponentUpdate","updates","handleComponentValueChange","handleAddEntry","currentEntries","newEntryIndex","newEntry","uniqueComponentId","handleRemoveEntry","gridStyle","Grid","marginTop","datagrid","DfFormTable","lazy","Promise","resolve","then","dfFormTable","DfFormPreview","formComponents","currentDevice","isPreviewMode","initialFormData","onFormDataChange","formTitle","formDescription","setFormValues","setValidationErrors","setFormSubmitted","setTouchedFields","componentVisibility","setComponentVisibility","setRaisedThresholdIssues","thresholdActionCompletions","setThresholdActionCompletions","thresholdValidationState","setThresholdValidationState","initializeFormState","initializeComponentValues","cells","row","_rowIndex","cell","_cellIndex","_entryIndex","instructionValue","initialValues","seenIds","validateComponentIds","evaluateComponentConditionalLogic","visibility","shouldShowComponent","onFormValueChange","componentsWithSameId","existingValue","oldValue","newFormValues","threshold","newSet","delete","updateComponentValue","updatedCell","updatedEntry","findComponentById","found","hasValue","onFormControlBlur","onFormControlFocus","isFormValid","getMetThresholdConditions","validateThresholdConditions","completions","notesCompleted","attachmentsCompleted","missingActions","handleThresholdIssueRaised","handleThresholdActionCompletion","completed","newMap","validateAllFields","handleSubmit","firstErrorField","errorElement","getElementById","thresholdValidation","firstUnmet","scrollIntoView","behavior","block","updateComponentValues","finalValue","updatedComponent","finalFormData","getPreviewClasses","componentIdCacheRef","componentCounterRef","finalComponentId","cacheKey","cachedId","componentsWithSameValue","segmentProps","instructionFormValue","Suspense","fallback","updatedCells","updatedCellComponents","cellComp","nestedComp","currentComponent","datagridValue","compIndex","fileFormValue","isOptionBased","columnClass","column","getColumnClass","hasActionFeatures","DfFormComments","comment","onSave","isExpanded","setIsExpanded","currentComment","setCurrentComment","hasChanges","setHasChanges","handleInputChange","handleInputBlur","handleInputFocus","toggleComments","ensureComponentHasId","uuidv4","SimpleTableComponent","DraggableTableComponent","TableCellComponent","tableId","dropZoneId","cellStyle","verticalAlign","componentWithId","onTableSelect","hasAnyComponents","table","columns","handleTableClick","filteredComponents","cellsWithIds","rowIndex","cellIndex","tableStyle","tableElementStyle","borderCollapse","tableLayout","Table","displayAsTable","showColumns","colIndex","columnName","columnNames","headerBackgroundColor","headerTextColor","ELabelAlignment"],"mappings":"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","x_google_ignoreList":[0,1,2]}
|