@codefluss/base-types 0.0.2-alpha.1 → 0.0.2-alpha.2
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/common-types.d.ts +253 -26
- package/dist/common-types.d.ts.map +1 -1
- package/dist/common-types.js +8 -1
- package/dist/common-types.js.map +1 -1
- package/dist/dependencies.d.ts +545 -106
- package/dist/dependencies.d.ts.map +1 -1
- package/dist/dependencies.js +12 -2
- package/dist/dependencies.js.map +1 -1
- package/dist/plugin-system.d.ts +809 -204
- package/dist/plugin-system.d.ts.map +1 -1
- package/dist/plugin-system.js +8 -0
- package/dist/plugin-system.js.map +1 -1
- package/package.json +1 -1
- package/src/common-types.ts +286 -30
- package/src/dependencies.ts +770 -180
- package/src/plugin-system.ts +935 -263
package/dist/plugin-system.d.ts
CHANGED
|
@@ -4,379 +4,889 @@
|
|
|
4
4
|
* Core types for the headless plugin architecture.
|
|
5
5
|
* These types define the contract between plugins and the Context Panel UI.
|
|
6
6
|
*
|
|
7
|
+
* The plugin system uses a **headless** approach: plugins declare metadata
|
|
8
|
+
* (properties, capabilities, UI config) and the host application renders
|
|
9
|
+
* appropriate controls automatically in the Context Panel.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link PluginConfig} — Top-level plugin definition
|
|
12
|
+
* @see {@link PropertyDefinition} — How plugins declare editable properties
|
|
13
|
+
* @see {@link PluginCapabilities} — How plugins declare structural behavior
|
|
14
|
+
*
|
|
7
15
|
* @package @codefluss/base-types
|
|
8
16
|
* @version 1.0.0
|
|
9
17
|
*/
|
|
10
|
-
import type { ComponentType } from
|
|
11
|
-
import type { PluginDesignSystem, PluginUtils } from
|
|
18
|
+
import type { ComponentType } from 'react';
|
|
19
|
+
import type { PluginDesignSystem, PluginUtils } from './dependencies';
|
|
12
20
|
/**
|
|
13
|
-
* Property control type
|
|
14
|
-
*
|
|
21
|
+
* Property control type — determines which UI widget the Context Panel
|
|
22
|
+
* renders for a given property.
|
|
23
|
+
*
|
|
24
|
+
* Each value maps to a specific editor control component.
|
|
25
|
+
* The control's behavior is further configured via the corresponding
|
|
26
|
+
* field in {@link PropertyUIConfig}.
|
|
27
|
+
*
|
|
28
|
+
* @see {@link PropertyUIConfig} for per-control configuration
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // A slider control for font size
|
|
33
|
+
* const property: PropertyDefinition = {
|
|
34
|
+
* key: 'style.fontSize',
|
|
35
|
+
* type: 'range',
|
|
36
|
+
* label: 'Font Size',
|
|
37
|
+
* default: 16,
|
|
38
|
+
* ui: {
|
|
39
|
+
* control: 'slider',
|
|
40
|
+
* slider: { min: 8, max: 72, step: 1, unit: 'px' },
|
|
41
|
+
* },
|
|
42
|
+
* };
|
|
43
|
+
* ```
|
|
15
44
|
*/
|
|
16
|
-
export type PropertyControlType =
|
|
45
|
+
export type PropertyControlType = 'input' | 'slider' | 'select' | 'color-picker' | 'toggle' | 'textarea' | 'number-input' | 'number-with-unit' | 'box-model' | 'spacing' | 'spacing-combined' | 'grid' | 'typography-toolbar' | 'gradient-editor' | 'border-editor' | 'font-preset-select' | 'color-preset-select' | 'text-align-toggle' | 'vertical-align-toggle';
|
|
17
46
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
47
|
+
* Semantic type of a property value.
|
|
48
|
+
*
|
|
49
|
+
* While {@link PropertyControlType} determines the *UI widget*,
|
|
50
|
+
* `PropertyType` describes the *semantic meaning* of the stored value.
|
|
51
|
+
* A single `PropertyType` may be rendered by different controls depending
|
|
52
|
+
* on the plugin's UI configuration.
|
|
53
|
+
*
|
|
54
|
+
* @see {@link PropertyControlType} for the UI control counterpart
|
|
55
|
+
* @see {@link PropertyDefinition.type}
|
|
20
56
|
*/
|
|
21
|
-
export type PropertyType =
|
|
57
|
+
export type PropertyType = 'text' | 'number' | 'range' | 'select' | 'color' | 'toggle' | 'multiLangText' | 'boxModel' | 'box-model' | 'spacing' | 'spacing-combined' | 'grid' | 'toolbar' | 'gradient' | 'border';
|
|
22
58
|
/**
|
|
23
|
-
*
|
|
59
|
+
* Organizational category for properties in the Context Panel.
|
|
60
|
+
*
|
|
61
|
+
* Properties are grouped into collapsible sections by category,
|
|
62
|
+
* providing a consistent editing experience across all plugins.
|
|
63
|
+
*
|
|
64
|
+
* - `'content'` — Text, media, and data properties (shown first)
|
|
65
|
+
* - `'style'` — Visual appearance: colors, typography, backgrounds
|
|
66
|
+
* - `'layout'` — Spacing, positioning, grid/flexbox settings
|
|
67
|
+
* - `'advanced'` — CSS classes, ARIA labels, HTML tags, z-index
|
|
68
|
+
*
|
|
69
|
+
* @see {@link PropertyDefinition.category}
|
|
24
70
|
*/
|
|
25
|
-
export type PropertyCategory =
|
|
71
|
+
export type PropertyCategory = 'content' | 'style' | 'layout' | 'advanced';
|
|
26
72
|
/**
|
|
27
|
-
*
|
|
73
|
+
* Configuration for slider UI controls.
|
|
74
|
+
*
|
|
75
|
+
* @see {@link PropertyUIConfig.slider}
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const sliderConfig: SliderConfig = {
|
|
80
|
+
* min: 0,
|
|
81
|
+
* max: 100,
|
|
82
|
+
* step: 1,
|
|
83
|
+
* showValue: true,
|
|
84
|
+
* unit: 'px',
|
|
85
|
+
* };
|
|
86
|
+
* ```
|
|
28
87
|
*/
|
|
29
88
|
export interface SliderConfig {
|
|
89
|
+
/** Minimum allowed value */
|
|
30
90
|
min: number;
|
|
91
|
+
/** Maximum allowed value */
|
|
31
92
|
max: number;
|
|
93
|
+
/** Increment step between values */
|
|
32
94
|
step: number;
|
|
95
|
+
/**
|
|
96
|
+
* Whether to display the current numeric value next to the slider
|
|
97
|
+
* @default false
|
|
98
|
+
*/
|
|
33
99
|
showValue?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Unit label displayed after the value (e.g., `'px'`, `'%'`, `'em'`)
|
|
102
|
+
* @default undefined
|
|
103
|
+
*/
|
|
34
104
|
unit?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Discrete labeled positions on the slider track
|
|
107
|
+
* @default undefined
|
|
108
|
+
*/
|
|
35
109
|
marks?: Array<{
|
|
36
110
|
value: number;
|
|
37
111
|
label: string;
|
|
38
112
|
}>;
|
|
39
113
|
}
|
|
40
114
|
/**
|
|
41
|
-
*
|
|
115
|
+
* Configuration for numeric input controls.
|
|
116
|
+
*
|
|
117
|
+
* All fields are optional — unset fields inherit sensible browser defaults.
|
|
118
|
+
*
|
|
119
|
+
* @see {@link PropertyUIConfig.number}
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const numberConfig: NumberConfig = {
|
|
124
|
+
* min: 0,
|
|
125
|
+
* max: 9999,
|
|
126
|
+
* step: 1,
|
|
127
|
+
* unit: 'px',
|
|
128
|
+
* };
|
|
129
|
+
* ```
|
|
42
130
|
*/
|
|
43
131
|
export interface NumberConfig {
|
|
132
|
+
/** Minimum allowed value */
|
|
44
133
|
min?: number;
|
|
134
|
+
/** Maximum allowed value */
|
|
45
135
|
max?: number;
|
|
136
|
+
/** Increment step */
|
|
46
137
|
step?: number;
|
|
138
|
+
/**
|
|
139
|
+
* Unit label displayed after the value (e.g., `'px'`, `'%'`, `'em'`)
|
|
140
|
+
* @default undefined
|
|
141
|
+
*/
|
|
47
142
|
unit?: string;
|
|
48
143
|
}
|
|
49
144
|
/**
|
|
50
|
-
*
|
|
145
|
+
* Configuration for number-with-unit controls (primarily used by containers).
|
|
146
|
+
*
|
|
147
|
+
* Unlike {@link NumberConfig}, this control lets the user **switch between
|
|
148
|
+
* multiple CSS units** via a dropdown alongside the numeric input.
|
|
149
|
+
*
|
|
150
|
+
* @see {@link PropertyUIConfig.numberWithUnit}
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* // Container max-width control
|
|
155
|
+
* const config: NumberWithUnitConfig = {
|
|
156
|
+
* min: 0,
|
|
157
|
+
* max: 9999,
|
|
158
|
+
* step: 10,
|
|
159
|
+
* units: ['px', '%', 'rem', 'ch', 'vw', 'auto'],
|
|
160
|
+
* defaultUnit: 'px',
|
|
161
|
+
* allowEmpty: true,
|
|
162
|
+
* };
|
|
163
|
+
* ```
|
|
51
164
|
*/
|
|
52
165
|
export interface NumberWithUnitConfig {
|
|
166
|
+
/** Minimum allowed value */
|
|
53
167
|
min?: number;
|
|
168
|
+
/** Maximum allowed value */
|
|
54
169
|
max?: number;
|
|
170
|
+
/** Increment step */
|
|
55
171
|
step?: number;
|
|
172
|
+
/**
|
|
173
|
+
* Available CSS units the user can select
|
|
174
|
+
* @default undefined
|
|
175
|
+
* @example ['px', '%', 'em', 'rem', 'vw', 'vh']
|
|
176
|
+
*/
|
|
56
177
|
units?: string[];
|
|
178
|
+
/**
|
|
179
|
+
* Initially selected unit
|
|
180
|
+
* @default undefined
|
|
181
|
+
*/
|
|
57
182
|
defaultUnit?: string;
|
|
183
|
+
/**
|
|
184
|
+
* Whether the field accepts empty / null values.
|
|
185
|
+
* Typically `true` for container properties like `minHeight` or `maxWidth`
|
|
186
|
+
* where "auto" or no value is meaningful.
|
|
187
|
+
* @default undefined
|
|
188
|
+
*/
|
|
58
189
|
allowEmpty?: boolean;
|
|
59
190
|
}
|
|
60
191
|
/**
|
|
61
|
-
*
|
|
192
|
+
* Configuration for select / dropdown controls.
|
|
193
|
+
*
|
|
194
|
+
* @see {@link PropertyUIConfig.select}
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```typescript
|
|
198
|
+
* const selectConfig: SelectConfig = {
|
|
199
|
+
* options: [
|
|
200
|
+
* { value: 'flexbox', label: 'Flexbox' },
|
|
201
|
+
* { value: 'grid', label: 'Grid' },
|
|
202
|
+
* ],
|
|
203
|
+
* searchable: false,
|
|
204
|
+
* };
|
|
205
|
+
* ```
|
|
62
206
|
*/
|
|
63
207
|
export interface SelectConfig {
|
|
208
|
+
/** Available options for the dropdown */
|
|
64
209
|
options: Array<{
|
|
65
210
|
value: string;
|
|
66
211
|
label: string;
|
|
67
212
|
icon?: ComponentType;
|
|
68
213
|
}>;
|
|
214
|
+
/**
|
|
215
|
+
* Enable type-ahead search filtering for long option lists
|
|
216
|
+
* @default false
|
|
217
|
+
*/
|
|
69
218
|
searchable?: boolean;
|
|
70
219
|
}
|
|
71
220
|
/**
|
|
72
|
-
*
|
|
221
|
+
* Configuration for single-line text input controls.
|
|
222
|
+
*
|
|
223
|
+
* @see {@link PropertyUIConfig.input}
|
|
73
224
|
*/
|
|
74
225
|
export interface InputConfig {
|
|
226
|
+
/**
|
|
227
|
+
* Placeholder text shown when the input is empty
|
|
228
|
+
* @example 'e.g., custom-class my-style'
|
|
229
|
+
*/
|
|
75
230
|
placeholder?: string;
|
|
231
|
+
/** Regex pattern for client-side validation */
|
|
76
232
|
pattern?: RegExp;
|
|
233
|
+
/** Message shown when validation fails */
|
|
77
234
|
validationMessage?: string;
|
|
78
235
|
}
|
|
79
236
|
/**
|
|
80
|
-
*
|
|
237
|
+
* Configuration for color picker controls.
|
|
238
|
+
*
|
|
239
|
+
* @see {@link PropertyUIConfig.colorPicker}
|
|
240
|
+
*
|
|
241
|
+
* @example
|
|
242
|
+
* ```typescript
|
|
243
|
+
* const colorConfig: ColorPickerConfig = {
|
|
244
|
+
* format: 'hex',
|
|
245
|
+
* alpha: true,
|
|
246
|
+
* presets: ['#ff0000', '#00ff00', '#0000ff'],
|
|
247
|
+
* };
|
|
248
|
+
* ```
|
|
81
249
|
*/
|
|
82
250
|
export interface ColorPickerConfig {
|
|
83
|
-
|
|
251
|
+
/**
|
|
252
|
+
* Output color format
|
|
253
|
+
* @default 'hex'
|
|
254
|
+
*/
|
|
255
|
+
format?: 'hex' | 'rgb' | 'hsl';
|
|
256
|
+
/**
|
|
257
|
+
* Whether to allow alpha (transparency) channel
|
|
258
|
+
* @default false
|
|
259
|
+
*/
|
|
84
260
|
alpha?: boolean;
|
|
261
|
+
/** Preset color swatches shown for quick selection */
|
|
85
262
|
presets?: string[];
|
|
86
263
|
}
|
|
87
264
|
/**
|
|
88
|
-
*
|
|
265
|
+
* Configuration for multi-line textarea controls.
|
|
266
|
+
*
|
|
267
|
+
* @see {@link PropertyUIConfig.textarea}
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```typescript
|
|
271
|
+
* const textareaConfig: TextareaConfig = {
|
|
272
|
+
* rows: 1,
|
|
273
|
+
* autoResize: true,
|
|
274
|
+
* };
|
|
275
|
+
* ```
|
|
89
276
|
*/
|
|
90
277
|
export interface TextareaConfig {
|
|
278
|
+
/**
|
|
279
|
+
* Initial number of visible text rows
|
|
280
|
+
* @default 3
|
|
281
|
+
*/
|
|
91
282
|
rows?: number;
|
|
283
|
+
/**
|
|
284
|
+
* Automatically grow the textarea height to fit content
|
|
285
|
+
* @default false
|
|
286
|
+
*/
|
|
92
287
|
autoResize?: boolean;
|
|
288
|
+
/** Placeholder text shown when empty */
|
|
93
289
|
placeholder?: string;
|
|
94
290
|
}
|
|
95
291
|
/**
|
|
96
|
-
*
|
|
292
|
+
* Configuration for box-model (margin/padding) controls.
|
|
293
|
+
*
|
|
294
|
+
* Renders a four-sided input (top, right, bottom, left) with
|
|
295
|
+
* optional linked-sides mode.
|
|
296
|
+
*
|
|
297
|
+
* @see {@link PropertyUIConfig.boxModel}
|
|
298
|
+
* @see {@link SpacingConfig} for the combined margin + padding variant
|
|
97
299
|
*/
|
|
98
300
|
export interface BoxModelConfig {
|
|
301
|
+
/** Minimum value per side */
|
|
99
302
|
min?: number;
|
|
303
|
+
/** Maximum value per side */
|
|
100
304
|
max?: number;
|
|
305
|
+
/**
|
|
306
|
+
* CSS unit for all sides
|
|
307
|
+
* @default 'px'
|
|
308
|
+
*/
|
|
101
309
|
unit?: string;
|
|
310
|
+
/**
|
|
311
|
+
* Whether all four sides are linked (same value) by default
|
|
312
|
+
* @default false
|
|
313
|
+
*/
|
|
102
314
|
linkedByDefault?: boolean;
|
|
103
315
|
}
|
|
104
316
|
/**
|
|
105
|
-
*
|
|
317
|
+
* Configuration for the combined spacing control (margin + padding in one UI).
|
|
318
|
+
*
|
|
319
|
+
* @see {@link PropertyUIConfig.spacing}
|
|
320
|
+
* @see {@link BoxModelConfig} for individual margin or padding controls
|
|
106
321
|
*/
|
|
107
322
|
export interface SpacingConfig {
|
|
323
|
+
/** Minimum padding value per side */
|
|
108
324
|
paddingMin?: number;
|
|
325
|
+
/** Maximum padding value per side */
|
|
109
326
|
paddingMax?: number;
|
|
327
|
+
/** Minimum margin value per side (can be negative) */
|
|
110
328
|
marginMin?: number;
|
|
329
|
+
/** Maximum margin value per side */
|
|
111
330
|
marginMax?: number;
|
|
331
|
+
/**
|
|
332
|
+
* CSS unit for all values
|
|
333
|
+
* @default 'px'
|
|
334
|
+
*/
|
|
112
335
|
unit?: string;
|
|
113
336
|
}
|
|
114
337
|
/**
|
|
115
|
-
*
|
|
338
|
+
* Configuration for the typography toolbar control.
|
|
339
|
+
*
|
|
340
|
+
* Toggles visibility of individual formatting buttons (bold, italic, etc.).
|
|
341
|
+
*
|
|
342
|
+
* @see {@link PropertyUIConfig.typographyToolbar}
|
|
116
343
|
*/
|
|
117
344
|
export interface TypographyToolbarConfig {
|
|
345
|
+
/** Show bold toggle button @default true */
|
|
118
346
|
showBold?: boolean;
|
|
347
|
+
/** Show italic toggle button @default true */
|
|
119
348
|
showItalic?: boolean;
|
|
349
|
+
/** Show underline toggle button @default true */
|
|
120
350
|
showUnderline?: boolean;
|
|
351
|
+
/** Show text alignment buttons @default true */
|
|
121
352
|
showAlignment?: boolean;
|
|
353
|
+
/** Show font size control @default true */
|
|
122
354
|
showFontSize?: boolean;
|
|
355
|
+
/** Show color picker @default true */
|
|
123
356
|
showColor?: boolean;
|
|
124
357
|
}
|
|
125
358
|
/**
|
|
126
|
-
*
|
|
359
|
+
* Configuration for gradient editor controls.
|
|
360
|
+
*
|
|
361
|
+
* @see {@link PropertyUIConfig.gradientEditor}
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* ```typescript
|
|
365
|
+
* const gradientConfig: GradientEditorConfig = {
|
|
366
|
+
* allowLinear: true,
|
|
367
|
+
* allowRadial: true,
|
|
368
|
+
* maxStops: 5,
|
|
369
|
+
* colorFormat: 'hex',
|
|
370
|
+
* };
|
|
371
|
+
* ```
|
|
127
372
|
*/
|
|
128
373
|
export interface GradientEditorConfig {
|
|
374
|
+
/**
|
|
375
|
+
* Allow linear gradient type
|
|
376
|
+
* @default true
|
|
377
|
+
*/
|
|
129
378
|
allowLinear?: boolean;
|
|
379
|
+
/**
|
|
380
|
+
* Allow radial gradient type
|
|
381
|
+
* @default true
|
|
382
|
+
*/
|
|
130
383
|
allowRadial?: boolean;
|
|
384
|
+
/**
|
|
385
|
+
* Maximum number of color stops
|
|
386
|
+
* @default undefined (unlimited)
|
|
387
|
+
*/
|
|
131
388
|
maxStops?: number;
|
|
132
|
-
|
|
389
|
+
/**
|
|
390
|
+
* Output color format for gradient stops
|
|
391
|
+
* @default 'hex'
|
|
392
|
+
*/
|
|
393
|
+
colorFormat?: 'hex' | 'rgb' | 'hsl';
|
|
133
394
|
}
|
|
134
395
|
/**
|
|
135
|
-
*
|
|
396
|
+
* Configuration for border editor controls.
|
|
397
|
+
*
|
|
398
|
+
* @see {@link PropertyUIConfig.borderEditor}
|
|
136
399
|
*/
|
|
137
400
|
export interface BorderEditorConfig {
|
|
401
|
+
/**
|
|
402
|
+
* Allow editing each border side independently
|
|
403
|
+
* @default false
|
|
404
|
+
*/
|
|
138
405
|
allowIndividualSides?: boolean;
|
|
406
|
+
/**
|
|
407
|
+
* Show border-radius control
|
|
408
|
+
* @default true
|
|
409
|
+
*/
|
|
139
410
|
allowRadius?: boolean;
|
|
411
|
+
/**
|
|
412
|
+
* Maximum border width in pixels
|
|
413
|
+
* @default 20
|
|
414
|
+
*/
|
|
140
415
|
maxWidth?: number;
|
|
141
416
|
}
|
|
142
417
|
/**
|
|
143
|
-
*
|
|
144
|
-
*
|
|
418
|
+
* Configuration for the font preset select control.
|
|
419
|
+
*
|
|
420
|
+
* Displays typography presets from the Design System as a dropdown.
|
|
421
|
+
* The presets are sourced from {@link PluginDesignSystem.fonts}.
|
|
422
|
+
*
|
|
423
|
+
* @see {@link PropertyUIConfig.fontPresetSelect}
|
|
145
424
|
*/
|
|
146
425
|
export interface FontPresetSelectConfig {
|
|
147
|
-
/**
|
|
426
|
+
/**
|
|
427
|
+
* Filter fonts by category (e.g., `"heading"`, `"body"`)
|
|
428
|
+
* @default undefined (show all fonts)
|
|
429
|
+
*/
|
|
148
430
|
category?: string;
|
|
149
|
-
/** Placeholder text */
|
|
431
|
+
/** Placeholder text when no preset is selected */
|
|
150
432
|
placeholder?: string;
|
|
151
433
|
}
|
|
152
434
|
/**
|
|
153
|
-
*
|
|
154
|
-
*
|
|
435
|
+
* Configuration for the color preset select control.
|
|
436
|
+
*
|
|
437
|
+
* Displays color presets from the Design System as a dropdown with
|
|
438
|
+
* optional color swatches. Unlike `color-picker`, this control only
|
|
439
|
+
* allows preset selection — no free-form color input.
|
|
440
|
+
*
|
|
441
|
+
* @see {@link PropertyUIConfig.colorPresetSelect}
|
|
155
442
|
*/
|
|
156
443
|
export interface ColorPresetSelectConfig {
|
|
157
|
-
/**
|
|
444
|
+
/**
|
|
445
|
+
* Filter colors by category
|
|
446
|
+
* @default undefined (show all colors)
|
|
447
|
+
*/
|
|
158
448
|
category?: string;
|
|
159
|
-
/** Placeholder text */
|
|
449
|
+
/** Placeholder text when no preset is selected */
|
|
160
450
|
placeholder?: string;
|
|
161
|
-
/**
|
|
451
|
+
/**
|
|
452
|
+
* Show a colored swatch preview next to each option
|
|
453
|
+
* @default true
|
|
454
|
+
*/
|
|
162
455
|
showSwatch?: boolean;
|
|
163
|
-
/**
|
|
456
|
+
/**
|
|
457
|
+
* Allow a "None" option for transparent / no color
|
|
458
|
+
* @default false
|
|
459
|
+
*/
|
|
164
460
|
allowNone?: boolean;
|
|
165
461
|
}
|
|
166
462
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
463
|
+
* Configuration for icon-based alignment toggle buttons.
|
|
464
|
+
*
|
|
465
|
+
* Used for both horizontal text alignment (`text-align-toggle`)
|
|
466
|
+
* and vertical alignment (`vertical-align-toggle`).
|
|
467
|
+
*
|
|
468
|
+
* @see {@link PropertyUIConfig.alignmentToggle}
|
|
169
469
|
*/
|
|
170
470
|
export interface AlignmentToggleConfig {
|
|
171
|
-
/**
|
|
471
|
+
/**
|
|
472
|
+
* Include "justify" option (horizontal alignment only)
|
|
473
|
+
* @default false
|
|
474
|
+
*/
|
|
172
475
|
includeJustify?: boolean;
|
|
173
|
-
/**
|
|
476
|
+
/**
|
|
477
|
+
* Include "stretch" option (vertical alignment only)
|
|
478
|
+
* @default false
|
|
479
|
+
*/
|
|
174
480
|
includeStretch?: boolean;
|
|
175
|
-
/**
|
|
481
|
+
/**
|
|
482
|
+
* Include "auto" / "inherit" option
|
|
483
|
+
* @default false
|
|
484
|
+
*/
|
|
176
485
|
includeAuto?: boolean;
|
|
177
486
|
}
|
|
178
487
|
/**
|
|
179
|
-
* Display
|
|
488
|
+
* Display and layout configuration for a property control in the Context Panel.
|
|
489
|
+
*
|
|
490
|
+
* Controls how and when a property is visible, its layout arrangement,
|
|
491
|
+
* and conditional visibility based on sibling property values.
|
|
492
|
+
*
|
|
493
|
+
* @see {@link PropertyUIConfig.display}
|
|
494
|
+
*
|
|
495
|
+
* @example
|
|
496
|
+
* ```typescript
|
|
497
|
+
* // Show this property only when layout mode is 'flexbox'
|
|
498
|
+
* const display: DisplayConfig = {
|
|
499
|
+
* layout: 'grid-2',
|
|
500
|
+
* condition: {
|
|
501
|
+
* when: 'layout.mode',
|
|
502
|
+
* equals: 'flexbox',
|
|
503
|
+
* },
|
|
504
|
+
* };
|
|
505
|
+
* ```
|
|
180
506
|
*/
|
|
181
507
|
export interface DisplayConfig {
|
|
182
508
|
/**
|
|
183
|
-
*
|
|
509
|
+
* Where this property's control is rendered
|
|
510
|
+
* @default 'panel'
|
|
184
511
|
*/
|
|
185
|
-
mode?:
|
|
512
|
+
mode?: 'tooltip' | 'panel' | 'both';
|
|
186
513
|
/**
|
|
187
|
-
*
|
|
514
|
+
* Whether this property section can be collapsed
|
|
515
|
+
* @default false
|
|
188
516
|
*/
|
|
189
517
|
collapsible?: boolean;
|
|
190
518
|
/**
|
|
191
|
-
*
|
|
519
|
+
* Initial collapsed state (only relevant when `collapsible` is `true`)
|
|
520
|
+
* @default false
|
|
192
521
|
*/
|
|
193
522
|
defaultCollapsed?: boolean;
|
|
194
523
|
/**
|
|
195
|
-
* Layout
|
|
196
|
-
*
|
|
524
|
+
* Layout arrangement for controls within the panel section.
|
|
525
|
+
* - `'single'` — one control per row (default)
|
|
526
|
+
* - `'grid-2'` — two controls side by side
|
|
527
|
+
* - `'grid-3'` — three controls per row
|
|
528
|
+
*
|
|
529
|
+
* Primarily used by container plugins to create compact property grids.
|
|
197
530
|
*/
|
|
198
|
-
layout?:
|
|
531
|
+
layout?: 'grid-2' | 'grid-3' | 'single' | string;
|
|
199
532
|
/**
|
|
200
|
-
* Conditional visibility based on
|
|
201
|
-
*
|
|
533
|
+
* Conditional visibility: show/hide this property based on another
|
|
534
|
+
* property's current value.
|
|
535
|
+
*
|
|
536
|
+
* @example
|
|
537
|
+
* ```typescript
|
|
538
|
+
* // Show only when layout mode is 'grid'
|
|
539
|
+
* { when: 'layout.mode', equals: 'grid' }
|
|
540
|
+
*
|
|
541
|
+
* // Show only when border style is NOT 'none'
|
|
542
|
+
* { when: 'border.style', notEquals: 'none' }
|
|
543
|
+
* ```
|
|
202
544
|
*/
|
|
203
545
|
condition?: {
|
|
546
|
+
/** Property key (dot-notation) to observe */
|
|
204
547
|
when: string;
|
|
548
|
+
/** Show this control when the observed property equals this value */
|
|
205
549
|
equals?: unknown;
|
|
550
|
+
/** Show this control when the observed property does NOT equal this value */
|
|
206
551
|
notEquals?: unknown;
|
|
207
552
|
};
|
|
208
553
|
}
|
|
209
554
|
/**
|
|
210
|
-
* UI configuration for property
|
|
211
|
-
*
|
|
555
|
+
* UI configuration metadata for a property.
|
|
556
|
+
*
|
|
557
|
+
* Tells the Context Panel **how** to render a property's editor control.
|
|
558
|
+
* Each property specifies a `control` type and then provides the
|
|
559
|
+
* matching configuration object (e.g., `slider` config for a `'slider'` control).
|
|
560
|
+
*
|
|
561
|
+
* @see {@link PropertyDefinition.ui}
|
|
562
|
+
* @see {@link PropertyControlType} for the list of available controls
|
|
563
|
+
*
|
|
564
|
+
* @example
|
|
565
|
+
* ```typescript
|
|
566
|
+
* const ui: PropertyUIConfig = {
|
|
567
|
+
* control: 'slider',
|
|
568
|
+
* slider: { min: 0, max: 100, step: 1, unit: 'px' },
|
|
569
|
+
* display: { layout: 'grid-2' },
|
|
570
|
+
* };
|
|
571
|
+
* ```
|
|
212
572
|
*/
|
|
213
573
|
export interface PropertyUIConfig {
|
|
574
|
+
/** Which UI control widget to render in the Context Panel */
|
|
214
575
|
control: PropertyControlType;
|
|
576
|
+
/** Configuration when `control` is `'slider'` @see {@link SliderConfig} */
|
|
215
577
|
slider?: SliderConfig;
|
|
578
|
+
/** Configuration when `control` is `'number-input'` @see {@link NumberConfig} */
|
|
216
579
|
number?: NumberConfig;
|
|
580
|
+
/** Configuration when `control` is `'number-with-unit'` @see {@link NumberWithUnitConfig} */
|
|
217
581
|
numberWithUnit?: NumberWithUnitConfig;
|
|
582
|
+
/** Configuration when `control` is `'select'` @see {@link SelectConfig} */
|
|
218
583
|
select?: SelectConfig;
|
|
584
|
+
/** Configuration when `control` is `'input'` @see {@link InputConfig} */
|
|
219
585
|
input?: InputConfig;
|
|
586
|
+
/** Configuration when `control` is `'textarea'` @see {@link TextareaConfig} */
|
|
220
587
|
textarea?: TextareaConfig;
|
|
588
|
+
/** Configuration when `control` is `'color-picker'` @see {@link ColorPickerConfig} */
|
|
221
589
|
colorPicker?: ColorPickerConfig;
|
|
590
|
+
/** Configuration when `control` is `'box-model'` @see {@link BoxModelConfig} */
|
|
222
591
|
boxModel?: BoxModelConfig;
|
|
592
|
+
/** Configuration when `control` is `'spacing'` or `'spacing-combined'` @see {@link SpacingConfig} */
|
|
223
593
|
spacing?: SpacingConfig;
|
|
594
|
+
/** Configuration when `control` is `'typography-toolbar'` @see {@link TypographyToolbarConfig} */
|
|
224
595
|
typographyToolbar?: TypographyToolbarConfig;
|
|
596
|
+
/** Configuration when `control` is `'gradient-editor'` @see {@link GradientEditorConfig} */
|
|
225
597
|
gradientEditor?: GradientEditorConfig;
|
|
598
|
+
/** Configuration when `control` is `'border-editor'` @see {@link BorderEditorConfig} */
|
|
226
599
|
borderEditor?: BorderEditorConfig;
|
|
600
|
+
/** Configuration when `control` is `'font-preset-select'` @see {@link FontPresetSelectConfig} */
|
|
227
601
|
fontPresetSelect?: FontPresetSelectConfig;
|
|
602
|
+
/** Configuration when `control` is `'color-preset-select'` @see {@link ColorPresetSelectConfig} */
|
|
228
603
|
colorPresetSelect?: ColorPresetSelectConfig;
|
|
604
|
+
/** Configuration when `control` is `'text-align-toggle'` or `'vertical-align-toggle'` @see {@link AlignmentToggleConfig} */
|
|
229
605
|
alignmentToggle?: AlignmentToggleConfig;
|
|
606
|
+
/** Layout, visibility, and conditional display settings @see {@link DisplayConfig} */
|
|
230
607
|
display?: DisplayConfig;
|
|
231
608
|
}
|
|
232
609
|
/**
|
|
233
|
-
*
|
|
610
|
+
* Validation rules for a property value.
|
|
611
|
+
*
|
|
612
|
+
* Applied client-side when the user edits properties in the Context Panel.
|
|
613
|
+
*
|
|
614
|
+
* @see {@link PropertyDefinition.validation}
|
|
615
|
+
*
|
|
616
|
+
* @example
|
|
617
|
+
* ```typescript
|
|
618
|
+
* const validation: PropertyValidation = {
|
|
619
|
+
* min: 0,
|
|
620
|
+
* max: 100,
|
|
621
|
+
* message: 'Value must be between 0 and 100',
|
|
622
|
+
* };
|
|
623
|
+
* ```
|
|
234
624
|
*/
|
|
235
625
|
export interface PropertyValidation {
|
|
626
|
+
/** Regex pattern the string value must match */
|
|
236
627
|
pattern?: RegExp;
|
|
628
|
+
/** Minimum numeric value */
|
|
237
629
|
min?: number;
|
|
630
|
+
/** Maximum numeric value */
|
|
238
631
|
max?: number;
|
|
632
|
+
/** Error message shown when validation fails */
|
|
239
633
|
message?: string;
|
|
634
|
+
/**
|
|
635
|
+
* Custom validation function.
|
|
636
|
+
* Return `true` for valid, or a string error message for invalid.
|
|
637
|
+
*/
|
|
240
638
|
custom?: (value: unknown) => boolean | string;
|
|
241
639
|
}
|
|
242
640
|
/**
|
|
243
|
-
* Property priority for progressive disclosure
|
|
244
|
-
*
|
|
641
|
+
* Property priority for progressive disclosure in the Context Panel.
|
|
642
|
+
*
|
|
643
|
+
* Controls visual hierarchy and default visibility:
|
|
644
|
+
* - `'quick'` — Always visible at the top, no accordion (most important properties)
|
|
645
|
+
* - `'common'` — Collapsible section, expanded by default (frequently used)
|
|
646
|
+
* - `'advanced'` — Collapsible section, collapsed by default (rarely used)
|
|
647
|
+
*
|
|
648
|
+
* @default 'common'
|
|
649
|
+
* @see {@link PropertyDefinition.priority}
|
|
245
650
|
*/
|
|
246
|
-
export type PropertyPriority =
|
|
651
|
+
export type PropertyPriority = 'quick' | 'common' | 'advanced';
|
|
247
652
|
/**
|
|
248
|
-
* Property definition
|
|
653
|
+
* Property definition — the core metadata interface for plugin properties.
|
|
654
|
+
*
|
|
655
|
+
* Each plugin declares an array of `PropertyDefinition` objects that describe
|
|
656
|
+
* its editable properties. The Context Panel reads these definitions and
|
|
657
|
+
* auto-generates the appropriate editor controls.
|
|
658
|
+
*
|
|
659
|
+
* Properties support:
|
|
660
|
+
* - **Dot-notation keys** for nested data structures (`'style.fontSize'`)
|
|
661
|
+
* - **Design System integration** via `useGlobal` / `globalKey`
|
|
662
|
+
* - **Progressive disclosure** via `priority`
|
|
663
|
+
* - **Conditional visibility** via `ui.display.condition`
|
|
249
664
|
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
665
|
+
* @see {@link PluginConfig.properties}
|
|
666
|
+
* @see {@link PropertyUIConfig} for UI control configuration
|
|
667
|
+
* @see {@link PropertyCategory} for organizational grouping
|
|
668
|
+
*
|
|
669
|
+
* @example
|
|
670
|
+
* ```typescript
|
|
671
|
+
* const fontSizeProperty: PropertyDefinition = {
|
|
672
|
+
* key: 'style.fontSize',
|
|
673
|
+
* type: 'range',
|
|
674
|
+
* label: 'Font Size',
|
|
675
|
+
* default: 16,
|
|
676
|
+
* category: 'style',
|
|
677
|
+
* priority: 'quick',
|
|
678
|
+
* useGlobal: true,
|
|
679
|
+
* globalKey: 'fonts.body.size',
|
|
680
|
+
* ui: {
|
|
681
|
+
* control: 'slider',
|
|
682
|
+
* slider: { min: 8, max: 72, step: 1, unit: 'px', showValue: true },
|
|
683
|
+
* },
|
|
684
|
+
* };
|
|
685
|
+
* ```
|
|
252
686
|
*/
|
|
253
687
|
export interface PropertyDefinition {
|
|
254
688
|
/**
|
|
255
|
-
* Property key
|
|
256
|
-
*
|
|
689
|
+
* Property key using dot notation for nested data structures.
|
|
690
|
+
*
|
|
691
|
+
* This key maps directly to the path in the plugin's `data` object.
|
|
692
|
+
*
|
|
693
|
+
* @example 'style.fontSize', 'layout.padding.top', 'contentI18n'
|
|
257
694
|
*/
|
|
258
695
|
key: string;
|
|
259
696
|
/**
|
|
260
|
-
*
|
|
697
|
+
* Semantic type of the property value.
|
|
698
|
+
* @see {@link PropertyType}
|
|
261
699
|
*/
|
|
262
700
|
type: PropertyType;
|
|
263
701
|
/**
|
|
264
|
-
*
|
|
702
|
+
* Human-readable label displayed in the Context Panel
|
|
265
703
|
*/
|
|
266
704
|
label: string;
|
|
267
705
|
/**
|
|
268
|
-
* Default value
|
|
706
|
+
* Default value for new plugin instances.
|
|
707
|
+
* Set to `null` to inherit from the Design System global default
|
|
708
|
+
* (when `useGlobal` is `true`).
|
|
269
709
|
*/
|
|
270
710
|
default: unknown;
|
|
271
711
|
/**
|
|
272
|
-
*
|
|
712
|
+
* Help text / tooltip shown below or beside the control in the UI
|
|
273
713
|
*/
|
|
274
714
|
description?: string;
|
|
275
715
|
/**
|
|
276
|
-
*
|
|
716
|
+
* Organizational category — determines which panel section this property
|
|
717
|
+
* appears in.
|
|
718
|
+
*
|
|
719
|
+
* @default 'style'
|
|
720
|
+
* @see {@link PropertyCategory}
|
|
277
721
|
*/
|
|
278
722
|
category?: PropertyCategory;
|
|
279
723
|
/**
|
|
280
|
-
* Whether
|
|
724
|
+
* Whether a value is required before the element can be saved
|
|
725
|
+
* @default false
|
|
281
726
|
*/
|
|
282
727
|
required?: boolean;
|
|
283
728
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
* Defaults to 'common' if not specified
|
|
729
|
+
* Controls progressive disclosure and default visibility.
|
|
730
|
+
*
|
|
731
|
+
* @default 'common'
|
|
732
|
+
* @see {@link PropertyPriority}
|
|
289
733
|
*/
|
|
290
734
|
priority?: PropertyPriority;
|
|
291
735
|
/**
|
|
292
|
-
* Design System integration
|
|
293
|
-
*
|
|
736
|
+
* Enable Design System integration for this property.
|
|
737
|
+
* When `true`, the UI shows a "Use Global Default" toggle that
|
|
738
|
+
* lets the user fall back to the design system value specified
|
|
739
|
+
* by {@link globalKey}.
|
|
740
|
+
*
|
|
741
|
+
* @default false
|
|
294
742
|
*/
|
|
295
743
|
useGlobal?: boolean;
|
|
296
744
|
/**
|
|
297
|
-
* Design System
|
|
745
|
+
* Dot-notation path into the Design System to read the global default.
|
|
746
|
+
* Only used when `useGlobal` is `true`.
|
|
747
|
+
*
|
|
298
748
|
* @example 'fonts.body.size', 'colors.text-primary'
|
|
299
749
|
*/
|
|
300
750
|
globalKey?: string;
|
|
301
751
|
/**
|
|
302
|
-
* UI control configuration
|
|
752
|
+
* UI control configuration — tells the Context Panel which widget
|
|
753
|
+
* to render and how to configure it.
|
|
754
|
+
*
|
|
755
|
+
* @see {@link PropertyUIConfig}
|
|
303
756
|
*/
|
|
304
757
|
ui?: PropertyUIConfig;
|
|
305
758
|
/**
|
|
306
|
-
*
|
|
759
|
+
* Client-side validation rules applied when the user edits this property.
|
|
760
|
+
* @see {@link PropertyValidation}
|
|
307
761
|
*/
|
|
308
762
|
validation?: PropertyValidation;
|
|
309
763
|
}
|
|
310
764
|
/**
|
|
311
|
-
*
|
|
765
|
+
* Optional metadata about a plugin, shown in plugin listings and documentation.
|
|
766
|
+
*
|
|
767
|
+
* @see {@link PluginConfig.meta}
|
|
768
|
+
*
|
|
769
|
+
* @example
|
|
770
|
+
* ```typescript
|
|
771
|
+
* const meta: PluginMeta = {
|
|
772
|
+
* description: 'Semantic heading component (h1-h6) for page structure and SEO',
|
|
773
|
+
* tags: ['heading', 'h1', 'title', 'semantic', 'seo'],
|
|
774
|
+
* thumbnail: '/plugins/base-heading/thumbnail.png',
|
|
775
|
+
* documentation: 'https://docs.codefluss.com/plugins/base-heading',
|
|
776
|
+
* };
|
|
777
|
+
* ```
|
|
312
778
|
*/
|
|
313
779
|
export interface PluginMeta {
|
|
780
|
+
/** Short description of what the plugin does */
|
|
314
781
|
description?: string;
|
|
782
|
+
/** Search / filter tags for plugin discovery in the editor toolbar */
|
|
315
783
|
tags?: string[];
|
|
784
|
+
/** Path or URL to a thumbnail image for the plugin browser */
|
|
316
785
|
thumbnail?: string;
|
|
786
|
+
/** URL to external documentation */
|
|
317
787
|
documentation?: string;
|
|
318
788
|
}
|
|
319
789
|
/**
|
|
320
|
-
* Plugin
|
|
790
|
+
* Plugin capabilities — declares **what** a plugin can do structurally.
|
|
791
|
+
*
|
|
792
|
+
* This is the core of the **plugin-driven architecture**: each plugin
|
|
793
|
+
* declares its own capabilities (container vs leaf, allowed children, etc.)
|
|
794
|
+
* and the application reads these to determine valid operations (drag-drop
|
|
795
|
+
* constraints, nesting rules, toolbar options).
|
|
796
|
+
*
|
|
797
|
+
* @see {@link PluginConfig.capabilities}
|
|
798
|
+
*
|
|
799
|
+
* @example
|
|
800
|
+
* ```typescript
|
|
801
|
+
* // Container plugin (e.g., base-container)
|
|
802
|
+
* const containerCaps: PluginCapabilities = {
|
|
803
|
+
* supportsChildren: true,
|
|
804
|
+
* isRootComponent: true,
|
|
805
|
+
* requiresParent: false,
|
|
806
|
+
* childrenType: 'nested',
|
|
807
|
+
* allowedChildPlugins: [], // any child allowed
|
|
808
|
+
* maxChildren: null, // unlimited
|
|
809
|
+
* minChildren: 0,
|
|
810
|
+
* };
|
|
321
811
|
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
812
|
+
* // Leaf plugin (e.g., base-heading)
|
|
813
|
+
* const headingCaps: PluginCapabilities = {
|
|
814
|
+
* supportsChildren: false,
|
|
815
|
+
* isRootComponent: false,
|
|
816
|
+
* requiresParent: true,
|
|
817
|
+
* childrenType: null,
|
|
818
|
+
* allowedChildPlugins: [],
|
|
819
|
+
* maxChildren: null,
|
|
820
|
+
* minChildren: 0,
|
|
821
|
+
* };
|
|
822
|
+
* ```
|
|
325
823
|
*/
|
|
326
824
|
export interface PluginCapabilities {
|
|
327
825
|
/**
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
826
|
+
* Whether this plugin can contain child components.
|
|
827
|
+
*
|
|
828
|
+
* - `true` — container/layout component (e.g., `base-container`, `form-container`)
|
|
829
|
+
* - `false` — leaf component (e.g., `base-heading`, `base-image`, `base-button`)
|
|
331
830
|
*/
|
|
332
831
|
supportsChildren: boolean;
|
|
333
832
|
/**
|
|
334
|
-
*
|
|
335
|
-
*
|
|
336
|
-
*
|
|
833
|
+
* Whether this plugin can be placed at the canvas / section root level.
|
|
834
|
+
*
|
|
835
|
+
* - `true` — can be placed directly on the canvas (containers, sections)
|
|
836
|
+
* - `false` — must be inside another component (text, buttons, images)
|
|
337
837
|
*/
|
|
338
838
|
isRootComponent: boolean;
|
|
339
839
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
*
|
|
840
|
+
* Whether this plugin must be nested inside a parent container.
|
|
841
|
+
*
|
|
842
|
+
* - `true` — cannot exist at top level, must be inside a container
|
|
843
|
+
* - `false` — can be placed directly on the canvas
|
|
343
844
|
*
|
|
344
|
-
* @example
|
|
345
|
-
*
|
|
845
|
+
* @example
|
|
846
|
+
* // Text: requiresParent = true (must be in a container)
|
|
847
|
+
* // Container: requiresParent = false (can be at top level)
|
|
346
848
|
*/
|
|
347
849
|
requiresParent: boolean;
|
|
348
850
|
/**
|
|
349
|
-
* Children architecture type
|
|
350
|
-
*
|
|
351
|
-
* '
|
|
352
|
-
*
|
|
851
|
+
* Children architecture type (only relevant when `supportsChildren` is `true`).
|
|
852
|
+
*
|
|
853
|
+
* - `'nested'` — Children stored as direct arrays in the parent's data (**recommended**)
|
|
854
|
+
* - `'flat'` — Children reference parent via `parentId` (**deprecated**)
|
|
855
|
+
* - `null` — Does not support children
|
|
353
856
|
*/
|
|
354
|
-
childrenType:
|
|
857
|
+
childrenType: 'nested' | 'flat' | null;
|
|
355
858
|
/**
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* [
|
|
359
|
-
*
|
|
859
|
+
* Restricts which plugins may be added as children.
|
|
860
|
+
*
|
|
861
|
+
* - Empty array `[]` — all plugins allowed as children
|
|
862
|
+
* - `['base-text', 'base-image']` — only listed plugin IDs allowed
|
|
863
|
+
*
|
|
864
|
+
* Only applicable when `supportsChildren` is `true`.
|
|
360
865
|
*/
|
|
361
866
|
allowedChildPlugins: string[];
|
|
362
867
|
/**
|
|
363
|
-
*
|
|
364
|
-
*
|
|
365
|
-
* [
|
|
366
|
-
*
|
|
868
|
+
* Restricts which container plugins this plugin may be placed inside.
|
|
869
|
+
*
|
|
870
|
+
* - `undefined` or empty array `[]` — can be a child of any container
|
|
871
|
+
* - `['base-container']` — can only be inside the listed containers
|
|
872
|
+
*
|
|
873
|
+
* Only applicable when `requiresParent` is `true`.
|
|
367
874
|
*/
|
|
368
875
|
allowedParentPlugins?: string[];
|
|
369
876
|
/**
|
|
370
|
-
* Maximum number of children
|
|
371
|
-
*
|
|
372
|
-
*
|
|
373
|
-
*
|
|
877
|
+
* Maximum number of children this container can hold.
|
|
878
|
+
*
|
|
879
|
+
* - `null` — unlimited children
|
|
880
|
+
* - A positive number — enforced limit
|
|
881
|
+
*
|
|
882
|
+
* Only applicable when `supportsChildren` is `true`.
|
|
374
883
|
*/
|
|
375
884
|
maxChildren: number | null;
|
|
376
885
|
/**
|
|
377
|
-
* Minimum number of children required
|
|
378
|
-
*
|
|
379
|
-
* Only applicable
|
|
886
|
+
* Minimum number of children required by this container.
|
|
887
|
+
*
|
|
888
|
+
* Only applicable when `supportsChildren` is `true`.
|
|
889
|
+
* @default 0
|
|
380
890
|
*/
|
|
381
891
|
minChildren: number;
|
|
382
892
|
}
|
|
@@ -395,37 +905,60 @@ export interface PluginCapabilities {
|
|
|
395
905
|
* - Clear separation between editor and view mode
|
|
396
906
|
*/
|
|
397
907
|
/**
|
|
398
|
-
*
|
|
908
|
+
* External dependencies injected into plugin components by the host application.
|
|
909
|
+
*
|
|
910
|
+
* Provides access to the Design System, utility functions, and optional
|
|
911
|
+
* editor callbacks. These are passed via the `dependencies` prop.
|
|
399
912
|
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
402
|
-
*
|
|
913
|
+
* **Note:** This is the simplified dependency interface used in `plugin-system.ts`.
|
|
914
|
+
* The full dependency interface (including `PluginRenderer` component and
|
|
915
|
+
* `callbacks`) is defined in `dependencies.ts`.
|
|
916
|
+
*
|
|
917
|
+
* @see {@link BasePluginProps.dependencies}
|
|
918
|
+
* @see {@link PluginDesignSystem} for design token access
|
|
919
|
+
* @see {@link PluginUtils} for utility functions
|
|
403
920
|
*/
|
|
404
921
|
export interface PluginDependencies {
|
|
405
922
|
/**
|
|
406
|
-
* Design System instance
|
|
407
|
-
*
|
|
923
|
+
* Design System instance providing access to fonts, colors, spacing,
|
|
924
|
+
* breakpoints, and other design tokens.
|
|
925
|
+
*
|
|
926
|
+
* @see {@link PluginDesignSystem}
|
|
408
927
|
*/
|
|
409
928
|
designSystem: PluginDesignSystem;
|
|
410
929
|
/**
|
|
411
|
-
* Utility functions
|
|
412
|
-
*
|
|
930
|
+
* Utility functions (e.g., `cn` for class name merging)
|
|
931
|
+
* @see {@link PluginUtils}
|
|
413
932
|
*/
|
|
414
933
|
utils: PluginUtils;
|
|
415
934
|
/**
|
|
416
|
-
*
|
|
417
|
-
*
|
|
935
|
+
* Callback invoked when the user edits text content (Editor mode only).
|
|
936
|
+
*
|
|
937
|
+
* @param elementId - Unique ID of the element being edited
|
|
938
|
+
* @param language - ISO language code of the content being changed
|
|
939
|
+
* @param content - New content value
|
|
418
940
|
*/
|
|
419
941
|
onContentChange?: (elementId: string, language: string, content: unknown) => void;
|
|
942
|
+
/**
|
|
943
|
+
* Callback invoked when a property value changes via the Context Panel
|
|
944
|
+
* (Editor mode only).
|
|
945
|
+
*
|
|
946
|
+
* @param elementId - Unique ID of the element being edited
|
|
947
|
+
* @param property - Dot-notation property path (e.g., `'style.fontSize'`)
|
|
948
|
+
* @param value - New property value
|
|
949
|
+
*/
|
|
420
950
|
onPropertyChange?: (elementId: string, property: string, value: unknown) => void;
|
|
421
951
|
}
|
|
422
952
|
/**
|
|
423
|
-
* Base
|
|
953
|
+
* Base props required by **every** plugin component.
|
|
954
|
+
*
|
|
955
|
+
* Both Editor Components and Renderers must accept these props.
|
|
956
|
+
* Use the generic parameter `TData` to specify the plugin's data shape.
|
|
424
957
|
*
|
|
425
|
-
*
|
|
426
|
-
* Both Editor Components and Renderers should extend this interface.
|
|
958
|
+
* @template TData - Plugin-specific data type (defaults to `unknown`)
|
|
427
959
|
*
|
|
428
|
-
* @
|
|
960
|
+
* @see {@link EditorModeProps} for additional editor-only props
|
|
961
|
+
* @see {@link RendererProps} for the minimal SSR variant
|
|
429
962
|
*
|
|
430
963
|
* @example
|
|
431
964
|
* ```typescript
|
|
@@ -435,36 +968,36 @@ export interface PluginDependencies {
|
|
|
435
968
|
*/
|
|
436
969
|
export interface BasePluginProps<TData = unknown> {
|
|
437
970
|
/**
|
|
438
|
-
* Unique element ID
|
|
439
|
-
*
|
|
971
|
+
* Unique element ID — used for data attributes, callbacks, and DOM references.
|
|
972
|
+
* @example 'heading-abc123'
|
|
440
973
|
*/
|
|
441
974
|
elementId: string;
|
|
442
975
|
/**
|
|
443
|
-
* Plugin-specific data
|
|
444
|
-
*
|
|
976
|
+
* Plugin-specific data object containing all configurable properties and content.
|
|
977
|
+
* The shape is defined by the plugin's type parameter `TData`.
|
|
445
978
|
*/
|
|
446
979
|
data: TData;
|
|
447
980
|
/**
|
|
448
|
-
* Current language
|
|
449
|
-
* Used for multi-language content
|
|
981
|
+
* Current language as an ISO code.
|
|
982
|
+
* Used for resolving multi-language content (`MultiLangContent`).
|
|
450
983
|
* @example 'de', 'en', 'fr', 'es', 'it'
|
|
451
984
|
*/
|
|
452
985
|
language: string;
|
|
453
986
|
/**
|
|
454
|
-
* Injected dependencies
|
|
455
|
-
*
|
|
987
|
+
* Injected dependencies from the host application.
|
|
988
|
+
* @see {@link PluginDependencies}
|
|
456
989
|
*/
|
|
457
990
|
dependencies: PluginDependencies;
|
|
458
991
|
}
|
|
459
992
|
/**
|
|
460
|
-
* Editor
|
|
993
|
+
* Additional props for Editor Components only (`'use client'`).
|
|
461
994
|
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
995
|
+
* These enable interactive editing: selection highlighting, click handling,
|
|
996
|
+
* content editing, and property changes. Combine with {@link BasePluginProps}
|
|
997
|
+
* to form the full editor component props.
|
|
464
998
|
*
|
|
465
|
-
*
|
|
466
|
-
*
|
|
467
|
-
* - EditorModeProps (editor-specific features)
|
|
999
|
+
* @see {@link BasePluginProps}
|
|
1000
|
+
* @see {@link ContainerProps} for additional container-specific props
|
|
468
1001
|
*
|
|
469
1002
|
* @example
|
|
470
1003
|
* ```typescript
|
|
@@ -475,40 +1008,54 @@ export interface BasePluginProps<TData = unknown> {
|
|
|
475
1008
|
*/
|
|
476
1009
|
export interface EditorModeProps {
|
|
477
1010
|
/**
|
|
478
|
-
*
|
|
479
|
-
* Used for visual feedback
|
|
1011
|
+
* Whether this component is currently selected in the editor.
|
|
1012
|
+
* Used for visual feedback (selection border, handles, etc.).
|
|
1013
|
+
* @default false
|
|
480
1014
|
*/
|
|
481
1015
|
isSelected?: boolean;
|
|
482
1016
|
/**
|
|
483
|
-
* Click handler for component selection
|
|
484
|
-
*
|
|
1017
|
+
* Click handler for component selection in the editor.
|
|
1018
|
+
* @param elementId - ID of the clicked element
|
|
485
1019
|
*/
|
|
486
1020
|
onClick?: (elementId: string) => void;
|
|
487
1021
|
/**
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
* @
|
|
1022
|
+
* Callback for inline content editing (e.g., `contentEditable` text).
|
|
1023
|
+
*
|
|
1024
|
+
* @param elementId - ID of the element being edited
|
|
1025
|
+
* @param language - ISO language code
|
|
1026
|
+
* @param content - New content value
|
|
1027
|
+
*
|
|
1028
|
+
* @example
|
|
1029
|
+
* ```typescript
|
|
1030
|
+
* onContentChange('heading-1', 'de', 'Neuer Titel')
|
|
1031
|
+
* ```
|
|
491
1032
|
*/
|
|
492
1033
|
onContentChange?: (elementId: string, language: string, content: unknown) => void;
|
|
493
1034
|
/**
|
|
494
|
-
*
|
|
495
|
-
*
|
|
496
|
-
* @
|
|
1035
|
+
* Callback for property changes via the Context Panel.
|
|
1036
|
+
*
|
|
1037
|
+
* @param elementId - ID of the element being edited
|
|
1038
|
+
* @param property - Dot-notation property path
|
|
1039
|
+
* @param value - New property value
|
|
1040
|
+
*
|
|
1041
|
+
* @example
|
|
1042
|
+
* ```typescript
|
|
1043
|
+
* onPropertyChange('heading-1', 'style.fontSize', '32px')
|
|
1044
|
+
* ```
|
|
497
1045
|
*/
|
|
498
1046
|
onPropertyChange?: (elementId: string, property: string, value: unknown) => void;
|
|
499
1047
|
}
|
|
500
1048
|
/**
|
|
501
|
-
* Renderer
|
|
1049
|
+
* Props for Renderer (SSR / view-mode) components.
|
|
502
1050
|
*
|
|
503
|
-
*
|
|
504
|
-
*
|
|
1051
|
+
* Renderers are **server-safe**: they do NOT use `'use client'`, contain
|
|
1052
|
+
* no React hooks, and receive no editor callbacks. Only the Design System
|
|
1053
|
+
* and utility functions are injected as dependencies.
|
|
505
1054
|
*
|
|
506
|
-
*
|
|
507
|
-
* - No callbacks (onContentChange, onPropertyChange)
|
|
508
|
-
* - Minimal dependencies (only designSystem and utils, no callbacks)
|
|
509
|
-
* - Should use pure functions, no React hooks
|
|
1055
|
+
* @template TData - Plugin-specific data type (defaults to `unknown`)
|
|
510
1056
|
*
|
|
511
|
-
* @
|
|
1057
|
+
* @see {@link BasePluginProps} for the full editor variant
|
|
1058
|
+
* @see {@link ContainerProps} for container children
|
|
512
1059
|
*
|
|
513
1060
|
* @example
|
|
514
1061
|
* ```typescript
|
|
@@ -524,31 +1071,30 @@ export interface EditorModeProps {
|
|
|
524
1071
|
*/
|
|
525
1072
|
export interface RendererProps<TData = unknown> {
|
|
526
1073
|
/**
|
|
527
|
-
* Unique element ID
|
|
528
|
-
* Used for data attributes and DOM references
|
|
1074
|
+
* Unique element ID for data attributes and DOM references
|
|
529
1075
|
*/
|
|
530
1076
|
elementId: string;
|
|
531
1077
|
/**
|
|
532
|
-
* Plugin-specific data
|
|
533
|
-
* Contains all configurable properties and content
|
|
1078
|
+
* Plugin-specific data containing all properties and content
|
|
534
1079
|
*/
|
|
535
1080
|
data: TData;
|
|
536
1081
|
/**
|
|
537
|
-
* Current language (ISO code)
|
|
538
|
-
* Used for multi-language content resolution
|
|
1082
|
+
* Current language (ISO code) for multi-language content resolution
|
|
539
1083
|
*/
|
|
540
1084
|
language: string;
|
|
541
1085
|
/**
|
|
542
|
-
* Minimal dependencies
|
|
543
|
-
* No callbacks since renderers are read-only
|
|
1086
|
+
* Minimal dependencies — design system and utilities only.
|
|
1087
|
+
* No callbacks since renderers are read-only.
|
|
544
1088
|
*/
|
|
545
|
-
dependencies: Pick<PluginDependencies,
|
|
1089
|
+
dependencies: Pick<PluginDependencies, 'designSystem' | 'utils'>;
|
|
546
1090
|
}
|
|
547
1091
|
/**
|
|
548
|
-
*
|
|
1092
|
+
* Props for plugins that support children (containers / layout components).
|
|
549
1093
|
*
|
|
550
|
-
*
|
|
551
|
-
*
|
|
1094
|
+
* Used by both Editor Components and Renderers when the plugin has
|
|
1095
|
+
* `capabilities.supportsChildren = true`.
|
|
1096
|
+
*
|
|
1097
|
+
* @see {@link PluginCapabilities.supportsChildren}
|
|
552
1098
|
*
|
|
553
1099
|
* @example
|
|
554
1100
|
* ```typescript
|
|
@@ -566,92 +1112,151 @@ export interface RendererProps<TData = unknown> {
|
|
|
566
1112
|
*/
|
|
567
1113
|
export interface ContainerProps {
|
|
568
1114
|
/**
|
|
569
|
-
* Child components
|
|
570
|
-
* React nodes
|
|
1115
|
+
* Child components to render inside this container.
|
|
1116
|
+
* Provided as React nodes by the recursive element renderer.
|
|
571
1117
|
*/
|
|
572
1118
|
children?: React.ReactNode;
|
|
573
1119
|
/**
|
|
574
|
-
* Drop event handler (Editor only)
|
|
575
|
-
* Called when user drops an element into this container
|
|
1120
|
+
* Drop event handler (Editor mode only).
|
|
1121
|
+
* Called when the user drags and drops an element into this container.
|
|
576
1122
|
*
|
|
577
|
-
* @param targetId - Container element ID
|
|
578
|
-
* @param droppedId -
|
|
579
|
-
* @param position -
|
|
1123
|
+
* @param targetId - Container element ID receiving the drop
|
|
1124
|
+
* @param droppedId - ID of the element being dropped
|
|
1125
|
+
* @param position - Where to insert relative to existing children
|
|
580
1126
|
*/
|
|
581
|
-
onDrop?: (targetId: string, droppedId: string, position:
|
|
1127
|
+
onDrop?: (targetId: string, droppedId: string, position: 'before' | 'after' | 'inside') => void;
|
|
582
1128
|
}
|
|
583
1129
|
/**
|
|
584
|
-
*
|
|
1130
|
+
* Complete plugin configuration — the top-level definition object.
|
|
1131
|
+
*
|
|
1132
|
+
* Every plugin registers a `PluginConfig` that describes its component,
|
|
1133
|
+
* editable properties, capabilities, defaults, and metadata. The editor
|
|
1134
|
+
* and runtime use this to render, configure, and constrain plugin instances.
|
|
585
1135
|
*
|
|
586
|
-
*
|
|
1136
|
+
* @see {@link PropertyDefinition} for how properties are declared
|
|
1137
|
+
* @see {@link PluginCapabilities} for structural capabilities
|
|
1138
|
+
* @see {@link PluginMeta} for optional metadata
|
|
1139
|
+
*
|
|
1140
|
+
* @example
|
|
1141
|
+
* ```typescript
|
|
1142
|
+
* const headingConfig: PluginConfig = {
|
|
1143
|
+
* id: 'base-heading',
|
|
1144
|
+
* name: 'Heading',
|
|
1145
|
+
* version: '0.1.0',
|
|
1146
|
+
* category: 'basic',
|
|
1147
|
+
* icon: Heading1,
|
|
1148
|
+
* component: HeadingComponent,
|
|
1149
|
+
* properties: [ ... ],
|
|
1150
|
+
* defaults: { contentI18n: { en: 'Heading Text', de: 'Überschrift' } },
|
|
1151
|
+
* locales: headingLocales,
|
|
1152
|
+
* ssr: true,
|
|
1153
|
+
* responsive: true,
|
|
1154
|
+
* capabilities: {
|
|
1155
|
+
* supportsChildren: false,
|
|
1156
|
+
* isRootComponent: false,
|
|
1157
|
+
* requiresParent: true,
|
|
1158
|
+
* childrenType: null,
|
|
1159
|
+
* allowedChildPlugins: [],
|
|
1160
|
+
* maxChildren: null,
|
|
1161
|
+
* minChildren: 0,
|
|
1162
|
+
* },
|
|
1163
|
+
* meta: { description: 'Semantic heading (h1-h6)', tags: ['heading'] },
|
|
1164
|
+
* };
|
|
1165
|
+
* ```
|
|
587
1166
|
*/
|
|
588
1167
|
export interface PluginConfig {
|
|
589
1168
|
/**
|
|
590
|
-
* Unique plugin identifier
|
|
1169
|
+
* Unique plugin identifier used for registration and lookups.
|
|
1170
|
+
* Convention: `'base-heading'`, `'form-input'`, `'blog-title'`.
|
|
591
1171
|
*/
|
|
592
1172
|
id: string;
|
|
593
1173
|
/**
|
|
594
|
-
*
|
|
1174
|
+
* Human-readable display name shown in the editor toolbar and plugin browser.
|
|
1175
|
+
* @example 'Heading', 'Container', 'Form Input'
|
|
595
1176
|
*/
|
|
596
1177
|
name: string;
|
|
597
1178
|
/**
|
|
598
|
-
* Semantic version
|
|
1179
|
+
* Semantic version string
|
|
1180
|
+
* @example '0.1.0'
|
|
599
1181
|
*/
|
|
600
1182
|
version: string;
|
|
601
1183
|
/**
|
|
602
|
-
* Plugin category
|
|
1184
|
+
* Plugin category — determines which toolbar section the plugin appears in.
|
|
1185
|
+
*
|
|
1186
|
+
* - `'basic'` — Common components (text, heading, image, button, container)
|
|
1187
|
+
* - `'layout'` — Layout-focused components
|
|
1188
|
+
* - `'forms'` — Form-related components (inputs, selects, form container)
|
|
1189
|
+
* - `'advanced'` — Specialized or complex components
|
|
603
1190
|
*/
|
|
604
|
-
category:
|
|
1191
|
+
category: 'basic' | 'layout' | 'forms' | 'advanced';
|
|
605
1192
|
/**
|
|
606
|
-
*
|
|
607
|
-
*
|
|
608
|
-
* - [
|
|
609
|
-
* - ['
|
|
610
|
-
* - ['
|
|
1193
|
+
* Restricts which project types can use this plugin.
|
|
1194
|
+
*
|
|
1195
|
+
* - `undefined` or `[]` — available for ALL project types (default, backward-compatible)
|
|
1196
|
+
* - `['landing']` — only landing page projects
|
|
1197
|
+
* - `['blog']` — only blog projects
|
|
1198
|
+
* - `['landing', 'blog']` — both types
|
|
1199
|
+
*
|
|
1200
|
+
* @default undefined
|
|
611
1201
|
*/
|
|
612
1202
|
projectTypes?: string[];
|
|
613
1203
|
/**
|
|
614
1204
|
* Semantic context for dynamic data binding.
|
|
615
|
-
*
|
|
616
|
-
* - '
|
|
1205
|
+
*
|
|
1206
|
+
* - `'static'` — Content defined at design time (default for most plugins)
|
|
1207
|
+
* - `'dynamic'` — Content bound to a collection entry at runtime (blog posts, shop items)
|
|
1208
|
+
*
|
|
1209
|
+
* @default 'static'
|
|
617
1210
|
*/
|
|
618
|
-
contentBinding?:
|
|
1211
|
+
contentBinding?: 'static' | 'dynamic';
|
|
619
1212
|
/**
|
|
620
|
-
* Icon component
|
|
1213
|
+
* Icon component rendered in the editor toolbar and plugin browser.
|
|
1214
|
+
* Typically a Lucide icon.
|
|
621
1215
|
*/
|
|
622
1216
|
icon?: ComponentType;
|
|
623
1217
|
/**
|
|
624
|
-
* React component to render
|
|
1218
|
+
* React component to render for this plugin.
|
|
1219
|
+
* Must accept props compatible with {@link BasePluginProps}.
|
|
625
1220
|
*/
|
|
626
1221
|
component: ComponentType<any>;
|
|
627
1222
|
/**
|
|
628
|
-
*
|
|
1223
|
+
* Array of property definitions describing editable properties.
|
|
1224
|
+
* The Context Panel auto-generates UI controls from these definitions.
|
|
1225
|
+
*
|
|
1226
|
+
* @see {@link PropertyDefinition}
|
|
629
1227
|
*/
|
|
630
1228
|
properties: PropertyDefinition[];
|
|
631
1229
|
/**
|
|
632
|
-
* Default values
|
|
1230
|
+
* Default values applied when creating a new instance of this plugin.
|
|
1231
|
+
* Keys correspond to top-level data paths; nested objects are supported.
|
|
633
1232
|
*/
|
|
634
1233
|
defaults: Record<string, unknown>;
|
|
635
1234
|
/**
|
|
636
|
-
* Localized strings
|
|
1235
|
+
* Localized UI strings keyed by locale code (e.g., `{ de: {...}, en: {...} }`).
|
|
1236
|
+
* Used for translating property labels and descriptions in the Context Panel.
|
|
637
1237
|
*/
|
|
638
1238
|
locales: Record<string, unknown>;
|
|
639
1239
|
/**
|
|
640
|
-
*
|
|
1240
|
+
* Whether this plugin supports server-side rendering.
|
|
1241
|
+
* When `true`, the plugin should provide a Renderer component
|
|
1242
|
+
* that works without `'use client'`.
|
|
641
1243
|
*/
|
|
642
1244
|
ssr: boolean;
|
|
643
1245
|
/**
|
|
644
|
-
*
|
|
1246
|
+
* Whether this plugin adapts to different viewport sizes.
|
|
1247
|
+
* When `true`, the plugin uses responsive values from the Design System.
|
|
645
1248
|
*/
|
|
646
1249
|
responsive: boolean;
|
|
647
1250
|
/**
|
|
648
|
-
*
|
|
649
|
-
*
|
|
650
|
-
*
|
|
1251
|
+
* Structural capabilities of this plugin — determines nesting rules,
|
|
1252
|
+
* container behavior, and allowed children.
|
|
1253
|
+
*
|
|
1254
|
+
* @see {@link PluginCapabilities}
|
|
651
1255
|
*/
|
|
652
1256
|
capabilities: PluginCapabilities;
|
|
653
1257
|
/**
|
|
654
|
-
*
|
|
1258
|
+
* Optional metadata for plugin listings and documentation.
|
|
1259
|
+
* @see {@link PluginMeta}
|
|
655
1260
|
*/
|
|
656
1261
|
meta?: PluginMeta;
|
|
657
1262
|
}
|