@netlisian/softconfig 0.1.8 → 0.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -153,87 +153,169 @@ type VersionedSoftComponent = {
153
153
  type SoftComponents = Record<string, VersionedSoftComponent>;
154
154
 
155
155
  type CompletedComponentResult = {
156
+ /**
157
+ * The generated unique registry key/identifier of the completed soft component.
158
+ */
156
159
  id: string;
160
+ /**
161
+ * The resolved semantic version string of the completed soft component version.
162
+ */
157
163
  version: string;
164
+ /**
165
+ * The compiled underlying JSON definition representing the soft component structure.
166
+ */
158
167
  softComponent: VersionedSoftComponent["versions"][string];
159
168
  };
160
169
  type BuildersSlice = {
161
170
  /**
162
- * Build a new soft component based on the selected item in history.
171
+ * Initializes the "build" mode to package standard component tree elements into a
172
+ * brand-new, unified, and reusable soft component.
173
+ *
174
+ * @param history - The current Puck workspace history timeline stack. Used to store
175
+ * the undo/redo states so they can be restored if the session is canceled.
176
+ * @param selectedItem - The component instance selected in the workspace that will
177
+ * serve as the seed/root of the building sandbox.
178
+ * @param itemSelector - Placement and index metadata of the selected item in the editor.
179
+ * @param puckDispatch - The Puck API dispatch function to apply state modifications.
180
+ * @param name - Optional initial user-facing label/display name for the new soft component.
181
+ *
182
+ * @throws {Error} If no item is selected or the item selector is null.
163
183
  *
164
- * Steps:
165
- * 1. Data Modifications:
166
- * - Store History
167
- * - Set currently selected item to the root
168
- * 2. Soft Config Modifications:
169
- * - Update root to include: name, fields, fieldSettings, for soft component
170
- * - Update each component config to map the soft fields to component fields
171
- * - Update each component for slot settings (Dropzone enable/disable)
184
+ * Lifecycle & Side Effects:
185
+ * 1. Clones and caches the current core soft configuration and history to the store.
186
+ * 2. Scans the workspace sub-tree to collect all descendent element IDs.
187
+ * 3. Schedules edit visibility highlights to visual-lock edits within the builder boundaries.
188
+ * 4. Transitions the builder workflow state to "building".
172
189
  */
173
190
  build: (history: History<AppState>[], selectedItem: PuckApi["selectedItem"], itemSelector: {
174
191
  index: number;
175
192
  zone?: string;
176
193
  } | null, puckDispatch: PuckApi["dispatch"], name?: string) => void | null;
177
194
  /**
178
- * Remodel the selected soft component by decomposing it and resetting as root.
195
+ * Enters "remodel" mode for an existing soft component, decomposing its compiled structure back
196
+ * into constituent discrete components inside the builder workspace.
179
197
  *
180
- * Steps:
181
- * 1. Data Modifications:
182
- * - Store History
183
- * - Decompose and set selected soft component to root
184
- * 2. Soft Config Modifications:
185
- * - Update root with name, fields, fieldSettings for soft component
186
- * - Update each component config to map soft fields to component fields
187
- * - Update each component for slot settings (Dropzone enable/disable)
188
- * - Remove selected component or dependencies to avoid circular dependencies
198
+ * @param history - The current Puck history list to cache for later restoration.
199
+ * @param selectedItem - The compiled soft component instance selected in the editor.
200
+ * @param itemSelector - Workspace index and droppable zone metadata of the selected component.
201
+ * @param puckDispatch - The Puck API dispatch function.
202
+ * @param refreshPermission - Callback function to refresh access permissions (currently unused).
203
+ *
204
+ * @throws {Error} If the selection parameters are missing, or if the target soft component
205
+ * definition cannot be resolved from the cache.
206
+ *
207
+ * Lifecycle & Side Effects:
208
+ * 1. Fetches the soft component version schema from the Zustand store.
209
+ * 2. Evaluates the reverse dependency graph to identify components depending on this soft component.
210
+ * This locks editing on dependent elements to avoid creating circular dependencies.
211
+ * 3. Explodes the soft component into its constituent raw components in-place within the document data.
212
+ * 4. Updates visual iframe overlays to confine editing to the decomposed sub-tree.
213
+ * 5. Transitions the builder workspace state to "remodeling".
189
214
  */
190
215
  remodel: (history: History<AppState>[], selectedItem: PuckApi["selectedItem"], itemSelector: {
191
216
  index: number;
192
217
  zone?: string;
193
218
  } | null, puckDispatch: PuckApi["dispatch"], refreshPermission: () => void) => void;
194
219
  /**
195
- * Switch to a different version of the soft component being remodeled.
220
+ * Switches the active soft component inside the remodeling session to a different
221
+ * registered semantic version.
222
+ *
223
+ * @param componentName - The unique registry key of the soft component.
224
+ * @param newVersion - The target version to activate.
225
+ * @param currentProps - The current top-level properties configured for this element instance.
226
+ * @param puckDispatch - The Puck API dispatch function.
227
+ *
228
+ * @throws {Error} If the store is not currently in the 'remodeling' state, or if the
229
+ * requested version is missing.
196
230
  *
197
- * Steps:
198
- * 1. Get the soft component for the selected version
199
- * 2. Convert it back to AppState format
200
- * 3. Update the puck data with the new version's content
231
+ * Lifecycle & Side Effects:
232
+ * 1. Resolves the target version's raw layout structure from the store.
233
+ * 2. Re-runs soft component-to-AppState conversions for the target version.
234
+ * 3. Replaces the active remodeling workspace content in-place with the selected version's elements.
201
235
  */
202
236
  setVersion: (componentName: string, newVersion: string, currentProps: Record<string, any>, puckDispatch: PuckApi["dispatch"]) => void;
203
237
  /**
204
- * Mark the current build/remodel as complete.
238
+ * Finalizes the current build or remodel session, packaging all active workspace components
239
+ * into a compiled, versioned, reusable soft component configuration.
205
240
  *
206
- * Steps:
207
- * 1. Config Modifications:
208
- * - Compose the build settings into soft component
209
- * - Set the component to the config
210
- * - Restore permissions, resolve fields and resolve data of all components
211
- * 2. Data Modifications:
212
- * - Transform the last item of history to replace the source components into composed soft component
213
- * - Strip the build settings fields
214
- * - Apply modified history to puck data.
241
+ * @param appState - The current state of the builder editor workspace containing the composed elements.
242
+ * @param setHistories - Puck API callback to restore the original builder history timeline.
243
+ * @param getItemBySelector - Puck API utility to resolve a workspace item using its selector.
244
+ * @returns An object containing the generated component ID, version, and compiled soft component structure.
245
+ *
246
+ * @throws {Error} If the store is not in building/remodeling state, the root component is unnamed,
247
+ * or if the selected item cannot be resolved in the workspace.
248
+ *
249
+ * Lifecycle & Side Effects:
250
+ * 1. Converts display labels into safe, unique PascalCase configuration registration keys.
251
+ * 2. Packages workspace child items into a JSON-serializable versioned schema.
252
+ * 3. Re-registers the component with the core configuration components registry.
253
+ * 4. Categorizes the component within layout groups.
254
+ * 5. Restores original history timelines and transitions store state to "inspecting".
255
+ * 6. Rebuilds all other registered soft components that depend on this updated component.
215
256
  */
216
257
  complete: (appState: AppState<any>, setHistories: PuckApi["history"]["setHistories"], getItemBySelector: PuckApi["getItemBySelector"]) => CompletedComponentResult;
258
+ /**
259
+ * Permanently deletes a soft component registration and purges all of its active
260
+ * occurrences/instances from the active workspace document data.
261
+ *
262
+ * @param componentName - The unique registry name of the soft component to delete.
263
+ * @param data - The active workspace document data to scan and clean.
264
+ * @param puckDispatch - The Puck API dispatch function to apply document cleanups.
265
+ *
266
+ * @throws {Error} If the store is not currently in the stable 'ready' state.
267
+ */
217
268
  demolish: (componentName: string, data: AppState["data"], puckDispatch: PuckApi["dispatch"]) => void;
269
+ /**
270
+ * Concludes the inspection workflow, replacing the temporary seed item within the
271
+ * editor workspace document with the newly compiled soft component instance.
272
+ *
273
+ * @param componentName - The final compiled component registry name.
274
+ * @param puckDispatch - The Puck API dispatch function.
275
+ *
276
+ * @throws {Error} If the store is not currently in the 'inspecting' state.
277
+ *
278
+ * Lifecycle & Side Effects:
279
+ * 1. Walk the workspace tree to locate the temporary component being built/remodeled.
280
+ * 2. Replace it with the compiled component type and default versioned props.
281
+ * 3. Flushes layout restriction overlays on the iframe.
282
+ * 4. Resets active builder metadata and transitions state back to "ready".
283
+ */
218
284
  inspect: (componentName: string, puckDispatch: PuckApi["dispatch"]) => void;
219
285
  /**
220
- * Mark the current build/remodel as complete.
286
+ * Discards all modifications made during the current build or remodel session,
287
+ * reverting the editor config, workspace elements, and histories back to their original state.
221
288
  *
222
- * Steps:
223
- * 1. Config Modifications:
224
- * - Restore permissions, resolve fields and resolve data of all components
225
- * 2. Data Modifications:
226
- * - Restore history to puck data.
289
+ * @param setHistories - Puck API callback to restore the original history list.
290
+ *
291
+ * Lifecycle & Side Effects:
292
+ * 1. Transitions store state to "cancelling" to suppress conflicting updates.
293
+ * 2. Re-applies the original workspace config and timeline histories.
294
+ * 3. Clears visual iframe constraints and resets active builder metadata back to normal.
227
295
  */
228
296
  cancel: (setHistories: PuckApi["history"]["setHistories"]) => void;
229
- /** Compose multiple components into a soft component.
230
- * 1. SoftComponent: Get soft fields + default values from the appState.root + sub-component maps + fixedProps
297
+ /**
298
+ * Internal compiler hook that converts builder editor workspace states (root props, children)
299
+ * into a unified `SoftComponent` schema and creates a versioned config.
300
+ *
301
+ * @param appState - The current builder editor state.
302
+ * @param componentName - The unique registry key for the soft component.
303
+ * @param editedItem - The original seed component that initiated the build session.
304
+ * @param displayName - The user-facing display name of the soft component.
305
+ * @param category - Optional layout category placement inside the component toolbox.
306
+ * @returns A tuple containing the `ComponentConfig` and its resolved version string, or undefined if failed.
307
+ *
308
+ * @throws {Error} If the component name is empty or collides with existing configs during a new build.
231
309
  */
232
310
  compose: (appState: AppState, componentName: string, editedItem: ComponentData, displayName: string, category?: string) => [ComponentConfig, string] | undefined;
233
- /** Break down a composed component into its parts.
234
- * 1. Get softComponentProps
235
- * 2. Create a virtual component with all the props from soft-component.
236
- * 3. Replace the softComponent with hardComponent
311
+ /**
312
+ * Utility to break down a composed soft component's props and children back into
313
+ * their discrete, uncompiled constituent elements.
314
+ *
315
+ * @param componentData - The compiled component data instance.
316
+ * @returns An array of unpacked standard child component data objects.
317
+ *
318
+ * @throws {Error} If the input component data lacks type or ID.
237
319
  */
238
320
  decompose: (componentData: ComponentData) => ComponentData[];
239
321
  };
@@ -306,7 +388,7 @@ type RenderFunc<Props extends Record<string, unknown> = {
306
388
  type Overrides = {
307
389
  componentLabelToName?: (label: string, context: Partial<BuilderRootConfig> & {
308
390
  existingKeys: string[];
309
- state: "building" | "remodeling" | "ready" | "inspecting";
391
+ state: Status;
310
392
  }) => string;
311
393
  componentNameToLabel?: (name: string) => string;
312
394
  onRemodel?: (name: string) => Record<string, unknown>;
@@ -346,7 +428,7 @@ type Overrides = {
346
428
  };
347
429
 
348
430
  /** Represents the current editing mode of the Puck editor. */
349
- type Status = "building" | "remodeling" | "ready" | "inspecting";
431
+ type Status = "building" | "remodeling" | "ready" | "cancelling" | "inspecting";
350
432
  type AppStore = {
351
433
  /** The current merged Puck config (hard + soft components). Rebuilt on soft component changes. */
352
434
  softConfig: Config;
@@ -746,4 +828,4 @@ declare const isArrayMappingPath: (path: string) => boolean;
746
828
  declare const getArrayBasePath: (arrayPath: string) => string | null;
747
829
  declare const getArrayItemSubPath: (arrayPath: string) => string | null;
748
830
 
749
- export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type ApplyMappingOptions, type ApplyMappingResult, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Drawer as ComponentList, type CustomFieldDefinition, type CustomFieldReturnType, type CustomFields, Drawer, DrawerItem, type FieldSettings, Header, HeaderActions, type MapEntry, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type SoftFieldDefinition, type SoftFieldSettings, type VersionedSoftComponent, applyMapping, confirm, createActionCallback, createSoftConfigStore, createUseSoftConfig, filterToOptionsForFrom, getArrayBasePath, getArrayItemSubPath, isArrayMappingPath, notify, resolveSoftConfig, resolveValueByPath, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig, useSoftConfigStore };
831
+ export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type ApplyMappingOptions, type ApplyMappingResult, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Drawer as ComponentList, type CustomFieldDefinition, type CustomFieldReturnType, type CustomFields, Drawer, DrawerItem, type FieldSettings, Header, HeaderActions, type MapEntry, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type SoftFieldDefinition, type SoftFieldSettings, type Status, type VersionedSoftComponent, applyMapping, confirm, createActionCallback, createSoftConfigStore, createUseSoftConfig, filterToOptionsForFrom, getArrayBasePath, getArrayItemSubPath, isArrayMappingPath, notify, resolveSoftConfig, resolveValueByPath, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig, useSoftConfigStore };
@@ -153,87 +153,169 @@ type VersionedSoftComponent = {
153
153
  type SoftComponents = Record<string, VersionedSoftComponent>;
154
154
 
155
155
  type CompletedComponentResult = {
156
+ /**
157
+ * The generated unique registry key/identifier of the completed soft component.
158
+ */
156
159
  id: string;
160
+ /**
161
+ * The resolved semantic version string of the completed soft component version.
162
+ */
157
163
  version: string;
164
+ /**
165
+ * The compiled underlying JSON definition representing the soft component structure.
166
+ */
158
167
  softComponent: VersionedSoftComponent["versions"][string];
159
168
  };
160
169
  type BuildersSlice = {
161
170
  /**
162
- * Build a new soft component based on the selected item in history.
171
+ * Initializes the "build" mode to package standard component tree elements into a
172
+ * brand-new, unified, and reusable soft component.
173
+ *
174
+ * @param history - The current Puck workspace history timeline stack. Used to store
175
+ * the undo/redo states so they can be restored if the session is canceled.
176
+ * @param selectedItem - The component instance selected in the workspace that will
177
+ * serve as the seed/root of the building sandbox.
178
+ * @param itemSelector - Placement and index metadata of the selected item in the editor.
179
+ * @param puckDispatch - The Puck API dispatch function to apply state modifications.
180
+ * @param name - Optional initial user-facing label/display name for the new soft component.
181
+ *
182
+ * @throws {Error} If no item is selected or the item selector is null.
163
183
  *
164
- * Steps:
165
- * 1. Data Modifications:
166
- * - Store History
167
- * - Set currently selected item to the root
168
- * 2. Soft Config Modifications:
169
- * - Update root to include: name, fields, fieldSettings, for soft component
170
- * - Update each component config to map the soft fields to component fields
171
- * - Update each component for slot settings (Dropzone enable/disable)
184
+ * Lifecycle & Side Effects:
185
+ * 1. Clones and caches the current core soft configuration and history to the store.
186
+ * 2. Scans the workspace sub-tree to collect all descendent element IDs.
187
+ * 3. Schedules edit visibility highlights to visual-lock edits within the builder boundaries.
188
+ * 4. Transitions the builder workflow state to "building".
172
189
  */
173
190
  build: (history: History<AppState>[], selectedItem: PuckApi["selectedItem"], itemSelector: {
174
191
  index: number;
175
192
  zone?: string;
176
193
  } | null, puckDispatch: PuckApi["dispatch"], name?: string) => void | null;
177
194
  /**
178
- * Remodel the selected soft component by decomposing it and resetting as root.
195
+ * Enters "remodel" mode for an existing soft component, decomposing its compiled structure back
196
+ * into constituent discrete components inside the builder workspace.
179
197
  *
180
- * Steps:
181
- * 1. Data Modifications:
182
- * - Store History
183
- * - Decompose and set selected soft component to root
184
- * 2. Soft Config Modifications:
185
- * - Update root with name, fields, fieldSettings for soft component
186
- * - Update each component config to map soft fields to component fields
187
- * - Update each component for slot settings (Dropzone enable/disable)
188
- * - Remove selected component or dependencies to avoid circular dependencies
198
+ * @param history - The current Puck history list to cache for later restoration.
199
+ * @param selectedItem - The compiled soft component instance selected in the editor.
200
+ * @param itemSelector - Workspace index and droppable zone metadata of the selected component.
201
+ * @param puckDispatch - The Puck API dispatch function.
202
+ * @param refreshPermission - Callback function to refresh access permissions (currently unused).
203
+ *
204
+ * @throws {Error} If the selection parameters are missing, or if the target soft component
205
+ * definition cannot be resolved from the cache.
206
+ *
207
+ * Lifecycle & Side Effects:
208
+ * 1. Fetches the soft component version schema from the Zustand store.
209
+ * 2. Evaluates the reverse dependency graph to identify components depending on this soft component.
210
+ * This locks editing on dependent elements to avoid creating circular dependencies.
211
+ * 3. Explodes the soft component into its constituent raw components in-place within the document data.
212
+ * 4. Updates visual iframe overlays to confine editing to the decomposed sub-tree.
213
+ * 5. Transitions the builder workspace state to "remodeling".
189
214
  */
190
215
  remodel: (history: History<AppState>[], selectedItem: PuckApi["selectedItem"], itemSelector: {
191
216
  index: number;
192
217
  zone?: string;
193
218
  } | null, puckDispatch: PuckApi["dispatch"], refreshPermission: () => void) => void;
194
219
  /**
195
- * Switch to a different version of the soft component being remodeled.
220
+ * Switches the active soft component inside the remodeling session to a different
221
+ * registered semantic version.
222
+ *
223
+ * @param componentName - The unique registry key of the soft component.
224
+ * @param newVersion - The target version to activate.
225
+ * @param currentProps - The current top-level properties configured for this element instance.
226
+ * @param puckDispatch - The Puck API dispatch function.
227
+ *
228
+ * @throws {Error} If the store is not currently in the 'remodeling' state, or if the
229
+ * requested version is missing.
196
230
  *
197
- * Steps:
198
- * 1. Get the soft component for the selected version
199
- * 2. Convert it back to AppState format
200
- * 3. Update the puck data with the new version's content
231
+ * Lifecycle & Side Effects:
232
+ * 1. Resolves the target version's raw layout structure from the store.
233
+ * 2. Re-runs soft component-to-AppState conversions for the target version.
234
+ * 3. Replaces the active remodeling workspace content in-place with the selected version's elements.
201
235
  */
202
236
  setVersion: (componentName: string, newVersion: string, currentProps: Record<string, any>, puckDispatch: PuckApi["dispatch"]) => void;
203
237
  /**
204
- * Mark the current build/remodel as complete.
238
+ * Finalizes the current build or remodel session, packaging all active workspace components
239
+ * into a compiled, versioned, reusable soft component configuration.
205
240
  *
206
- * Steps:
207
- * 1. Config Modifications:
208
- * - Compose the build settings into soft component
209
- * - Set the component to the config
210
- * - Restore permissions, resolve fields and resolve data of all components
211
- * 2. Data Modifications:
212
- * - Transform the last item of history to replace the source components into composed soft component
213
- * - Strip the build settings fields
214
- * - Apply modified history to puck data.
241
+ * @param appState - The current state of the builder editor workspace containing the composed elements.
242
+ * @param setHistories - Puck API callback to restore the original builder history timeline.
243
+ * @param getItemBySelector - Puck API utility to resolve a workspace item using its selector.
244
+ * @returns An object containing the generated component ID, version, and compiled soft component structure.
245
+ *
246
+ * @throws {Error} If the store is not in building/remodeling state, the root component is unnamed,
247
+ * or if the selected item cannot be resolved in the workspace.
248
+ *
249
+ * Lifecycle & Side Effects:
250
+ * 1. Converts display labels into safe, unique PascalCase configuration registration keys.
251
+ * 2. Packages workspace child items into a JSON-serializable versioned schema.
252
+ * 3. Re-registers the component with the core configuration components registry.
253
+ * 4. Categorizes the component within layout groups.
254
+ * 5. Restores original history timelines and transitions store state to "inspecting".
255
+ * 6. Rebuilds all other registered soft components that depend on this updated component.
215
256
  */
216
257
  complete: (appState: AppState<any>, setHistories: PuckApi["history"]["setHistories"], getItemBySelector: PuckApi["getItemBySelector"]) => CompletedComponentResult;
258
+ /**
259
+ * Permanently deletes a soft component registration and purges all of its active
260
+ * occurrences/instances from the active workspace document data.
261
+ *
262
+ * @param componentName - The unique registry name of the soft component to delete.
263
+ * @param data - The active workspace document data to scan and clean.
264
+ * @param puckDispatch - The Puck API dispatch function to apply document cleanups.
265
+ *
266
+ * @throws {Error} If the store is not currently in the stable 'ready' state.
267
+ */
217
268
  demolish: (componentName: string, data: AppState["data"], puckDispatch: PuckApi["dispatch"]) => void;
269
+ /**
270
+ * Concludes the inspection workflow, replacing the temporary seed item within the
271
+ * editor workspace document with the newly compiled soft component instance.
272
+ *
273
+ * @param componentName - The final compiled component registry name.
274
+ * @param puckDispatch - The Puck API dispatch function.
275
+ *
276
+ * @throws {Error} If the store is not currently in the 'inspecting' state.
277
+ *
278
+ * Lifecycle & Side Effects:
279
+ * 1. Walk the workspace tree to locate the temporary component being built/remodeled.
280
+ * 2. Replace it with the compiled component type and default versioned props.
281
+ * 3. Flushes layout restriction overlays on the iframe.
282
+ * 4. Resets active builder metadata and transitions state back to "ready".
283
+ */
218
284
  inspect: (componentName: string, puckDispatch: PuckApi["dispatch"]) => void;
219
285
  /**
220
- * Mark the current build/remodel as complete.
286
+ * Discards all modifications made during the current build or remodel session,
287
+ * reverting the editor config, workspace elements, and histories back to their original state.
221
288
  *
222
- * Steps:
223
- * 1. Config Modifications:
224
- * - Restore permissions, resolve fields and resolve data of all components
225
- * 2. Data Modifications:
226
- * - Restore history to puck data.
289
+ * @param setHistories - Puck API callback to restore the original history list.
290
+ *
291
+ * Lifecycle & Side Effects:
292
+ * 1. Transitions store state to "cancelling" to suppress conflicting updates.
293
+ * 2. Re-applies the original workspace config and timeline histories.
294
+ * 3. Clears visual iframe constraints and resets active builder metadata back to normal.
227
295
  */
228
296
  cancel: (setHistories: PuckApi["history"]["setHistories"]) => void;
229
- /** Compose multiple components into a soft component.
230
- * 1. SoftComponent: Get soft fields + default values from the appState.root + sub-component maps + fixedProps
297
+ /**
298
+ * Internal compiler hook that converts builder editor workspace states (root props, children)
299
+ * into a unified `SoftComponent` schema and creates a versioned config.
300
+ *
301
+ * @param appState - The current builder editor state.
302
+ * @param componentName - The unique registry key for the soft component.
303
+ * @param editedItem - The original seed component that initiated the build session.
304
+ * @param displayName - The user-facing display name of the soft component.
305
+ * @param category - Optional layout category placement inside the component toolbox.
306
+ * @returns A tuple containing the `ComponentConfig` and its resolved version string, or undefined if failed.
307
+ *
308
+ * @throws {Error} If the component name is empty or collides with existing configs during a new build.
231
309
  */
232
310
  compose: (appState: AppState, componentName: string, editedItem: ComponentData, displayName: string, category?: string) => [ComponentConfig, string] | undefined;
233
- /** Break down a composed component into its parts.
234
- * 1. Get softComponentProps
235
- * 2. Create a virtual component with all the props from soft-component.
236
- * 3. Replace the softComponent with hardComponent
311
+ /**
312
+ * Utility to break down a composed soft component's props and children back into
313
+ * their discrete, uncompiled constituent elements.
314
+ *
315
+ * @param componentData - The compiled component data instance.
316
+ * @returns An array of unpacked standard child component data objects.
317
+ *
318
+ * @throws {Error} If the input component data lacks type or ID.
237
319
  */
238
320
  decompose: (componentData: ComponentData) => ComponentData[];
239
321
  };
@@ -306,7 +388,7 @@ type RenderFunc<Props extends Record<string, unknown> = {
306
388
  type Overrides = {
307
389
  componentLabelToName?: (label: string, context: Partial<BuilderRootConfig> & {
308
390
  existingKeys: string[];
309
- state: "building" | "remodeling" | "ready" | "inspecting";
391
+ state: Status;
310
392
  }) => string;
311
393
  componentNameToLabel?: (name: string) => string;
312
394
  onRemodel?: (name: string) => Record<string, unknown>;
@@ -346,7 +428,7 @@ type Overrides = {
346
428
  };
347
429
 
348
430
  /** Represents the current editing mode of the Puck editor. */
349
- type Status = "building" | "remodeling" | "ready" | "inspecting";
431
+ type Status = "building" | "remodeling" | "ready" | "cancelling" | "inspecting";
350
432
  type AppStore = {
351
433
  /** The current merged Puck config (hard + soft components). Rebuilt on soft component changes. */
352
434
  softConfig: Config;
@@ -746,4 +828,4 @@ declare const isArrayMappingPath: (path: string) => boolean;
746
828
  declare const getArrayBasePath: (arrayPath: string) => string | null;
747
829
  declare const getArrayItemSubPath: (arrayPath: string) => string | null;
748
830
 
749
- export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type ApplyMappingOptions, type ApplyMappingResult, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Drawer as ComponentList, type CustomFieldDefinition, type CustomFieldReturnType, type CustomFields, Drawer, DrawerItem, type FieldSettings, Header, HeaderActions, type MapEntry, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type SoftFieldDefinition, type SoftFieldSettings, type VersionedSoftComponent, applyMapping, confirm, createActionCallback, createSoftConfigStore, createUseSoftConfig, filterToOptionsForFrom, getArrayBasePath, getArrayItemSubPath, isArrayMappingPath, notify, resolveSoftConfig, resolveValueByPath, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig, useSoftConfigStore };
831
+ export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type ApplyMappingOptions, type ApplyMappingResult, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Drawer as ComponentList, type CustomFieldDefinition, type CustomFieldReturnType, type CustomFields, Drawer, DrawerItem, type FieldSettings, Header, HeaderActions, type MapEntry, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type SoftFieldDefinition, type SoftFieldSettings, type Status, type VersionedSoftComponent, applyMapping, confirm, createActionCallback, createSoftConfigStore, createUseSoftConfig, filterToOptionsForFrom, getArrayBasePath, getArrayItemSubPath, isArrayMappingPath, notify, resolveSoftConfig, resolveValueByPath, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig, useSoftConfigStore };
@@ -2299,25 +2299,6 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2299
2299
  if (!selectedItem || !itemSelector) {
2300
2300
  throw new Error("No item selected to build from.");
2301
2301
  }
2302
- puckDispatch({
2303
- type: "set",
2304
- state: (previous) => {
2305
- var _a;
2306
- return {
2307
- ui: __spreadProps(__spreadValues({}, previous.ui), {
2308
- itemSelector: null
2309
- }),
2310
- data: __spreadProps(__spreadValues({}, previous.data), {
2311
- root: __spreadProps(__spreadValues({}, previous.data.root), {
2312
- props: __spreadProps(__spreadValues({}, (_a = previous.data.root) == null ? void 0 : _a.props), {
2313
- _name: name || "New Soft Component"
2314
- })
2315
- })
2316
- // content: [{ ...selectedItem }],
2317
- })
2318
- };
2319
- }
2320
- });
2321
2302
  const config = __spreadValues({}, get().softConfig);
2322
2303
  const overrides = get().overrides;
2323
2304
  const buildConfig = builderConfig(
@@ -2363,10 +2344,21 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2363
2344
  }));
2364
2345
  requestAnimationFrame(
2365
2346
  () => puckDispatch({
2366
- type: "replaceRoot",
2367
- root: {
2368
- title: "Soft Component Builder",
2369
- _name: name || "New Soft Component"
2347
+ type: "set",
2348
+ state: (previous) => {
2349
+ var _a;
2350
+ return {
2351
+ ui: __spreadProps(__spreadValues({}, previous.ui), {
2352
+ itemSelector: null
2353
+ }),
2354
+ data: __spreadProps(__spreadValues({}, previous.data), {
2355
+ root: __spreadProps(__spreadValues({}, previous.data.root), {
2356
+ props: __spreadProps(__spreadValues({}, (_a = previous.data.root) == null ? void 0 : _a.props), {
2357
+ _name: name || "New Soft Component"
2358
+ })
2359
+ })
2360
+ })
2361
+ };
2370
2362
  }
2371
2363
  })
2372
2364
  );
@@ -2391,12 +2383,6 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2391
2383
  `Soft component "${softComponentName}" with version "${softComponentVersion}" not found.`
2392
2384
  );
2393
2385
  }
2394
- puckDispatch({
2395
- type: "setUi",
2396
- ui: (previous) => __spreadProps(__spreadValues({}, previous), {
2397
- itemSelector: void 0
2398
- })
2399
- });
2400
2386
  const { root, content } = softComponentToAppState(
2401
2387
  softComponent,
2402
2388
  softComponentName,
@@ -2432,36 +2418,45 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2432
2418
  return components;
2433
2419
  }
2434
2420
  );
2435
- puckDispatch({
2436
- type: "setData",
2437
- data: (prevData) => ({
2438
- root: __spreadProps(__spreadValues({}, root), { _versions: versions }),
2439
- content: (0, import_puck4.walkTree)(__spreadValues({}, prevData), __spreadValues({}, config), (components) => {
2440
- const next = components.map((component) => __spreadProps(__spreadValues({}, component), {
2441
- props: __spreadValues({}, component.props)
2442
- }));
2443
- const index = next.findIndex(
2444
- (component) => component.props.id === selectedItem.props.id
2445
- );
2446
- if (index !== -1) {
2447
- next.splice(
2448
- index,
2449
- 1,
2450
- ...decomposedComponents.map((component) => __spreadProps(__spreadValues({}, component), {
2451
- props: __spreadValues({}, component.props)
2452
- }))
2453
- );
2454
- }
2455
- return next;
2456
- }).content
2457
- })
2458
- });
2459
- requestAnimationFrame(
2460
- () => setEditVisibility(get().iframeDoc, {
2421
+ requestAnimationFrame(() => {
2422
+ puckDispatch({
2423
+ type: "set",
2424
+ state: (previous) => ({
2425
+ data: {
2426
+ root: __spreadProps(__spreadValues({}, root), { _versions: versions }),
2427
+ content: (0, import_puck4.walkTree)(
2428
+ __spreadValues({}, previous.data),
2429
+ __spreadValues({}, config),
2430
+ (components) => {
2431
+ const next = components.map((component) => __spreadProps(__spreadValues({}, component), {
2432
+ props: __spreadValues({}, component.props)
2433
+ }));
2434
+ const index = next.findIndex(
2435
+ (component) => component.props.id === selectedItem.props.id
2436
+ );
2437
+ if (index !== -1) {
2438
+ next.splice(
2439
+ index,
2440
+ 1,
2441
+ ...decomposedComponents.map((component) => __spreadProps(__spreadValues({}, component), {
2442
+ props: __spreadValues({}, component.props)
2443
+ }))
2444
+ );
2445
+ }
2446
+ return next;
2447
+ }
2448
+ ).content
2449
+ },
2450
+ ui: __spreadProps(__spreadValues({}, previous.ui), {
2451
+ itemSelector: null
2452
+ })
2453
+ })
2454
+ });
2455
+ setEditVisibility(get().iframeDoc, {
2461
2456
  mode: "remodel",
2462
2457
  editableIds
2463
- })
2464
- );
2458
+ });
2459
+ });
2465
2460
  set((s) => __spreadProps(__spreadValues({}, s), {
2466
2461
  storedConfig: config,
2467
2462
  softConfig: buildConfig,
@@ -2568,6 +2563,7 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2568
2563
  }),
2569
2564
  storedConfig: void 0,
2570
2565
  state: "inspecting",
2566
+ // Temporarily shift state to inspect() before finalizing back to ready
2571
2567
  originalHistory: []
2572
2568
  });
2573
2569
  });
@@ -2616,34 +2612,41 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2616
2612
  type: "setData",
2617
2613
  data: (data) => {
2618
2614
  return reconstructedTree(data);
2619
- }
2615
+ },
2616
+ recordHistory: true
2617
+ // Record this swap on the standard undo/redo stack
2620
2618
  });
2619
+ clearEditVisibility(get().iframeDoc);
2620
+ set((s) => __spreadProps(__spreadValues({}, s), {
2621
+ state: "ready",
2622
+ setItemSelector: void 0,
2623
+ setOriginalItem: void 0,
2624
+ editingComponent: null,
2625
+ editingComponentId: null,
2626
+ editableComponentIds: /* @__PURE__ */ new Set()
2627
+ }));
2621
2628
  });
2622
- requestAnimationFrame(() => clearEditVisibility(get().iframeDoc));
2623
- set((s) => __spreadProps(__spreadValues({}, s), {
2624
- state: "ready",
2625
- setItemSelector: void 0,
2626
- setOriginalItem: void 0,
2627
- editingComponent: null,
2628
- editingComponentId: null,
2629
- editableComponentIds: /* @__PURE__ */ new Set()
2630
- }));
2631
2629
  },
2632
2630
  cancel: (setHistories) => {
2633
2631
  const storedHistories = get().originalHistory;
2634
- requestAnimationFrame(() => setHistories([...storedHistories]));
2635
- requestAnimationFrame(() => clearEditVisibility(get().iframeDoc));
2636
2632
  set((s) => __spreadProps(__spreadValues({}, s), {
2637
- softConfig: get().storedConfig || initialConfig,
2638
- storedConfig: void 0,
2639
- originalHistory: [],
2640
- itemSelector: null,
2641
- originalItem: null,
2642
- state: "ready",
2643
- editingComponent: null,
2644
- editingComponentId: null,
2645
- editableComponentIds: /* @__PURE__ */ new Set()
2633
+ state: "cancelling"
2646
2634
  }));
2635
+ setHistories([...storedHistories]);
2636
+ requestAnimationFrame(() => {
2637
+ clearEditVisibility(get().iframeDoc);
2638
+ set((s) => __spreadProps(__spreadValues({}, s), {
2639
+ softConfig: get().storedConfig || initialConfig,
2640
+ storedConfig: void 0,
2641
+ originalHistory: [],
2642
+ itemSelector: null,
2643
+ originalItem: null,
2644
+ state: "ready",
2645
+ editingComponent: null,
2646
+ editingComponentId: null,
2647
+ editableComponentIds: /* @__PURE__ */ new Set()
2648
+ }));
2649
+ });
2647
2650
  },
2648
2651
  compose: (appState, componentName, editedItem, displayName, category) => {
2649
2652
  if (!componentName) {
@@ -3783,7 +3786,6 @@ var usePublish = () => {
3783
3786
  // src/puck/overrides/Header.tsx
3784
3787
  var import_jsx_runtime8 = require("react/jsx-runtime");
3785
3788
  var getClassName2 = get_class_name_factory_default("Header", Header_module_default);
3786
- var usePuck = (0, import_puck13.createUsePuck)();
3787
3789
  var Header = ({
3788
3790
  onPublish,
3789
3791
  children
@@ -3833,7 +3835,7 @@ var ActionBar_module_default = { "ActionBar": "_ActionBar_pvuie_5", "ActionBar-l
3833
3835
  var import_shallow = require("zustand/shallow");
3834
3836
  var import_jsx_runtime9 = require("react/jsx-runtime");
3835
3837
  var getClassName3 = get_class_name_factory_default("ActionBar", ActionBar_module_default);
3836
- var usePuck2 = (0, import_puck14.createUsePuck)();
3838
+ var usePuck = (0, import_puck14.createUsePuck)();
3837
3839
  var ActionBarOverride = (props) => {
3838
3840
  var _a, _b;
3839
3841
  const { handleBuild } = useBuild(props.label ? props.label + " Soft Component" : "New Soft Component");
@@ -3842,10 +3844,10 @@ var ActionBarOverride = (props) => {
3842
3844
  const overrides = useSoftConfig((s) => s.overrides);
3843
3845
  const softComponents = useSoftConfig((s) => s.softComponents, import_shallow.shallow);
3844
3846
  const editableIds = useSoftConfig((s) => s.editableComponentIds);
3845
- const selectedItem = usePuck2((s) => s.selectedItem);
3846
- const rootProps = usePuck2((s) => s.appState.data.root.props);
3847
+ const selectedItem = usePuck((s) => s.selectedItem);
3848
+ const rootProps = usePuck((s) => s.appState.data.root.props);
3847
3849
  const status = useSoftConfig((s) => s.state);
3848
- const itemSelector = usePuck2((s) => s.appState.ui.itemSelector);
3850
+ const itemSelector = usePuck((s) => s.appState.ui.itemSelector);
3849
3851
  const softKeys = Object.keys(softComponents);
3850
3852
  const key = (0, import_react9.useMemo)(() => {
3851
3853
  const selectedType = selectedItem == null ? void 0 : selectedItem.type;
@@ -4000,14 +4002,14 @@ var Modal = ({
4000
4002
  var import_shallow2 = require("zustand/shallow");
4001
4003
  var import_jsx_runtime11 = require("react/jsx-runtime");
4002
4004
  var getClassName5 = get_class_name_factory_default("DrawerItem", DrawerItem_module_default);
4003
- var usePuck3 = (0, import_puck15.createUsePuck)();
4005
+ var usePuck2 = (0, import_puck15.createUsePuck)();
4004
4006
  var DrawerItem = (props) => {
4005
4007
  const componentMeta = useSoftConfig((s) => s.softComponents[props.name]);
4006
4008
  const displayName = props.label || (componentMeta == null ? void 0 : componentMeta.name) || props.name;
4007
4009
  const softComponents = new Set(
4008
4010
  Object.keys(useSoftConfig((s) => s.softComponents, import_shallow2.shallow))
4009
4011
  );
4010
- const getPermissions = usePuck3((s) => s.getPermissions);
4012
+ const getPermissions = usePuck2((s) => s.getPermissions);
4011
4013
  const insertAllowed = getPermissions({ type: props.name }).insert;
4012
4014
  const removeSoftComponentVersion = useSoftConfig(
4013
4015
  (s) => s.removeSoftComponentVersion
@@ -4233,7 +4235,7 @@ var Drawer_module_default = { "Drawer": "_Drawer_12zq5_1", "Drawer-category": "_
4233
4235
  var import_jsx_runtime12 = require("react/jsx-runtime");
4234
4236
  var getClassName6 = get_class_name_factory_default("Drawer", Drawer_module_default);
4235
4237
  var getCategoryClassName = get_class_name_factory_default("Drawer-category", Drawer_module_default);
4236
- var usePuck4 = (0, import_puck16.createUsePuck)();
4238
+ var usePuck3 = (0, import_puck16.createUsePuck)();
4237
4239
  var CategorySection = ({
4238
4240
  id,
4239
4241
  title,
@@ -4267,8 +4269,8 @@ var CategorySection = ({
4267
4269
  ] });
4268
4270
  var Drawer = (_props) => {
4269
4271
  var _a, _b;
4270
- const config = usePuck4((s) => s.config);
4271
- const getPermissions = usePuck4((s) => s.getPermissions);
4272
+ const config = usePuck3((s) => s.config);
4273
+ const getPermissions = usePuck3((s) => s.getPermissions);
4272
4274
  const categories = (_a = config.categories) != null ? _a : {};
4273
4275
  const categorised = new Set(
4274
4276
  Object.values(categories).flatMap((cat) => {
@@ -4341,11 +4343,11 @@ var Drawer = (_props) => {
4341
4343
  // src/puck/overrides/HeaderActions.tsx
4342
4344
  var import_puck17 = require("@measured/puck");
4343
4345
  var import_jsx_runtime13 = require("react/jsx-runtime");
4344
- var usePuck5 = (0, import_puck17.createUsePuck)();
4346
+ var usePuck4 = (0, import_puck17.createUsePuck)();
4345
4347
  var HeaderActions = ({ children }) => {
4346
4348
  const { handleComplete } = useComplete();
4347
4349
  const { handleCancel, canCancel } = useCancel();
4348
- const dispatch = usePuck5((s) => s.dispatch);
4350
+ const dispatch = usePuck4((s) => s.dispatch);
4349
4351
  const inspect = useSoftConfig((s) => s.builder.inspect);
4350
4352
  return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_jsx_runtime13.Fragment, { children: canCancel ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
4351
4353
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_puck17.Button, { onClick: handleCancel, children: "Cancel" }),
@@ -2239,25 +2239,6 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2239
2239
  if (!selectedItem || !itemSelector) {
2240
2240
  throw new Error("No item selected to build from.");
2241
2241
  }
2242
- puckDispatch({
2243
- type: "set",
2244
- state: (previous) => {
2245
- var _a;
2246
- return {
2247
- ui: __spreadProps(__spreadValues({}, previous.ui), {
2248
- itemSelector: null
2249
- }),
2250
- data: __spreadProps(__spreadValues({}, previous.data), {
2251
- root: __spreadProps(__spreadValues({}, previous.data.root), {
2252
- props: __spreadProps(__spreadValues({}, (_a = previous.data.root) == null ? void 0 : _a.props), {
2253
- _name: name || "New Soft Component"
2254
- })
2255
- })
2256
- // content: [{ ...selectedItem }],
2257
- })
2258
- };
2259
- }
2260
- });
2261
2242
  const config = __spreadValues({}, get().softConfig);
2262
2243
  const overrides = get().overrides;
2263
2244
  const buildConfig = builderConfig(
@@ -2303,10 +2284,21 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2303
2284
  }));
2304
2285
  requestAnimationFrame(
2305
2286
  () => puckDispatch({
2306
- type: "replaceRoot",
2307
- root: {
2308
- title: "Soft Component Builder",
2309
- _name: name || "New Soft Component"
2287
+ type: "set",
2288
+ state: (previous) => {
2289
+ var _a;
2290
+ return {
2291
+ ui: __spreadProps(__spreadValues({}, previous.ui), {
2292
+ itemSelector: null
2293
+ }),
2294
+ data: __spreadProps(__spreadValues({}, previous.data), {
2295
+ root: __spreadProps(__spreadValues({}, previous.data.root), {
2296
+ props: __spreadProps(__spreadValues({}, (_a = previous.data.root) == null ? void 0 : _a.props), {
2297
+ _name: name || "New Soft Component"
2298
+ })
2299
+ })
2300
+ })
2301
+ };
2310
2302
  }
2311
2303
  })
2312
2304
  );
@@ -2331,12 +2323,6 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2331
2323
  `Soft component "${softComponentName}" with version "${softComponentVersion}" not found.`
2332
2324
  );
2333
2325
  }
2334
- puckDispatch({
2335
- type: "setUi",
2336
- ui: (previous) => __spreadProps(__spreadValues({}, previous), {
2337
- itemSelector: void 0
2338
- })
2339
- });
2340
2326
  const { root, content } = softComponentToAppState(
2341
2327
  softComponent,
2342
2328
  softComponentName,
@@ -2372,36 +2358,45 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2372
2358
  return components;
2373
2359
  }
2374
2360
  );
2375
- puckDispatch({
2376
- type: "setData",
2377
- data: (prevData) => ({
2378
- root: __spreadProps(__spreadValues({}, root), { _versions: versions }),
2379
- content: walkTree3(__spreadValues({}, prevData), __spreadValues({}, config), (components) => {
2380
- const next = components.map((component) => __spreadProps(__spreadValues({}, component), {
2381
- props: __spreadValues({}, component.props)
2382
- }));
2383
- const index = next.findIndex(
2384
- (component) => component.props.id === selectedItem.props.id
2385
- );
2386
- if (index !== -1) {
2387
- next.splice(
2388
- index,
2389
- 1,
2390
- ...decomposedComponents.map((component) => __spreadProps(__spreadValues({}, component), {
2391
- props: __spreadValues({}, component.props)
2392
- }))
2393
- );
2394
- }
2395
- return next;
2396
- }).content
2397
- })
2398
- });
2399
- requestAnimationFrame(
2400
- () => setEditVisibility(get().iframeDoc, {
2361
+ requestAnimationFrame(() => {
2362
+ puckDispatch({
2363
+ type: "set",
2364
+ state: (previous) => ({
2365
+ data: {
2366
+ root: __spreadProps(__spreadValues({}, root), { _versions: versions }),
2367
+ content: walkTree3(
2368
+ __spreadValues({}, previous.data),
2369
+ __spreadValues({}, config),
2370
+ (components) => {
2371
+ const next = components.map((component) => __spreadProps(__spreadValues({}, component), {
2372
+ props: __spreadValues({}, component.props)
2373
+ }));
2374
+ const index = next.findIndex(
2375
+ (component) => component.props.id === selectedItem.props.id
2376
+ );
2377
+ if (index !== -1) {
2378
+ next.splice(
2379
+ index,
2380
+ 1,
2381
+ ...decomposedComponents.map((component) => __spreadProps(__spreadValues({}, component), {
2382
+ props: __spreadValues({}, component.props)
2383
+ }))
2384
+ );
2385
+ }
2386
+ return next;
2387
+ }
2388
+ ).content
2389
+ },
2390
+ ui: __spreadProps(__spreadValues({}, previous.ui), {
2391
+ itemSelector: null
2392
+ })
2393
+ })
2394
+ });
2395
+ setEditVisibility(get().iframeDoc, {
2401
2396
  mode: "remodel",
2402
2397
  editableIds
2403
- })
2404
- );
2398
+ });
2399
+ });
2405
2400
  set((s) => __spreadProps(__spreadValues({}, s), {
2406
2401
  storedConfig: config,
2407
2402
  softConfig: buildConfig,
@@ -2508,6 +2503,7 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2508
2503
  }),
2509
2504
  storedConfig: void 0,
2510
2505
  state: "inspecting",
2506
+ // Temporarily shift state to inspect() before finalizing back to ready
2511
2507
  originalHistory: []
2512
2508
  });
2513
2509
  });
@@ -2556,34 +2552,41 @@ var createBuildersSlice = (set, get, initialConfig) => ({
2556
2552
  type: "setData",
2557
2553
  data: (data) => {
2558
2554
  return reconstructedTree(data);
2559
- }
2555
+ },
2556
+ recordHistory: true
2557
+ // Record this swap on the standard undo/redo stack
2560
2558
  });
2559
+ clearEditVisibility(get().iframeDoc);
2560
+ set((s) => __spreadProps(__spreadValues({}, s), {
2561
+ state: "ready",
2562
+ setItemSelector: void 0,
2563
+ setOriginalItem: void 0,
2564
+ editingComponent: null,
2565
+ editingComponentId: null,
2566
+ editableComponentIds: /* @__PURE__ */ new Set()
2567
+ }));
2561
2568
  });
2562
- requestAnimationFrame(() => clearEditVisibility(get().iframeDoc));
2563
- set((s) => __spreadProps(__spreadValues({}, s), {
2564
- state: "ready",
2565
- setItemSelector: void 0,
2566
- setOriginalItem: void 0,
2567
- editingComponent: null,
2568
- editingComponentId: null,
2569
- editableComponentIds: /* @__PURE__ */ new Set()
2570
- }));
2571
2569
  },
2572
2570
  cancel: (setHistories) => {
2573
2571
  const storedHistories = get().originalHistory;
2574
- requestAnimationFrame(() => setHistories([...storedHistories]));
2575
- requestAnimationFrame(() => clearEditVisibility(get().iframeDoc));
2576
2572
  set((s) => __spreadProps(__spreadValues({}, s), {
2577
- softConfig: get().storedConfig || initialConfig,
2578
- storedConfig: void 0,
2579
- originalHistory: [],
2580
- itemSelector: null,
2581
- originalItem: null,
2582
- state: "ready",
2583
- editingComponent: null,
2584
- editingComponentId: null,
2585
- editableComponentIds: /* @__PURE__ */ new Set()
2573
+ state: "cancelling"
2586
2574
  }));
2575
+ setHistories([...storedHistories]);
2576
+ requestAnimationFrame(() => {
2577
+ clearEditVisibility(get().iframeDoc);
2578
+ set((s) => __spreadProps(__spreadValues({}, s), {
2579
+ softConfig: get().storedConfig || initialConfig,
2580
+ storedConfig: void 0,
2581
+ originalHistory: [],
2582
+ itemSelector: null,
2583
+ originalItem: null,
2584
+ state: "ready",
2585
+ editingComponent: null,
2586
+ editingComponentId: null,
2587
+ editableComponentIds: /* @__PURE__ */ new Set()
2588
+ }));
2589
+ });
2587
2590
  },
2588
2591
  compose: (appState, componentName, editedItem, displayName, category) => {
2589
2592
  if (!componentName) {
@@ -3680,7 +3683,7 @@ var useSetDefaultVersion = () => {
3680
3683
  };
3681
3684
 
3682
3685
  // src/puck/overrides/Header.tsx
3683
- import { Button, createUsePuck as createUsePuck10 } from "@measured/puck";
3686
+ import { Button } from "@measured/puck";
3684
3687
 
3685
3688
  // css-module:/home/osamu/Documents/netlisian-soft/packages/soft-config/src/puck/overrides/Header.module.css#css-module
3686
3689
  var Header_module_default = { "Header": "_Header_19oj9_1" };
@@ -3723,7 +3726,6 @@ var usePublish = () => {
3723
3726
  // src/puck/overrides/Header.tsx
3724
3727
  import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs2 } from "react/jsx-runtime";
3725
3728
  var getClassName2 = get_class_name_factory_default("Header", Header_module_default);
3726
- var usePuck = createUsePuck10();
3727
3729
  var Header = ({
3728
3730
  onPublish,
3729
3731
  children
@@ -3773,7 +3775,7 @@ var ActionBar_module_default = { "ActionBar": "_ActionBar_pvuie_5", "ActionBar-l
3773
3775
  import { shallow } from "zustand/shallow";
3774
3776
  import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
3775
3777
  var getClassName3 = get_class_name_factory_default("ActionBar", ActionBar_module_default);
3776
- var usePuck2 = createUsePuck11();
3778
+ var usePuck = createUsePuck11();
3777
3779
  var ActionBarOverride = (props) => {
3778
3780
  var _a, _b;
3779
3781
  const { handleBuild } = useBuild(props.label ? props.label + " Soft Component" : "New Soft Component");
@@ -3782,10 +3784,10 @@ var ActionBarOverride = (props) => {
3782
3784
  const overrides = useSoftConfig((s) => s.overrides);
3783
3785
  const softComponents = useSoftConfig((s) => s.softComponents, shallow);
3784
3786
  const editableIds = useSoftConfig((s) => s.editableComponentIds);
3785
- const selectedItem = usePuck2((s) => s.selectedItem);
3786
- const rootProps = usePuck2((s) => s.appState.data.root.props);
3787
+ const selectedItem = usePuck((s) => s.selectedItem);
3788
+ const rootProps = usePuck((s) => s.appState.data.root.props);
3787
3789
  const status = useSoftConfig((s) => s.state);
3788
- const itemSelector = usePuck2((s) => s.appState.ui.itemSelector);
3790
+ const itemSelector = usePuck((s) => s.appState.ui.itemSelector);
3789
3791
  const softKeys = Object.keys(softComponents);
3790
3792
  const key = useMemo3(() => {
3791
3793
  const selectedType = selectedItem == null ? void 0 : selectedItem.type;
@@ -3940,14 +3942,14 @@ var Modal = ({
3940
3942
  import { shallow as shallow2 } from "zustand/shallow";
3941
3943
  import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs4 } from "react/jsx-runtime";
3942
3944
  var getClassName5 = get_class_name_factory_default("DrawerItem", DrawerItem_module_default);
3943
- var usePuck3 = createUsePuck12();
3945
+ var usePuck2 = createUsePuck12();
3944
3946
  var DrawerItem = (props) => {
3945
3947
  const componentMeta = useSoftConfig((s) => s.softComponents[props.name]);
3946
3948
  const displayName = props.label || (componentMeta == null ? void 0 : componentMeta.name) || props.name;
3947
3949
  const softComponents = new Set(
3948
3950
  Object.keys(useSoftConfig((s) => s.softComponents, shallow2))
3949
3951
  );
3950
- const getPermissions = usePuck3((s) => s.getPermissions);
3952
+ const getPermissions = usePuck2((s) => s.getPermissions);
3951
3953
  const insertAllowed = getPermissions({ type: props.name }).insert;
3952
3954
  const removeSoftComponentVersion = useSoftConfig(
3953
3955
  (s) => s.removeSoftComponentVersion
@@ -4173,7 +4175,7 @@ var Drawer_module_default = { "Drawer": "_Drawer_12zq5_1", "Drawer-category": "_
4173
4175
  import { jsx as jsx12, jsxs as jsxs5 } from "react/jsx-runtime";
4174
4176
  var getClassName6 = get_class_name_factory_default("Drawer", Drawer_module_default);
4175
4177
  var getCategoryClassName = get_class_name_factory_default("Drawer-category", Drawer_module_default);
4176
- var usePuck4 = createUsePuck13();
4178
+ var usePuck3 = createUsePuck13();
4177
4179
  var CategorySection = ({
4178
4180
  id,
4179
4181
  title,
@@ -4207,8 +4209,8 @@ var CategorySection = ({
4207
4209
  ] });
4208
4210
  var Drawer = (_props) => {
4209
4211
  var _a, _b;
4210
- const config = usePuck4((s) => s.config);
4211
- const getPermissions = usePuck4((s) => s.getPermissions);
4212
+ const config = usePuck3((s) => s.config);
4213
+ const getPermissions = usePuck3((s) => s.getPermissions);
4212
4214
  const categories = (_a = config.categories) != null ? _a : {};
4213
4215
  const categorised = new Set(
4214
4216
  Object.values(categories).flatMap((cat) => {
@@ -4281,11 +4283,11 @@ var Drawer = (_props) => {
4281
4283
  // src/puck/overrides/HeaderActions.tsx
4282
4284
  import { Button as Button3, createUsePuck as createUsePuck14 } from "@measured/puck";
4283
4285
  import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
4284
- var usePuck5 = createUsePuck14();
4286
+ var usePuck4 = createUsePuck14();
4285
4287
  var HeaderActions = ({ children }) => {
4286
4288
  const { handleComplete } = useComplete();
4287
4289
  const { handleCancel, canCancel } = useCancel();
4288
- const dispatch = usePuck5((s) => s.dispatch);
4290
+ const dispatch = usePuck4((s) => s.dispatch);
4289
4291
  const inspect = useSoftConfig((s) => s.builder.inspect);
4290
4292
  return /* @__PURE__ */ jsx13(Fragment6, { children: canCancel ? /* @__PURE__ */ jsxs6(Fragment6, { children: [
4291
4293
  /* @__PURE__ */ jsx13(Button3, { onClick: handleCancel, children: "Cancel" }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netlisian/softconfig",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",