k3-plugin-api 1.4.5 → 1.6.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/dist/index.d.ts CHANGED
@@ -1,4 +1,7 @@
1
- import type React from "react";
1
+ import React from "react";
2
+
3
+ //#region index.d.ts
4
+
2
5
  /**
3
6
  * Get plugin-specific settings from the K3 store.
4
7
  * Returns a snapshot of the current settings - not reactive.
@@ -15,268 +18,403 @@ import type React from "react";
15
18
  * }
16
19
  * ```
17
20
  */
18
- export declare function getSettings(pluginId: string): unknown;
21
+ declare function getSettings(pluginId: string): unknown;
22
+ /**
23
+ * Get plugin-specific settings from the K3 store as a reactive hook.
24
+ * Re-renders the component whenever the settings change.
25
+ * Use this in plugin React components.
26
+ *
27
+ * @param pluginId - The unique plugin ID (e.g. "acme.my-plugin")
28
+ * @returns The settings object for this plugin, or `{}` if none are configured
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const settings = useK3PluginSettings("acme.my-plugin") as { apiKey?: string };
33
+ * ```
34
+ */
35
+ declare function useK3PluginSettings(pluginId: string): unknown;
36
+ /**
37
+ * Reactive hook – returns all current configuration variables as a key-value map.
38
+ * Keys are the variable's stable `key` string. Values are resolved (labels, not raw IDs).
39
+ * Re-renders whenever any selection changes.
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * const variables = useConfigurationVariables();
44
+ * const color = variables["color"] as K3SimplifiedValue;
45
+ * ```
46
+ */
47
+ declare function useConfigurationVariables(): K3ConfigurationVariables;
48
+ /**
49
+ * Reactive hook – returns the resolved value for a specific variable by its key,
50
+ * or `undefined` if the variable has no active selection.
51
+ *
52
+ * @param variableKey - The stable key of the variable (as defined in the admin)
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const width = useConfigurationVariable("width") as number;
57
+ * const material = useConfigurationVariable("material") as K3SimplifiedValue;
58
+ * ```
59
+ */
60
+ declare function useConfigurationVariable(variableKey: string): K3ConfigurationVariableEntry | undefined;
61
+ /**
62
+ * Reactive hook – returns the current Bill of Materials (Stückliste).
63
+ * Re-renders whenever the BOM changes (i.e. on any selection change).
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const bom = useBOM() as K3BomEntry[];
68
+ * const total = bom.reduce((sum, e) => sum + e.price.price * e.qty, 0);
69
+ * ```
70
+ */
71
+ declare function useBOM(): K3BomEntry[];
72
+ /**
73
+ * Reactive hook – returns the current total price as a raw number.
74
+ * Re-renders whenever the price changes.
75
+ */
76
+ declare function useTotalPrice(): number;
77
+ /**
78
+ * Reactive hook – returns the current total price formatted as a locale string
79
+ * (e.g. `"1.299,00 €"`), ready for display.
80
+ * Re-renders whenever the price changes.
81
+ */
82
+ declare function useFormattedTotalPrice(): string;
83
+ /**
84
+ * Reactive hook – returns the current K3 app metadata, including the booked
85
+ * product identifier. Returns `null` while the app has not yet loaded.
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const app = useApp() as K3AppInfo | null;
90
+ * if (app?.product === "k3-pro") {
91
+ * // enable pro-only features
92
+ * }
93
+ * ```
94
+ */
95
+ declare function useApp(): K3AppInfo | null;
19
96
  /**
20
97
  * Called by K3 when the plugin is loaded to inject runtime API functions.
21
98
  * @internal This function is called by K3 automatically - plugins should not call it directly.
22
99
  */
23
- export declare function init(api: {
24
- getSettings: (pluginId: string) => unknown;
100
+ declare function init(api: {
101
+ getSettings: (pluginId: string) => unknown;
102
+ usePluginSettings: (pluginId: string) => unknown;
103
+ useConfigurationVariables: () => K3ConfigurationVariables;
104
+ useConfigurationVariable: (variableKey: string) => K3ConfigurationVariableEntry | undefined;
105
+ useBOM: () => unknown[];
106
+ useTotalPrice: () => number;
107
+ useFormattedTotalPrice: () => string;
108
+ useApp: () => unknown | null;
25
109
  }): void;
26
110
  /** A Higher-Order Component: takes the default component, returns a new one. */
27
- export type HOC<P = Record<string, unknown>> = (comp: React.FC<P>) => React.FC<P>;
111
+ type HOC<P = Record<string, unknown>> = (comp: React.FC<P>) => React.FC<P>;
28
112
  /** Four editor languages supported by K3. */
29
- export type LocalizedString = {
30
- de?: string;
31
- en?: string;
32
- nl?: string;
33
- fr?: string;
113
+ type LocalizedString = {
114
+ de?: string;
115
+ en?: string;
116
+ nl?: string;
117
+ fr?: string;
34
118
  };
35
119
  /** An HOC slot with a required description for the admin UI. */
36
- export interface HOCWithDescription<P = Record<string, unknown>> {
37
- hoc: HOC<P>;
38
- /** Describe what this extension point does. Shown in the plugin extensions dialog. */
39
- description: string | LocalizedString;
120
+ interface HOCWithDescription<P = Record<string, unknown>> {
121
+ hoc: HOC<P>;
122
+ /** Describe what this extension point does. Shown in the plugin extensions dialog. */
123
+ description: string | LocalizedString;
40
124
  }
41
125
  /** A logic callback with a required description for the admin UI. */
42
- export interface CallbackWithDescription<T> {
43
- fn: T;
44
- /** Describe what this callback does. Shown in the plugin extensions dialog. */
45
- description: string | LocalizedString;
46
- }
47
- export interface K3PluginDescriptor {
48
- /** Unique stable identifier, e.g. "vendor.myplugin". Required for collision detection. */
49
- id: string;
50
- /** Semver string, e.g. "1.0.0". */
51
- version: string;
52
- /** UI extension points: layout HOCs, input HOCs, dialog HOCs. */
53
- ui?: K3UIExtensions;
54
- /** Viewer / 3D extension points: canvas, scene components, layout components, dynamic models. */
55
- viewer?: K3ViewerExtensions;
56
- /** Logic/callback hooks: config, camera, core. */
57
- logic?: K3LogicExtensions;
58
- settings?: React.ComponentType<{
59
- settings: unknown;
60
- onSave: (settings: unknown) => void;
61
- }>;
62
- /** @deprecated Use viewer.models instead. */
63
- dynamicModels?: DynamicModel[];
64
- }
65
- export interface K3UIExtensions {
66
- /** Override layout shell components. */
67
- layout?: K3LayoutExtensions;
68
- /** Register new variable visualisations (renderers) per variable data type. */
69
- inputs?: K3InputExtensions;
70
- /** Override dialog components. */
71
- dialogs?: K3DialogExtensions;
72
- }
73
- export interface K3LayoutExtensions {
74
- /** Wraps the outermost app shell component. */
75
- root?: HOCWithDescription;
76
- /** Wraps the top header bar containing branding, navigation buttons, and scene controls. */
77
- header?: HOCWithDescription;
78
- /** Wraps the sidebar container that lists groups and variables. */
79
- sidebar?: HOCWithDescription;
80
- /** Wraps the header section inside the sidebar (above the groups list). */
81
- sidebarHeader?: HOCWithDescription;
82
- /** Wraps the footer section inside the sidebar (below the groups list). */
83
- sidebarFooter?: HOCWithDescription;
84
- /** Wraps the bottom footer bar of the app shell. */
85
- footer?: HOCWithDescription;
86
- /** Wraps the main content / viewer area of the configurator page. */
87
- contentView?: HOCWithDescription;
88
- /** Wraps the gallery / image viewer page layout. */
89
- gallery?: HOCWithDescription;
90
- /** Wraps the branding slot in the header (typically a logo + brand name). */
91
- branding?: HOCWithDescription;
92
- /** Wraps the logo image component inside the branding area. */
93
- logo?: HOCWithDescription;
94
- /** Wraps the previous/next group navigation button bar. */
95
- navigationButtons?: HOCWithDescription;
96
- /** Wraps the exit / close configurator button(s). */
97
- exitButtons?: HOCWithDescription;
98
- /** Wraps the 3D scene action buttons (e.g. AR, fullscreen, screenshot). */
99
- sceneButtons?: HOCWithDescription;
100
- /** Wraps the price display component shown in the header or footer. */
101
- price?: HOCWithDescription;
102
- /** Wraps the label/hotspot action display overlay rendered on the desktop 3D canvas. */
103
- labelActionDisplay?: HOCWithDescription;
104
- /** Wraps the label/hotspot action display overlay rendered on mobile. */
105
- mobileLabelActionDisplay?: HOCWithDescription;
106
- /** Wraps the modal shown when a selection violates a mandatory rule. */
107
- invalidRuleModal?: HOCWithDescription;
108
- /** Wraps a component that is only mounted after the app has fully loaded. */
109
- mountedWhenLoaded?: HOCWithDescription;
110
- /** Wraps the top-level configurator page layout (groups navigation + variable panel). */
111
- configurator?: HOCWithDescription;
112
- /** Wraps each group label in the sidebar navigation list. */
113
- groupLabel?: HOCWithDescription;
114
- /** Wraps the expandable group panel that contains its variables. */
115
- groupPanel?: HOCWithDescription;
116
- /** Wraps the additional-groups slot appended below the main groups list. */
117
- additionalGroups?: HOCWithDescription;
118
- /** Wraps the additional-variables slot appended at the end of a group's variable list. */
119
- additionalVars?: HOCWithDescription;
120
- /** Wraps each individual variable label inside a group panel. */
121
- variableLabel?: HOCWithDescription;
126
+ interface CallbackWithDescription<T> {
127
+ fn: T;
128
+ /** Describe what this callback does. Shown in the plugin extensions dialog. */
129
+ description: string | LocalizedString;
130
+ }
131
+ interface K3PluginDescriptor {
132
+ /** Unique stable identifier, e.g. "vendor.myplugin". Required for collision detection. */
133
+ id: string;
134
+ /** Semver string, e.g. "1.0.0". */
135
+ version: string;
136
+ /** UI extension points: layout HOCs, input HOCs, dialog HOCs. */
137
+ ui?: K3UIExtensions;
138
+ /** Viewer / 3D extension points: canvas, scene components, layout components, dynamic models. */
139
+ viewer?: K3ViewerExtensions;
140
+ /** Logic/callback hooks: config, camera, core. */
141
+ logic?: K3LogicExtensions;
142
+ settings?: React.ComponentType<{
143
+ settings: unknown;
144
+ onSave: (settings: unknown) => void;
145
+ }>;
146
+ /** @deprecated Use viewer.models instead. */
147
+ dynamicModels?: DynamicModel[];
148
+ }
149
+ interface K3UIExtensions {
150
+ /** Override layout shell components. */
151
+ layout?: K3LayoutExtensions;
152
+ /** Register new variable visualisations (renderers) per variable data type. */
153
+ inputs?: K3InputExtensions;
154
+ /** Override dialog components. */
155
+ dialogs?: K3DialogExtensions;
156
+ }
157
+ interface K3LayoutExtensions {
158
+ /** Wraps the outermost app shell component. */
159
+ root?: HOCWithDescription;
160
+ /** Wraps the top header bar containing branding, navigation buttons, and scene controls. */
161
+ header?: HOCWithDescription;
162
+ /** Wraps the sidebar container that lists groups and variables. */
163
+ sidebar?: HOCWithDescription;
164
+ /** Wraps the header section inside the sidebar (above the groups list). */
165
+ sidebarHeader?: HOCWithDescription;
166
+ /** Wraps the footer section inside the sidebar (below the groups list). */
167
+ sidebarFooter?: HOCWithDescription;
168
+ /** Wraps the bottom footer bar of the app shell. */
169
+ footer?: HOCWithDescription;
170
+ /** Wraps the main content / viewer area of the configurator page. */
171
+ contentView?: HOCWithDescription;
172
+ /** Wraps the gallery / image viewer page layout. */
173
+ gallery?: HOCWithDescription;
174
+ /** Wraps the branding slot in the header (typically a logo + brand name). */
175
+ branding?: HOCWithDescription;
176
+ /** Wraps the logo image component inside the branding area. */
177
+ logo?: HOCWithDescription;
178
+ /** Wraps the previous/next group navigation button bar. */
179
+ navigationButtons?: HOCWithDescription;
180
+ /** Wraps the exit / close configurator button(s). */
181
+ exitButtons?: HOCWithDescription;
182
+ /** Wraps the 3D scene action buttons (e.g. AR, fullscreen, screenshot). */
183
+ sceneButtons?: HOCWithDescription;
184
+ /** Wraps the price display component shown in the header or footer. */
185
+ price?: HOCWithDescription;
186
+ /** Wraps the label/hotspot action display overlay rendered on the desktop 3D canvas. */
187
+ labelActionDisplay?: HOCWithDescription;
188
+ /** Wraps the label/hotspot action display overlay rendered on mobile. */
189
+ mobileLabelActionDisplay?: HOCWithDescription;
190
+ /** Wraps the modal shown when a selection violates a mandatory rule. */
191
+ invalidRuleModal?: HOCWithDescription;
192
+ /** Wraps a component that is only mounted after the app has fully loaded. */
193
+ mountedWhenLoaded?: HOCWithDescription;
194
+ /** Wraps the top-level configurator page layout (groups navigation + variable panel). */
195
+ configurator?: HOCWithDescription;
196
+ /** Wraps each group label in the sidebar navigation list. */
197
+ groupLabel?: HOCWithDescription;
198
+ /** Wraps the expandable group panel that contains its variables. */
199
+ groupPanel?: HOCWithDescription;
200
+ /** Wraps the additional-groups slot appended below the main groups list. */
201
+ additionalGroups?: HOCWithDescription;
202
+ /** Wraps the additional-variables slot appended at the end of a group's variable list. */
203
+ additionalVars?: HOCWithDescription;
204
+ /** Wraps each individual variable label inside a group panel. */
205
+ variableLabel?: HOCWithDescription;
122
206
  }
123
207
  /**
124
208
  * Props passed to a plugin variable component (VariableVisualisation.component) at runtime.
125
209
  * Use these to render a fully custom variable input UI.
126
210
  */
127
- export interface K3VariableComponentProps {
128
- /** The variable definition for which this component is rendered. */
129
- variable: {
130
- /** Database ID of the variable. */
131
- id: string | number;
132
- /** Translated display label of the variable. */
133
- label: string;
134
- /** Data type of the variable (list, color, number, …). */
135
- type: VariableTypes;
136
- settings?: {
137
- /** Key of the VariableVisualisation that should be used to render this variable. */
138
- template?: string;
139
- templateOptions?: {
140
- min?: number;
141
- max?: number;
142
- digits?: number;
143
- [key: string]: unknown;
144
- };
145
- [key: string]: unknown;
146
- };
211
+ interface K3VariableComponentProps {
212
+ /** The variable definition for which this component is rendered. */
213
+ variable: {
214
+ /** Database ID of the variable. */
215
+ id: string | number;
216
+ /** Translated display label of the variable. */
217
+ label: string;
218
+ /** Data type of the variable (list, color, number, …). */
219
+ type: VariableTypes;
220
+ settings?: {
221
+ /** Key of the VariableVisualisation that should be used to render this variable. */
222
+ template?: string;
223
+ templateOptions?: {
224
+ min?: number;
225
+ max?: number;
226
+ digits?: number;
147
227
  [key: string]: unknown;
228
+ };
229
+ [key: string]: unknown;
148
230
  };
149
- /** The currently active selection for this variable, if any. */
150
- selection?: {
151
- /** ID of the currently selected value. */
152
- id: string | number;
153
- data?: {
154
- inputValue?: number;
155
- [key: string]: unknown;
156
- };
157
- [key: string]: unknown;
231
+ [key: string]: unknown;
232
+ };
233
+ /** The currently active selection for this variable, if any. */
234
+ selection?: {
235
+ /** ID of the currently selected value. */
236
+ id: string | number;
237
+ data?: {
238
+ inputValue?: number;
239
+ [key: string]: unknown;
158
240
  };
159
- /** All available value options for this variable. */
160
- values?: Array<{
161
- /** Database ID of the value. */
162
- id: string | number;
163
- /** Translated display label of the value. */
164
- label: string;
165
- /** Raw value payload (hex color, boolean, etc.). */
166
- value?: string | boolean | null;
167
- [key: string]: unknown;
168
- }>;
169
- /**
170
- * Commit a selection.
171
- * Number variables: onChange(values[0].id, { inputValue: numericValue })
172
- * List/color/boolean: onChange(value.id)
173
- */
174
- onChange: (valueId: string | number, metadata?: {
175
- inputValue?: number;
176
- }) => void;
177
- /** When `true`, the variable is locked and user interaction should be blocked. */
178
- disabled?: boolean;
241
+ [key: string]: unknown;
242
+ };
243
+ /** All available value options for this variable. */
244
+ values?: Array<{
245
+ /** Database ID of the value. */
246
+ id: string | number;
247
+ /** Translated display label of the value. */
248
+ label: string;
249
+ /** Raw value payload (hex color, boolean, etc.). */
250
+ value?: string | boolean | null;
251
+ [key: string]: unknown;
252
+ }>;
253
+ /**
254
+ * Commit a selection.
255
+ * Number variables: onChange(values[0].id, { inputValue: numericValue })
256
+ * List/color/boolean: onChange(value.id)
257
+ */
258
+ onChange: (valueId: string | number, metadata?: {
259
+ inputValue?: number;
260
+ }) => void;
261
+ /** When `true`, the variable is locked and user interaction should be blocked. */
262
+ disabled?: boolean;
179
263
  }
180
264
  /**
181
265
  * A plugin-registered variable renderer (VariableVisualisation).
182
266
  * Displayed as a selectable option in the admin visualisation chooser.
183
267
  * The component owns its full UI — label, input, chrome.
184
268
  */
185
- export interface VariableVisualisation {
186
- /**
187
- * Globally unique template key, e.g. "acme.mySlider".
188
- * Set variable.settings.template = this key to use this visualisation.
189
- * Must be namespaced to avoid collisions.
190
- */
191
- key: string;
192
- /** Label shown in the admin visualisation chooser. */
193
- label: string;
194
- /** Describe what this visualisation does. Shown in the plugin extensions dialog. */
195
- description: string | LocalizedString;
196
- /** Full variable renderer component. Receives K3VariableComponentProps. */
197
- component: React.ComponentType<K3VariableComponentProps>;
198
- }
199
- export interface K3InputExtensions {
200
- /** Register new visualisations for list-type variables. */
201
- list?: VariableVisualisation[];
202
- /** Register new visualisations for color-type variables. */
203
- color?: VariableVisualisation[];
204
- /** Register new visualisations for number-type variables (e.g. custom slider). */
205
- number?: VariableVisualisation[];
206
- /** Register new visualisations for text-type variables. */
207
- text?: VariableVisualisation[];
208
- /** Register new visualisations for boolean-type variables. */
209
- boolean?: VariableVisualisation[];
210
- /** Register new visualisations for image-type variables. */
211
- image?: VariableVisualisation[];
212
- /** Register new visualisations for upload-type variables. */
213
- upload?: VariableVisualisation[];
214
- /** Register new visualisations for components-type variables. */
215
- components?: VariableVisualisation[];
216
- /** Register new visualisations for information-type variables. */
217
- information?: VariableVisualisation[];
218
- }
219
- export interface K3DialogExtensions {
220
- /** Extension points for the order / summary dialog (contact form, price table, confirmation). */
221
- order?: K3OrderDialogExtensions;
222
- /** Extension points for inline selection-warning components shown in the sidebar. */
223
- warnings?: K3WarningExtensions;
224
- }
225
- export interface K3OrderDialogExtensions {
226
- /** Wraps the entire order dialog modal. */
227
- root?: HOCWithDescription;
228
- /** Wraps the dialog headline / title element. */
229
- headline?: HOCWithDescription;
230
- /** Wraps the customer contact form fields (name, email, …). */
231
- contactFields?: HOCWithDescription;
232
- /** Wraps the price table container in the order summary. */
233
- priceTable?: HOCWithDescription;
234
- /** Wraps the list of selected option rows inside the price table. */
235
- priceTableSelectionList?: HOCWithDescription;
236
- /** Wraps the list of article/BOM rows inside the price table. */
237
- priceTableArticleList?: HOCWithDescription;
238
- /** Wraps the totals row at the bottom of the price table. */
239
- priceTableTotal?: HOCWithDescription;
240
- /** Wraps the success confirmation screen shown after a successful order submission. */
241
- confirmationSuccess?: HOCWithDescription;
242
- /** Wraps the error confirmation screen shown after a failed order submission. */
243
- confirmationError?: HOCWithDescription;
244
- }
245
- export interface K3WarningExtensions {
246
- /** Wraps the full invalid-selection warning component (red badge next to a variable value). */
247
- invalidSelection?: HOCWithDescription;
248
- /** Wraps the icon inside the invalid-selection warning. */
249
- invalidSelectionIcon?: HOCWithDescription;
250
- /** Wraps the tooltip content shown when hovering the invalid-selection warning. */
251
- invalidSelectionTooltip?: HOCWithDescription;
252
- /** Wraps the tooltip content shown when a number variable value is out of bounds. */
253
- numberWarningTooltip?: HOCWithDescription;
269
+ interface VariableVisualisation {
270
+ /**
271
+ * Globally unique template key, e.g. "acme.mySlider".
272
+ * Set variable.settings.template = this key to use this visualisation.
273
+ * Must be namespaced to avoid collisions.
274
+ */
275
+ key: string;
276
+ /** Label shown in the admin visualisation chooser. */
277
+ label: string;
278
+ /** Describe what this visualisation does. Shown in the plugin extensions dialog. */
279
+ description: string | LocalizedString;
280
+ /** Full variable renderer component. Receives K3VariableComponentProps. */
281
+ component: React.ComponentType<K3VariableComponentProps>;
282
+ }
283
+ interface K3InputExtensions {
284
+ /** Register new visualisations for list-type variables. */
285
+ list?: VariableVisualisation[];
286
+ /** Register new visualisations for color-type variables. */
287
+ color?: VariableVisualisation[];
288
+ /** Register new visualisations for number-type variables (e.g. custom slider). */
289
+ number?: VariableVisualisation[];
290
+ /** Register new visualisations for text-type variables. */
291
+ text?: VariableVisualisation[];
292
+ /** Register new visualisations for boolean-type variables. */
293
+ boolean?: VariableVisualisation[];
294
+ /** Register new visualisations for image-type variables. */
295
+ image?: VariableVisualisation[];
296
+ /** Register new visualisations for upload-type variables. */
297
+ upload?: VariableVisualisation[];
298
+ /** Register new visualisations for components-type variables. */
299
+ components?: VariableVisualisation[];
300
+ /** Register new visualisations for information-type variables. */
301
+ information?: VariableVisualisation[];
302
+ }
303
+ interface K3DialogExtensions {
304
+ /** Extension points for the order / summary dialog (contact form, price table, confirmation). */
305
+ order?: K3OrderDialogExtensions;
306
+ /** Extension points for inline selection-warning components shown in the sidebar. */
307
+ warnings?: K3WarningExtensions;
308
+ }
309
+ interface K3OrderDialogExtensions {
310
+ /** Wraps the entire order dialog modal. */
311
+ root?: HOCWithDescription;
312
+ /** Wraps the dialog headline / title element. */
313
+ headline?: HOCWithDescription;
314
+ /** Wraps the customer contact form fields (name, email, …). */
315
+ contactFields?: HOCWithDescription;
316
+ /** Wraps the price table container in the order summary. */
317
+ priceTable?: HOCWithDescription;
318
+ /** Wraps the list of selected option rows inside the price table. */
319
+ priceTableSelectionList?: HOCWithDescription;
320
+ /** Wraps the list of article/BOM rows inside the price table. */
321
+ priceTableArticleList?: HOCWithDescription;
322
+ /** Wraps the totals row at the bottom of the price table. */
323
+ priceTableTotal?: HOCWithDescription;
324
+ /** Wraps the success confirmation screen shown after a successful order submission. */
325
+ confirmationSuccess?: HOCWithDescription;
326
+ /** Wraps the error confirmation screen shown after a failed order submission. */
327
+ confirmationError?: HOCWithDescription;
328
+ }
329
+ interface K3WarningExtensions {
330
+ /** Wraps the full invalid-selection warning component (red badge next to a variable value). */
331
+ invalidSelection?: HOCWithDescription;
332
+ /** Wraps the icon inside the invalid-selection warning. */
333
+ invalidSelectionIcon?: HOCWithDescription;
334
+ /** Wraps the tooltip content shown when hovering the invalid-selection warning. */
335
+ invalidSelectionTooltip?: HOCWithDescription;
336
+ /** Wraps the tooltip content shown when a number variable value is out of bounds. */
337
+ numberWarningTooltip?: HOCWithDescription;
338
+ }
339
+ /**
340
+ * Simplified app metadata exposed to plugins.
341
+ * Useful for reading the booked product and subscription info.
342
+ */
343
+ interface K3AppInfo {
344
+ /** Database ID of the app. */
345
+ id: number;
346
+ /** Human-readable app label. */
347
+ label: string;
348
+ /** Unique stable app code. */
349
+ code: string;
350
+ /**
351
+ * Identifier of the booked product (e.g. `"k3-pro"`).
352
+ * Use this to conditionally enable features based on the customer's plan.
353
+ */
354
+ product?: string;
355
+ /** Subscription billing interval for this app. */
356
+ interval?: "month" | "year";
357
+ /** Feature flags of the currently booked product. */
358
+ productDetails?: Record<string, unknown>;
359
+ [key: string]: unknown;
360
+ }
361
+ /**
362
+ * A resolved value option (list, color, boolean, image, upload, multiSelect).
363
+ * Contains human-readable labels and the underlying data value.
364
+ */
365
+ interface K3SimplifiedValue {
366
+ /** Database ID of the value. */
367
+ id: number | string;
368
+ /** Stable key of the value, if defined. */
369
+ key?: string | null;
370
+ /** Translated display label. */
371
+ label: string;
372
+ /** Underlying data: hex color string, boolean flag, or generic string payload. */
373
+ value?: string | boolean | null;
374
+ /** Thumbnail image URL. */
375
+ thumbnail?: string | null;
254
376
  }
377
+ /**
378
+ * A single configuration variable entry. The concrete type depends on the variable type:
379
+ * - Number variables → `number`
380
+ * - Text variables → `string`
381
+ * - List / Color / Boolean / Image / Upload → `K3SimplifiedValue`
382
+ * - MultiSelect → `K3SimplifiedValue[]`
383
+ * - Component variables → `K3ComponentInstanceVariables[]` (recursive)
384
+ */
385
+ type K3ConfigurationVariableEntry = number | string | K3SimplifiedValue | K3SimplifiedValue[] | K3ComponentInstanceVariables[];
386
+ /** A single component instance's variables, keyed by variable key. */
387
+ type K3ComponentInstanceVariables = Record<string, K3ConfigurationVariableEntry>;
388
+ /**
389
+ * The full configuration variables map, keyed by the variable's stable `key` string.
390
+ * Returned by `useConfigurationVariables()`.
391
+ */
392
+ type K3ConfigurationVariables = Record<string, K3ConfigurationVariableEntry>;
255
393
  /**
256
394
  * A single Bill-of-Materials entry exposed to plugin components.
257
395
  * Mirrors the internal BOMEntry shape using only primitive/simple types.
258
396
  */
259
- export interface K3BomEntry {
260
- article: {
261
- id: number;
262
- /** Article number as defined in the K3 admin. */
263
- no: string;
264
- name: string;
265
- description?: string | null;
266
- thumbnail?: string | null;
267
- category?: string | null;
268
- };
269
- /** Quantity of this article for the current selection. */
270
- qty: number;
271
- /** Optional override quantity from the article amount modal. */
272
- amount?: number | null;
273
- /** Price of a single unit of this article. */
274
- price: {
275
- price: number;
276
- unit?: string;
277
- };
278
- /** Whether this is a main article (`true`) or an accessory/surcharge (`false`). */
279
- main?: boolean;
397
+ interface K3BomEntry {
398
+ article: {
399
+ id: number;
400
+ /** Article number as defined in the K3 admin. */
401
+ no: string;
402
+ name: string;
403
+ description?: string | null;
404
+ thumbnail?: string | null;
405
+ category?: string | null;
406
+ };
407
+ /** Quantity of this article for the current selection. */
408
+ qty: number;
409
+ /** Optional override quantity from the article amount modal. */
410
+ amount?: number | null;
411
+ /** Price of a single unit of this article. */
412
+ price: {
413
+ price: number;
414
+ unit?: string;
415
+ };
416
+ /** Whether this is a main article (`true`) or an accessory/surcharge (`false`). */
417
+ main?: boolean;
280
418
  }
281
419
  /**
282
420
  * Props automatically injected into every `customLayoutComponents` entry.
@@ -284,498 +422,498 @@ export interface K3BomEntry {
284
422
  * @remarks TODO(WIP) — This interface will grow as more configurator data is
285
423
  * exposed to plugins.
286
424
  */
287
- export interface CustomLayoutComponentProps {
288
- /** The slot name this component was mounted under. */
289
- name: string;
290
- /**
291
- * Live Bill-of-Materials rows derived from the current selection.
292
- * Each entry represents one article line or surcharge line.
293
- */
294
- bom: K3BomEntry[];
295
- /**
296
- * Aggregated total price for the current configuration in the app's currency unit.
297
- * TODO(WIP): Currency/formatting helpers are not yet part of the public API.
298
- */
299
- totalPrice: number;
300
- /** Any additional props forwarded by the layout. */
301
- [key: string]: unknown;
302
- }
303
- export interface K3ViewerExtensions {
304
- /** Wraps the root Three.js / R3F canvas element. */
305
- canvas?: HOCWithDescription;
306
- /**
307
- * Named React components injected into the configurator layout by key.
308
- * Consumed by `getDynamicComponents` to render plugin-provided UI inside layout slots.
309
- * Use a plain component (no HOC wrapping needed).
310
- *
311
- * Components receive {@link CustomLayoutComponentProps} with BOM and total price data.
312
- */
313
- customLayoutComponents?: Record<string, React.ComponentType<CustomLayoutComponentProps>>;
314
- /** Dynamic 3D model definitions contributed by this plugin. Equivalent to the top-level `dynamicModels`. */
315
- models?: DynamicModel[];
316
- /** Override the label / hotspot overlay components rendered on the 3D canvas. */
317
- labels?: {
318
- /** Wraps the label action display overlay on desktop. Alias for `ui.layout.labelActionDisplay`. */
319
- display?: HOCWithDescription;
320
- /** Wraps the label action display overlay on mobile. Alias for `ui.layout.mobileLabelActionDisplay`. */
321
- mobile?: HOCWithDescription;
322
- };
425
+ interface CustomLayoutComponentProps {
426
+ /** The slot name this component was mounted under. */
427
+ name: string;
428
+ /**
429
+ * Live Bill-of-Materials rows derived from the current selection.
430
+ * Each entry represents one article line or surcharge line.
431
+ */
432
+ bom: K3BomEntry[];
433
+ /**
434
+ * Aggregated total price for the current configuration in the app's currency unit.
435
+ * TODO(WIP): Currency/formatting helpers are not yet part of the public API.
436
+ */
437
+ totalPrice: number;
438
+ /** Any additional props forwarded by the layout. */
439
+ [key: string]: unknown;
440
+ }
441
+ interface K3ViewerExtensions {
442
+ /** Wraps the root Three.js / R3F canvas element. */
443
+ canvas?: HOCWithDescription;
444
+ /**
445
+ * Named React components injected into the configurator layout by key.
446
+ * Consumed by `getDynamicComponents` to render plugin-provided UI inside layout slots.
447
+ * Use a plain component (no HOC wrapping needed).
448
+ *
449
+ * Components receive {@link CustomLayoutComponentProps} with BOM and total price data.
450
+ */
451
+ customLayoutComponents?: Record<string, React.ComponentType<CustomLayoutComponentProps>>;
452
+ /** Dynamic 3D model definitions contributed by this plugin. Equivalent to the top-level `dynamicModels`. */
453
+ models?: DynamicModel[];
454
+ /** Override the label / hotspot overlay components rendered on the 3D canvas. */
455
+ labels?: {
456
+ /** Wraps the label action display overlay on desktop. Alias for `ui.layout.labelActionDisplay`. */
457
+ display?: HOCWithDescription;
458
+ /** Wraps the label action display overlay on mobile. Alias for `ui.layout.mobileLabelActionDisplay`. */
459
+ mobile?: HOCWithDescription;
460
+ };
323
461
  }
324
462
  /** [x, y, z] coordinate tuple used on camera objects. */
325
- export type K3Coordinates = [number, number, number];
463
+ type K3Coordinates = [number, number, number];
326
464
  /**
327
465
  * Restricts a camera to a specific configurator context.
328
466
  * `"group"` / `"variable"` — camera activates only when that item is in view; `id` is the entity's database ID.
329
467
  * `"general"` — camera is always available regardless of the active group or variable.
330
468
  */
331
- export type K3CameraScope = {
332
- type: "group" | "variable";
333
- id: number;
469
+ type K3CameraScope = {
470
+ type: "group" | "variable";
471
+ id: number;
334
472
  } | {
335
- type: "general";
336
- id?: null;
473
+ type: "general";
474
+ id?: null;
337
475
  };
338
476
  interface K3BaseCamera {
339
- /** Unique database ID of the camera record. */
340
- id: string;
341
- /** Human-readable camera name as set in the scene editor. */
342
- name: string;
343
- /** World-space XYZ position of the camera. */
344
- position: K3Coordinates;
345
- /** World-space XYZ point the camera is aimed at. */
346
- lookAt: K3Coordinates;
347
- /** Euler rotation [x, y, z] in radians. */
348
- rotation: K3Coordinates;
349
- /** Optional override for the screenshot render resolution in pixels. */
350
- resolution?: {
351
- width: number;
352
- height: number;
353
- };
354
- /** Transition easing threshold used by the camera animation driver. */
355
- threshold?: number;
356
- /**
357
- * How the camera's look-at target is computed.
358
- * `"dynamic"` — recalculated from the current scene bounding box (default).
359
- * `"static"` — uses the stored `lookAt` value unchanged.
360
- */
361
- focusType?: "dynamic" | "static";
362
- /** Restricts this camera to a specific group or variable context, or `"general"` for all contexts. */
363
- scope?: K3CameraScope;
364
- /** Orthographic zoom factor or perspective field-of-view multiplier. */
365
- zoom?: number;
366
- [key: string]: unknown;
477
+ /** Unique database ID of the camera record. */
478
+ id: string;
479
+ /** Human-readable camera name as set in the scene editor. */
480
+ name: string;
481
+ /** World-space XYZ position of the camera. */
482
+ position: K3Coordinates;
483
+ /** World-space XYZ point the camera is aimed at. */
484
+ lookAt: K3Coordinates;
485
+ /** Euler rotation [x, y, z] in radians. */
486
+ rotation: K3Coordinates;
487
+ /** Optional override for the screenshot render resolution in pixels. */
488
+ resolution?: {
489
+ width: number;
490
+ height: number;
491
+ };
492
+ /** Transition easing threshold used by the camera animation driver. */
493
+ threshold?: number;
494
+ /**
495
+ * How the camera's look-at target is computed.
496
+ * `"dynamic"` — recalculated from the current scene bounding box (default).
497
+ * `"static"` — uses the stored `lookAt` value unchanged.
498
+ */
499
+ focusType?: "dynamic" | "static";
500
+ /** Restricts this camera to a specific group or variable context, or `"general"` for all contexts. */
501
+ scope?: K3CameraScope;
502
+ /** Orthographic zoom factor or perspective field-of-view multiplier. */
503
+ zoom?: number;
504
+ [key: string]: unknown;
367
505
  }
368
506
  /** A perspective camera configured in the K3 scene editor. */
369
- export interface K3PerspectiveCamera extends K3BaseCamera {
370
- type: "PerspectiveCamera";
371
- /** Intrinsic perspective parameters: field-of-view in degrees, aspect ratio, near/far clip planes. */
372
- baseSettings?: {
373
- fov: number;
374
- aspect: number;
375
- near: number;
376
- far: number;
377
- };
507
+ interface K3PerspectiveCamera extends K3BaseCamera {
508
+ type: "PerspectiveCamera";
509
+ /** Intrinsic perspective parameters: field-of-view in degrees, aspect ratio, near/far clip planes. */
510
+ baseSettings?: {
511
+ fov: number;
512
+ aspect: number;
513
+ near: number;
514
+ far: number;
515
+ };
378
516
  }
379
517
  /** An orthographic camera configured in the K3 scene editor. */
380
- export interface K3OrthographicCamera extends K3BaseCamera {
381
- type: "OrthographicCamera";
382
- /** Intrinsic orthographic parameters: frustum left/right/top/bottom extents and near/far clip planes. */
383
- baseSettings?: {
384
- left: number;
385
- right: number;
386
- top: number;
387
- bottom: number;
388
- near: number;
389
- far: number;
390
- };
518
+ interface K3OrthographicCamera extends K3BaseCamera {
519
+ type: "OrthographicCamera";
520
+ /** Intrinsic orthographic parameters: frustum left/right/top/bottom extents and near/far clip planes. */
521
+ baseSettings?: {
522
+ left: number;
523
+ right: number;
524
+ top: number;
525
+ bottom: number;
526
+ near: number;
527
+ far: number;
528
+ };
391
529
  }
392
530
  /** A scene camera — perspective or orthographic. Passed to screenshot / camera-list callbacks. */
393
- export type K3Camera = K3PerspectiveCamera | K3OrthographicCamera;
531
+ type K3Camera = K3PerspectiveCamera | K3OrthographicCamera;
394
532
  /** Pixel dimensions used for screenshot rendering. */
395
- export interface K3ScreenshotDimensions {
396
- width: number;
397
- height: number;
533
+ interface K3ScreenshotDimensions {
534
+ width: number;
535
+ height: number;
398
536
  }
399
537
  /** AR platform identifier. */
400
- export type K3ARPlatform = "iOS" | "AndroidOS";
538
+ type K3ARPlatform = "iOS" | "AndroidOS";
401
539
  /**
402
540
  * Minimal structural representation of a Three.js scene graph node.
403
541
  * Cast to `import("three").Object3D` for full Three.js access.
404
542
  */
405
- export interface K3Scene {
406
- /** Three.js object type string, e.g. `"Scene"`, `"Mesh"`, `"Group"`. */
407
- type: string;
408
- /** Direct child nodes of this scene graph node. */
409
- children: readonly K3Scene[];
410
- /** Arbitrary metadata attached by K3 or the GLTF loader (e.g. material names, model IDs). */
411
- userData: Record<string, unknown>;
412
- traverse(callback: (object: K3Scene) => void): void;
413
- getObjectByName(name: string): K3Scene | undefined;
543
+ interface K3Scene {
544
+ /** Three.js object type string, e.g. `"Scene"`, `"Mesh"`, `"Group"`. */
545
+ type: string;
546
+ /** Direct child nodes of this scene graph node. */
547
+ children: readonly K3Scene[];
548
+ /** Arbitrary metadata attached by K3 or the GLTF loader (e.g. material names, model IDs). */
549
+ userData: Record<string, unknown>;
550
+ traverse(callback: (object: K3Scene) => void): void;
551
+ getObjectByName(name: string): K3Scene | undefined;
414
552
  }
415
553
  /** Context passed to `core.onExportAR`. */
416
- export interface K3ARExportContext {
417
- /** Platform the AR export is targeting. */
418
- platform: K3ARPlatform;
419
- /**
420
- * Live Three.js scene graph.
421
- * Cast to `import("three").Object3D` for full Three.js access.
422
- */
423
- scene: K3Scene;
554
+ interface K3ARExportContext {
555
+ /** Platform the AR export is targeting. */
556
+ platform: K3ARPlatform;
557
+ /**
558
+ * Live Three.js scene graph.
559
+ * Cast to `import("three").Object3D` for full Three.js access.
560
+ */
561
+ scene: K3Scene;
424
562
  }
425
563
  /** An uploaded file in a save operation (e.g. a screenshot per camera). */
426
- export interface K3UploadFile {
427
- /** Camera name or custom key identifying this file. */
428
- key: string;
429
- /** The file data. */
430
- file: Blob;
431
- /** Optional explicit file name. */
432
- fileName?: string;
564
+ interface K3UploadFile {
565
+ /** Camera name or custom key identifying this file. */
566
+ key: string;
567
+ /** The file data. */
568
+ file: Blob;
569
+ /** Optional explicit file name. */
570
+ fileName?: string;
433
571
  }
434
572
  /** Result returned to `core.onOpenPdf` after a save/order action. */
435
- export interface K3SaveResult {
436
- /** Generated configuration code. */
437
- code?: string;
438
- /** Pricing verification info. */
439
- price?: {
440
- okay: boolean;
441
- priceSent?: number;
442
- priceCalculated?: number;
443
- };
444
- /** `true` if the save action encountered a server-side error. */
445
- error?: boolean;
446
- /** Optional human-readable error or status message from the server. */
447
- message?: string;
448
- /** URL to a shop or cart page the user can be redirected to after saving. */
449
- shopLink?: string;
450
- /** URL to the generated PDF. */
451
- pdf?: string;
452
- /** Suggested file name for the generated PDF download. */
453
- pdfName?: string;
454
- [key: string]: unknown;
573
+ interface K3SaveResult {
574
+ /** Generated configuration code. */
575
+ code?: string;
576
+ /** Pricing verification info. */
577
+ price?: {
578
+ okay: boolean;
579
+ priceSent?: number;
580
+ priceCalculated?: number;
581
+ };
582
+ /** `true` if the save action encountered a server-side error. */
583
+ error?: boolean;
584
+ /** Optional human-readable error or status message from the server. */
585
+ message?: string;
586
+ /** URL to a shop or cart page the user can be redirected to after saving. */
587
+ shopLink?: string;
588
+ /** URL to the generated PDF. */
589
+ pdf?: string;
590
+ /** Suggested file name for the generated PDF download. */
591
+ pdfName?: string;
592
+ [key: string]: unknown;
455
593
  }
456
594
  /**
457
595
  * Payload dispatched when a configuration is saved (e.g. "order", "cart", "pdf").
458
596
  * Passed to `config.onSaveEvent`.
459
597
  */
460
- export interface K3ConfigurationSavedEvent {
461
- type: "K3ConfigurationSaved";
462
- /** Save action key, e.g. "cart", "pdf", "email". */
463
- actionKey: string;
464
- /** Generated configuration code. */
465
- code: string;
466
- /** Optional customer data if collected during the save flow. */
467
- customer?: {
468
- email?: string;
469
- firstName?: string;
470
- lastName?: string;
471
- [key: string]: unknown;
472
- };
598
+ interface K3ConfigurationSavedEvent {
599
+ type: "K3ConfigurationSaved";
600
+ /** Save action key, e.g. "cart", "pdf", "email". */
601
+ actionKey: string;
602
+ /** Generated configuration code. */
603
+ code: string;
604
+ /** Optional customer data if collected during the save flow. */
605
+ customer?: {
606
+ email?: string;
607
+ firstName?: string;
608
+ lastName?: string;
473
609
  [key: string]: unknown;
610
+ };
611
+ [key: string]: unknown;
474
612
  }
475
613
  /** A persisted configuration object. Passed to `config.onUpdate` and `config.onSave`. */
476
- export interface K3Configuration {
477
- /** Database ID of the saved configuration record. */
478
- id: number | string;
479
- /** ID of the K3 app this configuration belongs to. */
480
- appId: number;
481
- /** Human-readable configuration code generated by the backend (e.g. "ABC-123"). */
482
- code: string;
483
- /** Calculated total price, or `null` if pricing is not configured. */
484
- price: number | null;
485
- /** ISO language code. */
486
- lang: string;
487
- /** Serialised selection state and BOM. */
488
- json: {
489
- /** Array of variable selection states at save time. */
490
- variables: unknown[];
491
- /** Bill-of-materials rows derived from the current selection. */
492
- bom: unknown[];
493
- /** Aggregated summary data (e.g. totals, labels). */
494
- summary: unknown;
495
- [key: string]: unknown;
496
- };
497
- /** Screenshot files, keyed by camera name then file name. */
498
- files: Record<string, Record<string, string>>;
614
+ interface K3Configuration {
615
+ /** Database ID of the saved configuration record. */
616
+ id: number | string;
617
+ /** ID of the K3 app this configuration belongs to. */
618
+ appId: number;
619
+ /** Human-readable configuration code generated by the backend (e.g. "ABC-123"). */
620
+ code: string;
621
+ /** Calculated total price, or `null` if pricing is not configured. */
622
+ price: number | null;
623
+ /** ISO language code. */
624
+ lang: string;
625
+ /** Serialised selection state and BOM. */
626
+ json: {
627
+ /** Array of variable selection states at save time. */
628
+ variables: unknown[];
629
+ /** Bill-of-materials rows derived from the current selection. */
630
+ bom: unknown[];
631
+ /** Aggregated summary data (e.g. totals, labels). */
632
+ summary: unknown;
499
633
  [key: string]: unknown;
634
+ };
635
+ /** Screenshot files, keyed by camera name then file name. */
636
+ files: Record<string, Record<string, string>>;
637
+ [key: string]: unknown;
500
638
  }
501
639
  /** A configuration not yet persisted (no `id` or `code`). */
502
- export type K3NewConfiguration = Omit<K3Configuration, "id" | "code">;
640
+ type K3NewConfiguration = Omit<K3Configuration, "id" | "code">;
503
641
  /** An individual variable selection state. */
504
- export interface K3Selection {
505
- /** Unique selection ID. */
506
- id: string;
507
- /** ID of the variable this selection belongs to. */
508
- variableId: number;
509
- /** ID of the chosen value, or `null` / `undefined` when no value is selected. */
510
- valueId?: number | string | null;
511
- data?: {
512
- /** Number variable input value. */
513
- inputValue?: number;
514
- /** Text variable input value. */
515
- inputText?: string;
516
- /** Image variable URL. */
517
- url?: string;
518
- [key: string]: unknown;
519
- };
642
+ interface K3Selection {
643
+ /** Unique selection ID. */
644
+ id: string;
645
+ /** ID of the variable this selection belongs to. */
646
+ variableId: number;
647
+ /** ID of the chosen value, or `null` / `undefined` when no value is selected. */
648
+ valueId?: number | string | null;
649
+ data?: {
650
+ /** Number variable input value. */
651
+ inputValue?: number;
652
+ /** Text variable input value. */
653
+ inputText?: string;
654
+ /** Image variable URL. */
655
+ url?: string;
520
656
  [key: string]: unknown;
657
+ };
658
+ [key: string]: unknown;
521
659
  }
522
660
  /** Full application snapshot passed to `core.preprocessFullApp` before the store initialises. */
523
- export interface K3FullApp {
524
- app: {
525
- id: number;
526
- [key: string]: unknown;
527
- };
528
- client: {
529
- id: number;
530
- [key: string]: unknown;
531
- };
532
- groups: Array<{
533
- id: number;
534
- [key: string]: unknown;
535
- }>;
536
- variables: Array<{
537
- id: number;
538
- [key: string]: unknown;
539
- }>;
540
- values: Array<{
541
- id: number | string;
542
- [key: string]: unknown;
543
- }>;
544
- articles: Array<{
545
- id: number;
546
- [key: string]: unknown;
547
- }>;
548
- prices: Array<{
549
- id: number;
550
- [key: string]: unknown;
551
- }>;
552
- materials: Array<{
553
- id: number;
554
- [key: string]: unknown;
555
- }>;
556
- models: Array<{
557
- id: number;
558
- [key: string]: unknown;
559
- }>;
560
- images: Array<{
561
- id: number;
562
- [key: string]: unknown;
563
- }>;
564
- rules: Array<{
565
- id: number;
566
- [key: string]: unknown;
567
- }>;
568
- ruleItems: Array<{
569
- id: number;
570
- [key: string]: unknown;
571
- }>;
661
+ interface K3FullApp {
662
+ app: {
663
+ id: number;
664
+ [key: string]: unknown;
665
+ };
666
+ client: {
667
+ id: number;
668
+ [key: string]: unknown;
669
+ };
670
+ groups: Array<{
671
+ id: number;
672
+ [key: string]: unknown;
673
+ }>;
674
+ variables: Array<{
675
+ id: number;
676
+ [key: string]: unknown;
677
+ }>;
678
+ values: Array<{
679
+ id: number | string;
680
+ [key: string]: unknown;
681
+ }>;
682
+ articles: Array<{
683
+ id: number;
684
+ [key: string]: unknown;
685
+ }>;
686
+ prices: Array<{
687
+ id: number;
688
+ [key: string]: unknown;
689
+ }>;
690
+ materials: Array<{
691
+ id: number;
692
+ [key: string]: unknown;
693
+ }>;
694
+ models: Array<{
695
+ id: number;
696
+ [key: string]: unknown;
697
+ }>;
698
+ images: Array<{
699
+ id: number;
700
+ [key: string]: unknown;
701
+ }>;
702
+ rules: Array<{
703
+ id: number;
572
704
  [key: string]: unknown;
705
+ }>;
706
+ ruleItems: Array<{
707
+ id: number;
708
+ [key: string]: unknown;
709
+ }>;
710
+ [key: string]: unknown;
573
711
  }
574
- export interface K3LogicExtensions {
575
- /** Hooks into the configuration data lifecycle (create, update, save). */
576
- config?: {
577
- /**
578
- * Called every time the active configuration object is updated in the store (e.g. on every selection change).
579
- * Return a modified copy to alter prices, codes, or any other configuration field.
580
- */
581
- onUpdate?: CallbackWithDescription<(config: K3Configuration) => K3Configuration>;
582
- /**
583
- * Called just before a configuration is persisted (order, cart, email, …).
584
- * Return a modified copy to inject extra fields or override values before saving.
585
- */
586
- onSave?: CallbackWithDescription<(config: K3Configuration | K3NewConfiguration) => K3Configuration | K3NewConfiguration>;
587
- /**
588
- * Called with the list of screenshot files that will be uploaded alongside the save.
589
- * Return a modified array to add, remove, or rename files.
590
- */
591
- onSaveFiles?: CallbackWithDescription<(files: K3UploadFile[]) => K3UploadFile[]>;
592
- /**
593
- * Called after a successful save action with the dispatched event payload.
594
- * Return a modified payload to add custom fields consumed by downstream integrations.
595
- */
596
- onSaveEvent?: CallbackWithDescription<(payload: K3ConfigurationSavedEvent) => K3ConfigurationSavedEvent>;
597
- };
598
- /** Hooks into the camera and screenshot pipeline. */
599
- camera?: {
600
- /**
601
- * Called with the list of cameras used for automated screenshot capture.
602
- * Return a modified array to add, remove, or reorder screenshot cameras.
603
- */
604
- onSetScreenshotCameras?: CallbackWithDescription<(cameras: K3Camera[]) => K3Camera[]>;
605
- /**
606
- * Called with the full list of scene cameras available in the viewer.
607
- * Return a modified array to filter or reorder cameras shown in the UI.
608
- */
609
- onSetCameraList?: CallbackWithDescription<(cameras: K3Camera[]) => K3Camera[]>;
610
- /**
611
- * Called to determine the pixel dimensions used when rendering screenshots.
612
- * Return modified dimensions to override the default canvas size.
613
- */
614
- getScreenshotDimensions?: CallbackWithDescription<(dim: K3ScreenshotDimensions) => K3ScreenshotDimensions>;
615
- };
616
- /** Core app lifecycle hooks. */
617
- core?: {
618
- /**
619
- * Called once with the full application data object before the K3 store is initialised.
620
- * Return a modified copy to patch groups, variables, values, rules, or any other app data.
621
- */
622
- preprocessFullApp?: CallbackWithDescription<(app: K3FullApp) => K3FullApp>;
623
- /**
624
- * Called after a PDF is generated and the save result is available.
625
- * Use this to open, download, or post-process the PDF URL from `result.pdf`.
626
- */
627
- onOpenPdf?: CallbackWithDescription<(result: K3SaveResult) => void>;
628
- /**
629
- * Called when the user triggers an AR export.
630
- * Receives the target platform and live Three.js scene; must return a `Blob` of the AR file.
631
- */
632
- onExportAR?: CallbackWithDescription<(ctx: K3ARExportContext) => Promise<Blob>>;
633
- };
712
+ interface K3LogicExtensions {
713
+ /** Hooks into the configuration data lifecycle (create, update, save). */
714
+ config?: {
715
+ /**
716
+ * Called every time the active configuration object is updated in the store (e.g. on every selection change).
717
+ * Return a modified copy to alter prices, codes, or any other configuration field.
718
+ */
719
+ onUpdate?: CallbackWithDescription<(config: K3Configuration) => K3Configuration>;
720
+ /**
721
+ * Called just before a configuration is persisted (order, cart, email, …).
722
+ * Return a modified copy to inject extra fields or override values before saving.
723
+ */
724
+ onSave?: CallbackWithDescription<(config: K3Configuration | K3NewConfiguration) => K3Configuration | K3NewConfiguration>;
725
+ /**
726
+ * Called with the list of screenshot files that will be uploaded alongside the save.
727
+ * Return a modified array to add, remove, or rename files.
728
+ */
729
+ onSaveFiles?: CallbackWithDescription<(files: K3UploadFile[]) => K3UploadFile[]>;
730
+ /**
731
+ * Called after a successful save action with the dispatched event payload.
732
+ * Return a modified payload to add custom fields consumed by downstream integrations.
733
+ */
734
+ onSaveEvent?: CallbackWithDescription<(payload: K3ConfigurationSavedEvent) => K3ConfigurationSavedEvent>;
735
+ };
736
+ /** Hooks into the camera and screenshot pipeline. */
737
+ camera?: {
738
+ /**
739
+ * Called with the list of cameras used for automated screenshot capture.
740
+ * Return a modified array to add, remove, or reorder screenshot cameras.
741
+ */
742
+ onSetScreenshotCameras?: CallbackWithDescription<(cameras: K3Camera[]) => K3Camera[]>;
743
+ /**
744
+ * Called with the full list of scene cameras available in the viewer.
745
+ * Return a modified array to filter or reorder cameras shown in the UI.
746
+ */
747
+ onSetCameraList?: CallbackWithDescription<(cameras: K3Camera[]) => K3Camera[]>;
748
+ /**
749
+ * Called to determine the pixel dimensions used when rendering screenshots.
750
+ * Return modified dimensions to override the default canvas size.
751
+ */
752
+ getScreenshotDimensions?: CallbackWithDescription<(dim: K3ScreenshotDimensions) => K3ScreenshotDimensions>;
753
+ };
754
+ /** Core app lifecycle hooks. */
755
+ core?: {
756
+ /**
757
+ * Called once with the full application data object before the K3 store is initialised.
758
+ * Return a modified copy to patch groups, variables, values, rules, or any other app data.
759
+ */
760
+ preprocessFullApp?: CallbackWithDescription<(app: K3FullApp) => K3FullApp>;
761
+ /**
762
+ * Called after a PDF is generated and the save result is available.
763
+ * Use this to open, download, or post-process the PDF URL from `result.pdf`.
764
+ */
765
+ onOpenPdf?: CallbackWithDescription<(result: K3SaveResult) => void>;
766
+ /**
767
+ * Called when the user triggers an AR export.
768
+ * Receives the target platform and live Three.js scene; must return a `Blob` of the AR file.
769
+ */
770
+ onExportAR?: CallbackWithDescription<(ctx: K3ARExportContext) => Promise<Blob>>;
771
+ };
634
772
  }
635
773
  /**
636
774
  * Declares a named slot where child models can be placed inside a parent dynamic model.
637
775
  * Attach an array of these to `DynamicModel.slotDefinitions`.
638
776
  */
639
- export interface SlotDefinition {
640
- /** Unique identifier (UUID) — primary key used in rule columns to reference this slot. */
641
- id: string;
642
- /** Human-readable name shown in the admin slot picker. */
643
- name: string;
644
- /** Optional fallback model ID rendered when no rule assigns a model to this slot. */
645
- defaultModelId?: string | number;
777
+ interface SlotDefinition {
778
+ /** Unique identifier (UUID) — primary key used in rule columns to reference this slot. */
779
+ id: string;
780
+ /** Human-readable name shown in the admin slot picker. */
781
+ name: string;
782
+ /** Optional fallback model ID rendered when no rule assigns a model to this slot. */
783
+ defaultModelId?: string | number;
646
784
  }
647
785
  /**
648
786
  * A resolved model instance placed into a slot at runtime.
649
787
  * Received via `DynamicModelComponentProps.slots[slotId]`.
650
788
  */
651
- export interface SlotModelInstance {
652
- /** The model data object for this slot instance. */
653
- model: {
654
- id: string | number;
655
- [key: string]: unknown;
656
- };
657
- /** URL of the model's 3D file, or `undefined` if this is a dynamic model with a component. */
658
- fileURL: string | undefined;
659
- /** The React component used to render this model if it is a dynamic model otherwise `undefined`. */
660
- component: React.ComponentType<any> | undefined;
661
- /** Evaluated props passed to the model component. */
662
- props: Record<string, unknown>;
663
- /** The rule-engine action that placed this model into the scene. */
664
- modelAction: {
665
- /** Unique ID of the model action record. */
666
- id: string;
667
- /** ID of the model referenced by this action. */
668
- modelId: string | number;
669
- /** Props overrides defined on the action. */
670
- props?: Record<string, unknown>;
671
- /** ID of the slot this action targets. */
672
- slotId?: string;
673
- [key: string]: unknown;
674
- };
675
- /** The slot definition this instance was placed into. */
676
- slotDefinition: SlotDefinition;
677
- /** Recursively nested slot instances when the slotted model itself has slots. */
678
- slots?: Record<string, SlotModelInstance[]>;
789
+ interface SlotModelInstance {
790
+ /** The model data object for this slot instance. */
791
+ model: {
792
+ id: string | number;
793
+ [key: string]: unknown;
794
+ };
795
+ /** URL of the model's 3D file, or `undefined` if this is a dynamic model with a component. */
796
+ fileURL: string | undefined;
797
+ /** The React component used to render this model if it is a dynamic model otherwise `undefined`. */
798
+ component: React.ComponentType<any> | undefined;
799
+ /** Evaluated props passed to the model component. */
800
+ props: Record<string, unknown>;
801
+ /** The rule-engine action that placed this model into the scene. */
802
+ modelAction: {
803
+ /** Unique ID of the model action record. */
804
+ id: string;
805
+ /** ID of the model referenced by this action. */
806
+ modelId: string | number;
807
+ /** Props overrides defined on the action. */
808
+ props?: Record<string, unknown>;
809
+ /** ID of the slot this action targets. */
810
+ slotId?: string;
811
+ [key: string]: unknown;
812
+ };
813
+ /** The slot definition this instance was placed into. */
814
+ slotDefinition: SlotDefinition;
815
+ /** Recursively nested slot instances when the slotted model itself has slots. */
816
+ slots?: Record<string, SlotModelInstance[]>;
679
817
  }
680
818
  /**
681
819
  * Props automatically injected into every `DynamicModel.component` at runtime.
682
820
  * Extend this with your custom prop types: `DynamicModelComponentProps & { myProp: string }`.
683
821
  */
684
- export interface DynamicModelComponentProps {
685
- /**
686
- * Resolved child model instances keyed by slot ID.
687
- * Only present when the model has `slotDefinitions` and at least one slot is filled.
688
- */
689
- slots?: Record<string, SlotModelInstance[]>;
690
- [key: string]: unknown;
691
- }
692
- export interface DynamicModel {
693
- /** Unique type key used to reference this model from rule items, e.g. `"acme.my-model"`. */
694
- type: string;
695
- /** Human-readable display name shown in the admin model picker. */
696
- label: string;
697
- /** Describe what this dynamic model does. Shown in the plugin extensions dialog. */
698
- description: string | LocalizedString;
699
- /** Optional URL to a preview screenshot shown in the admin model picker. */
700
- screenshot?: string;
701
- /** List of Three.js material name patterns this model applies to in the scene. */
702
- materials: string[];
703
- /** When `true`, this model is excluded from AR exports (e.g. because it uses unsupported shaders). */
704
- disabledForAR: boolean;
705
- /** The React component rendered inside the Three.js canvas for this model. */
706
- component: React.ComponentType<any>;
707
- /**
708
- * Schema for the admin props-editor dialog.
709
- * Each key maps to a `ModelProp` descriptor that controls which editor widget is rendered.
710
- */
711
- propsDialog: Record<string, ModelProp>;
712
- /**
713
- * Default prop values used when a new model action is created.
714
- * Each key matches a `propsDialog` key; values may be plain data or `{ expression: string }`.
715
- * Include `slotDefinitions` here to declare named slots for child models.
716
- */
717
- defaultProps: {
718
- slotDefinitions?: SlotDefinition[];
719
- [key: string]: string | number | boolean | ModelPropDefault | undefined | SlotDefinition[];
720
- };
721
- /** Optional tag used to group or filter models in the admin UI. */
722
- tag?: string;
723
- }
724
- export interface ModelProp {
725
- /**
726
- * Editor widget type for this prop in the admin dialog.
727
- * `"basic"` — plain text/number input.
728
- * `"model"` — K3 model selector.
729
- * `"variable"` — K3 variable selector.
730
- * `"expression"` — expression / formula editor.
731
- */
732
- type?: "basic" | "model" | "variable" | "expression";
733
- /** Human-readable label shown next to the editor widget in the admin dialog. */
734
- label?: string;
735
- /** For type="variable": restrict which variable types are selectable. */
736
- allowedTypes?: VariableTypes[];
737
- /** For type="model": allow selecting multiple models. */
738
- multiple?: boolean;
822
+ interface DynamicModelComponentProps {
823
+ /**
824
+ * Resolved child model instances keyed by slot ID.
825
+ * Only present when the model has `slotDefinitions` and at least one slot is filled.
826
+ */
827
+ slots?: Record<string, SlotModelInstance[]>;
828
+ [key: string]: unknown;
829
+ }
830
+ interface DynamicModel {
831
+ /** Unique type key used to reference this model from rule items, e.g. `"acme.my-model"`. */
832
+ type: string;
833
+ /** Human-readable display name shown in the admin model picker. */
834
+ label: string;
835
+ /** Describe what this dynamic model does. Shown in the plugin extensions dialog. */
836
+ description: string | LocalizedString;
837
+ /** Optional URL to a preview screenshot shown in the admin model picker. */
838
+ screenshot?: string;
839
+ /** List of Three.js material name patterns this model applies to in the scene. */
840
+ materials: string[];
841
+ /** When `true`, this model is excluded from AR exports (e.g. because it uses unsupported shaders). */
842
+ disabledForAR: boolean;
843
+ /** The React component rendered inside the Three.js canvas for this model. */
844
+ component: React.ComponentType<any>;
845
+ /**
846
+ * Schema for the admin props-editor dialog.
847
+ * Each key maps to a `ModelProp` descriptor that controls which editor widget is rendered.
848
+ */
849
+ propsDialog: Record<string, ModelProp>;
850
+ /**
851
+ * Default prop values used when a new model action is created.
852
+ * Each key matches a `propsDialog` key; values may be plain data or `{ expression: string }`.
853
+ * Include `slotDefinitions` here to declare named slots for child models.
854
+ */
855
+ defaultProps: {
856
+ slotDefinitions?: SlotDefinition[];
857
+ [key: string]: string | number | boolean | ModelPropDefault | undefined | SlotDefinition[];
858
+ };
859
+ /** Optional tag used to group or filter models in the admin UI. */
860
+ tag?: string;
861
+ }
862
+ interface ModelProp {
863
+ /**
864
+ * Editor widget type for this prop in the admin dialog.
865
+ * `"basic"` — plain text/number input.
866
+ * `"model"` — K3 model selector.
867
+ * `"variable"` — K3 variable selector.
868
+ * `"expression"` — expression / formula editor.
869
+ */
870
+ type?: "basic" | "model" | "variable" | "expression";
871
+ /** Human-readable label shown next to the editor widget in the admin dialog. */
872
+ label?: string;
873
+ /** For type="variable": restrict which variable types are selectable. */
874
+ allowedTypes?: VariableTypes[];
875
+ /** For type="model": allow selecting multiple models. */
876
+ multiple?: boolean;
739
877
  }
740
878
  /** All variable type string literals. */
741
- export declare const VariableType: {
742
- readonly List: "list";
743
- readonly Color: "color";
744
- readonly Number: "number";
745
- readonly Text: "text";
746
- readonly MultiSelect: "multiSelect";
747
- readonly Boolean: "boolean";
748
- readonly Image: "image";
749
- readonly Upload: "upload";
750
- readonly Components: "components";
751
- readonly Information: "information";
879
+ declare const VariableType: {
880
+ readonly List: "list";
881
+ readonly Color: "color";
882
+ readonly Number: "number";
883
+ readonly Text: "text";
884
+ readonly MultiSelect: "multiSelect";
885
+ readonly Boolean: "boolean";
886
+ readonly Image: "image";
887
+ readonly Upload: "upload";
888
+ readonly Components: "components";
889
+ readonly Information: "information";
752
890
  };
753
- export type VariableTypes = (typeof VariableType)[keyof typeof VariableType];
754
- export interface ModelPropDefault {
755
- /** An expression string evaluated at runtime instead of a static value (e.g. `"group.width * 2"`). */
756
- expression?: string;
891
+ type VariableTypes = (typeof VariableType)[keyof typeof VariableType];
892
+ interface ModelPropDefault {
893
+ /** An expression string evaluated at runtime instead of a static value (e.g. `"group.width * 2"`). */
894
+ expression?: string;
757
895
  }
758
896
  /** K3 Value object (list / color / boolean selection). */
759
- export interface Value {
760
- /** Unique database ID of the value. */
761
- id: number | string;
762
- /** Optional stable string key for the value, usable as an alternative identifier. */
763
- key?: string | null;
764
- /** The underlying data value: a hex color string, boolean flag, or generic string payload. */
765
- value?: string | boolean | null;
766
- /** Human-readable display label shown in the configurator UI. */
767
- label: string;
897
+ interface Value {
898
+ /** Unique database ID of the value. */
899
+ id: number | string;
900
+ /** Optional stable string key for the value, usable as an alternative identifier. */
901
+ key?: string | null;
902
+ /** The underlying data value: a hex color string, boolean flag, or generic string payload. */
903
+ value?: string | boolean | null;
904
+ /** Human-readable display label shown in the configurator UI. */
905
+ label: string;
768
906
  }
769
907
  /**
770
908
  * Context passed to plugin dynamic model components at runtime.
771
909
  */
772
- export interface PluginModelContext {
773
- /** Only set during screenshot rendering. */
774
- screenshotCameraName?: string;
775
- /** The unique ID of the model action this instance is rendered for. */
776
- modelActionId?: string;
910
+ interface PluginModelContext {
911
+ /** Only set during screenshot rendering. */
912
+ screenshotCameraName?: string;
913
+ /** The unique ID of the model action this instance is rendered for. */
914
+ modelActionId?: string;
777
915
  }
778
916
  /** @deprecated Use K3PluginDescriptor */
779
- export type K3Plugin = Pick<K3PluginDescriptor, "dynamicModels">;
780
- export {};
781
- //# sourceMappingURL=index.d.ts.map
917
+ type K3Plugin = Pick<K3PluginDescriptor, "dynamicModels">;
918
+ //#endregion
919
+ export { CallbackWithDescription, CustomLayoutComponentProps, DynamicModel, DynamicModelComponentProps, HOC, HOCWithDescription, K3ARExportContext, K3ARPlatform, K3AppInfo, K3BomEntry, K3Camera, K3CameraScope, K3ComponentInstanceVariables, K3Configuration, K3ConfigurationSavedEvent, K3ConfigurationVariableEntry, K3ConfigurationVariables, K3Coordinates, K3DialogExtensions, K3FullApp, K3InputExtensions, K3LayoutExtensions, K3LogicExtensions, K3NewConfiguration, K3OrderDialogExtensions, K3OrthographicCamera, K3PerspectiveCamera, K3Plugin, K3PluginDescriptor, K3SaveResult, K3Scene, K3ScreenshotDimensions, K3Selection, K3SimplifiedValue, K3UIExtensions, K3UploadFile, K3VariableComponentProps, K3ViewerExtensions, K3WarningExtensions, LocalizedString, ModelProp, ModelPropDefault, PluginModelContext, SlotDefinition, SlotModelInstance, Value, VariableType, VariableTypes, VariableVisualisation, getSettings, init, useApp, useBOM, useConfigurationVariable, useConfigurationVariables, useFormattedTotalPrice, useK3PluginSettings, useTotalPrice };