@visns-studio/visns-components 5.11.6 → 5.11.8

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.
@@ -37,12 +37,38 @@ const SectionEditor = ({ section, availableVariables = [], onSave, onCancel }) =
37
37
  }
38
38
  }, [section]);
39
39
 
40
+ // Function to extract variables from content
41
+ const extractVariablesFromContent = (content) => {
42
+ if (!content || typeof content !== 'string') return [];
43
+
44
+ const variableMatches = content.match(/{{(\w+)}}/g);
45
+ if (!variableMatches) return [];
46
+
47
+ const variables = variableMatches.map(match =>
48
+ match.replace(/[{}]/g, '')
49
+ );
50
+
51
+ // Return unique variables
52
+ return [...new Set(variables)];
53
+ };
54
+
40
55
  const handleInputChange = (field, value) => {
41
56
  console.log(`Field change: ${field} =`, value);
42
- setFormData(prev => ({
43
- ...prev,
44
- [field]: value
45
- }));
57
+
58
+ // If content is being changed, update variables automatically
59
+ if (field === 'content') {
60
+ const extractedVariables = extractVariablesFromContent(value);
61
+ setFormData(prev => ({
62
+ ...prev,
63
+ [field]: value,
64
+ variables: extractedVariables
65
+ }));
66
+ } else {
67
+ setFormData(prev => ({
68
+ ...prev,
69
+ [field]: value
70
+ }));
71
+ }
46
72
  };
47
73
 
48
74
  const handleStylingChange = (property, value) => {
@@ -61,17 +87,21 @@ const SectionEditor = ({ section, availableVariables = [], onSave, onCancel }) =
61
87
  // Try to insert at cursor position in TinyMCE editor
62
88
  if (window.tinymce && window.tinymce.activeEditor) {
63
89
  window.tinymce.activeEditor.insertContent(variableTag);
90
+
91
+ // Get the updated content and extract variables
92
+ setTimeout(() => {
93
+ const updatedContent = window.tinymce.activeEditor.getContent();
94
+ const extractedVariables = extractVariablesFromContent(updatedContent);
95
+ setFormData(prev => ({
96
+ ...prev,
97
+ content: updatedContent,
98
+ variables: extractedVariables
99
+ }));
100
+ }, 100);
64
101
  } else {
65
102
  // Fallback: append to content
66
- handleInputChange('content', formData.content + variableTag);
67
- }
68
-
69
- // Add to variables array if not already present
70
- if (!formData.variables.includes(variable)) {
71
- setFormData(prev => ({
72
- ...prev,
73
- variables: [...prev.variables, variable]
74
- }));
103
+ const updatedContent = formData.content + variableTag;
104
+ handleInputChange('content', updatedContent);
75
105
  }
76
106
 
77
107
  setShowVariableInserter(false);
@@ -105,9 +135,13 @@ const SectionEditor = ({ section, availableVariables = [], onSave, onCancel }) =
105
135
  }
106
136
  }
107
137
 
138
+ // Extract variables from final content before saving
139
+ const extractedVariables = extractVariablesFromContent(currentContent);
140
+
108
141
  const finalFormData = {
109
142
  ...formData,
110
- content: currentContent
143
+ content: currentContent,
144
+ variables: extractedVariables
111
145
  };
112
146
 
113
147
  console.log('Final form data being saved:', finalFormData);
@@ -274,4 +274,58 @@
274
274
  .section-type-modal-body {
275
275
  padding: 1rem;
276
276
  }
277
+ }
278
+
279
+ /* Disabled Section State */
280
+ .section-type-card.disabled {
281
+ opacity: 0.5;
282
+ cursor: not-allowed;
283
+ background: #f8f9fa !important;
284
+ border-color: #e9ecef !important;
285
+ transform: none !important;
286
+ }
287
+
288
+ .section-type-card.disabled:hover {
289
+ transform: none !important;
290
+ box-shadow: none !important;
291
+ border-color: #e9ecef !important;
292
+ }
293
+
294
+ .section-type-card.disabled .section-type-icon {
295
+ opacity: 0.6;
296
+ }
297
+
298
+ .section-type-card.disabled .section-type-name,
299
+ .section-type-card.disabled .section-type-description {
300
+ color: #6c757d !important;
301
+ }
302
+
303
+ /* Already Used Badge */
304
+ .used-badge {
305
+ display: inline-block;
306
+ background: #dc3545;
307
+ color: white;
308
+ font-size: 0.65rem;
309
+ font-weight: 500;
310
+ padding: 0.15rem 0.4rem;
311
+ border-radius: 0.25rem;
312
+ margin-left: 0.5rem;
313
+ text-transform: uppercase;
314
+ letter-spacing: 0.025em;
315
+ vertical-align: middle;
316
+ }
317
+
318
+ /* Dynamic Badge - Enhanced */
319
+ .dynamic-badge {
320
+ display: inline-block;
321
+ background: #28a745;
322
+ color: white;
323
+ font-size: 0.65rem;
324
+ font-weight: 500;
325
+ padding: 0.15rem 0.4rem;
326
+ border-radius: 0.25rem;
327
+ margin-left: 0.5rem;
328
+ text-transform: uppercase;
329
+ letter-spacing: 0.025em;
330
+ vertical-align: middle;
277
331
  }
@@ -76,7 +76,10 @@ const categoryColors = {
76
76
  footer: 'footer-category'
77
77
  };
78
78
 
79
- const SectionTypeSelector = ({ onSelect, onCancel }) => {
79
+ const SectionTypeSelector = ({ onSelect, onCancel, existingSections = [] }) => {
80
+ // Get list of existing section types
81
+ const existingSectionTypes = existingSections.map(section => section.section_type);
82
+
80
83
  const groupedSections = sectionTypes.reduce((acc, section) => {
81
84
  if (!acc[section.category]) {
82
85
  acc[section.category] = [];
@@ -110,11 +113,15 @@ const SectionTypeSelector = ({ onSelect, onCancel }) => {
110
113
  <div className="section-types-grid">
111
114
  {sections.map((section) => {
112
115
  const IconComponent = section.icon;
116
+ const isAlreadyUsed = existingSectionTypes.includes(section.id);
117
+
113
118
  return (
114
119
  <button
115
120
  key={section.id}
116
- onClick={() => onSelect(section.id)}
117
- className={`section-type-card ${categoryColors[category]}`}
121
+ onClick={() => !isAlreadyUsed && onSelect(section.id)}
122
+ className={`section-type-card ${categoryColors[category]} ${isAlreadyUsed ? 'disabled' : ''}`}
123
+ disabled={isAlreadyUsed}
124
+ title={isAlreadyUsed ? `${section.name} section already exists in this template` : `Add ${section.name} section`}
118
125
  >
119
126
  <div className="section-type-card-header">
120
127
  <div className="section-type-icon">
@@ -128,6 +135,11 @@ const SectionTypeSelector = ({ onSelect, onCancel }) => {
128
135
  Dynamic
129
136
  </span>
130
137
  )}
138
+ {isAlreadyUsed && (
139
+ <span className="used-badge">
140
+ Already Added
141
+ </span>
142
+ )}
131
143
  </h4>
132
144
  <p className="section-type-description">
133
145
  {section.description}