k3-plugin-api 1.5.0 → 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/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
 
14
14
  ## What is this package?
15
15
 
16
- `k3-plugin-api` contains the **TypeScript types** required to build K3 plugins — packages that extend the K3 configurator runtime with custom UI components, 3D models, pricing logic, and lifecycle hooks. The package ships zero runtime code; every export is a type, interface, or const enum.
16
+ `k3-plugin-api` provides the **TypeScript types and runtime hooks** required to build K3 plugins — packages that extend the K3 configurator runtime with custom UI components, 3D models, pricing logic, and lifecycle hooks. It ships a thin runtime layer (reactive hooks like `useBOM()`, `useApp()`, etc.) that K3 injects at load time, plus all the type definitions for the plugin descriptor API.
17
17
 
18
18
  ---
19
19
 
@@ -41,14 +41,20 @@ const plugin: K3PluginDescriptor = {
41
41
  ui: {
42
42
  layout: {
43
43
  // wrap the default header with your own component
44
- header: (Default) => (props) => <MyCustomHeader fallback={Default} {...props} />,
44
+ header: {
45
+ hoc: (Default) => (props) => <MyCustomHeader fallback={Default} {...props} />,
46
+ description: "Custom branded header",
47
+ },
45
48
  },
46
49
  },
47
50
 
48
51
  logic: {
49
52
  config: {
50
53
  // attach a custom order code to the configuration before it is persisted
51
- onSave: (config) => ({ ...config, code: `TEST-${config.code}` }),
54
+ onSave: {
55
+ fn: (config) => ({ ...config, code: `TEST-${config.code}` }),
56
+ description: "Prepend TEST- to configuration code",
57
+ },
52
58
  },
53
59
  },
54
60
  };
@@ -64,35 +70,62 @@ K3 plugins can extend three layers of the configurator.
64
70
 
65
71
  ### Runtime Hooks
66
72
 
67
- Plugins can access K3 configurator state at runtime using React hooks. These hooks are automatically injected when the plugin is loaded.
73
+ Plugins can access K3 configurator state at runtime using React hooks. These are automatically injected when the plugin is loaded via `init()`.
68
74
 
69
75
  ```ts
70
- import { useSettings, useBOM, usePrice } from "k3-plugin-api";
76
+ import {
77
+ useK3PluginSettings,
78
+ useConfigurationVariables,
79
+ useConfigurationVariable,
80
+ useBOM,
81
+ useTotalPrice,
82
+ useFormattedTotalPrice,
83
+ useApp,
84
+ getSettings,
85
+ } from "k3-plugin-api";
71
86
 
72
87
  const MyComponent = () => {
73
- // Access plugin-specific settings
74
- const settings = useSettings("acme.my-plugin");
75
-
76
- // Access current Bill-of-Materials
88
+ // Reactive plugin settings
89
+ const settings = useK3PluginSettings("acme.my-plugin") as { apiKey?: string };
90
+
91
+ // All configuration variables as a key-value map
92
+ const variables = useConfigurationVariables();
93
+
94
+ // Single variable by key
95
+ const color = useConfigurationVariable("color");
96
+
97
+ // Bill-of-Materials
77
98
  const bom = useBOM();
78
-
79
- // Access current total price
80
- const price = usePrice();
81
-
99
+
100
+ // Price (raw number or formatted string)
101
+ const price = useTotalPrice();
102
+ const formattedPrice = useFormattedTotalPrice();
103
+
104
+ // App metadata (product, subscription, etc.)
105
+ const app = useApp();
106
+
82
107
  return (
83
108
  <div>
84
109
  <p>API Key: {settings.apiKey}</p>
85
110
  <p>Total items: {bom.length}</p>
86
- <p>Price: {price}</p>
111
+ <p>Price: {formattedPrice}</p>
87
112
  </div>
88
113
  );
89
114
  };
90
115
  ```
91
116
 
92
- Available hooks:
93
- - `useSettings(pluginId: string)` — Access settings for a specific plugin
94
- - `useBOM()` — Get current Bill-of-Materials entries
95
- - `usePrice()` Get current total price (MOV-adjusted or overall)
117
+ Available hooks & functions:
118
+
119
+ | Export | Description |
120
+ | ------------------------------- | ----------------------------------------------------------------------------- |
121
+ | `getSettings(pluginId)` | Non-reactive snapshot of plugin settings |
122
+ | `useK3PluginSettings(pluginId)` | Reactive hook — re-renders on settings change |
123
+ | `useConfigurationVariables()` | All configuration variables as `Record<string, K3ConfigurationVariableEntry>` |
124
+ | `useConfigurationVariable(key)` | Single variable value by its stable key |
125
+ | `useBOM()` | Current Bill-of-Materials (`K3BomEntry[]`) |
126
+ | `useTotalPrice()` | Raw total price as `number` |
127
+ | `useFormattedTotalPrice()` | Locale-formatted price string (e.g. `"1.299,00 €"`) |
128
+ | `useApp()` | App metadata (`K3AppInfo \| null`) — product, subscription, feature flags |
96
129
 
97
130
  ### `settings` — Plugin Settings Component
98
131
 
@@ -120,6 +153,7 @@ const plugin: K3PluginDescriptor = {
120
153
  ```
121
154
 
122
155
  The `settings` component receives:
156
+
123
157
  - `settings: unknown` — The current settings object (initially `{}`)
124
158
  - `onSave: (settings: unknown) => void` — Callback to persist updated settings
125
159
 
@@ -187,18 +221,24 @@ const plugin: K3PluginDescriptor = {
187
221
 
188
222
  ## Key Types
189
223
 
190
- | Type | Description |
191
- | --------------------------- | --------------------------------------------------------------- |
192
- | `K3PluginDescriptor` | Root descriptor object exported by a plugin |
193
- | `K3Hooks` | Runtime hooks interface (useSettings, useBOM, usePrice) |
194
- | `HOC<P>` | Higher-Order Component: `(Default: FC<P>) => FC<P>` |
195
- | `VariableVisualisation` | Descriptor for a custom input visualisation |
196
- | `K3VariableComponentProps` | Props injected into a custom variable renderer |
197
- | `DynamicModel` | 3D model type definition for the viewer |
198
- | `K3Configuration` | A persisted configuration with code, price, and selection JSON |
199
- | `K3ConfigurationSavedEvent` | Event payload dispatched on completed save |
200
- | `K3BomEntry` | Single Bill-of-Materials entry |
201
- | `VariableType` | Const enum of all variable types |
224
+ | Type | Description |
225
+ | ------------------------------ | -------------------------------------------------------------- |
226
+ | `K3PluginDescriptor` | Root descriptor object exported by a plugin |
227
+ | `HOC<P>` | Higher-Order Component: `(Default: FC<P>) => FC<P>` |
228
+ | `HOCWithDescription` | HOC + admin description (used in layout/dialog slots) |
229
+ | `CallbackWithDescription<T>` | Logic callback + admin description |
230
+ | `VariableVisualisation` | Descriptor for a custom input visualisation |
231
+ | `K3VariableComponentProps` | Props injected into a custom variable renderer |
232
+ | `DynamicModel` | 3D model type definition for the viewer |
233
+ | `K3Configuration` | A persisted configuration with code, price, and selection JSON |
234
+ | `K3ConfigurationSavedEvent` | Event payload dispatched on completed save |
235
+ | `K3BomEntry` | Single Bill-of-Materials entry |
236
+ | `K3ConfigurationVariables` | Full variables map keyed by variable key |
237
+ | `K3ConfigurationVariableEntry` | Single variable value (number, string, or simplified value) |
238
+ | `K3SimplifiedValue` | Resolved value option (id, key, label, value, thumbnail) |
239
+ | `K3AppInfo` | App metadata (product, subscription, feature flags) |
240
+ | `K3FullApp` | Full app snapshot passed to `preprocessFullApp` |
241
+ | `VariableType` | Const enum of all variable types |
202
242
 
203
243
  ---
204
244
 
package/dist/index.cjs CHANGED
@@ -8,6 +8,18 @@ let _getSettings = null;
8
8
  * Internal reactive hook injected by K3 at runtime.
9
9
  */
10
10
  let _usePluginSettings = null;
11
+ /** @internal */
12
+ let _useSelections = null;
13
+ /** @internal */
14
+ let _useSelectionByVariableKey = null;
15
+ /** @internal */
16
+ let _useBOM = null;
17
+ /** @internal */
18
+ let _useTotalPrice = null;
19
+ /** @internal */
20
+ let _useFormattedTotalPrice = null;
21
+ /** @internal */
22
+ let _useApp = null;
11
23
  /**
12
24
  * Get plugin-specific settings from the K3 store.
13
25
  * Returns a snapshot of the current settings - not reactive.
@@ -46,12 +58,96 @@ function useK3PluginSettings(pluginId) {
46
58
  return _usePluginSettings(pluginId);
47
59
  }
48
60
  /**
61
+ * Reactive hook – returns all current configuration variables as a key-value map.
62
+ * Keys are the variable's stable `key` string. Values are resolved (labels, not raw IDs).
63
+ * Re-renders whenever any selection changes.
64
+ *
65
+ * @example
66
+ * ```typescript
67
+ * const variables = useConfigurationVariables();
68
+ * const color = variables["color"] as K3SimplifiedValue;
69
+ * ```
70
+ */
71
+ function useConfigurationVariables() {
72
+ if (!_useSelections) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useConfigurationVariables().");
73
+ return _useSelections();
74
+ }
75
+ /**
76
+ * Reactive hook – returns the resolved value for a specific variable by its key,
77
+ * or `undefined` if the variable has no active selection.
78
+ *
79
+ * @param variableKey - The stable key of the variable (as defined in the admin)
80
+ *
81
+ * @example
82
+ * ```typescript
83
+ * const width = useConfigurationVariable("width") as number;
84
+ * const material = useConfigurationVariable("material") as K3SimplifiedValue;
85
+ * ```
86
+ */
87
+ function useConfigurationVariable(variableKey) {
88
+ if (!_useSelectionByVariableKey) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useConfigurationVariable().");
89
+ return _useSelectionByVariableKey(variableKey);
90
+ }
91
+ /**
92
+ * Reactive hook – returns the current Bill of Materials (Stückliste).
93
+ * Re-renders whenever the BOM changes (i.e. on any selection change).
94
+ *
95
+ * @example
96
+ * ```typescript
97
+ * const bom = useBOM() as K3BomEntry[];
98
+ * const total = bom.reduce((sum, e) => sum + e.price.price * e.qty, 0);
99
+ * ```
100
+ */
101
+ function useBOM() {
102
+ if (!_useBOM) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useBOM().");
103
+ return _useBOM();
104
+ }
105
+ /**
106
+ * Reactive hook – returns the current total price as a raw number.
107
+ * Re-renders whenever the price changes.
108
+ */
109
+ function useTotalPrice() {
110
+ if (!_useTotalPrice) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useTotalPrice().");
111
+ return _useTotalPrice();
112
+ }
113
+ /**
114
+ * Reactive hook – returns the current total price formatted as a locale string
115
+ * (e.g. `"1.299,00 €"`), ready for display.
116
+ * Re-renders whenever the price changes.
117
+ */
118
+ function useFormattedTotalPrice() {
119
+ if (!_useFormattedTotalPrice) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useFormattedTotalPrice().");
120
+ return _useFormattedTotalPrice();
121
+ }
122
+ /**
123
+ * Reactive hook – returns the current K3 app metadata, including the booked
124
+ * product identifier. Returns `null` while the app has not yet loaded.
125
+ *
126
+ * @example
127
+ * ```typescript
128
+ * const app = useApp() as K3AppInfo | null;
129
+ * if (app?.product === "k3-pro") {
130
+ * // enable pro-only features
131
+ * }
132
+ * ```
133
+ */
134
+ function useApp() {
135
+ if (!_useApp) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useApp().");
136
+ return _useApp();
137
+ }
138
+ /**
49
139
  * Called by K3 when the plugin is loaded to inject runtime API functions.
50
140
  * @internal This function is called by K3 automatically - plugins should not call it directly.
51
141
  */
52
142
  function init(api) {
53
143
  _getSettings = api.getSettings;
54
144
  _usePluginSettings = api.usePluginSettings;
145
+ _useSelections = api.useConfigurationVariables;
146
+ _useSelectionByVariableKey = api.useConfigurationVariable;
147
+ _useBOM = api.useBOM;
148
+ _useTotalPrice = api.useTotalPrice;
149
+ _useFormattedTotalPrice = api.useFormattedTotalPrice;
150
+ _useApp = api.useApp;
55
151
  }
56
152
  /** All variable type string literals. */
57
153
  const VariableType = {
@@ -70,4 +166,10 @@ const VariableType = {
70
166
  exports.VariableType = VariableType;
71
167
  exports.getSettings = getSettings;
72
168
  exports.init = init;
169
+ exports.useApp = useApp;
170
+ exports.useBOM = useBOM;
171
+ exports.useConfigurationVariable = useConfigurationVariable;
172
+ exports.useConfigurationVariables = useConfigurationVariables;
173
+ exports.useFormattedTotalPrice = useFormattedTotalPrice;
73
174
  exports.useK3PluginSettings = useK3PluginSettings;
175
+ exports.useTotalPrice = useTotalPrice;
package/dist/index.d.cts CHANGED
@@ -33,6 +33,66 @@ declare function getSettings(pluginId: string): unknown;
33
33
  * ```
34
34
  */
35
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;
36
96
  /**
37
97
  * Called by K3 when the plugin is loaded to inject runtime API functions.
38
98
  * @internal This function is called by K3 automatically - plugins should not call it directly.
@@ -40,6 +100,12 @@ declare function useK3PluginSettings(pluginId: string): unknown;
40
100
  declare function init(api: {
41
101
  getSettings: (pluginId: string) => unknown;
42
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;
43
109
  }): void;
44
110
  /** A Higher-Order Component: takes the default component, returns a new one. */
45
111
  type HOC<P = Record<string, unknown>> = (comp: React.FC<P>) => React.FC<P>;
@@ -270,6 +336,60 @@ interface K3WarningExtensions {
270
336
  /** Wraps the tooltip content shown when a number variable value is out of bounds. */
271
337
  numberWarningTooltip?: HOCWithDescription;
272
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;
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>;
273
393
  /**
274
394
  * A single Bill-of-Materials entry exposed to plugin components.
275
395
  * Mirrors the internal BOMEntry shape using only primitive/simple types.
@@ -796,4 +916,4 @@ interface PluginModelContext {
796
916
  /** @deprecated Use K3PluginDescriptor */
797
917
  type K3Plugin = Pick<K3PluginDescriptor, "dynamicModels">;
798
918
  //#endregion
799
- export { CallbackWithDescription, CustomLayoutComponentProps, DynamicModel, DynamicModelComponentProps, HOC, HOCWithDescription, K3ARExportContext, K3ARPlatform, K3BomEntry, K3Camera, K3CameraScope, K3Configuration, K3ConfigurationSavedEvent, K3Coordinates, K3DialogExtensions, K3FullApp, K3InputExtensions, K3LayoutExtensions, K3LogicExtensions, K3NewConfiguration, K3OrderDialogExtensions, K3OrthographicCamera, K3PerspectiveCamera, K3Plugin, K3PluginDescriptor, K3SaveResult, K3Scene, K3ScreenshotDimensions, K3Selection, K3UIExtensions, K3UploadFile, K3VariableComponentProps, K3ViewerExtensions, K3WarningExtensions, LocalizedString, ModelProp, ModelPropDefault, PluginModelContext, SlotDefinition, SlotModelInstance, Value, VariableType, VariableTypes, VariableVisualisation, getSettings, init, useK3PluginSettings };
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 };
package/dist/index.d.ts CHANGED
@@ -33,6 +33,66 @@ declare function getSettings(pluginId: string): unknown;
33
33
  * ```
34
34
  */
35
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;
36
96
  /**
37
97
  * Called by K3 when the plugin is loaded to inject runtime API functions.
38
98
  * @internal This function is called by K3 automatically - plugins should not call it directly.
@@ -40,6 +100,12 @@ declare function useK3PluginSettings(pluginId: string): unknown;
40
100
  declare function init(api: {
41
101
  getSettings: (pluginId: string) => unknown;
42
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;
43
109
  }): void;
44
110
  /** A Higher-Order Component: takes the default component, returns a new one. */
45
111
  type HOC<P = Record<string, unknown>> = (comp: React.FC<P>) => React.FC<P>;
@@ -270,6 +336,60 @@ interface K3WarningExtensions {
270
336
  /** Wraps the tooltip content shown when a number variable value is out of bounds. */
271
337
  numberWarningTooltip?: HOCWithDescription;
272
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;
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>;
273
393
  /**
274
394
  * A single Bill-of-Materials entry exposed to plugin components.
275
395
  * Mirrors the internal BOMEntry shape using only primitive/simple types.
@@ -796,4 +916,4 @@ interface PluginModelContext {
796
916
  /** @deprecated Use K3PluginDescriptor */
797
917
  type K3Plugin = Pick<K3PluginDescriptor, "dynamicModels">;
798
918
  //#endregion
799
- export { CallbackWithDescription, CustomLayoutComponentProps, DynamicModel, DynamicModelComponentProps, HOC, HOCWithDescription, K3ARExportContext, K3ARPlatform, K3BomEntry, K3Camera, K3CameraScope, K3Configuration, K3ConfigurationSavedEvent, K3Coordinates, K3DialogExtensions, K3FullApp, K3InputExtensions, K3LayoutExtensions, K3LogicExtensions, K3NewConfiguration, K3OrderDialogExtensions, K3OrthographicCamera, K3PerspectiveCamera, K3Plugin, K3PluginDescriptor, K3SaveResult, K3Scene, K3ScreenshotDimensions, K3Selection, K3UIExtensions, K3UploadFile, K3VariableComponentProps, K3ViewerExtensions, K3WarningExtensions, LocalizedString, ModelProp, ModelPropDefault, PluginModelContext, SlotDefinition, SlotModelInstance, Value, VariableType, VariableTypes, VariableVisualisation, getSettings, init, useK3PluginSettings };
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 };
package/dist/index.js CHANGED
@@ -7,6 +7,18 @@ let _getSettings = null;
7
7
  * Internal reactive hook injected by K3 at runtime.
8
8
  */
9
9
  let _usePluginSettings = null;
10
+ /** @internal */
11
+ let _useSelections = null;
12
+ /** @internal */
13
+ let _useSelectionByVariableKey = null;
14
+ /** @internal */
15
+ let _useBOM = null;
16
+ /** @internal */
17
+ let _useTotalPrice = null;
18
+ /** @internal */
19
+ let _useFormattedTotalPrice = null;
20
+ /** @internal */
21
+ let _useApp = null;
10
22
  /**
11
23
  * Get plugin-specific settings from the K3 store.
12
24
  * Returns a snapshot of the current settings - not reactive.
@@ -45,12 +57,96 @@ function useK3PluginSettings(pluginId) {
45
57
  return _usePluginSettings(pluginId);
46
58
  }
47
59
  /**
60
+ * Reactive hook – returns all current configuration variables as a key-value map.
61
+ * Keys are the variable's stable `key` string. Values are resolved (labels, not raw IDs).
62
+ * Re-renders whenever any selection changes.
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const variables = useConfigurationVariables();
67
+ * const color = variables["color"] as K3SimplifiedValue;
68
+ * ```
69
+ */
70
+ function useConfigurationVariables() {
71
+ if (!_useSelections) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useConfigurationVariables().");
72
+ return _useSelections();
73
+ }
74
+ /**
75
+ * Reactive hook – returns the resolved value for a specific variable by its key,
76
+ * or `undefined` if the variable has no active selection.
77
+ *
78
+ * @param variableKey - The stable key of the variable (as defined in the admin)
79
+ *
80
+ * @example
81
+ * ```typescript
82
+ * const width = useConfigurationVariable("width") as number;
83
+ * const material = useConfigurationVariable("material") as K3SimplifiedValue;
84
+ * ```
85
+ */
86
+ function useConfigurationVariable(variableKey) {
87
+ if (!_useSelectionByVariableKey) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useConfigurationVariable().");
88
+ return _useSelectionByVariableKey(variableKey);
89
+ }
90
+ /**
91
+ * Reactive hook – returns the current Bill of Materials (Stückliste).
92
+ * Re-renders whenever the BOM changes (i.e. on any selection change).
93
+ *
94
+ * @example
95
+ * ```typescript
96
+ * const bom = useBOM() as K3BomEntry[];
97
+ * const total = bom.reduce((sum, e) => sum + e.price.price * e.qty, 0);
98
+ * ```
99
+ */
100
+ function useBOM() {
101
+ if (!_useBOM) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useBOM().");
102
+ return _useBOM();
103
+ }
104
+ /**
105
+ * Reactive hook – returns the current total price as a raw number.
106
+ * Re-renders whenever the price changes.
107
+ */
108
+ function useTotalPrice() {
109
+ if (!_useTotalPrice) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useTotalPrice().");
110
+ return _useTotalPrice();
111
+ }
112
+ /**
113
+ * Reactive hook – returns the current total price formatted as a locale string
114
+ * (e.g. `"1.299,00 €"`), ready for display.
115
+ * Re-renders whenever the price changes.
116
+ */
117
+ function useFormattedTotalPrice() {
118
+ if (!_useFormattedTotalPrice) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useFormattedTotalPrice().");
119
+ return _useFormattedTotalPrice();
120
+ }
121
+ /**
122
+ * Reactive hook – returns the current K3 app metadata, including the booked
123
+ * product identifier. Returns `null` while the app has not yet loaded.
124
+ *
125
+ * @example
126
+ * ```typescript
127
+ * const app = useApp() as K3AppInfo | null;
128
+ * if (app?.product === "k3-pro") {
129
+ * // enable pro-only features
130
+ * }
131
+ * ```
132
+ */
133
+ function useApp() {
134
+ if (!_useApp) throw new Error("k3-plugin-api not initialized. Make sure K3 calls init() before using useApp().");
135
+ return _useApp();
136
+ }
137
+ /**
48
138
  * Called by K3 when the plugin is loaded to inject runtime API functions.
49
139
  * @internal This function is called by K3 automatically - plugins should not call it directly.
50
140
  */
51
141
  function init(api) {
52
142
  _getSettings = api.getSettings;
53
143
  _usePluginSettings = api.usePluginSettings;
144
+ _useSelections = api.useConfigurationVariables;
145
+ _useSelectionByVariableKey = api.useConfigurationVariable;
146
+ _useBOM = api.useBOM;
147
+ _useTotalPrice = api.useTotalPrice;
148
+ _useFormattedTotalPrice = api.useFormattedTotalPrice;
149
+ _useApp = api.useApp;
54
150
  }
55
151
  /** All variable type string literals. */
56
152
  const VariableType = {
@@ -66,4 +162,4 @@ const VariableType = {
66
162
  Information: "information"
67
163
  };
68
164
  //#endregion
69
- export { VariableType, getSettings, init, useK3PluginSettings };
165
+ export { VariableType, getSettings, init, useApp, useBOM, useConfigurationVariable, useConfigurationVariables, useFormattedTotalPrice, useK3PluginSettings, useTotalPrice };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k3-plugin-api",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Official TypeScript types and plugin API for the K3 product configurator",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",