@netlisian/softconfig 0.0.9 → 0.1.0

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/README.md CHANGED
File without changes
package/dist/index.css CHANGED
File without changes
package/dist/index.d.mts CHANGED
File without changes
package/dist/index.d.ts CHANGED
File without changes
package/dist/index.js CHANGED
File without changes
package/dist/index.mjs CHANGED
File without changes
@@ -1,5 +1,4 @@
1
- /* css-module:D:osamuProjects
2
- etlisianpackagessoft-configsrcpuckcomponentserror-boundarystyles.module.css\#css-module-data */
1
+ /* css-module:/media/osamu/3628738E28734BBD/osamuProjects/netlisian/packages/soft-config/src/puck/components/error-boundary/styles.module.css/#css-module-data */
3
2
  ._ErrorBoundary_1xl05_5 {
4
3
  padding: 20px;
5
4
  border: 1px solid #ff5858;
@@ -27,8 +26,7 @@ etlisianpackagessoft-configsrcpuckcomponentserror-boundarystyles.module.css\#css
27
26
  background-color: #b71c1c;
28
27
  }
29
28
 
30
- /* css-module:D:osamuProjects
31
- etlisianpackagessoft-configsrcpuckoverridesHeader.module.css\#css-module-data */
29
+ /* css-module:/media/osamu/3628738E28734BBD/osamuProjects/netlisian/packages/soft-config/src/puck/overrides/Header.module.css/#css-module-data */
32
30
  ._Header_19oj9_1 {
33
31
  display: flex;
34
32
  justify-content: space-between;
@@ -37,8 +35,7 @@ etlisianpackagessoft-configsrcpuckoverridesHeader.module.css\#css-module-data */
37
35
  flex-wrap: wrap;
38
36
  }
39
37
 
40
- /* css-module:D:osamuProjects
41
- etlisianpackagessoft-configsrcpuckoverridesActionBar.module.css\#css-module-data */
38
+ /* css-module:/media/osamu/3628738E28734BBD/osamuProjects/netlisian/packages/soft-config/src/puck/overrides/ActionBar.module.css/#css-module-data */
42
39
  ._ActionBar_pvuie_5 {
43
40
  align-items: center;
44
41
  cursor: default;
@@ -122,9 +119,8 @@ etlisianpackagessoft-configsrcpuckoverridesActionBar.module.css\#css-module-data
122
119
  margin: 0;
123
120
  }
124
121
 
125
- /* css-module:D:osamuProjects
126
- etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-data */
127
- ._ComponentItem_lp9eh_1 {
122
+ /* css-module:/media/osamu/3628738E28734BBD/osamuProjects/netlisian/packages/soft-config/src/puck/overrides/ComponentItem.module.css/#css-module-data */
123
+ ._ComponentItem_1kbi2_1 {
128
124
  background: var(--puck-color-white);
129
125
  cursor: grab;
130
126
  border: 1px solid var(--puck-color-grey-09);
@@ -136,7 +132,13 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
136
132
  transition: background-color 50ms ease-in, color 50ms ease-in;
137
133
  display: flex;
138
134
  }
139
- ._ComponentItem-content_lp9eh_14 {
135
+ ._ComponentItem--insertDisabled_1kbi2_14 {
136
+ cursor: not-allowed;
137
+ color: var(--puck-color-grey-5);
138
+ background: var(--puck-color-grey-11);
139
+ pointer-events: none;
140
+ }
141
+ ._ComponentItem-content_1kbi2_21 {
140
142
  flex: 1;
141
143
  display: flex;
142
144
  flex-direction: column;
@@ -145,53 +147,53 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
145
147
  white-space: nowrap;
146
148
  overflow-x: hidden;
147
149
  }
148
- ._ComponentItem-name_lp9eh_24 {
149
- font-weight: 500;
150
+ ._ComponentItem-name_1kbi2_31 {
151
+ font-weight: 400;
150
152
  }
151
- ._ComponentItem-version_lp9eh_28 {
153
+ ._ComponentItem-version_1kbi2_35 {
152
154
  font-size: 10px;
153
155
  color: var(--puck-color-grey-05);
154
156
  }
155
- ._ComponentItem-actions_lp9eh_33 {
157
+ ._ComponentItem-actions_1kbi2_40 {
156
158
  display: flex;
157
159
  align-items: center;
158
160
  gap: 8px;
159
161
  }
160
- ._ComponentItem-settingsButton_lp9eh_39 {
162
+ ._ComponentItem-settingsButton_1kbi2_46 {
161
163
  opacity: 0;
162
164
  transition: opacity 120ms ease;
163
165
  color: var(--puck-color-grey-05);
164
166
  }
165
- ._ComponentItem_lp9eh_1:hover ._ComponentItem-settingsButton_lp9eh_39 {
167
+ ._ComponentItem_1kbi2_1:hover ._ComponentItem-settingsButton_1kbi2_46 {
166
168
  opacity: 1;
167
169
  }
168
- ._ComponentItem-grip_lp9eh_49 {
170
+ ._ComponentItem-grip_1kbi2_56 {
169
171
  color: var(--puck-color-grey-05);
170
172
  display: flex;
171
173
  align-items: center;
172
174
  }
173
- ._ComponentItem-modal_lp9eh_56 {
175
+ ._ComponentItem-modal_1kbi2_63 {
174
176
  background: var(--puck-color-white);
175
177
  display: flex;
176
178
  flex-direction: column;
177
179
  height: 100%;
178
180
  }
179
- ._ComponentItem-modalHeader_lp9eh_63 {
181
+ ._ComponentItem-modalHeader_1kbi2_70 {
180
182
  padding: 24px 32px;
181
183
  border-bottom: 1px solid var(--puck-color-grey-09);
182
184
  }
183
- ._ComponentItem-modalTitle_lp9eh_68 {
185
+ ._ComponentItem-modalTitle_1kbi2_75 {
184
186
  margin: 0 0 4px 0;
185
187
  font-size: 24px;
186
188
  font-weight: 600;
187
189
  color: var(--puck-color-black);
188
190
  }
189
- ._ComponentItem-modalSubtitle_lp9eh_75 {
191
+ ._ComponentItem-modalSubtitle_1kbi2_82 {
190
192
  margin: 0;
191
193
  font-size: 14px;
192
194
  color: var(--puck-color-grey-04);
193
195
  }
194
- ._ComponentItem-modalBody_lp9eh_81 {
196
+ ._ComponentItem-modalBody_1kbi2_88 {
195
197
  flex: 1;
196
198
  padding: 32px;
197
199
  overflow-y: auto;
@@ -199,28 +201,28 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
199
201
  flex-direction: column;
200
202
  gap: 32px;
201
203
  }
202
- ._ComponentItem-section_lp9eh_90 {
204
+ ._ComponentItem-section_1kbi2_97 {
203
205
  display: flex;
204
206
  flex-direction: column;
205
207
  gap: 16px;
206
208
  }
207
- ._ComponentItem-sectionTitle_lp9eh_96 {
209
+ ._ComponentItem-sectionTitle_1kbi2_103 {
208
210
  margin: 0;
209
211
  font-size: 16px;
210
212
  font-weight: 600;
211
213
  color: var(--puck-color-black);
212
214
  }
213
- ._ComponentItem-sectionDescription_lp9eh_103 {
215
+ ._ComponentItem-sectionDescription_1kbi2_110 {
214
216
  margin: 0;
215
217
  font-size: 14px;
216
218
  color: var(--puck-color-grey-04);
217
219
  }
218
- ._ComponentItem-versionList_lp9eh_109 {
220
+ ._ComponentItem-versionList_1kbi2_116 {
219
221
  display: flex;
220
222
  flex-direction: column;
221
223
  gap: 8px;
222
224
  }
223
- ._ComponentItem-versionRow_lp9eh_115 {
225
+ ._ComponentItem-versionRow_1kbi2_122 {
224
226
  display: flex;
225
227
  justify-content: space-between;
226
228
  align-items: center;
@@ -230,26 +232,26 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
230
232
  background: var(--puck-color-white);
231
233
  transition: all 150ms ease;
232
234
  }
233
- ._ComponentItem-versionRow--isDefault_lp9eh_126 {
235
+ ._ComponentItem-versionRow--isDefault_1kbi2_133 {
234
236
  border-color: var(--puck-color-azure-07);
235
237
  background: var(--puck-color-azure-10);
236
238
  }
237
- ._ComponentItem-versionRow--isMarkedForDeletion_lp9eh_131 {
239
+ ._ComponentItem-versionRow--isMarkedForDeletion_1kbi2_138 {
238
240
  opacity: 0.6;
239
241
  background: var(--puck-color-grey-11);
240
242
  }
241
- ._ComponentItem-versionInfo_lp9eh_136 {
243
+ ._ComponentItem-versionInfo_1kbi2_143 {
242
244
  display: flex;
243
245
  align-items: center;
244
246
  gap: 12px;
245
247
  flex: 1;
246
248
  }
247
- ._ComponentItem-versionNumber_lp9eh_143 {
249
+ ._ComponentItem-versionNumber_1kbi2_150 {
248
250
  font-size: 14px;
249
251
  font-weight: 500;
250
252
  color: var(--puck-color-black);
251
253
  }
252
- ._ComponentItem-defaultBadge_lp9eh_149 {
254
+ ._ComponentItem-defaultBadge_1kbi2_156 {
253
255
  font-size: 11px;
254
256
  padding: 3px 8px;
255
257
  border-radius: 4px;
@@ -259,7 +261,7 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
259
261
  text-transform: uppercase;
260
262
  letter-spacing: 0.5px;
261
263
  }
262
- ._ComponentItem-deleteBadge_lp9eh_160 {
264
+ ._ComponentItem-deleteBadge_1kbi2_167 {
263
265
  font-size: 11px;
264
266
  padding: 3px 8px;
265
267
  border-radius: 4px;
@@ -269,15 +271,15 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
269
271
  text-transform: uppercase;
270
272
  letter-spacing: 0.5px;
271
273
  }
272
- ._ComponentItem-versionActions_lp9eh_171 {
274
+ ._ComponentItem-versionActions_1kbi2_178 {
273
275
  display: flex;
274
276
  gap: 8px;
275
277
  align-items: center;
276
278
  }
277
- ._ComponentItem-migrationOptions_lp9eh_177 {
279
+ ._ComponentItem-migrationOptions_1kbi2_184 {
278
280
  width: 100%;
279
281
  }
280
- ._ComponentItem-select_lp9eh_181 {
282
+ ._ComponentItem-select_1kbi2_188 {
281
283
  width: 100%;
282
284
  padding: 10px 12px;
283
285
  border: 1px solid var(--puck-color-grey-09);
@@ -288,14 +290,14 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
288
290
  cursor: pointer;
289
291
  transition: border-color 150ms ease;
290
292
  }
291
- ._ComponentItem-select_lp9eh_181:hover {
293
+ ._ComponentItem-select_1kbi2_188:hover {
292
294
  border-color: var(--puck-color-grey-07);
293
295
  }
294
- ._ComponentItem-select_lp9eh_181:focus {
296
+ ._ComponentItem-select_1kbi2_188:focus {
295
297
  outline: none;
296
298
  border-color: var(--puck-color-azure-07);
297
299
  }
298
- ._ComponentItem-modalFooter_lp9eh_202 {
300
+ ._ComponentItem-modalFooter_1kbi2_209 {
299
301
  padding: 20px 32px;
300
302
  border-top: 1px solid var(--puck-color-grey-09);
301
303
  display: flex;
@@ -303,17 +305,16 @@ etlisianpackagessoft-configsrcpuckoverridesComponentItem.module.css\#css-module-
303
305
  align-items: center;
304
306
  background: var(--puck-color-grey-11);
305
307
  }
306
- ._ComponentItem-footerLeft_lp9eh_211 {
308
+ ._ComponentItem-footerLeft_1kbi2_218 {
307
309
  display: flex;
308
310
  gap: 12px;
309
311
  }
310
- ._ComponentItem-footerRight_lp9eh_216 {
312
+ ._ComponentItem-footerRight_1kbi2_223 {
311
313
  display: flex;
312
314
  gap: 12px;
313
315
  }
314
316
 
315
- /* css-module:D:osamuProjects
316
- etlisianpackagessoft-configsrcpuckcomponentsmodalstyles.module.css\#css-module-data */
317
+ /* css-module:/media/osamu/3628738E28734BBD/osamuProjects/netlisian/packages/soft-config/src/puck/components/modal/styles.module.css/#css-module-data */
317
318
  ._Modal_pvj02_1 {
318
319
  background: color-mix(in srgb, var(--puck-color-black) 75%, transparent);
319
320
  display: none;
@@ -1,6 +1,6 @@
1
1
  import * as zustand from 'zustand';
2
2
  import { StoreApi } from 'zustand';
3
- import { History, AppState, PuckApi, ComponentConfig, ComponentData, DefaultComponentProps, Field, Config, Fields, Data } from '@measured/puck';
3
+ import { History, AppState, PuckApi, ComponentData, ComponentConfig, DefaultComponentProps, Field, Config, Fields, PuckAction, Data } from '@measured/puck';
4
4
  import * as react from 'react';
5
5
  import react__default, { ReactNode, ReactElement } from 'react';
6
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -38,7 +38,7 @@ type BuildersSlice = {
38
38
  remodel: (history: History<AppState>[], selectedItem: PuckApi["selectedItem"], itemSelector: {
39
39
  index: number;
40
40
  zone?: string;
41
- } | null, puckDispatch: PuckApi["dispatch"]) => void;
41
+ } | null, puckDispatch: PuckApi["dispatch"], refreshPermission: () => void) => void;
42
42
  /**
43
43
  * Switch to a different version of the soft component being remodeled.
44
44
  *
@@ -61,7 +61,7 @@ type BuildersSlice = {
61
61
  * - Strip the build settings fields
62
62
  * - Apply modified history to puck data.
63
63
  */
64
- complete: (appState: AppState<any>, setHistories: PuckApi["history"]["setHistories"]) => string;
64
+ complete: (appState: AppState<any>, setHistories: PuckApi["history"]["setHistories"], getItemBySelector: PuckApi["getItemBySelector"]) => string;
65
65
  demolish: (componentName: string, data: AppState["data"], puckDispatch: PuckApi["dispatch"]) => void;
66
66
  inspect: (componentName: string, puckDispatch: PuckApi["dispatch"]) => void;
67
67
  /**
@@ -77,7 +77,7 @@ type BuildersSlice = {
77
77
  /** Compose multiple components into a soft component.
78
78
  * 1. SoftComponent: Get soft fields + default values from the appState.root + sub-component maps + fixedProps
79
79
  */
80
- compose: (appState: AppState, componentName: string) => [ComponentConfig, string] | undefined;
80
+ compose: (appState: AppState, componentName: string, editedItem: ComponentData) => [ComponentConfig, string] | undefined;
81
81
  /** Break down a composed component into its parts.
82
82
  * 1. Get softComponentProps
83
83
  * 2. Create a virtual component with all the props from soft-component.
@@ -146,6 +146,13 @@ type VersionedSoftComponent = {
146
146
  };
147
147
  };
148
148
  };
149
+ /**
150
+ * Dependencies map: version -> Set of component names this component depends on
151
+ * Automatically inferred from component structure but can be overridden
152
+ */
153
+ dependencies?: {
154
+ [version: string]: Set<string>;
155
+ };
149
156
  };
150
157
  type SoftComponents = Record<string, VersionedSoftComponent>;
151
158
 
@@ -265,11 +272,54 @@ type AppStore = {
265
272
  removeSoftCategoryConfig: (key: string) => void;
266
273
  builder: BuildersSlice;
267
274
  setSoftComponent: (key: string, version: string, component: SoftComponent) => void;
275
+ setSoftComponents: (components: SoftComponents) => void;
276
+ hydrateTransforms: () => void;
268
277
  setSoftComponentDefaultVersion: (key: string, version: string) => void;
269
278
  removeSoftComponent: (key: string) => void;
279
+ editingComponentId: string | null;
280
+ editableComponentIds: Set<string>;
281
+ setEditableComponentIds: (ids: Set<string>) => void;
282
+ addEditableComponentId: (id: string) => void;
283
+ clearEditingState: () => void;
284
+ /**
285
+ * Reverse dependency graph: componentName -> Set of components that depend on it
286
+ * Used to efficiently rebuild dependent components when a soft component is updated
287
+ */
288
+ dependencyGraph: Map<string, Set<string>>;
289
+ /**
290
+ * Rebuild all dependent components after a soft component is updated
291
+ * Only rebuilds components that depend on the changed component
292
+ *
293
+ * @param componentName - The component that was updated
294
+ * @param version - The version that was updated
295
+ */
296
+ rebuildDependents: (componentName: string, version: string) => void;
297
+ /**
298
+ * Iframe document reference for applying styling and edit visibility
299
+ * Stored as a mutable ref to avoid triggering store updates.
300
+ */
301
+ iframeDocRef: {
302
+ current: Document | null;
303
+ };
304
+ /**
305
+ * Get the current iframe document reference
306
+ */
307
+ getIframeDoc: () => Document | null;
308
+ /**
309
+ * Set the iframe document reference without causing re-renders
310
+ */
311
+ setIframeDoc: (doc: Document | null) => void;
312
+ /**
313
+ * Flag to control visibility of version config fields
314
+ */
315
+ showVersionFields: boolean;
316
+ /**
317
+ * Toggle the visibility of version config fields
318
+ */
319
+ setShowVersionFields: (show: boolean) => void;
270
320
  };
271
321
  type AppStoreApi = StoreApi<AppStore>;
272
- declare const createSoftConfigStore: (hardConfig?: Config, softComponents?: SoftComponents, overrides?: Overrides, onActions?: OnActionsCallback) => zustand.UseBoundStore<Omit<Omit<StoreApi<AppStore>, "subscribe"> & {
322
+ declare const createSoftConfigStore: (hardConfig?: Config, softComponents?: SoftComponents, overrides?: Overrides, onActions?: OnActionsCallback, showVersionFields?: boolean) => zustand.UseBoundStore<Omit<StoreApi<AppStore>, "subscribe"> & {
273
323
  subscribe: {
274
324
  (listener: (selectedState: AppStore, previousSelectedState: AppStore) => void): () => void;
275
325
  <U>(selector: (state: AppStore) => U, listener: (selectedState: U, previousSelectedState: U) => void, options?: {
@@ -277,35 +327,20 @@ declare const createSoftConfigStore: (hardConfig?: Config, softComponents?: Soft
277
327
  fireImmediately?: boolean;
278
328
  } | undefined): () => void;
279
329
  };
280
- }, "setState" | "devtools"> & {
281
- setState(partial: AppStore | Partial<AppStore> | ((state: AppStore) => AppStore | Partial<AppStore>), replace?: false | undefined, action?: (string | {
282
- [x: string]: unknown;
283
- [x: number]: unknown;
284
- [x: symbol]: unknown;
285
- type: string;
286
- }) | undefined): void;
287
- setState(state: AppStore | ((state: AppStore) => AppStore), replace: true, action?: (string | {
288
- [x: string]: unknown;
289
- [x: number]: unknown;
290
- [x: symbol]: unknown;
291
- type: string;
292
- }) | undefined): void;
293
- devtools: {
294
- cleanup: () => void;
295
- };
296
330
  }>;
297
331
 
298
- declare const SoftConfigProvider: ({ children, hardConfig, softComponents, overrides, value, onActions, }: {
299
- children: (softConfig: Config, softComponents: SoftComponents) => ReactNode;
332
+ declare const SoftConfigProvider: ({ children, hardConfig, softComponents, overrides, value, onActions, useVersioning, }: {
333
+ children: (softConfig: Config, softComponents: SoftComponents, iframeDoc: AppStore["setIframeDoc"], validateAction: (action: PuckAction) => boolean) => ReactNode;
300
334
  hardConfig: Config;
301
335
  softComponents: SoftComponents;
302
- overrides: Overrides;
336
+ overrides?: Overrides;
303
337
  value?: StoreApi<AppStore>;
304
338
  onActions?: OnActionsCallback;
339
+ useVersioning?: boolean;
305
340
  }) => react_jsx_runtime.JSX.Element;
306
341
 
307
- declare const createUseSoftConfig: () => <T>(selector: (state: AppStore) => T) => T;
308
- declare const useSoftConfig: <T>(selector: (state: AppStore) => T) => T;
342
+ declare const createUseSoftConfig: () => <T>(selector: (state: AppStore) => T, equalityFn?: (a: T, b: T) => boolean) => T;
343
+ declare const useSoftConfig: <T>(selector: (state: AppStore) => T, equalityFn?: (a: T, b: T) => boolean) => T;
309
344
 
310
345
  declare const useBuild: () => {
311
346
  handleBuild: () => void;
@@ -384,6 +419,15 @@ declare const setConfirmHandler: (handler: ConfirmHandler) => void;
384
419
  */
385
420
  declare const confirm: (message: string) => Promise<boolean>;
386
421
 
422
+ /**
423
+ * Create an action callback that validates and handles actions with undo support
424
+ *
425
+ * @param validateAction Function to validate if an action is allowed
426
+ * @param undo Function to undo the last action (from Puck's history)
427
+ * @returns Action handler function
428
+ */
429
+ declare const createActionCallback: (validateAction: (action: PuckAction) => boolean, undo: PuckApi["history"]["back"]) => (action: PuckAction) => void;
430
+
387
431
  /**
388
432
  * Resolves soft components in data by dissolving them to hard components only.
389
433
  *
@@ -409,4 +453,4 @@ declare const Modal: ({ children, onClose, isOpen, }: {
409
453
  isOpen: boolean;
410
454
  }) => react_jsx_runtime.JSX.Element;
411
455
 
412
- export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Header, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type VersionedSoftComponent, confirm, createSoftConfigStore, createUseSoftConfig, notify, resolveSoftConfig, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig };
456
+ export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Header, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type VersionedSoftComponent, confirm, createActionCallback, createSoftConfigStore, createUseSoftConfig, notify, resolveSoftConfig, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig };
@@ -1,6 +1,6 @@
1
1
  import * as zustand from 'zustand';
2
2
  import { StoreApi } from 'zustand';
3
- import { History, AppState, PuckApi, ComponentConfig, ComponentData, DefaultComponentProps, Field, Config, Fields, Data } from '@measured/puck';
3
+ import { History, AppState, PuckApi, ComponentData, ComponentConfig, DefaultComponentProps, Field, Config, Fields, PuckAction, Data } from '@measured/puck';
4
4
  import * as react from 'react';
5
5
  import react__default, { ReactNode, ReactElement } from 'react';
6
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -38,7 +38,7 @@ type BuildersSlice = {
38
38
  remodel: (history: History<AppState>[], selectedItem: PuckApi["selectedItem"], itemSelector: {
39
39
  index: number;
40
40
  zone?: string;
41
- } | null, puckDispatch: PuckApi["dispatch"]) => void;
41
+ } | null, puckDispatch: PuckApi["dispatch"], refreshPermission: () => void) => void;
42
42
  /**
43
43
  * Switch to a different version of the soft component being remodeled.
44
44
  *
@@ -61,7 +61,7 @@ type BuildersSlice = {
61
61
  * - Strip the build settings fields
62
62
  * - Apply modified history to puck data.
63
63
  */
64
- complete: (appState: AppState<any>, setHistories: PuckApi["history"]["setHistories"]) => string;
64
+ complete: (appState: AppState<any>, setHistories: PuckApi["history"]["setHistories"], getItemBySelector: PuckApi["getItemBySelector"]) => string;
65
65
  demolish: (componentName: string, data: AppState["data"], puckDispatch: PuckApi["dispatch"]) => void;
66
66
  inspect: (componentName: string, puckDispatch: PuckApi["dispatch"]) => void;
67
67
  /**
@@ -77,7 +77,7 @@ type BuildersSlice = {
77
77
  /** Compose multiple components into a soft component.
78
78
  * 1. SoftComponent: Get soft fields + default values from the appState.root + sub-component maps + fixedProps
79
79
  */
80
- compose: (appState: AppState, componentName: string) => [ComponentConfig, string] | undefined;
80
+ compose: (appState: AppState, componentName: string, editedItem: ComponentData) => [ComponentConfig, string] | undefined;
81
81
  /** Break down a composed component into its parts.
82
82
  * 1. Get softComponentProps
83
83
  * 2. Create a virtual component with all the props from soft-component.
@@ -146,6 +146,13 @@ type VersionedSoftComponent = {
146
146
  };
147
147
  };
148
148
  };
149
+ /**
150
+ * Dependencies map: version -> Set of component names this component depends on
151
+ * Automatically inferred from component structure but can be overridden
152
+ */
153
+ dependencies?: {
154
+ [version: string]: Set<string>;
155
+ };
149
156
  };
150
157
  type SoftComponents = Record<string, VersionedSoftComponent>;
151
158
 
@@ -265,11 +272,54 @@ type AppStore = {
265
272
  removeSoftCategoryConfig: (key: string) => void;
266
273
  builder: BuildersSlice;
267
274
  setSoftComponent: (key: string, version: string, component: SoftComponent) => void;
275
+ setSoftComponents: (components: SoftComponents) => void;
276
+ hydrateTransforms: () => void;
268
277
  setSoftComponentDefaultVersion: (key: string, version: string) => void;
269
278
  removeSoftComponent: (key: string) => void;
279
+ editingComponentId: string | null;
280
+ editableComponentIds: Set<string>;
281
+ setEditableComponentIds: (ids: Set<string>) => void;
282
+ addEditableComponentId: (id: string) => void;
283
+ clearEditingState: () => void;
284
+ /**
285
+ * Reverse dependency graph: componentName -> Set of components that depend on it
286
+ * Used to efficiently rebuild dependent components when a soft component is updated
287
+ */
288
+ dependencyGraph: Map<string, Set<string>>;
289
+ /**
290
+ * Rebuild all dependent components after a soft component is updated
291
+ * Only rebuilds components that depend on the changed component
292
+ *
293
+ * @param componentName - The component that was updated
294
+ * @param version - The version that was updated
295
+ */
296
+ rebuildDependents: (componentName: string, version: string) => void;
297
+ /**
298
+ * Iframe document reference for applying styling and edit visibility
299
+ * Stored as a mutable ref to avoid triggering store updates.
300
+ */
301
+ iframeDocRef: {
302
+ current: Document | null;
303
+ };
304
+ /**
305
+ * Get the current iframe document reference
306
+ */
307
+ getIframeDoc: () => Document | null;
308
+ /**
309
+ * Set the iframe document reference without causing re-renders
310
+ */
311
+ setIframeDoc: (doc: Document | null) => void;
312
+ /**
313
+ * Flag to control visibility of version config fields
314
+ */
315
+ showVersionFields: boolean;
316
+ /**
317
+ * Toggle the visibility of version config fields
318
+ */
319
+ setShowVersionFields: (show: boolean) => void;
270
320
  };
271
321
  type AppStoreApi = StoreApi<AppStore>;
272
- declare const createSoftConfigStore: (hardConfig?: Config, softComponents?: SoftComponents, overrides?: Overrides, onActions?: OnActionsCallback) => zustand.UseBoundStore<Omit<Omit<StoreApi<AppStore>, "subscribe"> & {
322
+ declare const createSoftConfigStore: (hardConfig?: Config, softComponents?: SoftComponents, overrides?: Overrides, onActions?: OnActionsCallback, showVersionFields?: boolean) => zustand.UseBoundStore<Omit<StoreApi<AppStore>, "subscribe"> & {
273
323
  subscribe: {
274
324
  (listener: (selectedState: AppStore, previousSelectedState: AppStore) => void): () => void;
275
325
  <U>(selector: (state: AppStore) => U, listener: (selectedState: U, previousSelectedState: U) => void, options?: {
@@ -277,35 +327,20 @@ declare const createSoftConfigStore: (hardConfig?: Config, softComponents?: Soft
277
327
  fireImmediately?: boolean;
278
328
  } | undefined): () => void;
279
329
  };
280
- }, "setState" | "devtools"> & {
281
- setState(partial: AppStore | Partial<AppStore> | ((state: AppStore) => AppStore | Partial<AppStore>), replace?: false | undefined, action?: (string | {
282
- [x: string]: unknown;
283
- [x: number]: unknown;
284
- [x: symbol]: unknown;
285
- type: string;
286
- }) | undefined): void;
287
- setState(state: AppStore | ((state: AppStore) => AppStore), replace: true, action?: (string | {
288
- [x: string]: unknown;
289
- [x: number]: unknown;
290
- [x: symbol]: unknown;
291
- type: string;
292
- }) | undefined): void;
293
- devtools: {
294
- cleanup: () => void;
295
- };
296
330
  }>;
297
331
 
298
- declare const SoftConfigProvider: ({ children, hardConfig, softComponents, overrides, value, onActions, }: {
299
- children: (softConfig: Config, softComponents: SoftComponents) => ReactNode;
332
+ declare const SoftConfigProvider: ({ children, hardConfig, softComponents, overrides, value, onActions, useVersioning, }: {
333
+ children: (softConfig: Config, softComponents: SoftComponents, iframeDoc: AppStore["setIframeDoc"], validateAction: (action: PuckAction) => boolean) => ReactNode;
300
334
  hardConfig: Config;
301
335
  softComponents: SoftComponents;
302
- overrides: Overrides;
336
+ overrides?: Overrides;
303
337
  value?: StoreApi<AppStore>;
304
338
  onActions?: OnActionsCallback;
339
+ useVersioning?: boolean;
305
340
  }) => react_jsx_runtime.JSX.Element;
306
341
 
307
- declare const createUseSoftConfig: () => <T>(selector: (state: AppStore) => T) => T;
308
- declare const useSoftConfig: <T>(selector: (state: AppStore) => T) => T;
342
+ declare const createUseSoftConfig: () => <T>(selector: (state: AppStore) => T, equalityFn?: (a: T, b: T) => boolean) => T;
343
+ declare const useSoftConfig: <T>(selector: (state: AppStore) => T, equalityFn?: (a: T, b: T) => boolean) => T;
309
344
 
310
345
  declare const useBuild: () => {
311
346
  handleBuild: () => void;
@@ -384,6 +419,15 @@ declare const setConfirmHandler: (handler: ConfirmHandler) => void;
384
419
  */
385
420
  declare const confirm: (message: string) => Promise<boolean>;
386
421
 
422
+ /**
423
+ * Create an action callback that validates and handles actions with undo support
424
+ *
425
+ * @param validateAction Function to validate if an action is allowed
426
+ * @param undo Function to undo the last action (from Puck's history)
427
+ * @returns Action handler function
428
+ */
429
+ declare const createActionCallback: (validateAction: (action: PuckAction) => boolean, undo: PuckApi["history"]["back"]) => (action: PuckAction) => void;
430
+
387
431
  /**
388
432
  * Resolves soft components in data by dissolving them to hard components only.
389
433
  *
@@ -409,4 +453,4 @@ declare const Modal: ({ children, onClose, isOpen, }: {
409
453
  isOpen: boolean;
410
454
  }) => react_jsx_runtime.JSX.Element;
411
455
 
412
- export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Header, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type VersionedSoftComponent, confirm, createSoftConfigStore, createUseSoftConfig, notify, resolveSoftConfig, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig };
456
+ export { ActionBarOverride as ActionBar, type ActionEventPayload, type AppStore, type AppStoreApi, type BuilderComponentConfig, type BuilderConfig, type BuilderRootConfig, ComponentItem, Header, Modal, type OnActionsCallback, type Overrides, type SoftComponent, type SoftComponents, SoftConfigProvider, type VersionedSoftComponent, confirm, createActionCallback, createSoftConfigStore, createUseSoftConfig, notify, resolveSoftConfig, setConfirmHandler, setNotificationHandler, useBuild, useCancel, useComplete, useDecompose, useDemolish, useInspect, useRemodel, useSetDefaultVersion, useSoftConfig };