@codefluss/base-types 0.0.1-alpha.1

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.
@@ -0,0 +1,785 @@
1
+ /**
2
+ * Plugin System Type Definitions
3
+ *
4
+ * Core types for the headless plugin architecture.
5
+ * These types define the contract between plugins and the Context Panel UI.
6
+ *
7
+ * @package @codefluss/base-types
8
+ * @version 1.0.0
9
+ */
10
+
11
+ import type { ComponentType } from "react";
12
+ import type { PluginDesignSystem, PluginUtils } from "./dependencies";
13
+
14
+ /**
15
+ * Property control type
16
+ * Defines which UI control to render in Context Panel
17
+ */
18
+ export type PropertyControlType =
19
+ | "input"
20
+ | "slider"
21
+ | "select"
22
+ | "color-picker"
23
+ | "toggle"
24
+ | "textarea"
25
+ | "number-input"
26
+ | "number-with-unit" // Container-specific
27
+ | "box-model"
28
+ | "spacing" // Combined margin + padding control
29
+ | "spacing-combined" // Combined margin + padding control (UI variant)
30
+ | "grid" // Container-specific
31
+ | "typography-toolbar"
32
+ | "gradient-editor"
33
+ | "border-editor"
34
+ | "font-preset-select" // Design System font presets
35
+ | "color-preset-select" // Design System color presets
36
+ | "text-align-toggle" // Horizontal text alignment toggle buttons
37
+ | "vertical-align-toggle"; // Vertical alignment toggle buttons (align-self)
38
+
39
+ /**
40
+ * Property type
41
+ * Semantic type of the property value
42
+ */
43
+ export type PropertyType =
44
+ | "text"
45
+ | "number"
46
+ | "range"
47
+ | "select"
48
+ | "color"
49
+ | "toggle"
50
+ | "multiLangText"
51
+ | "boxModel"
52
+ | "box-model"
53
+ | "spacing" // Combined margin + padding
54
+ | "spacing-combined" // Combined margin + padding (UI variant)
55
+ | "grid"
56
+ | "toolbar"
57
+ | "gradient"
58
+ | "border";
59
+
60
+ /**
61
+ * Property category for organization
62
+ */
63
+ export type PropertyCategory = "content" | "style" | "layout" | "advanced";
64
+
65
+ /**
66
+ * Slider control configuration
67
+ */
68
+ export interface SliderConfig {
69
+ min: number;
70
+ max: number;
71
+ step: number;
72
+ showValue?: boolean;
73
+ unit?: string; // 'px', '%', 'em', etc.
74
+ marks?: Array<{ value: number; label: string }>;
75
+ }
76
+
77
+ /**
78
+ * Number input control configuration
79
+ */
80
+ export interface NumberConfig {
81
+ min?: number;
82
+ max?: number;
83
+ step?: number;
84
+ unit?: string; // 'px', '%', 'em', etc.
85
+ }
86
+
87
+ /**
88
+ * Number with unit control configuration (Container-specific)
89
+ */
90
+ export interface NumberWithUnitConfig {
91
+ min?: number;
92
+ max?: number;
93
+ step?: number;
94
+ units?: string[]; // ['px', '%', 'em', 'rem', 'vw', 'vh']
95
+ defaultUnit?: string;
96
+ allowEmpty?: boolean; // Allow empty/null values (container-specific)
97
+ }
98
+
99
+ /**
100
+ * Select control configuration
101
+ */
102
+ export interface SelectConfig {
103
+ options: Array<{ value: string; label: string; icon?: ComponentType }>;
104
+ searchable?: boolean;
105
+ }
106
+
107
+ /**
108
+ * Text input control configuration
109
+ */
110
+ export interface InputConfig {
111
+ placeholder?: string;
112
+ pattern?: RegExp;
113
+ validationMessage?: string;
114
+ }
115
+
116
+ /**
117
+ * Color picker control configuration
118
+ */
119
+ export interface ColorPickerConfig {
120
+ format?: "hex" | "rgb" | "hsl";
121
+ alpha?: boolean;
122
+ presets?: string[];
123
+ }
124
+
125
+ /**
126
+ * Textarea control configuration
127
+ */
128
+ export interface TextareaConfig {
129
+ rows?: number;
130
+ autoResize?: boolean;
131
+ placeholder?: string;
132
+ }
133
+
134
+ /**
135
+ * Box model control configuration
136
+ */
137
+ export interface BoxModelConfig {
138
+ min?: number;
139
+ max?: number;
140
+ unit?: string;
141
+ linkedByDefault?: boolean;
142
+ }
143
+
144
+ /**
145
+ * Spacing control configuration (combined margin + padding)
146
+ */
147
+ export interface SpacingConfig {
148
+ paddingMin?: number;
149
+ paddingMax?: number;
150
+ marginMin?: number;
151
+ marginMax?: number;
152
+ unit?: string;
153
+ }
154
+
155
+ /**
156
+ * Typography toolbar control configuration
157
+ */
158
+ export interface TypographyToolbarConfig {
159
+ showBold?: boolean;
160
+ showItalic?: boolean;
161
+ showUnderline?: boolean;
162
+ showAlignment?: boolean;
163
+ showFontSize?: boolean;
164
+ showColor?: boolean;
165
+ }
166
+
167
+ /**
168
+ * Gradient editor control configuration
169
+ */
170
+ export interface GradientEditorConfig {
171
+ allowLinear?: boolean;
172
+ allowRadial?: boolean;
173
+ maxStops?: number;
174
+ colorFormat?: "hex" | "rgb" | "hsl";
175
+ }
176
+
177
+ /**
178
+ * Border editor control configuration
179
+ */
180
+ export interface BorderEditorConfig {
181
+ allowIndividualSides?: boolean;
182
+ allowRadius?: boolean;
183
+ maxWidth?: number;
184
+ }
185
+
186
+ /**
187
+ * Font preset select control configuration
188
+ * Shows typography presets from Design System
189
+ */
190
+ export interface FontPresetSelectConfig {
191
+ /** Filter fonts by category (e.g., "heading", "body") */
192
+ category?: string;
193
+ /** Placeholder text */
194
+ placeholder?: string;
195
+ }
196
+
197
+ /**
198
+ * Color preset select control configuration
199
+ * Shows color presets from Design System (no free text)
200
+ */
201
+ export interface ColorPresetSelectConfig {
202
+ /** Filter colors by category */
203
+ category?: string;
204
+ /** Placeholder text */
205
+ placeholder?: string;
206
+ /** Show color preview swatch */
207
+ showSwatch?: boolean;
208
+ /** Allow "None" option for transparent/no color */
209
+ allowNone?: boolean;
210
+ }
211
+
212
+ /**
213
+ * Alignment toggle control configuration
214
+ * Icon-based toggle buttons for text-align or align-self
215
+ */
216
+ export interface AlignmentToggleConfig {
217
+ /** Include justify option for horizontal alignment */
218
+ includeJustify?: boolean;
219
+ /** Include stretch option for vertical alignment */
220
+ includeStretch?: boolean;
221
+ /** Include auto/inherit option */
222
+ includeAuto?: boolean;
223
+ }
224
+
225
+ /**
226
+ * Display mode configuration
227
+ */
228
+ export interface DisplayConfig {
229
+ /**
230
+ * Show in tooltip on hover vs always visible in panel
231
+ */
232
+ mode?: "tooltip" | "panel" | "both";
233
+
234
+ /**
235
+ * Collapsible section
236
+ */
237
+ collapsible?: boolean;
238
+
239
+ /**
240
+ * Default collapsed state
241
+ */
242
+ defaultCollapsed?: boolean;
243
+
244
+ /**
245
+ * Layout mode for property controls in panel (container-specific)
246
+ * Determines how controls are arranged (single column, 2-column grid, etc.)
247
+ */
248
+ layout?: "grid-2" | "grid-3" | "single" | string;
249
+
250
+ /**
251
+ * Conditional visibility based on other property values
252
+ * @example { when: 'layout.mode', equals: 'flexbox' }
253
+ */
254
+ condition?: {
255
+ when: string; // Property key to watch
256
+ equals?: unknown; // Show when equals this value
257
+ notEquals?: unknown; // Show when not equals this value
258
+ };
259
+ }
260
+
261
+ /**
262
+ * UI configuration for property
263
+ * This is the metadata that tells Context Panel HOW to render
264
+ */
265
+ export interface PropertyUIConfig {
266
+ control: PropertyControlType;
267
+ slider?: SliderConfig;
268
+ number?: NumberConfig;
269
+ numberWithUnit?: NumberWithUnitConfig; // Container-specific
270
+ select?: SelectConfig;
271
+ input?: InputConfig;
272
+ textarea?: TextareaConfig;
273
+ colorPicker?: ColorPickerConfig;
274
+ boxModel?: BoxModelConfig;
275
+ spacing?: SpacingConfig; // Combined margin + padding control
276
+ typographyToolbar?: TypographyToolbarConfig;
277
+ gradientEditor?: GradientEditorConfig;
278
+ borderEditor?: BorderEditorConfig;
279
+ fontPresetSelect?: FontPresetSelectConfig; // Design System font presets
280
+ colorPresetSelect?: ColorPresetSelectConfig; // Design System color presets
281
+ alignmentToggle?: AlignmentToggleConfig; // Alignment toggle buttons
282
+ display?: DisplayConfig;
283
+ }
284
+
285
+ /**
286
+ * Property validation rules
287
+ */
288
+ export interface PropertyValidation {
289
+ pattern?: RegExp;
290
+ min?: number;
291
+ max?: number;
292
+ message?: string;
293
+ custom?: (value: unknown) => boolean | string;
294
+ }
295
+
296
+ /**
297
+ * Property priority for progressive disclosure
298
+ * Determines visual hierarchy and default visibility in Context Panel
299
+ */
300
+ export type PropertyPriority = "quick" | "common" | "advanced";
301
+
302
+ /**
303
+ * Property definition (headless metadata)
304
+ *
305
+ * This is the core interface that plugins use to define their properties.
306
+ * The Context Panel UI reads this and auto-generates appropriate controls.
307
+ */
308
+ export interface PropertyDefinition {
309
+ /**
310
+ * Property key (dot notation for nested properties)
311
+ * @example 'style.fontSize', 'layout.padding.top'
312
+ */
313
+ key: string;
314
+
315
+ /**
316
+ * Property type (semantic)
317
+ */
318
+ type: PropertyType;
319
+
320
+ /**
321
+ * Display label for UI
322
+ */
323
+ label: string;
324
+
325
+ /**
326
+ * Default value (null = use global default if applicable)
327
+ */
328
+ default: unknown;
329
+
330
+ /**
331
+ * Description shown in UI
332
+ */
333
+ description?: string;
334
+
335
+ /**
336
+ * Property category for organization
337
+ */
338
+ category?: PropertyCategory;
339
+
340
+ /**
341
+ * Whether property is required
342
+ */
343
+ required?: boolean;
344
+
345
+ /**
346
+ * Property priority for progressive disclosure (optional)
347
+ * - quick: Always visible, no accordion (most important)
348
+ * - common: Collapsible, default open (frequently used)
349
+ * - advanced: Collapsible, default closed (rarely used)
350
+ * Defaults to 'common' if not specified
351
+ */
352
+ priority?: PropertyPriority;
353
+
354
+ /**
355
+ * Design System integration
356
+ * If true, shows "Use Global Default" toggle
357
+ */
358
+ useGlobal?: boolean;
359
+
360
+ /**
361
+ * Design System key to reference
362
+ * @example 'fonts.body.size', 'colors.text-primary'
363
+ */
364
+ globalKey?: string;
365
+
366
+ /**
367
+ * UI control configuration (headless)
368
+ */
369
+ ui?: PropertyUIConfig;
370
+
371
+ /**
372
+ * Validation rules
373
+ */
374
+ validation?: PropertyValidation;
375
+ }
376
+
377
+ /**
378
+ * Plugin metadata
379
+ */
380
+ export interface PluginMeta {
381
+ description?: string;
382
+ tags?: string[];
383
+ thumbnail?: string;
384
+ documentation?: string;
385
+ }
386
+
387
+ /**
388
+ * Plugin Capabilities - PLUGIN-DRIVEN ARCHITECTURE
389
+ *
390
+ * Declares what the plugin can do and how it should be handled by the app.
391
+ * This is the core of the plugin-driven architecture:
392
+ * The plugin ITSELF defines its capabilities, not the app.
393
+ */
394
+ export interface PluginCapabilities {
395
+ /**
396
+ * Can this plugin contain child components?
397
+ * true = container/layout component
398
+ * false = leaf component (text, image, button, etc.)
399
+ */
400
+ supportsChildren: boolean;
401
+
402
+ /**
403
+ * Is this a root component?
404
+ * true = can be placed at canvas/section level (containers, sections)
405
+ * false = must be inside another component (text, buttons, images)
406
+ */
407
+ isRootComponent: boolean;
408
+
409
+ /**
410
+ * Does this plugin require a parent container?
411
+ * true = cannot exist at top level, must be inside a container
412
+ * false = can be placed directly on canvas
413
+ *
414
+ * @example Text component: requiresParent = true (must be in container)
415
+ * @example Container component: requiresParent = false (can be at top level)
416
+ */
417
+ requiresParent: boolean;
418
+
419
+ /**
420
+ * Children architecture type
421
+ * 'nested' = NESTED architecture with direct children arrays (RECOMMENDED)
422
+ * 'flat' = FLAT architecture with parentId references (DEPRECATED)
423
+ * null = does not support children
424
+ */
425
+ childrenType: "nested" | "flat" | null;
426
+
427
+ /**
428
+ * Allowed child plugin IDs
429
+ * Empty array = all plugins allowed as children
430
+ * ['text', 'image'] = only specific plugins allowed
431
+ * Only applicable if supportsChildren = true
432
+ */
433
+ allowedChildPlugins: string[];
434
+
435
+ /**
436
+ * Allowed parent plugin IDs
437
+ * Empty array = can be child of any container
438
+ * ['base-container'] = can only be inside specific containers
439
+ * Only applicable if requiresParent = true
440
+ */
441
+ allowedParentPlugins?: string[];
442
+
443
+ /**
444
+ * Maximum number of children allowed
445
+ * null = unlimited children
446
+ * number = specific limit
447
+ * Only applicable if supportsChildren = true
448
+ */
449
+ maxChildren: number | null;
450
+
451
+ /**
452
+ * Minimum number of children required
453
+ * 0 = no minimum requirement
454
+ * Only applicable if supportsChildren = true
455
+ */
456
+ minChildren: number;
457
+ }
458
+
459
+ /**
460
+ * ============================================================================
461
+ * Dual-Component Architecture Props
462
+ * ============================================================================
463
+ *
464
+ * These interfaces support the Dual-Component Pattern where plugins have:
465
+ * - Editor Component ('use client') - Interactive editing with React hooks
466
+ * - Renderer Component (NO 'use client') - Server-side rendering for view mode
467
+ *
468
+ * This pattern enables:
469
+ * - Better SEO (content in initial HTML)
470
+ * - Improved performance (smaller JS bundles, faster FCP/LCP)
471
+ * - Clear separation between editor and view mode
472
+ */
473
+
474
+ /**
475
+ * Plugin Dependencies
476
+ *
477
+ * External dependencies injected by host application.
478
+ * These are provided by the web-app and contain design system,
479
+ * utilities, and callbacks needed by plugins.
480
+ */
481
+ export interface PluginDependencies {
482
+ /**
483
+ * Design System instance
484
+ * Provides access to fonts, colors, spacing, and other design tokens
485
+ */
486
+ designSystem: PluginDesignSystem;
487
+
488
+ /**
489
+ * Utility functions
490
+ * Helper functions for common operations
491
+ */
492
+ utils: PluginUtils;
493
+
494
+ /**
495
+ * Callbacks (Editor only)
496
+ * Functions to update element data and properties
497
+ */
498
+ onContentChange?: (
499
+ elementId: string,
500
+ language: string,
501
+ content: unknown,
502
+ ) => void;
503
+ onPropertyChange?: (
504
+ elementId: string,
505
+ property: string,
506
+ value: unknown,
507
+ ) => void;
508
+ }
509
+
510
+ /**
511
+ * Base Props for ALL Plugin Components
512
+ *
513
+ * Defines the minimal required props that EVERY plugin must accept.
514
+ * Both Editor Components and Renderers should extend this interface.
515
+ *
516
+ * @template TData - Plugin-specific data type
517
+ *
518
+ * @example
519
+ * ```typescript
520
+ * interface HeadingEditorProps extends BasePluginProps<HeadingComponentData>, EditorModeProps {}
521
+ * interface HeadingRendererProps extends RendererProps<HeadingComponentData> {}
522
+ * ```
523
+ */
524
+ export interface BasePluginProps<TData = unknown> {
525
+ /**
526
+ * Unique element ID
527
+ * Used for data attributes, callbacks, and DOM references
528
+ */
529
+ elementId: string;
530
+
531
+ /**
532
+ * Plugin-specific data
533
+ * Contains all configurable properties and content
534
+ */
535
+ data: TData;
536
+
537
+ /**
538
+ * Current language (ISO code)
539
+ * Used for multi-language content resolution
540
+ * @example 'de', 'en', 'fr', 'es', 'it'
541
+ */
542
+ language: string;
543
+
544
+ /**
545
+ * Injected dependencies
546
+ * Design system, utilities, and callbacks provided by host application
547
+ */
548
+ dependencies: PluginDependencies;
549
+ }
550
+
551
+ /**
552
+ * Editor Mode Props
553
+ *
554
+ * Additional props needed ONLY for Editor Components.
555
+ * These props enable interactive editing functionality.
556
+ *
557
+ * Editor Components should combine:
558
+ * - BasePluginProps<TData> (required base props)
559
+ * - EditorModeProps (editor-specific features)
560
+ *
561
+ * @example
562
+ * ```typescript
563
+ * export interface HeadingEditorProps
564
+ * extends BasePluginProps<HeadingComponentData>,
565
+ * EditorModeProps {}
566
+ * ```
567
+ */
568
+ export interface EditorModeProps {
569
+ /**
570
+ * Is component currently selected in editor?
571
+ * Used for visual feedback and activation of editing features
572
+ */
573
+ isSelected?: boolean;
574
+
575
+ /**
576
+ * Click handler for component selection
577
+ * Called when user clicks on the component
578
+ */
579
+ onClick?: (elementId: string) => void;
580
+
581
+ /**
582
+ * Content change callback
583
+ * Called when user edits text content (contentEditable)
584
+ * @example onContentChange('heading-1', 'de', 'Neuer Titel')
585
+ */
586
+ onContentChange?: (
587
+ elementId: string,
588
+ language: string,
589
+ content: unknown,
590
+ ) => void;
591
+
592
+ /**
593
+ * Property change callback
594
+ * Called when user changes properties via Context Panel
595
+ * @example onPropertyChange('heading-1', 'style.fontSize', '32px')
596
+ */
597
+ onPropertyChange?: (
598
+ elementId: string,
599
+ property: string,
600
+ value: unknown,
601
+ ) => void;
602
+ }
603
+
604
+ /**
605
+ * Renderer Props (View/SSR Mode)
606
+ *
607
+ * Minimal props for Server-Side Rendering components.
608
+ * These components do NOT use 'use client' and should work in Node.js environment.
609
+ *
610
+ * Key differences from BasePluginProps:
611
+ * - No callbacks (onContentChange, onPropertyChange)
612
+ * - Minimal dependencies (only designSystem and utils, no callbacks)
613
+ * - Should use pure functions, no React hooks
614
+ *
615
+ * @template TData - Plugin-specific data type
616
+ *
617
+ * @example
618
+ * ```typescript
619
+ * // heading-renderer.tsx (NO 'use client')
620
+ * export interface HeadingRendererProps extends RendererProps<HeadingComponentData> {}
621
+ *
622
+ * export function HeadingRenderer({ elementId, data, language, dependencies }: HeadingRendererProps) {
623
+ * const content = resolveTextContent(data, language); // Pure function
624
+ * const styles = resolveTextStyles(data, dependencies.designSystem); // Pure function
625
+ * return <h1 style={styles}>{content}</h1>;
626
+ * }
627
+ * ```
628
+ */
629
+ export interface RendererProps<TData = unknown> {
630
+ /**
631
+ * Unique element ID
632
+ * Used for data attributes and DOM references
633
+ */
634
+ elementId: string;
635
+
636
+ /**
637
+ * Plugin-specific data
638
+ * Contains all configurable properties and content
639
+ */
640
+ data: TData;
641
+
642
+ /**
643
+ * Current language (ISO code)
644
+ * Used for multi-language content resolution
645
+ */
646
+ language: string;
647
+
648
+ /**
649
+ * Minimal dependencies (design system and utils only)
650
+ * No callbacks since renderers are read-only
651
+ */
652
+ dependencies: Pick<PluginDependencies, "designSystem" | "utils">;
653
+ }
654
+
655
+ /**
656
+ * Container Props
657
+ *
658
+ * Additional props for plugins that support children (containers, layouts).
659
+ * Used by both Editor Components and Renderers when the plugin has supportsChildren = true.
660
+ *
661
+ * @example
662
+ * ```typescript
663
+ * // Editor Component
664
+ * export interface ContainerEditorProps
665
+ * extends BasePluginProps<ContainerData>,
666
+ * EditorModeProps,
667
+ * ContainerProps {}
668
+ *
669
+ * // Renderer Component
670
+ * export interface ContainerRendererProps
671
+ * extends RendererProps<ContainerData>,
672
+ * Pick<ContainerProps, 'children'> {}
673
+ * ```
674
+ */
675
+ export interface ContainerProps {
676
+ /**
677
+ * Child components (rendered recursively)
678
+ * React nodes to be rendered inside this container
679
+ */
680
+ children?: React.ReactNode;
681
+
682
+ /**
683
+ * Drop event handler (Editor only)
684
+ * Called when user drops an element into this container
685
+ *
686
+ * @param targetId - Container element ID
687
+ * @param droppedId - Dragged element ID
688
+ * @param position - Drop position ('before', 'after', 'inside')
689
+ */
690
+ onDrop?: (
691
+ targetId: string,
692
+ droppedId: string,
693
+ position: "before" | "after" | "inside",
694
+ ) => void;
695
+ }
696
+
697
+ /**
698
+ * Plugin configuration (headless)
699
+ *
700
+ * Complete plugin definition with component, properties, and metadata.
701
+ */
702
+ export interface PluginConfig {
703
+ /**
704
+ * Unique plugin identifier
705
+ */
706
+ id: string;
707
+
708
+ /**
709
+ * Display name
710
+ */
711
+ name: string;
712
+
713
+ /**
714
+ * Semantic version
715
+ */
716
+ version: string;
717
+
718
+ /**
719
+ * Plugin category
720
+ */
721
+ category: "basic" | "layout" | "advanced";
722
+
723
+ /**
724
+ * Project types this plugin is available for.
725
+ * - undefined or [] = available for ALL project types (default, backward-compatible)
726
+ * - ['landing'] = only available for landing page projects
727
+ * - ['blog'] = only available for blog projects
728
+ * - ['landing', 'blog'] = available for both
729
+ */
730
+ projectTypes?: string[];
731
+
732
+ /**
733
+ * Semantic context for dynamic data binding.
734
+ * - 'static' = content defined at design time (default for most plugins)
735
+ * - 'dynamic' = content bound to collection entry at runtime (blog, shop items)
736
+ */
737
+ contentBinding?: "static" | "dynamic";
738
+
739
+ /**
740
+ * Icon component (optional)
741
+ */
742
+ icon?: ComponentType;
743
+
744
+ /**
745
+ * React component to render
746
+ */
747
+ component: ComponentType<any>;
748
+
749
+ /**
750
+ * Property definitions
751
+ */
752
+ properties: PropertyDefinition[];
753
+
754
+ /**
755
+ * Default values for new instances
756
+ */
757
+ defaults: Record<string, unknown>;
758
+
759
+ /**
760
+ * Localized strings for UI
761
+ */
762
+ locales: Record<string, unknown>;
763
+
764
+ /**
765
+ * Server-side rendering support
766
+ */
767
+ ssr: boolean;
768
+
769
+ /**
770
+ * Responsive design support
771
+ */
772
+ responsive: boolean;
773
+
774
+ /**
775
+ * PLUGIN-DRIVEN ARCHITECTURE:
776
+ * Plugin capabilities define what the plugin can do
777
+ * The app reads these to understand how to handle the plugin
778
+ */
779
+ capabilities: PluginCapabilities;
780
+
781
+ /**
782
+ * Plugin metadata
783
+ */
784
+ meta?: PluginMeta;
785
+ }