@plusscommunities/pluss-feature-builder-web-a 1.0.2-beta.5 → 1.0.2-beta.7

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.cjs.js CHANGED
@@ -116,7 +116,7 @@ const selectFormState = state => getFeatureBuilderState(state).form;
116
116
  */
117
117
  const selectFormTitle = state => {
118
118
  const formState = selectFormState(state);
119
- return formState && formState.title;
119
+ return formState === null || formState === void 0 ? void 0 : formState.title;
120
120
  };
121
121
 
122
122
  /**
@@ -127,7 +127,7 @@ const selectFormTitle = state => {
127
127
  */
128
128
  const selectFormIcon = state => {
129
129
  const formState = selectFormState(state);
130
- return formState && formState.icon;
130
+ return formState === null || formState === void 0 ? void 0 : formState.icon;
131
131
  };
132
132
 
133
133
  /**
@@ -138,7 +138,7 @@ const selectFormIcon = state => {
138
138
  */
139
139
  const selectFormDisplayName = state => {
140
140
  const formState = selectFormState(state);
141
- return formState && formState.displayName;
141
+ return formState === null || formState === void 0 ? void 0 : formState.displayName;
142
142
  };
143
143
 
144
144
  /**
@@ -149,7 +149,7 @@ const selectFormDisplayName = state => {
149
149
  */
150
150
  const selectFormLayout = state => {
151
151
  const formState = selectFormState(state);
152
- return formState && formState.layout;
152
+ return formState === null || formState === void 0 ? void 0 : formState.layout;
153
153
  };
154
154
 
155
155
  /**
@@ -160,24 +160,24 @@ const selectFormLayout = state => {
160
160
  */
161
161
  const selectFormFields = state => {
162
162
  const formState = selectFormState(state);
163
- return formState && formState.fields || [];
163
+ return (formState === null || formState === void 0 ? void 0 : formState.fields) || [];
164
164
  };
165
165
  const selectFormField = fieldId => state => selectFormFields(state).find(field => field.id === fieldId);
166
166
  const selectFormIsInitial = state => {
167
167
  const formState = selectFormState(state);
168
- return formState && formState._isInitial;
168
+ return formState === null || formState === void 0 ? void 0 : formState._isInitial;
169
169
  };
170
170
  const selectFormIsSubmitting = state => {
171
171
  const formState = selectFormState(state);
172
- return formState && formState._isSubmitting;
172
+ return formState === null || formState === void 0 ? void 0 : formState._isSubmitting;
173
173
  };
174
174
  const selectFormSubmitError = state => {
175
175
  const formState = selectFormState(state);
176
- return formState && formState._submitError;
176
+ return formState === null || formState === void 0 ? void 0 : formState._submitError;
177
177
  };
178
178
  const selectFormSubmitSuccess = state => {
179
179
  const formState = selectFormState(state);
180
- return formState && formState._submitSuccess;
180
+ return formState === null || formState === void 0 ? void 0 : formState._submitSuccess;
181
181
  };
182
182
 
183
183
  // ============ DEFINITION SELECTORS ============
@@ -185,50 +185,59 @@ const selectFormSubmitSuccess = state => {
185
185
  const selectDefinitionState = state => getFeatureBuilderState(state).definition;
186
186
  const selectDefinition = state => {
187
187
  const definitionState = selectDefinitionState(state);
188
- return definitionState && definitionState.definition;
188
+ return definitionState === null || definitionState === void 0 ? void 0 : definitionState.definition;
189
189
  };
190
190
  const selectDefinitionId = state => {
191
191
  const definitionState = selectDefinitionState(state);
192
- return definitionState && definitionState.id;
192
+ return definitionState === null || definitionState === void 0 ? void 0 : definitionState.id;
193
193
  };
194
194
  const selectDefinitionIsLoading = state => {
195
195
  const definitionState = selectDefinitionState(state);
196
- return definitionState && definitionState.isLoading;
196
+ return definitionState === null || definitionState === void 0 ? void 0 : definitionState.isLoading;
197
197
  };
198
198
  const selectDefinitionError = state => {
199
199
  const definitionState = selectDefinitionState(state);
200
- return definitionState && definitionState.error;
200
+ return definitionState === null || definitionState === void 0 ? void 0 : definitionState.error;
201
201
  };
202
202
  const selectDefinitionMode = state => {
203
203
  const definitionState = selectDefinitionState(state);
204
- return definitionState && definitionState.mode;
204
+ return definitionState === null || definitionState === void 0 ? void 0 : definitionState.mode;
205
205
  };
206
206
 
207
- // Check if we have a definition loaded
208
- const selectHasDefinition = state => !!selectDefinition(state);
207
+ // Check if we have a definition loaded or if we've determined the mode
208
+ // This is used by hiddenFromFeaturePicker to determine if feature should be shown
209
+ // When mode is "create", definition is null but we've determined the feature doesn't exist
210
+ // When mode is "edit", definition exists and we've determined the feature exists
211
+ const selectHasDefinition = state => {
212
+ const definition = selectDefinition(state);
213
+ const mode = selectDefinitionMode(state);
214
+ // Consider feature "loaded" if definition exists OR mode is set
215
+ // Mode being set means we've successfully fetched and determined the state
216
+ return !!definition || !!mode;
217
+ };
209
218
 
210
219
  // ============ LISTINGS SELECTORS ============
211
220
 
212
221
  const selectListingsState = state => getFeatureBuilderState(state).listings;
213
222
  const selectListings = state => {
214
223
  const listingsState = selectListingsState(state);
215
- return listingsState && listingsState.listings || [];
224
+ return (listingsState === null || listingsState === void 0 ? void 0 : listingsState.listings) || [];
216
225
  };
217
226
  const selectListingsIsLoading = state => {
218
227
  const listingsState = selectListingsState(state);
219
- return listingsState && listingsState.isLoading;
228
+ return listingsState === null || listingsState === void 0 ? void 0 : listingsState.isLoading;
220
229
  };
221
230
  const selectListingsError = state => {
222
231
  const listingsState = selectListingsState(state);
223
- return listingsState && listingsState.error;
232
+ return listingsState === null || listingsState === void 0 ? void 0 : listingsState.error;
224
233
  };
225
234
  const selectListingsIsRestoring = state => {
226
235
  const listingsState = selectListingsState(state);
227
- return listingsState && listingsState.isRestoring;
236
+ return listingsState === null || listingsState === void 0 ? void 0 : listingsState.isRestoring;
228
237
  };
229
238
  const selectListingsIsInitiallyLoaded = state => {
230
239
  const listingsState = selectListingsState(state);
231
- return listingsState && listingsState.isInitiallyLoaded;
240
+ return listingsState === null || listingsState === void 0 ? void 0 : listingsState.isInitiallyLoaded;
232
241
  };
233
242
 
234
243
  // Get a specific listing by ID
@@ -261,7 +270,7 @@ const selectDeletedListings = state => {
261
270
  const selectWizardState = state => getFeatureBuilderState(state).wizard;
262
271
  const selectWizardMode = state => {
263
272
  const wizardState = selectWizardState(state);
264
- return wizardState && wizardState.mode;
273
+ return wizardState === null || wizardState === void 0 ? void 0 : wizardState.mode;
265
274
  };
266
275
 
267
276
  // Mode detection selectors - wizard mode is the SINGLE SOURCE OF TRUTH for create/edit mode
@@ -270,35 +279,35 @@ const selectIsCreateMode = state => selectWizardMode(state) === "create";
270
279
  const selectIsEditMode = state => selectWizardMode(state) === "edit";
271
280
  const selectNavigationState = state => {
272
281
  const wizardState = selectWizardState(state);
273
- return wizardState && wizardState.navigation;
282
+ return wizardState === null || wizardState === void 0 ? void 0 : wizardState.navigation;
274
283
  };
275
284
  const selectCurrentStep = state => {
276
285
  const navigationState = selectNavigationState(state);
277
- return navigationState && navigationState.currentStep;
286
+ return navigationState === null || navigationState === void 0 ? void 0 : navigationState.currentStep;
278
287
  };
279
288
  const selectStepValidation = state => {
280
289
  const wizardState = selectWizardState(state);
281
- return wizardState && wizardState.stepValidation;
290
+ return wizardState === null || wizardState === void 0 ? void 0 : wizardState.stepValidation;
282
291
  };
283
292
  const selectStepValidationState = step => state => {
284
293
  const stepValidation = selectStepValidation(state);
285
- return stepValidation && stepValidation[step];
294
+ return stepValidation === null || stepValidation === void 0 ? void 0 : stepValidation[step];
286
295
  };
287
296
  const selectIsStepValid = step => state => {
288
297
  const stepValidationState = selectStepValidationState(step)(state);
289
- return stepValidationState && stepValidationState.isValid;
298
+ return stepValidationState === null || stepValidationState === void 0 ? void 0 : stepValidationState.isValid;
290
299
  };
291
300
  const selectStepErrors = step => state => {
292
301
  const stepValidationState = selectStepValidationState(step)(state);
293
- return stepValidationState ? stepValidationState.errors : {};
302
+ return (stepValidationState === null || stepValidationState === void 0 ? void 0 : stepValidationState.errors) || {};
294
303
  };
295
304
  const selectStepCompletion = state => {
296
305
  const wizardState = selectWizardState(state);
297
- return wizardState && wizardState.stepCompletion;
306
+ return wizardState === null || wizardState === void 0 ? void 0 : wizardState.stepCompletion;
298
307
  };
299
308
  const selectIsStepComplete = step => state => {
300
309
  const stepCompletion = selectStepCompletion(state);
301
- return stepCompletion && stepCompletion[step];
310
+ return stepCompletion === null || stepCompletion === void 0 ? void 0 : stepCompletion[step];
302
311
  };
303
312
 
304
313
  // Check if current step should be accessible in current mode
@@ -329,13 +338,13 @@ const selectIsStepAccessible = step => state => {
329
338
  // Get current sort method
330
339
  const selectSortBy = state => {
331
340
  const listingsState = selectListingsState(state);
332
- return listingsState && listingsState.sortBy ? listingsState.sortBy : "newest";
341
+ return (listingsState === null || listingsState === void 0 ? void 0 : listingsState.sortBy) || "newest";
333
342
  };
334
343
 
335
344
  // Get show deleted toggle state
336
345
  const selectShowDeleted = state => {
337
346
  const listingsState = selectListingsState(state);
338
- return listingsState && listingsState.showDeleted ? listingsState.showDeleted : false;
347
+ return (listingsState === null || listingsState === void 0 ? void 0 : listingsState.showDeleted) || false;
339
348
  };
340
349
 
341
350
  // Get sorted and filtered listings
@@ -2120,846 +2129,838 @@ const Text$8 = Components$4.Text;
2120
2129
 
2121
2130
  function ownKeys$8(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2122
2131
  function _objectSpread$8(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$8(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$8(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2132
+ const {
2133
+ Helper: Helper$1,
2134
+ Session: Session$1
2135
+ } = PlussCore__namespace;
2136
+ const {
2137
+ getUrl: getUrl$1
2138
+ } = Helper$1;
2139
+ const {
2140
+ authedFunction: authedFunction$1
2141
+ } = Session$1;
2142
+ const featureDefinitionActions = {
2143
+ /**
2144
+ * Get the single feature definition by ID
2145
+ * Path: {id}
2146
+ */
2147
+ getSingle: async (id, site) => {
2148
+ const query = {
2149
+ id,
2150
+ site
2151
+ };
2152
+ return authedFunction$1({
2153
+ method: "GET",
2154
+ url: getUrl$1("feature-builder", "definition/get/single", query)
2155
+ });
2156
+ },
2157
+ /**
2158
+ * Creates a new feature definition with the provided configuration
2159
+ *
2160
+ * @param {string} id - The unique identifier for the new feature definition
2161
+ * @param {string} site - The site ID where the feature definition will be created
2162
+ * @param {FeatureDefinition} featureDefinition - The feature definition data to create
2163
+ * @returns {Promise<ApiResponse>} Promise resolving to API response with created feature definition
2164
+ * @throws {Error} When creation fails due to validation or API errors
2165
+ *
2166
+ */
2167
+ create: async (id, site, featureDefinition) => {
2168
+ return authedFunction$1({
2169
+ method: "POST",
2170
+ url: getUrl$1("feature-builder", "definition/update/create"),
2171
+ data: {
2172
+ id,
2173
+ site,
2174
+ featureDefinition
2175
+ }
2176
+ });
2177
+ },
2178
+ /**
2179
+ * Updates an existing feature definition with new configuration
2180
+ *
2181
+ * @param {FeatureDefinition} featureDefinitionData - The updated feature definition data
2182
+ * @param {string} featureDefinitionData.id - The unique identifier of the feature definition to update
2183
+ * @param {string} [featureDefinitionData.displayName] - Updated display name
2184
+ * @param {Field[]} [featureDefinitionData.fields] - Updated field definitions
2185
+ * @param {Object} [featureDefinitionData.layout] - Updated layout configuration
2186
+ * @param {string} site - The site ID where the feature definition exists
2187
+ * @returns {Promise<ApiResponse>} Promise resolving to API response with updated feature definition
2188
+ * @throws {Error} When update fails due to validation or API errors
2189
+ *
2190
+ * @example
2191
+ * try {
2192
+ * const response = await featureDefinitionActions.edit(
2193
+ * {
2194
+ * id: 'feature-123',
2195
+ * displayName: 'Updated Form',
2196
+ * fields: [...]
2197
+ * },
2198
+ * 'site-123'
2199
+ * );
2200
+ */
2201
+ edit: async (featureDefinitionData, site) => {
2202
+ // Ensure site is included in the request body
2203
+ const dataWithSite = _objectSpread$8({
2204
+ site: site
2205
+ }, featureDefinitionData);
2206
+ return authedFunction$1({
2207
+ method: "POST",
2208
+ url: getUrl$1("feature-builder", "definition/update/edit"),
2209
+ data: dataWithSite
2210
+ });
2211
+ },
2212
+ /**
2213
+ * Soft deletes a feature definition (marks as deleted but doesn't permanently remove)
2214
+ *
2215
+ * @param {string} id - The unique identifier of the feature definition to delete
2216
+ * @param {string} site - The site ID where the feature definition exists
2217
+ * @returns {Promise<ApiResponse>} Promise resolving to API response confirming deletion
2218
+ * @throws {Error} When deletion fails or feature definition is not found
2219
+ *
2220
+ */
2221
+ delete: async (id, site) => {
2222
+ return authedFunction$1({
2223
+ method: "POST",
2224
+ url: getUrl$1("feature-builder", "definition/update/delete"),
2225
+ data: {
2226
+ id,
2227
+ site
2228
+ }
2229
+ });
2230
+ }
2231
+ };
2123
2232
 
2124
- // Wizard action types
2125
- const REDUCER_PREFIX$2 = values.reducerKey.toUpperCase();
2126
- const SET_NAVIGATION_STATE$1 = "".concat(REDUCER_PREFIX$2, "_SET_NAVIGATION_STATE");
2127
- const UPDATE_STEP_VALIDATION$1 = "".concat(REDUCER_PREFIX$2, "_UPDATE_STEP_VALIDATION");
2128
- const MARK_STEP_COMPLETE$1 = "".concat(REDUCER_PREFIX$2, "_MARK_STEP_COMPLETE");
2129
- const setCurrentStep = function (step) {
2130
- let previousStep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
2131
- return {
2132
- type: SET_NAVIGATION_STATE$1,
2133
- payload: {
2134
- currentStep: step,
2135
- previousStep,
2136
- canGoBack: step !== "welcome",
2137
- canGoForward: true
2138
- }
2139
- };
2233
+ function ownKeys$7(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2234
+ function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$7(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$7(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2235
+
2236
+ // IMPORTANT: Using local UPDATE_STRINGS action type to make extension self-contained
2237
+ // The main app's StringsReducer will handle this action type the same way
2238
+ const UPDATE_STRINGS = "UPDATE_STRINGS";
2239
+ const updateFeatureBuilderString = title => (dispatch, getState) => {
2240
+ var _getState$strings;
2241
+ const currentStrings = ((_getState$strings = getState().strings) === null || _getState$strings === void 0 ? void 0 : _getState$strings.config) || {};
2242
+ const titleCased = toTitleCase(title) || values.textMenuTitle;
2243
+ const updatedStrings = _objectSpread$7(_objectSpread$7({}, currentStrings), {}, {
2244
+ sideNav: _objectSpread$7(_objectSpread$7({}, currentStrings.sideNav), {}, {
2245
+ [values.featureKey]: titleCased,
2246
+ [values.menuKey]: "Manage ".concat(titleCased)
2247
+ }),
2248
+ permission: _objectSpread$7(_objectSpread$7({}, currentStrings.permission), {}, {
2249
+ [values.permissionFeatureBuilderDefinition]: "Manage custom feature ".concat(titleCased),
2250
+ [values.permissionFeatureBuilderContent]: "Manage ".concat(titleCased, " content")
2251
+ })
2252
+ });
2253
+ dispatch({
2254
+ type: UPDATE_STRINGS,
2255
+ payload: updatedStrings
2256
+ });
2257
+ };
2258
+ const updateFeatureBuilderIcon = icon => (dispatch, getState) => {
2259
+ var _getState$strings2;
2260
+ const currentStrings = ((_getState$strings2 = getState().strings) === null || _getState$strings2 === void 0 ? void 0 : _getState$strings2.config) || {};
2261
+ const updatedStrings = _objectSpread$7(_objectSpread$7({}, currentStrings), {}, {
2262
+ sideNav: _objectSpread$7(_objectSpread$7({}, currentStrings.sideNav), {}, {
2263
+ [values.featureKey + "-icon"]: icon,
2264
+ [values.menuKey + "-icon"]: icon
2265
+ })
2266
+ });
2267
+ dispatch({
2268
+ type: UPDATE_STRINGS,
2269
+ payload: updatedStrings
2270
+ });
2140
2271
  };
2141
- const goToStep = step => (dispatch, getState) => {
2142
- const state = getState()[require("../values.config").reducerKey];
2143
- const currentStep = state && state.wizard && state.wizard.navigation && state.wizard.navigation.currentStep;
2144
2272
 
2145
- // Clear form submission state when changing steps
2146
- const {
2147
- clearFormSubmissionState
2148
- } = require("./formActions");
2149
- dispatch(clearFormSubmissionState());
2150
- dispatch(setCurrentStep(step, currentStep));
2273
+ /**
2274
+ * @typedef {Object} FieldValues
2275
+ * @property {string} [label] - Field label text
2276
+ * @property {string} [placeholder] - Placeholder text for input
2277
+ * @property {boolean} [isRequired] - Whether field is required
2278
+ * @property {string} [helpText] - Help text for field guidance
2279
+ * @property {boolean} [allowCaption] - Whether field allows captions
2280
+ * @property {boolean} [useAsSummary] - Whether field is used as summary
2281
+ */
2282
+
2283
+ /**
2284
+ * @typedef {Object} FormField
2285
+ * @property {string} id - Unique field identifier
2286
+ * @property {string} type - Field type (text, title, description, image, file, cta, feature-image)
2287
+ * @property {boolean} isMandatory - Whether field is mandatory system field
2288
+ * @property {FieldValues} values - Field configuration values
2289
+ */
2290
+
2291
+ /**
2292
+ * @typedef {Object} LayoutConfig
2293
+ * @property {string} type - Layout type (round, square, etc.)
2294
+ * @property {string} [gridIcon] - Background image for grid layout
2295
+ */
2296
+
2297
+ const actionsTypes = {
2298
+ SET_INITIAL_VALUES: "".concat(values.reducerKey.toUpperCase(), "_SET_INITIAL_VALUES"),
2299
+ SET_TITLE: "".concat(values.reducerKey.toUpperCase(), "_SET_TITLE"),
2300
+ SET_ICON: "".concat(values.reducerKey.toUpperCase(), "_SET_ICON"),
2301
+ SET_DISPLAY_NAME: "".concat(values.reducerKey.toUpperCase(), "_SET_DISPLAY_NAME"),
2302
+ ADD_FIELD: "".concat(values.reducerKey.toUpperCase(), "_ADD_FIELD"),
2303
+ DELETE_FIELD: "".concat(values.reducerKey.toUpperCase(), "_DELETE_FIELD"),
2304
+ UPDATE_FIELD: "".concat(values.reducerKey.toUpperCase(), "_UPDATE_FIELD"),
2305
+ SET_LAYOUT_GRID_ICON: "".concat(values.reducerKey.toUpperCase(), "_SET_LAYOUT_GRID_ICON"),
2306
+ SET_LAYOUT_TYPE: "".concat(values.reducerKey.toUpperCase(), "_SET_LAYOUT_TYPE"),
2307
+ SUBMIT_FORM_REQUEST: "".concat(values.reducerKey.toUpperCase(), "_SUBMIT_FORM_REQUEST"),
2308
+ SUBMIT_FORM_SUCCESS: "".concat(values.reducerKey.toUpperCase(), "_SUBMIT_FORM_SUCCESS"),
2309
+ SUBMIT_FORM_FAILURE: "".concat(values.reducerKey.toUpperCase(), "_SUBMIT_FORM_FAILURE"),
2310
+ CLEAR_FORM_SUBMISSION_STATE: "".concat(values.reducerKey.toUpperCase(), "_CLEAR_FORM_SUBMISSION_STATE"),
2311
+ SET_SUMMARY_FIELD: "".concat(values.reducerKey.toUpperCase(), "_SET_SUMMARY_FIELD")
2151
2312
  };
2152
- const updateStepValidation = function (step, isValid) {
2153
- let errors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2313
+
2314
+ /**
2315
+ * Action creator to set initial form values
2316
+ * Initializes form state with existing feature definition data
2317
+ *
2318
+ * @param {Object} initialValues - Initial form values object
2319
+ * @param {string} initialValues.title - Feature title
2320
+ * @param {string} initialValues.icon - Feature icon
2321
+ * @param {string} initialValues.displayName - Feature display name
2322
+ * @param {LayoutConfig} initialValues.layout - Layout configuration
2323
+ * @param {FormField[]} initialValues.fields - Form fields array
2324
+ * @returns {Object} Redux action object with type and payload
2325
+ *
2326
+ * @example
2327
+ * dispatch(setInitialValues({
2328
+ * title: 'Contact Form',
2329
+ * icon: 'envelope',
2330
+ * fields: []
2331
+ * }));
2332
+ */
2333
+ const setInitialValues = initialValues => {
2154
2334
  return {
2155
- type: UPDATE_STEP_VALIDATION$1,
2156
- payload: {
2157
- step,
2158
- isValid,
2159
- errors
2160
- }
2335
+ type: actionsTypes.SET_INITIAL_VALUES,
2336
+ payload: initialValues
2161
2337
  };
2162
2338
  };
2163
- const validateAndUpdateStep = step => (dispatch, getState) => {
2164
- // Use existing selectors to get form data
2165
- const state = getState();
2166
- const title = selectFormTitle(state);
2167
- const icon = selectFormIcon(state);
2168
- const displayName = selectFormDisplayName(state);
2169
- const layout = selectFormLayout(state);
2170
- const fields = selectFormFields(state);
2171
- const form = {
2172
- title,
2173
- icon,
2174
- displayName,
2175
- layout,
2176
- fields
2339
+ const setTitle = title => {
2340
+ return {
2341
+ type: actionsTypes.SET_TITLE,
2342
+ payload: title
2177
2343
  };
2178
- const {
2179
- isValid,
2180
- errors
2181
- } = getFormValidation(form, step);
2182
- dispatch(updateStepValidation(step, isValid, errors));
2344
+ };
2183
2345
 
2184
- // If valid, mark as complete
2185
- if (isValid) {
2186
- dispatch({
2187
- type: MARK_STEP_COMPLETE$1,
2188
- payload: step
2189
- });
2190
- }
2191
- return {
2192
- isValid,
2193
- errors
2194
- };
2195
- };
2196
- const getFormValidation = (form, step) => {
2197
- // Return validation results for undefined form (prevent crashes)
2198
- if (!form) {
2199
- switch (step) {
2200
- case "overview":
2201
- return {
2202
- isValid: false,
2203
- errors: {
2204
- title: "Title is required",
2205
- displayName: "Display name is required",
2206
- icon: "Icon is required"
2207
- }
2208
- };
2209
- case "fields":
2210
- return {
2211
- isValid: false,
2212
- errors: {
2213
- missingTitle: "Title field is required",
2214
- missingImage: "Feature image field is required",
2215
- fieldLabels: "Some fields are missing labels"
2216
- }
2217
- };
2218
- case "layout":
2219
- return {
2220
- isValid: false,
2221
- errors: {
2222
- layoutType: "Layout type is required"
2223
- }
2224
- };
2225
- default:
2226
- return {
2227
- isValid: false,
2228
- errors: {}
2229
- };
2230
- }
2231
- }
2232
- switch (step) {
2233
- case "overview":
2234
- {
2235
- const hasTitle = form.title && form.title.trim().length > 0;
2236
- const hasDisplayName = form.displayName && form.displayName.trim().length > 0;
2237
- const hasIcon = form.icon && form.icon.length > 0;
2238
- return {
2239
- isValid: hasTitle && hasDisplayName && hasIcon,
2240
- errors: {
2241
- title: !hasTitle ? "Title is required" : null,
2242
- displayName: !hasDisplayName ? "Display name is required" : null,
2243
- icon: !hasIcon ? "Icon is required" : null
2244
- }
2245
- };
2246
- }
2247
- case "fields":
2248
- {
2249
- const hasTitleField = form.fields && form.fields.some(field => field.id === "mandatory-title");
2250
- const hasImageField = form.fields && form.fields.some(field => field.id === "mandatory-feature-image");
2251
-
2252
- // Check each field for missing labels and create field-specific errors
2253
- const fieldErrors = {};
2254
- let allFieldsHaveLabels = true;
2255
- if (form.fields) {
2256
- form.fields.forEach(field => {
2257
- if ((field.type === "text" || field.type === "description" || field.type === "title" || field.type === "image" || field.type === "gallery" || field.type === "feature-image" || field.type === "file" || field.type === "cta") && field.values) {
2258
- if (!field.values.label || field.values.label.trim().length === 0) {
2259
- fieldErrors[field.id] = "Field label is required";
2260
- allFieldsHaveLabels = false;
2261
- }
2262
- }
2263
- });
2264
- }
2265
- return {
2266
- isValid: hasTitleField && hasImageField && allFieldsHaveLabels,
2267
- errors: _objectSpread$8({
2268
- missingTitle: !hasTitleField ? "Title field is required" : null,
2269
- missingImage: !hasImageField ? "Feature image field is required" : null
2270
- }, fieldErrors)
2271
- };
2272
- }
2273
- case "layout":
2274
- {
2275
- const hasLayoutType = form.layout && form.layout.type && form.layout.type.length > 0;
2276
- return {
2277
- isValid: hasLayoutType,
2278
- errors: {
2279
- layoutType: !hasLayoutType ? "Layout type is required" : null
2280
- }
2281
- };
2282
- }
2283
- default:
2284
- return {
2285
- isValid: true,
2286
- errors: {}
2287
- };
2288
- }
2289
- };
2290
- const setCurrentStepAndSave = function (step) {
2291
- let previousStep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
2346
+ /**
2347
+ * Action creator to set form display name and update menu
2348
+ * Updates both form state and external menu string
2349
+ * Title cases the display name before updating the strings store
2350
+ *
2351
+ * @param {string} displayName - New display name for form
2352
+ * @returns {Function} Thunk function for Redux
2353
+ *
2354
+ * @example
2355
+ * dispatch(setDisplayName('Contact Information'));
2356
+ */
2357
+ const setDisplayName = displayName => {
2292
2358
  return dispatch => {
2293
- dispatch(setCurrentStep(step, previousStep));
2359
+ // Update menu string when display name changes (will be title cased in updateFeatureBuilderString)
2360
+ dispatch(updateFeatureBuilderString(displayName));
2361
+
2362
+ // Dispatch the actual action
2363
+ dispatch({
2364
+ type: actionsTypes.SET_DISPLAY_NAME,
2365
+ payload: displayName
2366
+ });
2294
2367
  };
2295
2368
  };
2296
2369
 
2297
- var css$d = ".SidebarLayout_module_fullWidthContent__0d6658dd {\n\tmax-width: 100%;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tpadding: 2rem 2rem 3rem 2rem; /* Add extra bottom padding */\n}\n\n/* Full-width container that allows scrollbar at edge */\n.SidebarLayout_module_fullWidthContainer__0d6658dd {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tmin-height: 0; /* Allow content to determine height */\n\twidth: 100%; /* Take full width to ensure scrollbar is at edge */\n}\n\n/* Content container to keep content centered */\n.SidebarLayout_module_contentContainer__0d6658dd {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tmin-height: 0;\n\tmax-width: 960px;\n\tmargin: 0 auto;\n\tpadding: 64px 32px;\n\twidth: 100%;\n\tbox-sizing: border-box;\n}\n\n/* Legacy container class for backward compatibility */\n.SidebarLayout_module_container__0d6658dd{\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tmin-height: 0; /* Allow content to determine height */\n max-width: 960px;\n margin: 0 auto;\n padding: 64px 32px;\n}\n\n/* Responsive adjustments for content container */\n@media (max-width: 768px) {\n\t.SidebarLayout_module_contentContainer__0d6658dd {\n\t\tpadding: 1.5rem 1.5rem 2.5rem 1.5rem; /* Slightly reduced but still adequate */\n\t}\n\t.SidebarLayout_module_container__0d6658dd {\n\t\tpadding: 1.5rem 1.5rem 2.5rem 1.5rem; /* Legacy container support */\n\t}\n}\n\n@media (max-width: 480px) {\n\t.SidebarLayout_module_contentContainer__0d6658dd {\n\t\tpadding: 1rem 1rem 2rem 1rem; /* Maintain padding on small screens */\n\t}\n\t.SidebarLayout_module_container__0d6658dd {\n\t\tpadding: 1rem 1rem 2rem 1rem; /* Legacy container support */\n\t}\n}\n\n/* Enhanced sidebar navigation for progress indication */\n\n/* Enhanced progress section */\n.hub-sideBar-section {\n\tborder-bottom: 2px solid var(--colour-branding-main-fade, rgba(74, 87, 183, 0.15));\n\tpadding-bottom: 1rem;\n\tmargin-bottom: 1rem;\n}\n\n.hub-sideBar-section:last-child {\n\tborder-bottom: none;\n}\n";
2298
- var modules_d5b6badf = {"fullWidthContent":"SidebarLayout_module_fullWidthContent__0d6658dd","fullWidthContainer":"SidebarLayout_module_fullWidthContainer__0d6658dd","contentContainer":"SidebarLayout_module_contentContainer__0d6658dd","container":"SidebarLayout_module_container__0d6658dd"};
2299
- n(css$d,{});
2300
-
2301
2370
  /**
2302
- * Sidebar Layout component for feature builder wizard
2303
- * Provides navigation sidebar with step progression, completion tracking
2304
- * Manages step accessibility based on wizard mode and validation state
2371
+ * Action creator to set form icon and update menu
2372
+ * Updates both form state and external menu icon
2305
2373
  *
2306
- * @param {Object} props - Component props
2307
- * @param {React.ReactNode} props.children - Child components to render in main content area
2308
- * @param {Object} props.history - React Router history object for navigation
2309
- * @returns {React.ReactElement} Layout component with sidebar navigation
2374
+ * @param {string} icon - Icon identifier or FontAwesome icon class
2375
+ * @returns {Function} Thunk function for Redux
2310
2376
  *
2311
2377
  * @example
2312
- * <SidebarLayout history={historyObject}>
2313
- * <YourMainContent />
2314
- * </SidebarLayout>
2378
+ * dispatch(setIcon('fa-user'));
2315
2379
  */
2316
- const SideBarInner = props => {
2317
- const {
2318
- children,
2319
- history
2320
- } = props;
2321
- const dispatch = reactRedux.useDispatch();
2380
+ const setIcon = icon => {
2381
+ return dispatch => {
2382
+ // Update menu icon when icon changes
2383
+ dispatch(updateFeatureBuilderIcon(icon));
2322
2384
 
2323
- // Get wizard state
2324
- const mode = reactRedux.useSelector(selectWizardMode);
2325
- const isEditMode = reactRedux.useSelector(selectIsEditMode);
2326
- const isCreateMode = reactRedux.useSelector(selectIsCreateMode);
2327
- const currentStep = reactRedux.useSelector(selectCurrentStep);
2328
- const goTo = url => history.push(url);
2329
- const isSelected = url => {
2330
- return history.location.pathname === url;
2385
+ // Dispatch the actual action
2386
+ dispatch({
2387
+ type: actionsTypes.SET_ICON,
2388
+ payload: icon
2389
+ });
2331
2390
  };
2391
+ };
2332
2392
 
2333
- // Define step configuration with dynamic URL based on mode
2334
- const getStepUrl = stepKey => {
2335
- // Use routes from values.config to support different variants (-a, -b, -c, -d)
2336
- switch (stepKey) {
2337
- case "overview":
2338
- return values.routeFormOverviewStep;
2339
- case "fields":
2340
- return values.routeFormFieldsStep;
2341
- case "layout":
2342
- return values.routeFormLayoutStep;
2343
- default:
2344
- return "";
2393
+ /**
2394
+ * Action creator to add a new field to the form
2395
+ * Generates unique ID and supports custom field types
2396
+ *
2397
+ * @param {string} [fieldType="text"] - Type of field to add (text, title, description, image, gallery, file, cta, feature-image)
2398
+ * @returns {Object} Redux action object with field ID and type
2399
+ *
2400
+ * @example
2401
+ * dispatch(addField('text'));
2402
+ * dispatch(addField('image'));
2403
+ */
2404
+ const addField = function () {
2405
+ let fieldType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "text";
2406
+ // Generate a unique ID for the new field
2407
+ const fieldId = "custom-field-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
2408
+ return {
2409
+ type: actionsTypes.ADD_FIELD,
2410
+ payload: {
2411
+ id: fieldId,
2412
+ type: fieldType
2345
2413
  }
2346
2414
  };
2347
- const steps = [{
2348
- key: "overview",
2349
- text: "Feature Overview",
2350
- icon: "info-circle",
2351
- url: getStepUrl("overview")
2352
- }, {
2353
- key: "fields",
2354
- text: "Configure Fields",
2355
- icon: "edit",
2356
- url: getStepUrl("fields")
2357
- }, {
2358
- key: "layout",
2359
- text: "Choose Layout",
2360
- icon: "columns",
2361
- url: getStepUrl("layout")
2362
- }];
2363
-
2364
- // Build sidebar items based on mode
2365
- const buildSidebarItems = () => {
2366
- const isWizardMode = mode === "create" || mode === "edit";
2367
- return steps.map((step, index) => {
2368
- const isCompleted = selectIsStepComplete(step.key);
2369
- const isAccessible = selectIsStepAccessible(step.key);
2370
-
2371
- // Add step number to text for better clarity
2372
- const stepText = "".concat(index + 1, ". ").concat(step.text);
2373
- const itemProps = {
2374
- type: "navItem",
2375
- text: stepText,
2376
- icon: step.icon,
2377
- selected: isSelected(step.url),
2378
- onclick: isWizardMode ? null : isAccessible ? () => {
2379
- goTo(step.url);
2380
- dispatch(goToStep(step.key));
2381
- } : null,
2382
- isFontAwesome: true,
2383
- // Enhanced completion indicator
2384
- completed: isCompleted,
2385
- // Disable all navigation in wizard mode
2386
- disabled: isWizardMode || mode === "create" && !isAccessible
2387
- };
2388
- return itemProps;
2389
- });
2390
- };
2391
-
2392
- // Determine sidebar title - always use "Build Your Feature" now
2393
- const getSidebarTitle = () => {
2394
- return "Build Your Feature";
2415
+ };
2416
+ const deleteField = id => {
2417
+ return {
2418
+ type: actionsTypes.DELETE_FIELD,
2419
+ payload: id
2395
2420
  };
2396
-
2397
- // Simple help text
2398
- const getHelpText = () => {
2399
- return "Get help with feature builder";
2421
+ };
2422
+ const updateFieldById = (id, updatedField) => {
2423
+ return {
2424
+ type: actionsTypes.UPDATE_FIELD,
2425
+ payload: {
2426
+ id,
2427
+ updatedField
2428
+ }
2400
2429
  };
2430
+ };
2401
2431
 
2402
- // Build sidebar sections - simplified without progress section
2403
- const sidebarSections = [{
2404
- title: getSidebarTitle(),
2405
- items: buildSidebarItems()
2406
- }];
2407
-
2408
- // Add effect to manually attach click handlers since HubSidebar might not use onclick properly
2409
- React.useEffect(() => {
2410
- const isWizardMode = mode === "create" || mode === "edit";
2411
- const attachClickHandlers = () => {
2412
- const stepsWithUrls = [{
2413
- key: "overview",
2414
- url: getStepUrl("overview")
2415
- }, {
2416
- key: "fields",
2417
- url: getStepUrl("fields")
2418
- }, {
2419
- key: "layout",
2420
- url: getStepUrl("layout")
2421
- }];
2422
- stepsWithUrls.forEach((step, index) => {
2423
- const navItem = Array.from(document.querySelectorAll(".hub-wrapperContainer .sideNav-item")).find(item => item.textContent && item.textContent.includes("".concat(index + 1, ".")));
2424
- if (navItem) {
2425
- // Remove any existing click listeners
2426
- navItem.onclick = null;
2427
-
2428
- // Check if this step is accessible
2429
- const isAccessible = selectIsStepAccessible(step.key)({
2430
- [values.reducerKey]: {
2431
- wizard: {
2432
- mode: mode,
2433
- navigation: {
2434
- currentStep: currentStep
2435
- }
2436
- }
2437
- }
2438
- });
2439
-
2440
- // Check if this is the current step (selected)
2441
- const isCurrentStep = isSelected(step.url);
2442
-
2443
- // In wizard mode, don't attach any click handlers
2444
- // Only attach click handler if not in wizard mode AND accessible
2445
- if (!isWizardMode && isAccessible) {
2446
- navItem.onclick = event => {
2447
- event.preventDefault();
2448
- event.stopPropagation();
2449
- history.push(step.url);
2450
- dispatch(goToStep(step.key));
2451
- };
2452
- }
2453
-
2454
- // Make sure it's styled appropriately
2455
- // In wizard mode: block clicks, but keep current step visible
2456
- navItem.style.pointerEvents = isWizardMode ? "none" : "auto";
2457
- if (isWizardMode) {
2458
- // Current step: full opacity, not-allowed cursor
2459
- // Other steps: reduced opacity
2460
- navItem.style.opacity = isCurrentStep ? "1" : "0.4";
2461
- navItem.style.cursor = "not-allowed";
2462
- } else {
2463
- // Not in wizard mode: normal styling based on accessibility
2464
- navItem.style.cursor = isAccessible ? "pointer" : "not-allowed";
2465
- navItem.style.opacity = isAccessible ? "1" : "0.5";
2466
- }
2467
- }
2468
- });
2469
- };
2470
-
2471
- // Initial attachment
2472
- attachClickHandlers();
2473
-
2474
- // Re-attach after a short delay to ensure HubSidebar has rendered
2475
- const timeoutId = setTimeout(attachClickHandlers, 100);
2476
-
2477
- // Also try to re-attach when DOM changes (observe for mutations)
2478
- const observer = new MutationObserver(() => {
2479
- setTimeout(attachClickHandlers, 50);
2480
- });
2481
-
2482
- // Start observing the document body for changes
2483
- observer.observe(document.body, {
2484
- childList: true,
2485
- subtree: true
2486
- });
2487
- return () => {
2488
- clearTimeout(timeoutId);
2489
- observer.disconnect();
2490
- };
2491
- }, [history, dispatch, isEditMode, isCreateMode, currentStep]);
2492
- return /*#__PURE__*/React__default["default"].createElement("div", {
2493
- className: "hub-wrapperContainer"
2494
- }, /*#__PURE__*/React__default["default"].createElement(HubSidebar, {
2495
- sections: sidebarSections,
2496
- helpGuide: {
2497
- text: getHelpText(),
2498
- url: "https://www.plusscommunities.com/user-guide"
2499
- }
2500
- }), /*#__PURE__*/React__default["default"].createElement("div", {
2501
- className: "hub-contentWrapper"
2502
- }, /*#__PURE__*/React__default["default"].createElement("div", {
2503
- className: modules_d5b6badf.fullWidthContainer
2504
- }, /*#__PURE__*/React__default["default"].createElement("div", {
2505
- className: modules_d5b6badf.contentContainer
2506
- }, children))));
2432
+ /**
2433
+ * Action creator to set a description field as the summary field
2434
+ * Ensures only one description field can be marked as summary by
2435
+ * automatically unsetting all other description fields when a new one is selected
2436
+ *
2437
+ * @param {string} fieldId - ID of the description field to set as summary
2438
+ * @returns {Object} Redux action object for summary field selection
2439
+ *
2440
+ * @example
2441
+ * dispatch(setSummaryField('field-description-123'));
2442
+ */
2443
+ const setSummaryField = fieldId => {
2444
+ return {
2445
+ type: actionsTypes.SET_SUMMARY_FIELD,
2446
+ payload: fieldId
2447
+ };
2507
2448
  };
2508
- const SidebarLayout = reactRouter.withRouter(SideBarInner);
2509
-
2510
- var css$c = ".Form_module_content__d62303b4 {\n\tflex: 1 1 auto;\n\tdisplay: flex;\n\tflex-flow: column nowrap;\n\tpadding: 2rem 0 3rem 0; /* Add proper top/bottom padding */\n\tmin-height: 100%; /* Ensure full height for proper spacing */\n}\n\n/* New page wrapper for centered container approach */\n.Form_module_pageWrapper__d62303b4 {\n\tpadding: 2rem 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\tjustify-content: flex-start;\n}\n\n@media (min-width: 768px) {\n\t.Form_module_pageWrapper__d62303b4 {\n\t\tpadding: 3rem 0;\n\t}\n}\n\n/* Form container styling when using CenteredContainer */\n.Form_module_formContainer__d62303b4 {\n\tbackground-color: var(--bg-white);\n}\n\n/* Section styling */\n.Form_module_section__d62303b4 {\n\tmargin-bottom: 2rem;\n\t\tpadding: 0 0 2em;\n}\n\n.Form_module_section_NoBorder__d62303b4 {\n\t\tborder-bottom: none;\n}\n\n.Form_module_subtitle__d62303b4 {\n\tcolor: var(--text-bluegrey, #6c7a90);\n}\n\n.Form_module_sectionHeader__d62303b4 {\n\t\tdisplay: flex;\n\t\tjustify-content: space-between;\n}\n\n/* Add Field Button styling */\n.Form_module_addFieldButton__d62303b4 {\n\tbackground: var(--colour-branding-action, #5c90df);\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 1.5rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tcursor: pointer;\n\tmargin-bottom: 2rem;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_addFieldButton__d62303b4:hover {\n\tbackground: var(--colour-branding-action-hover, #364196);\n\ttransform: translateY(-1px);\n\tbox-shadow: 0 2px 4px rgba(92, 144, 223, 0.3);\n}\n\n.Form_module_addFieldButton__d62303b4:focus {\n\toutline: 2px solid var(--colour-branding-action, #5c90df);\n\toutline-offset: 2px;\n}\n\n.Form_module_addFieldButton__d62303b4:active {\n\ttransform: translateY(0);\n}\n\n/* Refresh button styling */\n.Form_module_refreshButton__d62303b4 {\n\tmargin-left: 10px;\n\tpadding: 2px 8px;\n\tfont-size: 12px;\n\tbackground: var(--colour-dusk, #536280);\n\tcolor: white;\n\tborder: none;\n\tborder-radius: 4px;\n\tcursor: pointer;\n\ttransition: background-color 0.2s ease;\n}\n\n.Form_module_refreshButton__d62303b4:hover {\n\tbackground: var(--colour-dusk-hover, #485968);\n}\n\n/* Error message container */\n.Form_module_errorMessageContainer__d62303b4 {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.5rem;\n}\n\n/* Add Field Container - matches field structure */\n.Form_module_addFieldContainer__d62303b4 {\n\tdisplay: flex;\n\tmargin-top: 32px;\n}\n\n.Form_module_fieldNumberContainer__d62303b4 {\n\tdisplay: flex;\n\twidth: 40px;\n}\n\n/* Add Field Section */\n.Form_module_addFieldSection__d62303b4 {\n\tdisplay: flex;\n\tgap: 1rem;\n\talign-items: center;\n\tjustify-content: flex-start; /* Align to start to match field content */\n\tmargin-top: 0; /* Remove top margin since it's in the container */\n}\n\n/* Desktop: horizontal layout for field selector and button */\n@media (min-width: 769px) {\n\t.Form_module_addFieldSection__d62303b4 {\n\t\tflex-direction: row;\n\t\talign-items: baseline;\n\t\tgap: 2rem;\n\t\talign-items: flex-start;\n\t\tjustify-content: flex-start; /* Align to start to match field content */\n\t}\n}\n\n/* Help Section for Popup */\n.Form_module_helpSection__d62303b4 {\n\tbackground-color: var(--colour-branding-action-superlight);\n\tborder: 1px solid var(--colour-branding-inactive);\n\tborder-radius: 8px;\n\tpadding: 1.5rem;\n\tmargin-bottom: 1.5rem;\n}\n\n.Form_module_helpTitle__d62303b4 {\n\tcolor: var(--text-dark);\n\tfont-weight: 600;\n\tmargin-bottom: 0.75rem;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.5rem;\n\tfont-size: 1.25rem;\n}\n\n.Form_module_helpText__d62303b4 {\n\tcolor: var(--colour-branding-action);\n\tline-height: 1.6;\n\tfont-size: 1.25rem;\n}\n\n/* Field Type Cards for Popup */\n.Form_module_fieldTypeCards__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 1rem; /* Spacing between vertical cards */\n\tpadding: 1rem 0;\n}\n\n/* Responsive layout: maintain vertical layout on all screen sizes */\n@media (min-width: 768px) {\n\t.Form_module_fieldTypeCards__d62303b4 {\n\t\tgap: 1.5rem; /* Slightly larger gap on desktop */\n\t}\n}\n\n.Form_module_fieldTypeCard__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tpadding: 1.75rem 1.25rem; /* More vertical padding */\n\tborder: 1px solid var(--border-line-grey);\n\tborder-radius: 8px;\n\tbackground-color: var(--bg-white);\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n\tmin-height: 120px; /* Adjust height for horizontal layout */\n\tgap: 1rem; /* Space between icon and content */\n}\n\n.Form_module_fieldTypeCard__d62303b4:hover {\n\tborder-color: var(--text-light);\n\tbackground-color: var(--bg-bluegrey);\n\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n}\n\n.Form_module_fieldTypeCard__d62303b4:focus {\n\toutline: 2px solid var(--text-light);\n\toutline-offset: 2px;\n}\n\n.Form_module_fieldTypeCard__d62303b4:active {\n\ttransform: scale(0.98);\n\ttransition: transform 0.1s ease;\n}\n\n.Form_module_fieldTypeCardIcon__d62303b4 {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 48px;\n\theight: 48px;\n\tmargin-bottom: 0; /* Remove bottom margin for horizontal layout */\n\tfont-size: 20px;\n\tflex-shrink: 0;\n\tborder: 1px solid var(--border-line-grey); /* Subtle border */\n\tborder-radius: 8px;\n\tbackground-color: var(--bg-bluegrey);\n\tpadding: 8px;\n}\n\n\n.Form_module_fieldTypeCardContent__d62303b4 {\n\tflex: 1;\n\twidth: 100%;\n\tmin-width: 0; /* Prevent content from overflowing */\n}\n\n.Form_module_fieldTypeCardTitle__d62303b4 {\n\tmargin: 0 0 0.25rem 0;\n\tfont-weight: 600;\n\tfont-size: 1.4rem; /* Increased for better readability */\n}\n\n.Form_module_fieldTypeCardDescription__d62303b4 {\n\tmargin: 0 0 0.75rem 0;\n\tfont-size: 1.6rem; /* Increased for better readability */\n\tline-height: 1.5; /* Improved line height for better readability */\n}\n\n.Form_module_fieldTypeCardUseCase__d62303b4 {\n\tmargin: 0;\n\tfont-size: 1.4rem;\n\tfont-style: italic;\n\tcolor: var(--text-light);\n\tpadding-top: 0.5rem;\n\tborder-top: 1px solid var(--border-line-grey);\n}\n\n/* Field selector and button container - horizontal layout */\n.Form_module_addFieldSection__d62303b4> div:first-child {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 0.5rem;\n\tflex: 1;\n}\n\n/* Container for add field button alignment */\n.Form_module_addFieldButtonContainer__d62303b4 {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n}\n\n/* Empty State */\n.Form_module_emptyState__d62303b4 {\n\tpadding: 2rem;\n\ttext-align: center;\n\tbackground-color: var(--bg-bluegrey, #f4f7f9);\n\tborder-radius: 8px;\n\tborder: 1px dashed var(--border-line-grey, #dbddf1);\n\tmargin-bottom: 1rem;\n}\n\n.Form_module_emptyStateText__d62303b4 {\n\tcolor: var(--text-bluegrey, #6c7a90);\n\tfont-style: italic;\n}\n\n.Form_module_fieldTypeSelector__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmax-width: 500px; /* Increased from 300px to accommodate longer text */\n\twidth: 100%;\n}\n\n@media (max-width: 768px) {\n\t.Form_module_addFieldSection__d62303b4 {\n\t\talign-items: stretch;\n\t}\n\t\n\t.Form_module_fieldTypeSelector__d62303b4 {\n\t\tmax-width: none;\n\t}\n}\n\n.Form_module_grid__four__d62303b4 {\n max-width: 1200px;\n\tdisplay: grid;\n\tgrid-template-columns: repeat(2, minmax(250px, 1fr));\n margin: 2rem 0;\n\tgap: 2rem;\n\tjustify-items: center;\n}\n\n@media (max-width: 768px) {\n\t.Form_module_grid__four__d62303b4 {\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 2rem;\n\t}\n}\n\n/* Navigation styles */\n.Form_module_navigation__d62303b4 {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\tgap: 1rem;\n\tmargin-top: 3rem; /* Increase from 2rem */\n\tpadding-top: 2rem;\n\tpadding-bottom: 2rem; /* Add bottom padding */\n\tborder-top: 1px solid #e9ecef;\n}\n\n/* Single button alignment - align to right for overview step save button */\n.Form_module_navigation__d62303b4> :only-child {\n\tmargin-left: auto;\n\tmargin-right: 0;\n}\n\n/* Two button alignment - one left, one right */\n.Form_module_navigation__d62303b4> :first-child:not(:only-child) {\n\tmargin-right: auto;\n}\n\n.Form_module_navigation__d62303b4> :last-child:not(:only-child) {\n\tmargin-left: auto;\n}\n\n/* Special case for overview step - align save button to right */\n.Form_module_overviewStep__d62303b4 .Form_module_navigation__d62303b4> :only-child {\n\tmargin-left: auto;\n\tmargin-right: 0;\n}\n\n.Form_module_previousButton__d62303b4 {\n\tbackground: #6c757d;\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 1.5rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_previousButton__d62303b4:hover {\n\tbackground: #5a6268;\n}\n\n.Form_module_saveButton__d62303b4 {\n\tbackground: var(--colour-purple, #6e79c5);\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 2rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_saveButton__d62303b4:hover:not(:disabled) {\n\tbackground: var(--colour-purple-hover, #5a66b3);\n\ttransform: translateY(-1px);\n\tbox-shadow: 0 2px 4px rgba(110, 121, 197, 0.3);\n}\n\n.Form_module_saveButton__d62303b4:focus {\n\toutline: 2px solid var(--colour-purple, #6e79c5);\n\toutline-offset: 2px;\n}\n\n.Form_module_saveButton__d62303b4:disabled {\n\tbackground: #6c757d;\n\tcursor: not-allowed;\n\topacity: 0.65;\n\ttransform: none;\n\tbox-shadow: none;\n}\n\n.Form_module_nextButton__d62303b4 {\n\tbackground: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 2rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_nextButton__d62303b4:hover:not(:disabled) {\n\ttransform: translateY(-2px);\n\tbox-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);\n}\n\n.Form_module_nextButton__d62303b4:disabled {\n\tbackground: #6c757d;\n\tcursor: not-allowed;\n\topacity: 0.65;\n\ttransform: none;\n\tbox-shadow: none;\n}\n\n\n\n.Form_module_errorMessage__d62303b4 {\n\tcolor: var(--colour-red);\n\tmargin: 0.25rem 0;\n\tpadding: 0.25rem 0;\n\tfont-size: 0.875rem;\n\tline-height: 1.4;\n}\n\n/* Layout option styles */\n.Form_module_layoutOption__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\ttext-align: center;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n\tbackground-color: transparent;\n\topacity: 0.6;\n}\n\n.Form_module_layoutOption__d62303b4:hover {\n\topacity: 1;\n}\n\n.Form_module_layoutOptionImage__d62303b4 {\n\twidth: 250px;\n\theight: 250px;\n\tborder-radius: 12px;\n\toverflow: hidden;\n\tmargin-bottom: 1rem;\n\tborder: 2px solid var(--border-line-grey, #dbddf1);\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_layoutOption__d62303b4.Form_module_selected__d62303b4 .Form_module_layoutOptionImage__d62303b4 {\n\tborder-color: var(--colour-purple, #6e79c5);\n\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n.Form_module_layoutOption__d62303b4.Form_module_selected__d62303b4 {\n\topacity: 1;\n}\n\n.Form_module_layoutOptionImg__d62303b4 {\n\twidth: 100%;\n\theight: 100%;\n\tobject-fit: cover;\n}\n\n.Form_module_layoutOptionContent__d62303b4 {\n\tmax-width: 250px;\n\tmargin-bottom: 0.5rem;\n}\n\n.Form_module_layoutOptionTitle__d62303b4 {\n\tfont-size: 1.6rem;\n\tfont-weight: 600;\n\tmargin: 0 0 0.5rem 0;\n\tline-height: 1.3;\n\tcolor: #333;\n}\n\n.Form_module_layoutOptionDescription__d62303b4 {\n\tfont-size: 1.2rem;\n\tmargin: 0;\n\tline-height: 1.3;\n\tcolor: #6c757d;\n}\n\n.Form_module_layoutOption__d62303b4.Form_module_hasError__d62303b4 .Form_module_layoutOptionImage__d62303b4 {\n\tborder-color: var(--colour-red, #dc3545);\n}\n\n/* Field error styles */\n.Form_module_fieldError__d62303b4 {\n\tcolor: #dc3545;\n\tfont-size: 1.6rem;\n\tfont-weight: 500;\n\tmargin-top: 0.5rem;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.25rem;\n}\n\n.Form_module_errorIcon__d62303b4 {\n\tfont-size: 1rem;\n}\n\n/* Field wrapper styles are now handled in Fields.module.css */\n\n/* Field type indicator styles are now handled in Fields.module.css */\n\n@keyframes Form_module_errorShake__d62303b4 {\n\t0%, 100% { transform: translateX(0); }\n\t25% { transform: translateX(-3px); }\n\t75% { transform: translateX(3px); }\n}\n\n@keyframes Form_module_errorPulse__d62303b4 {\n\t0% { \n\t\tbox-shadow: 0 1px 3px rgba(192, 39, 67, 0.1), 0 1px 2px rgba(192, 39, 67, 0.08);\n\t}\n\t50% { \n\t\tbox-shadow: 0 2px 6px rgba(192, 39, 67, 0.2), 0 1px 3px rgba(192, 39, 67, 0.15);\n\t}\n\t100% { \n\t\tbox-shadow: 0 1px 3px rgba(192, 39, 67, 0.1), 0 1px 2px rgba(192, 39, 67, 0.08);\n\t}\n}\n\n.Form_module_successMessage__d62303b4 {\n\tbackground: var(--colour-branding-secondary-light);\n\tborder: 1px solid var(--colour-branding-secondary);\n\tborder-radius: 8px;\n\tpadding: 1rem;\n\tmargin-top: 1rem;\n\tcolor: var(--colour-green);\n\tfont-weight: 500;\n}\n\n/* Mode-aware styling */\n.Form_module_createMode__d62303b4 {\n\tcolor: var(--colour-purple, #6e79c5);\n}\n\n.Form_module_editMode__d62303b4 {\n\tcolor: var(--colour-branding-dark, #364196);\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n\t.Form_module_content__d62303b4 {\n\t\tpadding: 1.5rem 0 2.5rem 0; /* Maintain proper padding on mobile */\n\t}\n\t\n\t.Form_module_section__d62303b4 {\n\t\tmargin-bottom: 1.5rem;\n\t}\n\t\n\t/* Mobile: vertical layout for field selector and button */\n\t.Form_module_addFieldSection__d62303b4 {\n\t\tflex-direction: column;\n\t\talign-items: stretch; /* Stretch to fill available space */\n\t}\n\t\n\t/* Button should not be full width on mobile */\n\t.Form_module_addFieldSection__d62303b4 Button {\n\t\twidth: auto; /* Let button use its natural width */\n\t\tpadding: 1rem 1.5rem; /* Keep proper padding but not full width */\n\t}\n\t\n\t.Form_module_addFieldButtonContainer__d62303b4 {\n\t\talign-items: stretch;\n\t\tjustify-content: stretch;\n\t\tmin-height: auto;\n\t}\n\t\n\t.Form_module_navigation__d62303b4 {\n\t\tflex-direction: column;\n\t\tgap: 0.75rem;\n\t\tjustify-content: flex-start; /* Align to start on mobile */\n\t\tmargin-top: 2rem; /* Slightly reduce on mobile */\n\t\tpadding-top: 1.5rem;\n\t\tpadding-bottom: 1.5rem; /* Maintain bottom padding */\n\t}\n\t\n\t/* Mobile button alignment - single button aligns right, two buttons stack */\n\t.Form_module_navigation__d62303b4> :only-child {\n\t\tmargin-left: auto;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_navigation__d62303b4> :first-child:not(:only-child),\n\t.Form_module_navigation__d62303b4> :last-child:not(:only-child) {\n\t\tmargin-left: 0;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_previousButton__d62303b4,\n\t.Form_module_nextButton__d62303b4,\n\t.Form_module_saveButton__d62303b4 {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t}\n}\n\n@media (max-width: 480px) {\n\t.Form_module_content__d62303b4 {\n\t\tpadding: 1rem 0 2rem 0; /* Still maintain padding on small screens */\n\t}\n\t\n\t.Form_module_section__d62303b4 {\n\t\tmargin-bottom: 1rem;\n\t}\n\t\n\t.Form_module_navigation__d62303b4 {\n\t\tmargin-top: 1.5rem; /* Further reduce on very small screens */\n\t\tpadding-top: 1rem;\n\t\tpadding-bottom: 1.5rem;\n\t\tjustify-content: flex-start; /* Align to start on small screens */\n\t}\n\t\n\t/* Small screen button alignment */\n\t.Form_module_navigation__d62303b4> :only-child {\n\t\tmargin-left: auto;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_navigation__d62303b4> :first-child:not(:only-child),\n\t.Form_module_navigation__d62303b4> :last-child:not(:only-child) {\n\t\tmargin-left: 0;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_errorMessageContainer__d62303b4 {\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tgap: 0.75rem;\n\t}\n\t\n\t.Form_module_refreshButton__d62303b4 {\n\t\talign-self: flex-end;\n\t}\n}\n\n/* Full width content when sidebar is hidden */\n.hub-contentWrapper.fullWidthContent {\n\tmax-width: 1000px;\n\tmargin: 0 auto;\n\tpadding: 2rem;\n}\n\n.Form_module_hubContentWrapper_Col__d62303b4 {\n flex-flow: column;\n}\n\n/* Validation error message - displayed at top of form */\n.Form_module_validationErrorMessage__d62303b4 {\n\tbackground-color: var(--colour-branding-secondary-light);\n\tborder: 1px solid var(--colour-branding-secondary);\n\tborder-radius: 6px;\n\tcolor: var(--colour-red);\n\tpadding: 12px 16px;\n\tfont-weight: 500;\n\tfont-size: 14px;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\t\tmargin: 24px 32px;\n}\n\n.Form_module_validationErrorMessage__d62303b4::before {\n\tcontent: \"⚠\";\n\tfont-size: 16px;\n\tcolor: var(--colour-red);\n}\n\n/* Loading overlay for forms - deprecated, use SkeletonLoader instead */\n/*\n.loadingOverlay {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tbackground: rgba(255, 255, 255, 0.95);\n\tbackdrop-filter: blur(2px);\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tz-index: 10;\n\tborder-radius: 8px;\n\tanimation: fadeIn 0.2s ease-in-out;\n}\n\n@keyframes fadeIn {\n\tfrom { opacity: 0; }\n\tto { opacity: 1; }\n}\n*/\n\n/* Form header with buttons */\n.Form_module_formHeader__d62303b4 {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: flex-start;\n\tmargin-bottom: 16px;\n}\n\n/* Loading container for fields */\n.Form_module_fieldsLoadingContainer__d62303b4 {\n\ttext-align: center;\n\tpadding: 60px 20px;\n}\n\n/* Help note styling */\n.Form_module_helpNote__d62303b4 {\n\tfont-size: 13px;\n\tcolor: #6c757d;\n}\n\n/* Loading container for overview */\n.Form_module_overviewLoadingContainer__d62303b4 {\n\ttext-align: center;\n\tpadding: 60px 20px;\n}\n\n/* Form layout header */\n.Form_module_formLayoutHeader__d62303b4 {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: flex-start;\n\tmargin-bottom: 16px;\n}\n\n/* Section margins */\n.Form_module_gridIconSection__d62303b4 {\n\tmargin-bottom: 3rem;\n}\n\n.Form_module_layoutSection__d62303b4 {\n\tmargin-bottom: 2rem;\n}\n\n/* Grid icon loading state */\n.Form_module_gridIconLoading__d62303b4 {\n\tgrid-column: 1 / -1;\n}\n\n/* Hide upload button in grid icon section */\n.Form_module_gridIconSection__d62303b4 .iconLoader__buttonOverlay button:first-child {\n\tdisplay: none !important;\n}\n";
2511
- var modules_cd65a764 = {"content":"Form_module_content__d62303b4","pageWrapper":"Form_module_pageWrapper__d62303b4","formContainer":"Form_module_formContainer__d62303b4","section":"Form_module_section__d62303b4","section--no-border":"Form_module_section_NoBorder__d62303b4","subtitle":"Form_module_subtitle__d62303b4","sectionHeader":"Form_module_sectionHeader__d62303b4","addFieldButton":"Form_module_addFieldButton__d62303b4","refreshButton":"Form_module_refreshButton__d62303b4","errorMessageContainer":"Form_module_errorMessageContainer__d62303b4","addFieldContainer":"Form_module_addFieldContainer__d62303b4","fieldNumberContainer":"Form_module_fieldNumberContainer__d62303b4","addFieldSection":"Form_module_addFieldSection__d62303b4","helpSection":"Form_module_helpSection__d62303b4","helpTitle":"Form_module_helpTitle__d62303b4","helpText":"Form_module_helpText__d62303b4","fieldTypeCards":"Form_module_fieldTypeCards__d62303b4","fieldTypeCard":"Form_module_fieldTypeCard__d62303b4","fieldTypeCardIcon":"Form_module_fieldTypeCardIcon__d62303b4","fieldTypeCardContent":"Form_module_fieldTypeCardContent__d62303b4","fieldTypeCardTitle":"Form_module_fieldTypeCardTitle__d62303b4","fieldTypeCardDescription":"Form_module_fieldTypeCardDescription__d62303b4","fieldTypeCardUseCase":"Form_module_fieldTypeCardUseCase__d62303b4","addFieldButtonContainer":"Form_module_addFieldButtonContainer__d62303b4","emptyState":"Form_module_emptyState__d62303b4","emptyStateText":"Form_module_emptyStateText__d62303b4","fieldTypeSelector":"Form_module_fieldTypeSelector__d62303b4","grid__four":"Form_module_grid__four__d62303b4","navigation":"Form_module_navigation__d62303b4","overviewStep":"Form_module_overviewStep__d62303b4","previousButton":"Form_module_previousButton__d62303b4","saveButton":"Form_module_saveButton__d62303b4","nextButton":"Form_module_nextButton__d62303b4","errorMessage":"Form_module_errorMessage__d62303b4","layoutOption":"Form_module_layoutOption__d62303b4","layoutOptionImage":"Form_module_layoutOptionImage__d62303b4","selected":"Form_module_selected__d62303b4","layoutOptionImg":"Form_module_layoutOptionImg__d62303b4","layoutOptionContent":"Form_module_layoutOptionContent__d62303b4","layoutOptionTitle":"Form_module_layoutOptionTitle__d62303b4","layoutOptionDescription":"Form_module_layoutOptionDescription__d62303b4","hasError":"Form_module_hasError__d62303b4","fieldError":"Form_module_fieldError__d62303b4","errorIcon":"Form_module_errorIcon__d62303b4","successMessage":"Form_module_successMessage__d62303b4","createMode":"Form_module_createMode__d62303b4","editMode":"Form_module_editMode__d62303b4","hub-contentWrapper--col":"Form_module_hubContentWrapper_Col__d62303b4","validationErrorMessage":"Form_module_validationErrorMessage__d62303b4","formHeader":"Form_module_formHeader__d62303b4","fieldsLoadingContainer":"Form_module_fieldsLoadingContainer__d62303b4","helpNote":"Form_module_helpNote__d62303b4","overviewLoadingContainer":"Form_module_overviewLoadingContainer__d62303b4","formLayoutHeader":"Form_module_formLayoutHeader__d62303b4","gridIconSection":"Form_module_gridIconSection__d62303b4","layoutSection":"Form_module_layoutSection__d62303b4","gridIconLoading":"Form_module_gridIconLoading__d62303b4","errorShake":"Form_module_errorShake__d62303b4","errorPulse":"Form_module_errorPulse__d62303b4"};
2512
- n(css$c,{});
2513
-
2514
- function ownKeys$7(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2515
- function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$7(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$7(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2516
- const {
2517
- Helper: Helper$1,
2518
- Session: Session$1
2519
- } = PlussCore__namespace;
2520
- const {
2521
- getUrl: getUrl$1
2522
- } = Helper$1;
2523
- const {
2524
- authedFunction: authedFunction$1
2525
- } = Session$1;
2526
- const featureDefinitionActions = {
2527
- /**
2528
- * Get the single feature definition by ID
2529
- * Path: {id}
2530
- */
2531
- getSingle: async (id, site) => {
2532
- const query = {
2533
- id,
2534
- site
2535
- };
2536
- return authedFunction$1({
2537
- method: "GET",
2538
- url: getUrl$1("feature-builder", "definition/get/single", query)
2539
- });
2540
- },
2541
- /**
2542
- * Creates a new feature definition with the provided configuration
2543
- *
2544
- * @param {string} id - The unique identifier for the new feature definition
2545
- * @param {string} site - The site ID where the feature definition will be created
2546
- * @param {FeatureDefinition} featureDefinition - The feature definition data to create
2547
- * @returns {Promise<ApiResponse>} Promise resolving to API response with created feature definition
2548
- * @throws {Error} When creation fails due to validation or API errors
2549
- *
2550
- */
2551
- create: async (id, site, featureDefinition) => {
2552
- return authedFunction$1({
2553
- method: "POST",
2554
- url: getUrl$1("feature-builder", "definition/update/create"),
2555
- data: {
2556
- id,
2557
- site,
2558
- featureDefinition
2559
- }
2560
- });
2561
- },
2562
- /**
2563
- * Updates an existing feature definition with new configuration
2564
- *
2565
- * @param {FeatureDefinition} featureDefinitionData - The updated feature definition data
2566
- * @param {string} featureDefinitionData.id - The unique identifier of the feature definition to update
2567
- * @param {string} [featureDefinitionData.displayName] - Updated display name
2568
- * @param {Field[]} [featureDefinitionData.fields] - Updated field definitions
2569
- * @param {Object} [featureDefinitionData.layout] - Updated layout configuration
2570
- * @param {string} site - The site ID where the feature definition exists
2571
- * @returns {Promise<ApiResponse>} Promise resolving to API response with updated feature definition
2572
- * @throws {Error} When update fails due to validation or API errors
2573
- *
2574
- * @example
2575
- * try {
2576
- * const response = await featureDefinitionActions.edit(
2577
- * {
2578
- * id: 'feature-123',
2579
- * displayName: 'Updated Form',
2580
- * fields: [...]
2581
- * },
2582
- * 'site-123'
2583
- * );
2584
- */
2585
- edit: async (featureDefinitionData, site) => {
2586
- // Ensure site is included in the request body
2587
- const dataWithSite = _objectSpread$7({
2588
- site: site
2589
- }, featureDefinitionData);
2590
- return authedFunction$1({
2591
- method: "POST",
2592
- url: getUrl$1("feature-builder", "definition/update/edit"),
2593
- data: dataWithSite
2594
- });
2595
- },
2596
- /**
2597
- * Soft deletes a feature definition (marks as deleted but doesn't permanently remove)
2598
- *
2599
- * @param {string} id - The unique identifier of the feature definition to delete
2600
- * @param {string} site - The site ID where the feature definition exists
2601
- * @returns {Promise<ApiResponse>} Promise resolving to API response confirming deletion
2602
- * @throws {Error} When deletion fails or feature definition is not found
2603
- *
2604
- */
2605
- delete: async (id, site) => {
2606
- return authedFunction$1({
2607
- method: "POST",
2608
- url: getUrl$1("feature-builder", "definition/update/delete"),
2609
- data: {
2610
- id,
2611
- site
2612
- }
2613
- });
2614
- }
2449
+ const setLayoutType = layoutType => {
2450
+ return {
2451
+ type: actionsTypes.SET_LAYOUT_TYPE,
2452
+ payload: layoutType
2453
+ };
2615
2454
  };
2616
-
2617
- function ownKeys$6(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2618
- function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$6(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$6(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2619
-
2620
- // IMPORTANT: Using local UPDATE_STRINGS action type to make extension self-contained
2621
- // The main app's StringsReducer will handle this action type the same way
2622
- const UPDATE_STRINGS = "UPDATE_STRINGS";
2623
- const updateFeatureBuilderString = title => (dispatch, getState) => {
2624
- var _getState$strings;
2625
- const currentStrings = ((_getState$strings = getState().strings) === null || _getState$strings === void 0 ? void 0 : _getState$strings.config) || {};
2626
- const titleCased = toTitleCase(title) || values.textMenuTitle;
2627
- const updatedStrings = _objectSpread$6(_objectSpread$6({}, currentStrings), {}, {
2628
- sideNav: _objectSpread$6(_objectSpread$6({}, currentStrings.sideNav), {}, {
2629
- [values.featureKey]: titleCased,
2630
- [values.menuKey]: "Manage ".concat(titleCased)
2631
- }),
2632
- permission: _objectSpread$6(_objectSpread$6({}, currentStrings.permission), {}, {
2633
- [values.permissionFeatureBuilderDefinition]: "Manage custom feature ".concat(titleCased),
2634
- [values.permissionFeatureBuilderContent]: "Manage ".concat(titleCased, " content")
2635
- })
2636
- });
2637
- dispatch({
2638
- type: UPDATE_STRINGS,
2639
- payload: updatedStrings
2640
- });
2455
+ const submitFormRequest = () => {
2456
+ return {
2457
+ type: actionsTypes.SUBMIT_FORM_REQUEST
2458
+ };
2641
2459
  };
2642
- const updateFeatureBuilderIcon = icon => (dispatch, getState) => {
2643
- var _getState$strings2;
2644
- const currentStrings = ((_getState$strings2 = getState().strings) === null || _getState$strings2 === void 0 ? void 0 : _getState$strings2.config) || {};
2645
- const updatedStrings = _objectSpread$6(_objectSpread$6({}, currentStrings), {}, {
2646
- sideNav: _objectSpread$6(_objectSpread$6({}, currentStrings.sideNav), {}, {
2647
- [values.featureKey + "-icon"]: icon,
2648
- [values.menuKey + "-icon"]: icon
2649
- })
2650
- });
2651
- dispatch({
2652
- type: UPDATE_STRINGS,
2653
- payload: updatedStrings
2654
- });
2460
+ const submitFormSuccess = () => {
2461
+ return {
2462
+ type: actionsTypes.SUBMIT_FORM_SUCCESS
2463
+ };
2464
+ };
2465
+ const submitFormFailure = error => {
2466
+ return {
2467
+ type: actionsTypes.SUBMIT_FORM_FAILURE,
2468
+ payload: error
2469
+ };
2470
+ };
2471
+ const clearFormSubmissionState = () => {
2472
+ return {
2473
+ type: actionsTypes.CLEAR_FORM_SUBMISSION_STATE
2474
+ };
2655
2475
  };
2656
2476
 
2657
2477
  /**
2658
- * Form Actions for Feature Builder
2659
- * Manages form state including title, icon, fields, layout, and submission
2660
- * Handles CRUD operations for form fields and layout configuration
2661
- * Coordinates with external menu updates and feature definition actions
2478
+ * Submits the complete feature form to the server
2479
+ * Handles form validation, API submission, and error handling
2662
2480
  *
2663
- * @namespace formActions
2664
- */
2665
-
2666
- /**
2667
- * @typedef {Object} FieldValues
2668
- * @property {string} [label] - Field label text
2669
- * @property {string} [placeholder] - Placeholder text for input
2670
- * @property {boolean} [isRequired] - Whether field is required
2671
- * @property {string} [helpText] - Help text for field guidance
2672
- * @property {boolean} [allowCaption] - Whether field allows captions
2673
- * @property {boolean} [useAsSummary] - Whether field is used as summary
2481
+ * @returns {Function} Async thunk function for Redux
2482
+ * @throws {Error} When form validation fails or API submission encounters error
2674
2483
  */
2484
+ function submitForm() {
2485
+ return async (dispatch, getState) => {
2486
+ const state = getState()[values.reducerKey];
2487
+ const form = state === null || state === void 0 ? void 0 : state.form;
2488
+ if (!form) {
2489
+ dispatch(submitFormFailure(new Error("Form data is missing. Please refresh the page and try again.")));
2490
+ return;
2491
+ }
2492
+ dispatch(submitFormRequest());
2493
+ try {
2494
+ // Get site from auth store
2495
+ const site = getState().auth.site;
2496
+ if (!site) {
2497
+ throw new Error("Authentication error: Site context not found. Please refresh and login again.");
2498
+ }
2675
2499
 
2676
- /**
2677
- * @typedef {Object} FormField
2678
- * @property {string} id - Unique field identifier
2679
- * @property {string} type - Field type (text, title, description, image, file, cta, feature-image)
2680
- * @property {boolean} isMandatory - Whether field is mandatory system field
2681
- * @property {FieldValues} values - Field configuration values
2682
- */
2500
+ // Use mode from fetch instead of checking definition ID
2501
+ const definitionState = state === null || state === void 0 ? void 0 : state.definition;
2502
+ const mode = definitionState === null || definitionState === void 0 ? void 0 : definitionState.mode; // Use stored mode from fetch
2503
+ const definitionId = definitionState === null || definitionState === void 0 ? void 0 : definitionState.id;
2504
+ if (mode === "edit") {
2505
+ // Always update when in edit mode
2506
+ const updatedDefinition = {
2507
+ id: definitionId,
2508
+ site: site,
2509
+ // Include site from auth store
2510
+ featureDefinition: {
2511
+ // Wrap in expected structure for backend
2512
+ title: form.title,
2513
+ icon: form.icon,
2514
+ displayName: form.displayName,
2515
+ layout: form.layout,
2516
+ fields: form.fields
2517
+ }
2518
+ };
2519
+ await featureDefinitionActions.edit(updatedDefinition, site);
2520
+ } else {
2521
+ // Always create when in create mode (or mode is undefined/null)
2522
+ if (!values.featureId || !site) {
2523
+ throw new Error("Authentication error: Missing required context (featureId or site).");
2524
+ }
2525
+ await featureDefinitionActions.create(values.featureId, site,
2526
+ // Use actual site from auth store
2527
+ {
2528
+ title: form.title,
2529
+ icon: form.icon,
2530
+ displayName: form.displayName,
2531
+ layout: form.layout,
2532
+ fields: form.fields
2533
+ });
2534
+ }
2535
+ dispatch(submitFormSuccess());
2536
+ } catch (err) {
2537
+ // Handle different types of errors
2538
+ let errorToDisplay = err;
2539
+ if (err.response) {
2540
+ // API error (400, 401, 404, 500, etc.)
2541
+ const {
2542
+ status,
2543
+ data
2544
+ } = err.response;
2545
+ if (status === 400 && data !== null && data !== void 0 && data.error) {
2546
+ errorToDisplay = new Error("Validation error: ".concat(data.error));
2547
+ } else if (status === 401) {
2548
+ errorToDisplay = new Error("You are not authorized to perform this action");
2549
+ } else if (status === 404) {
2550
+ errorToDisplay = new Error("Feature definition not found");
2551
+ } else if (status >= 500) {
2552
+ errorToDisplay = new Error("Server error. Please try again later.");
2553
+ } else {
2554
+ errorToDisplay = new Error((data === null || data === void 0 ? void 0 : data.error) || "Request failed with status ".concat(status));
2555
+ }
2556
+ } else if (err.request) {
2557
+ // Network error (no response received)
2558
+ errorToDisplay = new Error("Network error. Please check your connection and try again.");
2559
+ } else if (err.message) {
2560
+ // Other JavaScript errors
2561
+ errorToDisplay = err;
2562
+ } else {
2563
+ // Unknown error
2564
+ errorToDisplay = new Error("An unexpected error occurred while saving");
2565
+ }
2566
+ dispatch(submitFormFailure(errorToDisplay));
2567
+ }
2568
+ };
2569
+ }
2683
2570
 
2684
- /**
2685
- * @typedef {Object} LayoutConfig
2686
- * @property {string} type - Layout type (round, square, etc.)
2687
- * @property {string} [gridIcon] - Background image for grid layout
2688
- */
2571
+ function ownKeys$6(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2572
+ function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$6(Object(t), !0).forEach(function (r) { _defineProperty__default["default"](e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$6(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
2689
2573
 
2690
- const actionsTypes = {
2691
- SET_INITIAL_VALUES: "".concat(values.reducerKey.toUpperCase(), "_SET_INITIAL_VALUES"),
2692
- SET_TITLE: "".concat(values.reducerKey.toUpperCase(), "_SET_TITLE"),
2693
- SET_ICON: "".concat(values.reducerKey.toUpperCase(), "_SET_ICON"),
2694
- SET_DISPLAY_NAME: "".concat(values.reducerKey.toUpperCase(), "_SET_DISPLAY_NAME"),
2695
- ADD_FIELD: "".concat(values.reducerKey.toUpperCase(), "_ADD_FIELD"),
2696
- DELETE_FIELD: "".concat(values.reducerKey.toUpperCase(), "_DELETE_FIELD"),
2697
- UPDATE_FIELD: "".concat(values.reducerKey.toUpperCase(), "_UPDATE_FIELD"),
2698
- SET_LAYOUT_GRID_ICON: "".concat(values.reducerKey.toUpperCase(), "_SET_LAYOUT_GRID_ICON"),
2699
- SET_LAYOUT_TYPE: "".concat(values.reducerKey.toUpperCase(), "_SET_LAYOUT_TYPE"),
2700
- SUBMIT_FORM_REQUEST: "".concat(values.reducerKey.toUpperCase(), "_SUBMIT_FORM_REQUEST"),
2701
- SUBMIT_FORM_SUCCESS: "".concat(values.reducerKey.toUpperCase(), "_SUBMIT_FORM_SUCCESS"),
2702
- SUBMIT_FORM_FAILURE: "".concat(values.reducerKey.toUpperCase(), "_SUBMIT_FORM_FAILURE"),
2703
- CLEAR_FORM_SUBMISSION_STATE: "".concat(values.reducerKey.toUpperCase(), "_CLEAR_FORM_SUBMISSION_STATE"),
2704
- SET_SUMMARY_FIELD: "".concat(values.reducerKey.toUpperCase(), "_SET_SUMMARY_FIELD")
2574
+ // Wizard action types
2575
+ const REDUCER_PREFIX$2 = values.reducerKey.toUpperCase();
2576
+ const SET_NAVIGATION_STATE$1 = "".concat(REDUCER_PREFIX$2, "_SET_NAVIGATION_STATE");
2577
+ const UPDATE_STEP_VALIDATION$1 = "".concat(REDUCER_PREFIX$2, "_UPDATE_STEP_VALIDATION");
2578
+ const MARK_STEP_COMPLETE$1 = "".concat(REDUCER_PREFIX$2, "_MARK_STEP_COMPLETE");
2579
+ const setCurrentStep = function (step) {
2580
+ let previousStep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
2581
+ return {
2582
+ type: SET_NAVIGATION_STATE$1,
2583
+ payload: {
2584
+ currentStep: step,
2585
+ previousStep,
2586
+ canGoBack: step !== "welcome",
2587
+ canGoForward: true
2588
+ }
2589
+ };
2705
2590
  };
2591
+ const goToStep = step => (dispatch, getState) => {
2592
+ var _state$wizard;
2593
+ const state = getState()[values.reducerKey];
2594
+ const currentStep = state === null || state === void 0 || (_state$wizard = state.wizard) === null || _state$wizard === void 0 || (_state$wizard = _state$wizard.navigation) === null || _state$wizard === void 0 ? void 0 : _state$wizard.currentStep;
2706
2595
 
2707
- /**
2708
- * Action creator to set initial form values
2709
- * Initializes form state with existing feature definition data
2710
- *
2711
- * @param {Object} initialValues - Initial form values object
2712
- * @param {string} initialValues.title - Feature title
2713
- * @param {string} initialValues.icon - Feature icon
2714
- * @param {string} initialValues.displayName - Feature display name
2715
- * @param {LayoutConfig} initialValues.layout - Layout configuration
2716
- * @param {FormField[]} initialValues.fields - Form fields array
2717
- * @returns {Object} Redux action object with type and payload
2718
- *
2719
- * @example
2720
- * dispatch(setInitialValues({
2721
- * title: 'Contact Form',
2722
- * icon: 'envelope',
2723
- * fields: []
2724
- * }));
2725
- */
2726
- const setInitialValues = initialValues => {
2596
+ // Clear form submission state when changing steps
2597
+ dispatch(clearFormSubmissionState());
2598
+ dispatch(setCurrentStep(step, currentStep));
2599
+ };
2600
+ const updateStepValidation = function (step, isValid) {
2601
+ let errors = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
2727
2602
  return {
2728
- type: actionsTypes.SET_INITIAL_VALUES,
2729
- payload: initialValues
2603
+ type: UPDATE_STEP_VALIDATION$1,
2604
+ payload: {
2605
+ step,
2606
+ isValid,
2607
+ errors
2608
+ }
2609
+ };
2610
+ };
2611
+ const validateAndUpdateStep = step => (dispatch, getState) => {
2612
+ // Use existing selectors to get form data
2613
+ const state = getState();
2614
+ const title = selectFormTitle(state);
2615
+ const icon = selectFormIcon(state);
2616
+ const displayName = selectFormDisplayName(state);
2617
+ const layout = selectFormLayout(state);
2618
+ const fields = selectFormFields(state);
2619
+ const form = {
2620
+ title,
2621
+ icon,
2622
+ displayName,
2623
+ layout,
2624
+ fields
2730
2625
  };
2731
- };
2732
- const setTitle = title => {
2626
+ const {
2627
+ isValid,
2628
+ errors
2629
+ } = getFormValidation(form, step);
2630
+ dispatch(updateStepValidation(step, isValid, errors));
2631
+
2632
+ // If valid, mark as complete
2633
+ if (isValid) {
2634
+ dispatch({
2635
+ type: MARK_STEP_COMPLETE$1,
2636
+ payload: step
2637
+ });
2638
+ }
2733
2639
  return {
2734
- type: actionsTypes.SET_TITLE,
2735
- payload: title
2640
+ isValid,
2641
+ errors
2736
2642
  };
2737
2643
  };
2644
+ const getFormValidation = (form, step) => {
2645
+ // Return validation results for undefined form (prevent crashes)
2646
+ if (!form) {
2647
+ switch (step) {
2648
+ case "overview":
2649
+ return {
2650
+ isValid: false,
2651
+ errors: {
2652
+ title: "Title is required",
2653
+ displayName: "Display name is required",
2654
+ icon: "Icon is required"
2655
+ }
2656
+ };
2657
+ case "fields":
2658
+ return {
2659
+ isValid: false,
2660
+ errors: {
2661
+ missingTitle: "Title field is required",
2662
+ missingImage: "Feature image field is required",
2663
+ fieldLabels: "Some fields are missing labels"
2664
+ }
2665
+ };
2666
+ case "layout":
2667
+ return {
2668
+ isValid: false,
2669
+ errors: {
2670
+ layoutType: "Layout type is required"
2671
+ }
2672
+ };
2673
+ default:
2674
+ return {
2675
+ isValid: false,
2676
+ errors: {}
2677
+ };
2678
+ }
2679
+ }
2680
+ switch (step) {
2681
+ case "overview":
2682
+ {
2683
+ var _form$title, _form$displayName, _form$icon;
2684
+ const hasTitle = ((_form$title = form.title) === null || _form$title === void 0 ? void 0 : _form$title.trim().length) > 0;
2685
+ const hasDisplayName = ((_form$displayName = form.displayName) === null || _form$displayName === void 0 ? void 0 : _form$displayName.trim().length) > 0;
2686
+ const hasIcon = ((_form$icon = form.icon) === null || _form$icon === void 0 ? void 0 : _form$icon.length) > 0;
2687
+ return {
2688
+ isValid: hasTitle && hasDisplayName && hasIcon,
2689
+ errors: {
2690
+ title: !hasTitle ? "Title is required" : null,
2691
+ displayName: !hasDisplayName ? "Display name is required" : null,
2692
+ icon: !hasIcon ? "Icon is required" : null
2693
+ }
2694
+ };
2695
+ }
2696
+ case "fields":
2697
+ {
2698
+ var _form$fields, _form$fields2;
2699
+ const hasTitleField = (_form$fields = form.fields) === null || _form$fields === void 0 ? void 0 : _form$fields.some(field => field.id === "mandatory-title");
2700
+ const hasImageField = (_form$fields2 = form.fields) === null || _form$fields2 === void 0 ? void 0 : _form$fields2.some(field => field.id === "mandatory-feature-image");
2738
2701
 
2739
- /**
2740
- * Action creator to set form display name and update menu
2741
- * Updates both form state and external menu string
2742
- * Title cases the display name before updating the strings store
2743
- *
2744
- * @param {string} displayName - New display name for form
2745
- * @returns {Function} Thunk function for Redux
2746
- *
2747
- * @example
2748
- * dispatch(setDisplayName('Contact Information'));
2749
- */
2750
- const setDisplayName = displayName => {
2702
+ // Check each field for missing labels and create field-specific errors
2703
+ const fieldErrors = {};
2704
+ let allFieldsHaveLabels = true;
2705
+ if (form.fields) {
2706
+ form.fields.forEach(field => {
2707
+ if ((field.type === "text" || field.type === "description" || field.type === "title" || field.type === "image" || field.type === "gallery" || field.type === "feature-image" || field.type === "file" || field.type === "cta") && field.values) {
2708
+ if (!field.values.label || field.values.label.trim().length === 0) {
2709
+ fieldErrors[field.id] = "Field label is required";
2710
+ allFieldsHaveLabels = false;
2711
+ }
2712
+ }
2713
+ });
2714
+ }
2715
+ return {
2716
+ isValid: hasTitleField && hasImageField && allFieldsHaveLabels,
2717
+ errors: _objectSpread$6({
2718
+ missingTitle: !hasTitleField ? "Title field is required" : null,
2719
+ missingImage: !hasImageField ? "Feature image field is required" : null
2720
+ }, fieldErrors)
2721
+ };
2722
+ }
2723
+ case "layout":
2724
+ {
2725
+ var _form$layout;
2726
+ const hasLayoutType = ((_form$layout = form.layout) === null || _form$layout === void 0 || (_form$layout = _form$layout.type) === null || _form$layout === void 0 ? void 0 : _form$layout.length) > 0;
2727
+ return {
2728
+ isValid: hasLayoutType,
2729
+ errors: {
2730
+ layoutType: !hasLayoutType ? "Layout type is required" : null
2731
+ }
2732
+ };
2733
+ }
2734
+ default:
2735
+ return {
2736
+ isValid: true,
2737
+ errors: {}
2738
+ };
2739
+ }
2740
+ };
2741
+ const setCurrentStepAndSave = function (step) {
2742
+ let previousStep = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
2751
2743
  return dispatch => {
2752
- // Update menu string when display name changes (will be title cased in updateFeatureBuilderString)
2753
- dispatch(updateFeatureBuilderString(displayName));
2754
-
2755
- // Dispatch the actual action
2756
- dispatch({
2757
- type: actionsTypes.SET_DISPLAY_NAME,
2758
- payload: displayName
2759
- });
2744
+ dispatch(setCurrentStep(step, previousStep));
2760
2745
  };
2761
2746
  };
2762
2747
 
2748
+ var css$d = ".SidebarLayout_module_fullWidthContent__0d6658dd {\n\tmax-width: 100%;\n\tmargin-left: auto;\n\tmargin-right: auto;\n\tpadding: 2rem 2rem 3rem 2rem; /* Add extra bottom padding */\n}\n\n/* Full-width container that allows scrollbar at edge */\n.SidebarLayout_module_fullWidthContainer__0d6658dd {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tmin-height: 0; /* Allow content to determine height */\n\twidth: 100%; /* Take full width to ensure scrollbar is at edge */\n}\n\n/* Content container to keep content centered */\n.SidebarLayout_module_contentContainer__0d6658dd {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tmin-height: 0;\n\tmax-width: 960px;\n\tmargin: 0 auto;\n\tpadding: 64px 32px;\n\twidth: 100%;\n\tbox-sizing: border-box;\n}\n\n/* Legacy container class for backward compatibility */\n.SidebarLayout_module_container__0d6658dd{\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1;\n\tmin-height: 0; /* Allow content to determine height */\n max-width: 960px;\n margin: 0 auto;\n padding: 64px 32px;\n}\n\n/* Responsive adjustments for content container */\n@media (max-width: 768px) {\n\t.SidebarLayout_module_contentContainer__0d6658dd {\n\t\tpadding: 1.5rem 1.5rem 2.5rem 1.5rem; /* Slightly reduced but still adequate */\n\t}\n\t.SidebarLayout_module_container__0d6658dd {\n\t\tpadding: 1.5rem 1.5rem 2.5rem 1.5rem; /* Legacy container support */\n\t}\n}\n\n@media (max-width: 480px) {\n\t.SidebarLayout_module_contentContainer__0d6658dd {\n\t\tpadding: 1rem 1rem 2rem 1rem; /* Maintain padding on small screens */\n\t}\n\t.SidebarLayout_module_container__0d6658dd {\n\t\tpadding: 1rem 1rem 2rem 1rem; /* Legacy container support */\n\t}\n}\n\n/* Enhanced sidebar navigation for progress indication */\n\n/* Enhanced progress section */\n.hub-sideBar-section {\n\tborder-bottom: 2px solid var(--colour-branding-main-fade, rgba(74, 87, 183, 0.15));\n\tpadding-bottom: 1rem;\n\tmargin-bottom: 1rem;\n}\n\n.hub-sideBar-section:last-child {\n\tborder-bottom: none;\n}\n";
2749
+ var modules_d5b6badf = {"fullWidthContent":"SidebarLayout_module_fullWidthContent__0d6658dd","fullWidthContainer":"SidebarLayout_module_fullWidthContainer__0d6658dd","contentContainer":"SidebarLayout_module_contentContainer__0d6658dd","container":"SidebarLayout_module_container__0d6658dd"};
2750
+ n(css$d,{});
2751
+
2763
2752
  /**
2764
- * Action creator to set form icon and update menu
2765
- * Updates both form state and external menu icon
2753
+ * Sidebar Layout component for feature builder wizard
2754
+ * Provides navigation sidebar with step progression, completion tracking
2755
+ * Manages step accessibility based on wizard mode and validation state
2766
2756
  *
2767
- * @param {string} icon - Icon identifier or FontAwesome icon class
2768
- * @returns {Function} Thunk function for Redux
2757
+ * @param {Object} props - Component props
2758
+ * @param {React.ReactNode} props.children - Child components to render in main content area
2759
+ * @param {Object} props.history - React Router history object for navigation
2760
+ * @returns {React.ReactElement} Layout component with sidebar navigation
2769
2761
  *
2770
2762
  * @example
2771
- * dispatch(setIcon('fa-user'));
2763
+ * <SidebarLayout history={historyObject}>
2764
+ * <YourMainContent />
2765
+ * </SidebarLayout>
2772
2766
  */
2773
- const setIcon = icon => {
2774
- return dispatch => {
2775
- // Update menu icon when icon changes
2776
- dispatch(updateFeatureBuilderIcon(icon));
2767
+ const SideBarInner = props => {
2768
+ const {
2769
+ children,
2770
+ history
2771
+ } = props;
2772
+ const dispatch = reactRedux.useDispatch();
2777
2773
 
2778
- // Dispatch the actual action
2779
- dispatch({
2780
- type: actionsTypes.SET_ICON,
2781
- payload: icon
2782
- });
2774
+ // Get wizard state
2775
+ const mode = reactRedux.useSelector(selectWizardMode);
2776
+ const isEditMode = reactRedux.useSelector(selectIsEditMode);
2777
+ const isCreateMode = reactRedux.useSelector(selectIsCreateMode);
2778
+ const currentStep = reactRedux.useSelector(selectCurrentStep);
2779
+ const goTo = url => history.push(url);
2780
+ const isSelected = url => {
2781
+ return history.location.pathname === url;
2783
2782
  };
2784
- };
2785
2783
 
2786
- /**
2787
- * Action creator to add a new field to the form
2788
- * Generates unique ID and supports custom field types
2789
- *
2790
- * @param {string} [fieldType="text"] - Type of field to add (text, title, description, image, gallery, file, cta, feature-image)
2791
- * @returns {Object} Redux action object with field ID and type
2792
- *
2793
- * @example
2794
- * dispatch(addField('text'));
2795
- * dispatch(addField('image'));
2796
- */
2797
- const addField = function () {
2798
- let fieldType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "text";
2799
- // Generate a unique ID for the new field
2800
- const fieldId = "custom-field-".concat(Date.now(), "-").concat(Math.random().toString(36).substr(2, 9));
2801
- return {
2802
- type: actionsTypes.ADD_FIELD,
2803
- payload: {
2804
- id: fieldId,
2805
- type: fieldType
2784
+ // Define step configuration with dynamic URL based on mode
2785
+ const getStepUrl = stepKey => {
2786
+ // Use routes from values.config to support different variants (-a, -b, -c, -d)
2787
+ switch (stepKey) {
2788
+ case "overview":
2789
+ return values.routeFormOverviewStep;
2790
+ case "fields":
2791
+ return values.routeFormFieldsStep;
2792
+ case "layout":
2793
+ return values.routeFormLayoutStep;
2794
+ default:
2795
+ return "";
2806
2796
  }
2807
2797
  };
2808
- };
2809
- const deleteField = id => {
2810
- return {
2811
- type: actionsTypes.DELETE_FIELD,
2812
- payload: id
2813
- };
2814
- };
2815
- const updateFieldById = (id, updatedField) => {
2816
- return {
2817
- type: actionsTypes.UPDATE_FIELD,
2818
- payload: {
2819
- id,
2820
- updatedField
2821
- }
2798
+ const steps = [{
2799
+ key: "overview",
2800
+ text: "Feature Overview",
2801
+ icon: "info-circle",
2802
+ url: getStepUrl("overview")
2803
+ }, {
2804
+ key: "fields",
2805
+ text: "Configure Fields",
2806
+ icon: "edit",
2807
+ url: getStepUrl("fields")
2808
+ }, {
2809
+ key: "layout",
2810
+ text: "Choose Layout",
2811
+ icon: "columns",
2812
+ url: getStepUrl("layout")
2813
+ }];
2814
+
2815
+ // Build sidebar items based on mode
2816
+ const buildSidebarItems = () => {
2817
+ const isWizardMode = mode === "create" || mode === "edit";
2818
+ return steps.map((step, index) => {
2819
+ const isCompleted = selectIsStepComplete(step.key);
2820
+ const isAccessible = selectIsStepAccessible(step.key);
2821
+
2822
+ // Add step number to text for better clarity
2823
+ const stepText = "".concat(index + 1, ". ").concat(step.text);
2824
+ const itemProps = {
2825
+ type: "navItem",
2826
+ text: stepText,
2827
+ icon: step.icon,
2828
+ selected: isSelected(step.url),
2829
+ onclick: isWizardMode ? null : isAccessible ? () => {
2830
+ goTo(step.url);
2831
+ dispatch(goToStep(step.key));
2832
+ } : null,
2833
+ isFontAwesome: true,
2834
+ // Enhanced completion indicator
2835
+ completed: isCompleted,
2836
+ // Disable all navigation in wizard mode
2837
+ disabled: isWizardMode || mode === "create" && !isAccessible
2838
+ };
2839
+ return itemProps;
2840
+ });
2822
2841
  };
2823
- };
2824
2842
 
2825
- /**
2826
- * Action creator to set a description field as the summary field
2827
- * Ensures only one description field can be marked as summary by
2828
- * automatically unsetting all other description fields when a new one is selected
2829
- *
2830
- * @param {string} fieldId - ID of the description field to set as summary
2831
- * @returns {Object} Redux action object for summary field selection
2832
- *
2833
- * @example
2834
- * dispatch(setSummaryField('field-description-123'));
2835
- */
2836
- const setSummaryField = fieldId => {
2837
- return {
2838
- type: actionsTypes.SET_SUMMARY_FIELD,
2839
- payload: fieldId
2840
- };
2841
- };
2842
- const setLayoutType = layoutType => {
2843
- return {
2844
- type: actionsTypes.SET_LAYOUT_TYPE,
2845
- payload: layoutType
2846
- };
2847
- };
2848
- const submitFormRequest = () => {
2849
- return {
2850
- type: actionsTypes.SUBMIT_FORM_REQUEST
2851
- };
2852
- };
2853
- const submitFormSuccess = () => {
2854
- return {
2855
- type: actionsTypes.SUBMIT_FORM_SUCCESS
2856
- };
2857
- };
2858
- const submitFormFailure = error => {
2859
- return {
2860
- type: actionsTypes.SUBMIT_FORM_FAILURE,
2861
- payload: error
2843
+ // Determine sidebar title - always use "Build Your Feature" now
2844
+ const getSidebarTitle = () => {
2845
+ return "Build Your Feature";
2862
2846
  };
2863
- };
2864
- const clearFormSubmissionState = () => {
2865
- return {
2866
- type: actionsTypes.CLEAR_FORM_SUBMISSION_STATE
2847
+
2848
+ // Simple help text
2849
+ const getHelpText = () => {
2850
+ return "Get help with feature builder";
2867
2851
  };
2868
- };
2869
2852
 
2870
- /**
2871
- * Submits the complete feature form to the server
2872
- * Handles form validation, API submission, and error handling
2873
- *
2874
- * @returns {Function} Async thunk function for Redux
2875
- * @throws {Error} When form validation fails or API submission encounters error
2876
- */
2877
- function submitForm() {
2878
- return async (dispatch, getState) => {
2879
- const state = getState()[values.reducerKey];
2880
- const form = state && state.form;
2881
- if (!form) {
2882
- dispatch(submitFormFailure(new Error("Form data is missing. Please refresh the page and try again.")));
2883
- return;
2884
- }
2885
- dispatch(submitFormRequest());
2886
- try {
2887
- // Get site from auth store
2888
- const site = getState().auth.site;
2889
- if (!site) {
2890
- throw new Error("Authentication error: Site context not found. Please refresh and login again.");
2891
- }
2853
+ // Build sidebar sections - simplified without progress section
2854
+ const sidebarSections = [{
2855
+ title: getSidebarTitle(),
2856
+ items: buildSidebarItems()
2857
+ }];
2892
2858
 
2893
- // Use mode from fetch instead of checking definition ID
2894
- const definitionState = state && state.definition;
2895
- const mode = definitionState && definitionState.mode; // Use stored mode from fetch
2896
- const definitionId = definitionState && definitionState.id;
2897
- if (mode === "edit") {
2898
- // Always update when in edit mode
2899
- const updatedDefinition = {
2900
- id: definitionId,
2901
- site: site,
2902
- // Include site from auth store
2903
- featureDefinition: {
2904
- // Wrap in expected structure for backend
2905
- title: form.title,
2906
- icon: form.icon,
2907
- displayName: form.displayName,
2908
- layout: form.layout,
2909
- fields: form.fields
2859
+ // Add effect to manually attach click handlers since HubSidebar might not use onclick properly
2860
+ React.useEffect(() => {
2861
+ const isWizardMode = mode === "create" || mode === "edit";
2862
+ const attachClickHandlers = () => {
2863
+ const stepsWithUrls = [{
2864
+ key: "overview",
2865
+ url: getStepUrl("overview")
2866
+ }, {
2867
+ key: "fields",
2868
+ url: getStepUrl("fields")
2869
+ }, {
2870
+ key: "layout",
2871
+ url: getStepUrl("layout")
2872
+ }];
2873
+ stepsWithUrls.forEach((step, index) => {
2874
+ const navItem = Array.from(document.querySelectorAll(".hub-wrapperContainer .sideNav-item")).find(item => item.textContent && item.textContent.includes("".concat(index + 1, ".")));
2875
+ if (navItem) {
2876
+ // Remove any existing click listeners
2877
+ navItem.onclick = null;
2878
+
2879
+ // Check if this step is accessible
2880
+ const isAccessible = selectIsStepAccessible(step.key)({
2881
+ [values.reducerKey]: {
2882
+ wizard: {
2883
+ mode: mode,
2884
+ navigation: {
2885
+ currentStep: currentStep
2886
+ }
2887
+ }
2888
+ }
2889
+ });
2890
+
2891
+ // Check if this is the current step (selected)
2892
+ const isCurrentStep = isSelected(step.url);
2893
+
2894
+ // In wizard mode, don't attach any click handlers
2895
+ // Only attach click handler if not in wizard mode AND accessible
2896
+ if (!isWizardMode && isAccessible) {
2897
+ navItem.onclick = event => {
2898
+ event.preventDefault();
2899
+ event.stopPropagation();
2900
+ history.push(step.url);
2901
+ dispatch(goToStep(step.key));
2902
+ };
2903
+ }
2904
+
2905
+ // Make sure it's styled appropriately
2906
+ // In wizard mode: block clicks, but keep current step visible
2907
+ navItem.style.pointerEvents = isWizardMode ? "none" : "auto";
2908
+ if (isWizardMode) {
2909
+ // Current step: full opacity, not-allowed cursor
2910
+ // Other steps: reduced opacity
2911
+ navItem.style.opacity = isCurrentStep ? "1" : "0.4";
2912
+ navItem.style.cursor = "not-allowed";
2913
+ } else {
2914
+ // Not in wizard mode: normal styling based on accessibility
2915
+ navItem.style.cursor = isAccessible ? "pointer" : "not-allowed";
2916
+ navItem.style.opacity = isAccessible ? "1" : "0.5";
2910
2917
  }
2911
- };
2912
- await featureDefinitionActions.edit(updatedDefinition, site);
2913
- } else {
2914
- // Always create when in create mode (or mode is undefined/null)
2915
- if (!values.featureId || !site) {
2916
- throw new Error("Authentication error: Missing required context (featureId or site).");
2917
- }
2918
- await featureDefinitionActions.create(values.featureId, site,
2919
- // Use actual site from auth store
2920
- {
2921
- title: form.title,
2922
- icon: form.icon,
2923
- displayName: form.displayName,
2924
- layout: form.layout,
2925
- fields: form.fields
2926
- });
2927
- }
2928
- dispatch(submitFormSuccess());
2929
- } catch (err) {
2930
- // Handle different types of errors
2931
- let errorToDisplay = err;
2932
- if (err.response) {
2933
- // API error (400, 401, 404, 500, etc.)
2934
- const {
2935
- status,
2936
- data
2937
- } = err.response;
2938
- if (status === 400 && data && data.error) {
2939
- errorToDisplay = new Error("Validation error: ".concat(data.error));
2940
- } else if (status === 401) {
2941
- errorToDisplay = new Error("You are not authorized to perform this action");
2942
- } else if (status === 404) {
2943
- errorToDisplay = new Error("Feature definition not found");
2944
- } else if (status >= 500) {
2945
- errorToDisplay = new Error("Server error. Please try again later.");
2946
- } else {
2947
- errorToDisplay = new Error(data && data.error || "Request failed with status ".concat(status));
2948
2918
  }
2949
- } else if (err.request) {
2950
- // Network error (no response received)
2951
- errorToDisplay = new Error("Network error. Please check your connection and try again.");
2952
- } else if (err.message) {
2953
- // Other JavaScript errors
2954
- errorToDisplay = err;
2955
- } else {
2956
- // Unknown error
2957
- errorToDisplay = new Error("An unexpected error occurred while saving");
2958
- }
2959
- dispatch(submitFormFailure(errorToDisplay));
2919
+ });
2920
+ };
2921
+
2922
+ // Initial attachment
2923
+ attachClickHandlers();
2924
+
2925
+ // Re-attach after a short delay to ensure HubSidebar has rendered
2926
+ const timeoutId = setTimeout(attachClickHandlers, 100);
2927
+
2928
+ // Also try to re-attach when DOM changes (observe for mutations)
2929
+ const observer = new MutationObserver(() => {
2930
+ setTimeout(attachClickHandlers, 50);
2931
+ });
2932
+
2933
+ // Start observing the document body for changes
2934
+ observer.observe(document.body, {
2935
+ childList: true,
2936
+ subtree: true
2937
+ });
2938
+ return () => {
2939
+ clearTimeout(timeoutId);
2940
+ observer.disconnect();
2941
+ };
2942
+ }, [history, dispatch, isEditMode, isCreateMode, currentStep]);
2943
+ return /*#__PURE__*/React__default["default"].createElement("div", {
2944
+ className: "hub-wrapperContainer"
2945
+ }, /*#__PURE__*/React__default["default"].createElement(HubSidebar, {
2946
+ sections: sidebarSections,
2947
+ helpGuide: {
2948
+ text: getHelpText(),
2949
+ url: "https://www.plusscommunities.com/user-guide"
2960
2950
  }
2961
- };
2962
- }
2951
+ }), /*#__PURE__*/React__default["default"].createElement("div", {
2952
+ className: "hub-contentWrapper"
2953
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
2954
+ className: modules_d5b6badf.fullWidthContainer
2955
+ }, /*#__PURE__*/React__default["default"].createElement("div", {
2956
+ className: modules_d5b6badf.contentContainer
2957
+ }, children))));
2958
+ };
2959
+ const SidebarLayout = reactRouter.withRouter(SideBarInner);
2960
+
2961
+ var css$c = ".Form_module_content__d62303b4 {\n\tflex: 1 1 auto;\n\tdisplay: flex;\n\tflex-flow: column nowrap;\n\tpadding: 2rem 0 3rem 0; /* Add proper top/bottom padding */\n\tmin-height: 100%; /* Ensure full height for proper spacing */\n}\n\n/* New page wrapper for centered container approach */\n.Form_module_pageWrapper__d62303b4 {\n\tpadding: 2rem 0;\n\tdisplay: flex;\n\tflex-direction: column;\n\tjustify-content: flex-start;\n}\n\n@media (min-width: 768px) {\n\t.Form_module_pageWrapper__d62303b4 {\n\t\tpadding: 3rem 0;\n\t}\n}\n\n/* Form container styling when using CenteredContainer */\n.Form_module_formContainer__d62303b4 {\n\tbackground-color: var(--bg-white);\n}\n\n/* Section styling */\n.Form_module_section__d62303b4 {\n\tmargin-bottom: 2rem;\n\t\tpadding: 0 0 2em;\n}\n\n.Form_module_section_NoBorder__d62303b4 {\n\t\tborder-bottom: none;\n}\n\n.Form_module_subtitle__d62303b4 {\n\tcolor: var(--text-bluegrey, #6c7a90);\n}\n\n.Form_module_sectionHeader__d62303b4 {\n\t\tdisplay: flex;\n\t\tjustify-content: space-between;\n}\n\n/* Add Field Button styling */\n.Form_module_addFieldButton__d62303b4 {\n\tbackground: var(--colour-branding-action, #5c90df);\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 1.5rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tcursor: pointer;\n\tmargin-bottom: 2rem;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_addFieldButton__d62303b4:hover {\n\tbackground: var(--colour-branding-action-hover, #364196);\n\ttransform: translateY(-1px);\n\tbox-shadow: 0 2px 4px rgba(92, 144, 223, 0.3);\n}\n\n.Form_module_addFieldButton__d62303b4:focus {\n\toutline: 2px solid var(--colour-branding-action, #5c90df);\n\toutline-offset: 2px;\n}\n\n.Form_module_addFieldButton__d62303b4:active {\n\ttransform: translateY(0);\n}\n\n/* Refresh button styling */\n.Form_module_refreshButton__d62303b4 {\n\tmargin-left: 10px;\n\tpadding: 2px 8px;\n\tfont-size: 12px;\n\tbackground: var(--colour-dusk, #536280);\n\tcolor: white;\n\tborder: none;\n\tborder-radius: 4px;\n\tcursor: pointer;\n\ttransition: background-color 0.2s ease;\n}\n\n.Form_module_refreshButton__d62303b4:hover {\n\tbackground: var(--colour-dusk-hover, #485968);\n}\n\n/* Error message container */\n.Form_module_errorMessageContainer__d62303b4 {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.5rem;\n}\n\n/* Add Field Container - matches field structure */\n.Form_module_addFieldContainer__d62303b4 {\n\tdisplay: flex;\n\tmargin-top: 32px;\n}\n\n.Form_module_fieldNumberContainer__d62303b4 {\n\tdisplay: flex;\n\twidth: 40px;\n}\n\n/* Add Field Section */\n.Form_module_addFieldSection__d62303b4 {\n\tdisplay: flex;\n\tgap: 1rem;\n\talign-items: center;\n\tjustify-content: flex-start; /* Align to start to match field content */\n\tmargin-top: 0; /* Remove top margin since it's in the container */\n}\n\n/* Desktop: horizontal layout for field selector and button */\n@media (min-width: 769px) {\n\t.Form_module_addFieldSection__d62303b4 {\n\t\tflex-direction: row;\n\t\talign-items: baseline;\n\t\tgap: 2rem;\n\t\talign-items: flex-start;\n\t\tjustify-content: flex-start; /* Align to start to match field content */\n\t}\n}\n\n/* Help Section for Popup */\n.Form_module_helpSection__d62303b4 {\n\tbackground-color: var(--colour-branding-action-superlight);\n\tborder: 1px solid var(--colour-branding-inactive);\n\tborder-radius: 8px;\n\tpadding: 1.5rem;\n\tmargin-bottom: 1.5rem;\n}\n\n.Form_module_helpTitle__d62303b4 {\n\tcolor: var(--text-dark);\n\tfont-weight: 600;\n\tmargin-bottom: 0.75rem;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.5rem;\n\tfont-size: 1.25rem;\n}\n\n.Form_module_helpText__d62303b4 {\n\tcolor: var(--colour-branding-action);\n\tline-height: 1.6;\n\tfont-size: 1.25rem;\n}\n\n/* Field Type Cards for Popup */\n.Form_module_fieldTypeCards__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 1rem; /* Spacing between vertical cards */\n\tpadding: 1rem 0;\n}\n\n/* Responsive layout: maintain vertical layout on all screen sizes */\n@media (min-width: 768px) {\n\t.Form_module_fieldTypeCards__d62303b4 {\n\t\tgap: 1.5rem; /* Slightly larger gap on desktop */\n\t}\n}\n\n.Form_module_fieldTypeCard__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: row;\n\talign-items: flex-start;\n\tpadding: 1.75rem 1.25rem; /* More vertical padding */\n\tborder: 1px solid var(--border-line-grey);\n\tborder-radius: 8px;\n\tbackground-color: var(--bg-white);\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n\tbox-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);\n\tmin-height: 120px; /* Adjust height for horizontal layout */\n\tgap: 1rem; /* Space between icon and content */\n}\n\n.Form_module_fieldTypeCard__d62303b4:hover {\n\tborder-color: var(--text-light);\n\tbackground-color: var(--bg-bluegrey);\n\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);\n}\n\n.Form_module_fieldTypeCard__d62303b4:focus {\n\toutline: 2px solid var(--text-light);\n\toutline-offset: 2px;\n}\n\n.Form_module_fieldTypeCard__d62303b4:active {\n\ttransform: scale(0.98);\n\ttransition: transform 0.1s ease;\n}\n\n.Form_module_fieldTypeCardIcon__d62303b4 {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\twidth: 48px;\n\theight: 48px;\n\tmargin-bottom: 0; /* Remove bottom margin for horizontal layout */\n\tfont-size: 20px;\n\tflex-shrink: 0;\n\tborder: 1px solid var(--border-line-grey); /* Subtle border */\n\tborder-radius: 8px;\n\tbackground-color: var(--bg-bluegrey);\n\tpadding: 8px;\n}\n\n\n.Form_module_fieldTypeCardContent__d62303b4 {\n\tflex: 1;\n\twidth: 100%;\n\tmin-width: 0; /* Prevent content from overflowing */\n}\n\n.Form_module_fieldTypeCardTitle__d62303b4 {\n\tmargin: 0 0 0.25rem 0;\n\tfont-weight: 600;\n\tfont-size: 1.4rem; /* Increased for better readability */\n}\n\n.Form_module_fieldTypeCardDescription__d62303b4 {\n\tmargin: 0 0 0.75rem 0;\n\tfont-size: 1.6rem; /* Increased for better readability */\n\tline-height: 1.5; /* Improved line height for better readability */\n}\n\n.Form_module_fieldTypeCardUseCase__d62303b4 {\n\tmargin: 0;\n\tfont-size: 1.4rem;\n\tfont-style: italic;\n\tcolor: var(--text-light);\n\tpadding-top: 0.5rem;\n\tborder-top: 1px solid var(--border-line-grey);\n}\n\n/* Field selector and button container - horizontal layout */\n.Form_module_addFieldSection__d62303b4> div:first-child {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 0.5rem;\n\tflex: 1;\n}\n\n/* Container for add field button alignment */\n.Form_module_addFieldButtonContainer__d62303b4 {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: flex-end;\n}\n\n/* Empty State */\n.Form_module_emptyState__d62303b4 {\n\tpadding: 2rem;\n\ttext-align: center;\n\tbackground-color: var(--bg-bluegrey, #f4f7f9);\n\tborder-radius: 8px;\n\tborder: 1px dashed var(--border-line-grey, #dbddf1);\n\tmargin-bottom: 1rem;\n}\n\n.Form_module_emptyStateText__d62303b4 {\n\tcolor: var(--text-bluegrey, #6c7a90);\n\tfont-style: italic;\n}\n\n.Form_module_fieldTypeSelector__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: column;\n\tmax-width: 500px; /* Increased from 300px to accommodate longer text */\n\twidth: 100%;\n}\n\n@media (max-width: 768px) {\n\t.Form_module_addFieldSection__d62303b4 {\n\t\talign-items: stretch;\n\t}\n\t\n\t.Form_module_fieldTypeSelector__d62303b4 {\n\t\tmax-width: none;\n\t}\n}\n\n.Form_module_grid__four__d62303b4 {\n max-width: 1200px;\n\tdisplay: grid;\n\tgrid-template-columns: repeat(2, minmax(250px, 1fr));\n margin: 2rem 0;\n\tgap: 2rem;\n\tjustify-items: center;\n}\n\n@media (max-width: 768px) {\n\t.Form_module_grid__four__d62303b4 {\n\t\tgrid-template-columns: 1fr;\n\t\tgap: 2rem;\n\t}\n}\n\n/* Navigation styles */\n.Form_module_navigation__d62303b4 {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\tgap: 1rem;\n\tmargin-top: 3rem; /* Increase from 2rem */\n\tpadding-top: 2rem;\n\tpadding-bottom: 2rem; /* Add bottom padding */\n\tborder-top: 1px solid #e9ecef;\n}\n\n/* Single button alignment - align to right for overview step save button */\n.Form_module_navigation__d62303b4> :only-child {\n\tmargin-left: auto;\n\tmargin-right: 0;\n}\n\n/* Two button alignment - one left, one right */\n.Form_module_navigation__d62303b4> :first-child:not(:only-child) {\n\tmargin-right: auto;\n}\n\n.Form_module_navigation__d62303b4> :last-child:not(:only-child) {\n\tmargin-left: auto;\n}\n\n/* Special case for overview step - align save button to right */\n.Form_module_overviewStep__d62303b4 .Form_module_navigation__d62303b4> :only-child {\n\tmargin-left: auto;\n\tmargin-right: 0;\n}\n\n.Form_module_previousButton__d62303b4 {\n\tbackground: #6c757d;\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 1.5rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_previousButton__d62303b4:hover {\n\tbackground: #5a6268;\n}\n\n.Form_module_saveButton__d62303b4 {\n\tbackground: var(--colour-purple, #6e79c5);\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 2rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_saveButton__d62303b4:hover:not(:disabled) {\n\tbackground: var(--colour-purple-hover, #5a66b3);\n\ttransform: translateY(-1px);\n\tbox-shadow: 0 2px 4px rgba(110, 121, 197, 0.3);\n}\n\n.Form_module_saveButton__d62303b4:focus {\n\toutline: 2px solid var(--colour-purple, #6e79c5);\n\toutline-offset: 2px;\n}\n\n.Form_module_saveButton__d62303b4:disabled {\n\tbackground: #6c757d;\n\tcursor: not-allowed;\n\topacity: 0.65;\n\ttransform: none;\n\tbox-shadow: none;\n}\n\n.Form_module_nextButton__d62303b4 {\n\tbackground: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n\tcolor: white;\n\tborder: none;\n\tpadding: 0.75rem 2rem;\n\tborder-radius: 6px;\n\tfont-size: 1rem;\n\tfont-weight: 500;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_nextButton__d62303b4:hover:not(:disabled) {\n\ttransform: translateY(-2px);\n\tbox-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);\n}\n\n.Form_module_nextButton__d62303b4:disabled {\n\tbackground: #6c757d;\n\tcursor: not-allowed;\n\topacity: 0.65;\n\ttransform: none;\n\tbox-shadow: none;\n}\n\n\n\n.Form_module_errorMessage__d62303b4 {\n\tcolor: var(--colour-red);\n\tmargin: 0.25rem 0;\n\tpadding: 0.25rem 0;\n\tfont-size: 0.875rem;\n\tline-height: 1.4;\n}\n\n/* Layout option styles */\n.Form_module_layoutOption__d62303b4 {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\ttext-align: center;\n\tcursor: pointer;\n\ttransition: all 0.2s ease;\n\tbackground-color: transparent;\n\topacity: 0.6;\n}\n\n.Form_module_layoutOption__d62303b4:hover {\n\topacity: 1;\n}\n\n.Form_module_layoutOptionImage__d62303b4 {\n\twidth: 250px;\n\theight: 250px;\n\tborder-radius: 12px;\n\toverflow: hidden;\n\tmargin-bottom: 1rem;\n\tborder: 2px solid var(--border-line-grey, #dbddf1);\n\ttransition: all 0.2s ease;\n}\n\n.Form_module_layoutOption__d62303b4.Form_module_selected__d62303b4 .Form_module_layoutOptionImage__d62303b4 {\n\tborder-color: var(--colour-purple, #6e79c5);\n\tbox-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n.Form_module_layoutOption__d62303b4.Form_module_selected__d62303b4 {\n\topacity: 1;\n}\n\n.Form_module_layoutOptionImg__d62303b4 {\n\twidth: 100%;\n\theight: 100%;\n\tobject-fit: cover;\n}\n\n.Form_module_layoutOptionContent__d62303b4 {\n\tmax-width: 250px;\n\tmargin-bottom: 0.5rem;\n}\n\n.Form_module_layoutOptionTitle__d62303b4 {\n\tfont-size: 1.6rem;\n\tfont-weight: 600;\n\tmargin: 0 0 0.5rem 0;\n\tline-height: 1.3;\n\tcolor: #333;\n}\n\n.Form_module_layoutOptionDescription__d62303b4 {\n\tfont-size: 1.2rem;\n\tmargin: 0;\n\tline-height: 1.3;\n\tcolor: #6c757d;\n}\n\n.Form_module_layoutOption__d62303b4.Form_module_hasError__d62303b4 .Form_module_layoutOptionImage__d62303b4 {\n\tborder-color: var(--colour-red, #dc3545);\n}\n\n/* Field error styles */\n.Form_module_fieldError__d62303b4 {\n\tcolor: #dc3545;\n\tfont-size: 1.6rem;\n\tfont-weight: 500;\n\tmargin-top: 0.5rem;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 0.25rem;\n}\n\n.Form_module_errorIcon__d62303b4 {\n\tfont-size: 1rem;\n}\n\n/* Field wrapper styles are now handled in Fields.module.css */\n\n/* Field type indicator styles are now handled in Fields.module.css */\n\n@keyframes Form_module_errorShake__d62303b4 {\n\t0%, 100% { transform: translateX(0); }\n\t25% { transform: translateX(-3px); }\n\t75% { transform: translateX(3px); }\n}\n\n@keyframes Form_module_errorPulse__d62303b4 {\n\t0% { \n\t\tbox-shadow: 0 1px 3px rgba(192, 39, 67, 0.1), 0 1px 2px rgba(192, 39, 67, 0.08);\n\t}\n\t50% { \n\t\tbox-shadow: 0 2px 6px rgba(192, 39, 67, 0.2), 0 1px 3px rgba(192, 39, 67, 0.15);\n\t}\n\t100% { \n\t\tbox-shadow: 0 1px 3px rgba(192, 39, 67, 0.1), 0 1px 2px rgba(192, 39, 67, 0.08);\n\t}\n}\n\n.Form_module_successMessage__d62303b4 {\n\tbackground: var(--colour-branding-secondary-light);\n\tborder: 1px solid var(--colour-branding-secondary);\n\tborder-radius: 8px;\n\tpadding: 1rem;\n\tmargin-top: 1rem;\n\tcolor: var(--colour-green);\n\tfont-weight: 500;\n}\n\n/* Mode-aware styling */\n.Form_module_createMode__d62303b4 {\n\tcolor: var(--colour-purple, #6e79c5);\n}\n\n.Form_module_editMode__d62303b4 {\n\tcolor: var(--colour-branding-dark, #364196);\n}\n\n/* Responsive Design */\n@media (max-width: 768px) {\n\t.Form_module_content__d62303b4 {\n\t\tpadding: 1.5rem 0 2.5rem 0; /* Maintain proper padding on mobile */\n\t}\n\t\n\t.Form_module_section__d62303b4 {\n\t\tmargin-bottom: 1.5rem;\n\t}\n\t\n\t/* Mobile: vertical layout for field selector and button */\n\t.Form_module_addFieldSection__d62303b4 {\n\t\tflex-direction: column;\n\t\talign-items: stretch; /* Stretch to fill available space */\n\t}\n\t\n\t/* Button should not be full width on mobile */\n\t.Form_module_addFieldSection__d62303b4 Button {\n\t\twidth: auto; /* Let button use its natural width */\n\t\tpadding: 1rem 1.5rem; /* Keep proper padding but not full width */\n\t}\n\t\n\t.Form_module_addFieldButtonContainer__d62303b4 {\n\t\talign-items: stretch;\n\t\tjustify-content: stretch;\n\t\tmin-height: auto;\n\t}\n\t\n\t.Form_module_navigation__d62303b4 {\n\t\tflex-direction: column;\n\t\tgap: 0.75rem;\n\t\tjustify-content: flex-start; /* Align to start on mobile */\n\t\tmargin-top: 2rem; /* Slightly reduce on mobile */\n\t\tpadding-top: 1.5rem;\n\t\tpadding-bottom: 1.5rem; /* Maintain bottom padding */\n\t}\n\t\n\t/* Mobile button alignment - single button aligns right, two buttons stack */\n\t.Form_module_navigation__d62303b4> :only-child {\n\t\tmargin-left: auto;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_navigation__d62303b4> :first-child:not(:only-child),\n\t.Form_module_navigation__d62303b4> :last-child:not(:only-child) {\n\t\tmargin-left: 0;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_previousButton__d62303b4,\n\t.Form_module_nextButton__d62303b4,\n\t.Form_module_saveButton__d62303b4 {\n\t\twidth: 100%;\n\t\tpadding: 1rem;\n\t}\n}\n\n@media (max-width: 480px) {\n\t.Form_module_content__d62303b4 {\n\t\tpadding: 1rem 0 2rem 0; /* Still maintain padding on small screens */\n\t}\n\t\n\t.Form_module_section__d62303b4 {\n\t\tmargin-bottom: 1rem;\n\t}\n\t\n\t.Form_module_navigation__d62303b4 {\n\t\tmargin-top: 1.5rem; /* Further reduce on very small screens */\n\t\tpadding-top: 1rem;\n\t\tpadding-bottom: 1.5rem;\n\t\tjustify-content: flex-start; /* Align to start on small screens */\n\t}\n\t\n\t/* Small screen button alignment */\n\t.Form_module_navigation__d62303b4> :only-child {\n\t\tmargin-left: auto;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_navigation__d62303b4> :first-child:not(:only-child),\n\t.Form_module_navigation__d62303b4> :last-child:not(:only-child) {\n\t\tmargin-left: 0;\n\t\tmargin-right: 0;\n\t}\n\t\n\t.Form_module_errorMessageContainer__d62303b4 {\n\t\tflex-direction: column;\n\t\talign-items: flex-start;\n\t\tgap: 0.75rem;\n\t}\n\t\n\t.Form_module_refreshButton__d62303b4 {\n\t\talign-self: flex-end;\n\t}\n}\n\n/* Full width content when sidebar is hidden */\n.hub-contentWrapper.fullWidthContent {\n\tmax-width: 1000px;\n\tmargin: 0 auto;\n\tpadding: 2rem;\n}\n\n.Form_module_hubContentWrapper_Col__d62303b4 {\n flex-flow: column;\n}\n\n/* Validation error message - displayed at top of form */\n.Form_module_validationErrorMessage__d62303b4 {\n\tbackground-color: var(--colour-branding-secondary-light);\n\tborder: 1px solid var(--colour-branding-secondary);\n\tborder-radius: 6px;\n\tcolor: var(--colour-red);\n\tpadding: 12px 16px;\n\tfont-weight: 500;\n\tfont-size: 14px;\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\t\tmargin: 24px 32px;\n}\n\n.Form_module_validationErrorMessage__d62303b4::before {\n\tcontent: \"⚠\";\n\tfont-size: 16px;\n\tcolor: var(--colour-red);\n}\n\n/* Loading overlay for forms - deprecated, use SkeletonLoader instead */\n/*\n.loadingOverlay {\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n\tbottom: 0;\n\tbackground: rgba(255, 255, 255, 0.95);\n\tbackdrop-filter: blur(2px);\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: center;\n\tz-index: 10;\n\tborder-radius: 8px;\n\tanimation: fadeIn 0.2s ease-in-out;\n}\n\n@keyframes fadeIn {\n\tfrom { opacity: 0; }\n\tto { opacity: 1; }\n}\n*/\n\n/* Form header with buttons */\n.Form_module_formHeader__d62303b4 {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: flex-start;\n\tmargin-bottom: 16px;\n}\n\n/* Loading container for fields */\n.Form_module_fieldsLoadingContainer__d62303b4 {\n\ttext-align: center;\n\tpadding: 60px 20px;\n}\n\n/* Help note styling */\n.Form_module_helpNote__d62303b4 {\n\tfont-size: 13px;\n\tcolor: #6c757d;\n}\n\n/* Loading container for overview */\n.Form_module_overviewLoadingContainer__d62303b4 {\n\ttext-align: center;\n\tpadding: 60px 20px;\n}\n\n/* Form layout header */\n.Form_module_formLayoutHeader__d62303b4 {\n\tdisplay: flex;\n\tjustify-content: space-between;\n\talign-items: flex-start;\n\tmargin-bottom: 16px;\n}\n\n/* Section margins */\n.Form_module_gridIconSection__d62303b4 {\n\tmargin-bottom: 3rem;\n}\n\n.Form_module_layoutSection__d62303b4 {\n\tmargin-bottom: 2rem;\n}\n\n/* Grid icon loading state */\n.Form_module_gridIconLoading__d62303b4 {\n\tgrid-column: 1 / -1;\n}\n\n/* Hide upload button in grid icon section */\n.Form_module_gridIconSection__d62303b4 .iconLoader__buttonOverlay button:first-child {\n\tdisplay: none !important;\n}\n";
2962
+ var modules_cd65a764 = {"content":"Form_module_content__d62303b4","pageWrapper":"Form_module_pageWrapper__d62303b4","formContainer":"Form_module_formContainer__d62303b4","section":"Form_module_section__d62303b4","section--no-border":"Form_module_section_NoBorder__d62303b4","subtitle":"Form_module_subtitle__d62303b4","sectionHeader":"Form_module_sectionHeader__d62303b4","addFieldButton":"Form_module_addFieldButton__d62303b4","refreshButton":"Form_module_refreshButton__d62303b4","errorMessageContainer":"Form_module_errorMessageContainer__d62303b4","addFieldContainer":"Form_module_addFieldContainer__d62303b4","fieldNumberContainer":"Form_module_fieldNumberContainer__d62303b4","addFieldSection":"Form_module_addFieldSection__d62303b4","helpSection":"Form_module_helpSection__d62303b4","helpTitle":"Form_module_helpTitle__d62303b4","helpText":"Form_module_helpText__d62303b4","fieldTypeCards":"Form_module_fieldTypeCards__d62303b4","fieldTypeCard":"Form_module_fieldTypeCard__d62303b4","fieldTypeCardIcon":"Form_module_fieldTypeCardIcon__d62303b4","fieldTypeCardContent":"Form_module_fieldTypeCardContent__d62303b4","fieldTypeCardTitle":"Form_module_fieldTypeCardTitle__d62303b4","fieldTypeCardDescription":"Form_module_fieldTypeCardDescription__d62303b4","fieldTypeCardUseCase":"Form_module_fieldTypeCardUseCase__d62303b4","addFieldButtonContainer":"Form_module_addFieldButtonContainer__d62303b4","emptyState":"Form_module_emptyState__d62303b4","emptyStateText":"Form_module_emptyStateText__d62303b4","fieldTypeSelector":"Form_module_fieldTypeSelector__d62303b4","grid__four":"Form_module_grid__four__d62303b4","navigation":"Form_module_navigation__d62303b4","overviewStep":"Form_module_overviewStep__d62303b4","previousButton":"Form_module_previousButton__d62303b4","saveButton":"Form_module_saveButton__d62303b4","nextButton":"Form_module_nextButton__d62303b4","errorMessage":"Form_module_errorMessage__d62303b4","layoutOption":"Form_module_layoutOption__d62303b4","layoutOptionImage":"Form_module_layoutOptionImage__d62303b4","selected":"Form_module_selected__d62303b4","layoutOptionImg":"Form_module_layoutOptionImg__d62303b4","layoutOptionContent":"Form_module_layoutOptionContent__d62303b4","layoutOptionTitle":"Form_module_layoutOptionTitle__d62303b4","layoutOptionDescription":"Form_module_layoutOptionDescription__d62303b4","hasError":"Form_module_hasError__d62303b4","fieldError":"Form_module_fieldError__d62303b4","errorIcon":"Form_module_errorIcon__d62303b4","successMessage":"Form_module_successMessage__d62303b4","createMode":"Form_module_createMode__d62303b4","editMode":"Form_module_editMode__d62303b4","hub-contentWrapper--col":"Form_module_hubContentWrapper_Col__d62303b4","validationErrorMessage":"Form_module_validationErrorMessage__d62303b4","formHeader":"Form_module_formHeader__d62303b4","fieldsLoadingContainer":"Form_module_fieldsLoadingContainer__d62303b4","helpNote":"Form_module_helpNote__d62303b4","overviewLoadingContainer":"Form_module_overviewLoadingContainer__d62303b4","formLayoutHeader":"Form_module_formLayoutHeader__d62303b4","gridIconSection":"Form_module_gridIconSection__d62303b4","layoutSection":"Form_module_layoutSection__d62303b4","gridIconLoading":"Form_module_gridIconLoading__d62303b4","errorShake":"Form_module_errorShake__d62303b4","errorPulse":"Form_module_errorPulse__d62303b4"};
2963
+ n(css$c,{});
2963
2964
 
2964
2965
  /*
2965
2966
  * Icon categories and definitions for the feature builder
@@ -3283,9 +3284,6 @@ const FormOverviewStepInner = props => {
3283
3284
 
3284
3285
  // Clear submission state after showing toast (only for non-edit cases)
3285
3286
  if (!isEditMode) {
3286
- const {
3287
- clearFormSubmissionState
3288
- } = require("../actions/formActions");
3289
3287
  dispatch(clearFormSubmissionState());
3290
3288
  }
3291
3289
  }
@@ -3979,8 +3977,9 @@ function fetchFeatureDefinitions() {
3979
3977
  dispatch(fetchFeaturesFailure(new Error("Unexpected response status: ".concat(response.status))));
3980
3978
  }
3981
3979
  } catch (err) {
3980
+ var _err$response;
3982
3981
  // Check if it's a 404 (feature doesn't exist)
3983
- if (err.response && err.response.status === 404) {
3982
+ if (((_err$response = err.response) === null || _err$response === void 0 ? void 0 : _err$response.status) === 404) {
3984
3983
  // 404: Feature doesn't exist → create mode
3985
3984
  dispatch(fetchFeaturesSuccess(null, "create"));
3986
3985
 
@@ -4636,8 +4635,7 @@ const FormLayoutStepInner = props => {
4636
4635
  // Use custom hook to handle definition loading
4637
4636
  const {
4638
4637
  definition,
4639
- definitionIsLoading,
4640
- reloadDefinition
4638
+ definitionIsLoading
4641
4639
  } = useFeatureDefinitionLoader();
4642
4640
 
4643
4641
  // Get form initialization state
@@ -5249,7 +5247,7 @@ const undeleteListing = id => {
5249
5247
  const response = await listingActions.undelete(id, site);
5250
5248
  // If API returns the restored listing, use it; otherwise we'll need to refetch
5251
5249
  const restoredListing = response.data;
5252
- if (restoredListing && restoredListing.id) {
5250
+ if (restoredListing !== null && restoredListing !== void 0 && restoredListing.id) {
5253
5251
  dispatch(undeleteListingSuccess(restoredListing));
5254
5252
  } else {
5255
5253
  // Trigger a refetch by dispatching the success with just ID, then fetch updated listings
@@ -5566,19 +5564,19 @@ const formReducer = function () {
5566
5564
  case actionsTypes.SET_INITIAL_VALUES:
5567
5565
  {
5568
5566
  // The actual definition data is in payload.featureDefinition.definition
5569
- const definitionWrapper = payload && payload.featureDefinition ? payload.featureDefinition : payload;
5570
- const definition = definitionWrapper && definitionWrapper.definition ? definitionWrapper.definition : definitionWrapper;
5567
+ const definitionWrapper = payload && payload.featureDefinition || payload;
5568
+ const definition = definitionWrapper && definitionWrapper.definition || definitionWrapper;
5571
5569
 
5572
5570
  // Validate and map definition data to form state structure
5573
5571
  const mappedValues = {
5574
- title: definition && definition.title || "",
5575
- icon: definition && definition.icon || "star",
5576
- displayName: definition && definition.displayName || "",
5577
- layout: definition && definition.layout || {
5572
+ title: (definition === null || definition === void 0 ? void 0 : definition.title) || "",
5573
+ icon: (definition === null || definition === void 0 ? void 0 : definition.icon) || "star",
5574
+ displayName: (definition === null || definition === void 0 ? void 0 : definition.displayName) || "",
5575
+ layout: (definition === null || definition === void 0 ? void 0 : definition.layout) || {
5578
5576
  gridIcon: undefined,
5579
5577
  type: "round"
5580
5578
  },
5581
- fields: definition && Array.isArray(definition.fields) ? definition.fields : state.fields
5579
+ fields: Array.isArray(definition === null || definition === void 0 ? void 0 : definition.fields) ? definition.fields : state.fields
5582
5580
  };
5583
5581
  const newState = _objectSpread$3(_objectSpread$3(_objectSpread$3({}, state), mappedValues), {}, {
5584
5582
  _isInitial: false
@@ -5783,14 +5781,15 @@ const definitionReducer = function () {
5783
5781
  let definitionId = values.featureId; // Always use hardcoded ID
5784
5782
 
5785
5783
  if (mode === "edit" && data) {
5784
+ var _definition;
5786
5785
  // Extract from API response for edit mode
5787
5786
  // Handle nested structure: data.featureDefinition.definition
5788
- const featureDefinitionWrapper = data && data.featureDefinition ? data.featureDefinition : data;
5789
- definition = featureDefinitionWrapper && featureDefinitionWrapper.definition ? featureDefinitionWrapper.definition : featureDefinitionWrapper;
5787
+ const featureDefinitionWrapper = data && data.featureDefinition || data;
5788
+ definition = featureDefinitionWrapper && featureDefinitionWrapper.definition || featureDefinitionWrapper;
5790
5789
  definitionId = featureDefinitionWrapper && featureDefinitionWrapper.id || values.featureId;
5791
5790
 
5792
5791
  // Ensure fields array exists and preserves order property
5793
- if (definition && definition.fields) {
5792
+ if ((_definition = definition) !== null && _definition !== void 0 && _definition.fields) {
5794
5793
  // Create a new array to ensure we preserve all field properties including order
5795
5794
  definition.fields = definition.fields.map(field => _objectSpread$3(_objectSpread$3({}, field), {}, {
5796
5795
  // Ensure order property exists, fallback to array index if missing
@@ -5829,7 +5828,7 @@ const definitionReducer = function () {
5829
5828
  // Optimistically update with new definition
5830
5829
  mode: "edit" // Switch to edit mode immediately
5831
5830
  }),
5832
- id: payload && payload.id,
5831
+ id: payload === null || payload === void 0 ? void 0 : payload.id,
5833
5832
  error: null
5834
5833
  });
5835
5834
  case FEATURE_EDIT_REQUEST:
@@ -7760,12 +7759,12 @@ const Reducers = (() => {
7760
7759
  })();
7761
7760
  const Screens = (() => {
7762
7761
  const screens = {};
7763
- screens["FormOverviewStep"] = FormOverviewStep;
7764
- screens["FormFieldsStep"] = FormFieldsStep;
7765
- screens["FormLayoutStep"] = FormLayoutStep;
7766
- screens["ListingScreen"] = ListingScreen$1;
7767
- screens["CreateListingPage"] = CreateListingPage;
7768
- screens["EditListingPage"] = EditListingPage;
7762
+ screens[values.screenFormOverviewStep] = FormOverviewStep;
7763
+ screens[values.screenFormFieldsStep] = FormFieldsStep;
7764
+ screens[values.screenFormLayoutStep] = FormLayoutStep;
7765
+ screens[values.screenListingScreen] = ListingScreen$1;
7766
+ screens[values.pageCreateListing] = CreateListingPage;
7767
+ screens[values.pageEditListing] = EditListingPage;
7769
7768
  return screens;
7770
7769
  })();
7771
7770