k3-plugin-api 1.3.0 → 1.4.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.
Files changed (3) hide show
  1. package/README.md +75 -10
  2. package/index.ts +61 -0
  3. package/package.json +6 -5
package/README.md CHANGED
@@ -62,6 +62,69 @@ export default plugin;
62
62
 
63
63
  K3 plugins can extend three layers of the configurator.
64
64
 
65
+ ### Runtime Hooks
66
+
67
+ Plugins can access K3 configurator state at runtime using React hooks. These hooks are automatically injected when the plugin is loaded.
68
+
69
+ ```ts
70
+ import { useSettings, useBOM, usePrice } from "k3-plugin-api";
71
+
72
+ const MyComponent = () => {
73
+ // Access plugin-specific settings
74
+ const settings = useSettings("acme.my-plugin");
75
+
76
+ // Access current Bill-of-Materials
77
+ const bom = useBOM();
78
+
79
+ // Access current total price
80
+ const price = usePrice();
81
+
82
+ return (
83
+ <div>
84
+ <p>API Key: {settings.apiKey}</p>
85
+ <p>Total items: {bom.length}</p>
86
+ <p>Price: €{price}</p>
87
+ </div>
88
+ );
89
+ };
90
+ ```
91
+
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)
96
+
97
+ ### `settings` — Plugin Settings Component
98
+
99
+ Plugins can provide a settings UI component that will be rendered in the K3 admin panel. This allows administrators to configure plugin-specific options that are persisted per plugin instance.
100
+
101
+ ```ts
102
+ import type { K3PluginDescriptor } from "k3-plugin-api";
103
+
104
+ const SettingsComponent = ({ settings, onSave }) => {
105
+ return (
106
+ <div>
107
+ <input
108
+ value={settings.apiKey || ""}
109
+ onChange={(e) => onSave({ ...settings, apiKey: e.target.value })}
110
+ />
111
+ </div>
112
+ );
113
+ };
114
+
115
+ const plugin: K3PluginDescriptor = {
116
+ id: "acme.my-plugin",
117
+ version: "1.0.0",
118
+ settings: SettingsComponent,
119
+ };
120
+ ```
121
+
122
+ The `settings` component receives:
123
+ - `settings: unknown` — The current settings object (initially `{}`)
124
+ - `onSave: (settings: unknown) => void` — Callback to persist updated settings
125
+
126
+ Settings are stored per plugin instance and can be accessed at runtime via the plugin's configuration.
127
+
65
128
  ### `ui` — UI Extensions
66
129
 
67
130
  | Property | Description |
@@ -124,16 +187,18 @@ const plugin: K3PluginDescriptor = {
124
187
 
125
188
  ## Key Types
126
189
 
127
- | Type | Description |
128
- | --------------------------- | -------------------------------------------------------------- |
129
- | `K3PluginDescriptor` | Root descriptor object exported by a plugin |
130
- | `HOC<P>` | Higher-Order Component: `(Default: FC<P>) => FC<P>` |
131
- | `VariableVisualisation` | Descriptor for a custom input visualisation |
132
- | `K3VariableComponentProps` | Props injected into a custom variable renderer |
133
- | `DynamicModel` | 3D model type definition for the viewer |
134
- | `K3Configuration` | A persisted configuration with code, price, and selection JSON |
135
- | `K3ConfigurationSavedEvent` | Event payload dispatched on completed save |
136
- | `VariableType` | Const enum of all variable types |
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 |
137
202
 
138
203
  ---
139
204
 
package/index.ts CHANGED
@@ -1,5 +1,62 @@
1
1
  import type React from "react";
2
2
 
3
+ // ─── Plugin Runtime Hooks ───────────────────────────────────────────────────
4
+
5
+ /**
6
+ * K3 runtime hooks available to plugins after initialization.
7
+ * Set via `init()` when the plugin is loaded.
8
+ */
9
+ export interface K3Hooks {
10
+ /**
11
+ * React hook to access plugin-specific settings.
12
+ * @param pluginId - The unique plugin ID (e.g. "acme.my-plugin")
13
+ * @returns The settings object for this plugin, or `{}` if none are configured
14
+ */
15
+ useSettings: (pluginId: string) => unknown;
16
+ /**
17
+ * React hook to access the current Bill-of-Materials.
18
+ * @returns Array of BOM entries derived from the current selection
19
+ */
20
+ useBOM: () => K3BomEntry[];
21
+ /**
22
+ * React hook to access the current total price.
23
+ * @returns The effective total price (MOV-adjusted or overall price)
24
+ */
25
+ usePrice: () => number;
26
+ }
27
+
28
+ /**
29
+ * Hook functions injected by K3 at runtime.
30
+ * Use these in your plugin components to access configurator state.
31
+ */
32
+ export let useSettings: K3Hooks["useSettings"] = () => {
33
+ throw new Error(
34
+ "k3-plugin-api not initialized. Make sure K3 calls init() before using hooks.",
35
+ );
36
+ };
37
+
38
+ export let useBOM: K3Hooks["useBOM"] = () => {
39
+ throw new Error(
40
+ "k3-plugin-api not initialized. Make sure K3 calls init() before using hooks.",
41
+ );
42
+ };
43
+
44
+ export let usePrice: K3Hooks["usePrice"] = () => {
45
+ throw new Error(
46
+ "k3-plugin-api not initialized. Make sure K3 calls init() before using hooks.",
47
+ );
48
+ };
49
+
50
+ /**
51
+ * Called by K3 when the plugin is loaded to inject runtime hooks.
52
+ * @internal This function is called by K3 automatically - plugins should not call it directly.
53
+ */
54
+ export function init(hooks: K3Hooks): void {
55
+ useSettings = hooks.useSettings;
56
+ useBOM = hooks.useBOM;
57
+ usePrice = hooks.usePrice;
58
+ }
59
+
3
60
  // ─── HOC type (mirrors K3 internal, no K3 imports) ──────────────────────────
4
61
 
5
62
  /** A Higher-Order Component: takes the default component, returns a new one. */
@@ -43,6 +100,10 @@ export interface K3PluginDescriptor {
43
100
  viewer?: K3ViewerExtensions;
44
101
  /** Logic/callback hooks: config, camera, core. */
45
102
  logic?: K3LogicExtensions;
103
+ settings?: React.ComponentType<{
104
+ settings: unknown;
105
+ onSave: (settings: unknown) => void;
106
+ }>;
46
107
 
47
108
  /** @deprecated Use viewer.models instead. */
48
109
  dynamicModels?: DynamicModel[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "k3-plugin-api",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Official TypeScript types and plugin API for the K3 product configurator",
5
5
  "main": "index.js",
6
6
  "types": "index.ts",
@@ -25,14 +25,15 @@
25
25
  ],
26
26
  "author": "ObjectCode GmbH <info@objectcode.de> (https://k3-konfigurator.de/)",
27
27
  "license": "MIT",
28
+ "scripts": {
29
+ "prepublishOnly": "tsc --emitDeclarationOnly",
30
+ "yalc": "pnpm prepublishOnly && yalc publish"
31
+ },
28
32
  "peerDependencies": {
29
33
  "react": ">=19"
30
34
  },
31
35
  "devDependencies": {
32
36
  "typescript": "^5.8.3",
33
37
  "@types/react": "^19.0.0"
34
- },
35
- "scripts": {
36
- "yalc": "pnpm prepublishOnly && yalc publish"
37
38
  }
38
- }
39
+ }