@codesinger0/shared-components 1.1.56 → 1.1.57

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.
@@ -7,10 +7,12 @@ const ArticlesList = ({
7
7
  title,
8
8
  subtitle,
9
9
  articles = [],
10
+ articleOpenType = 'modal',
10
11
  className = '',
11
12
  ...props
12
13
  }) => {
13
14
  const [selectedArticle, setSelectedArticle] = useState(null);
15
+ const [expandedArticleId, setExpandedArticleId] = useState(null);
14
16
 
15
17
  useScrollLock(selectedArticle !== null);
16
18
 
@@ -26,6 +28,14 @@ const ArticlesList = ({
26
28
  );
27
29
  }
28
30
 
31
+ const handleArticleClick = (article, index) => {
32
+ if (articleOpenType === 'modal') {
33
+ setSelectedArticle(article);
34
+ } else {
35
+ setExpandedArticleId(expandedArticleId === (article.id || index) ? null : (article.id || index));
36
+ }
37
+ };
38
+
29
39
  // Function to get first 3 lines of text
30
40
  const getExcerpt = (text) => {
31
41
  const lines = text?.trim().split('\n').filter(line => line.trim());
@@ -50,9 +60,9 @@ const ArticlesList = ({
50
60
  {title}
51
61
  </h2>
52
62
  )}
53
-
63
+
54
64
  <div className="w-20 h-1 bg-gradient-to-r from-primary to-primary-bright mx-auto mb-6"></div>
55
-
65
+
56
66
  {subtitle && (
57
67
  <p className="subtitle max-w-3xl mx-auto">
58
68
  {subtitle}
@@ -64,6 +74,7 @@ const ArticlesList = ({
64
74
  {/* Articles Grid */}
65
75
  <div className="grid lg:grid-cols-2 gap-8" dir="rtl">
66
76
  {articles.map((article, index) => {
77
+ const isExpanded = expandedArticleId === (article.id || index);
67
78
  const isEven = index % 2 === 0;
68
79
  const cardBg = isEven ? 'bg-gradient-to-br from-white to-green-50' : 'bg-gradient-to-br from-white to-sky-50';
69
80
  const iconGradient = isEven ? 'from-green-500 to-green-600' : 'from-sky-400 to-sky-500';
@@ -78,10 +89,11 @@ const ArticlesList = ({
78
89
  viewport={{ once: true }}
79
90
  transition={{ delay: index * 0.1 }}
80
91
  >
81
- <div
92
+ <div
82
93
  className={`h-full cursor-pointer border-none shadow-lg hover:shadow-xl transition-all duration-300 ${cardBg} group rounded-xl`}
83
- onClick={() => setSelectedArticle(article)}
94
+ onClick={() => handleArticleClick(article, index)}
84
95
  >
96
+ {/* Card Header - Always visible */}
85
97
  <div className="p-6 pb-4">
86
98
  <div className="flex items-start gap-4">
87
99
  <div className={`w-12 h-12 bg-gradient-to-br ${iconGradient} rounded-full flex items-center justify-center flex-shrink-0`}>
@@ -98,17 +110,36 @@ const ArticlesList = ({
98
110
  </div>
99
111
  </div>
100
112
  </div>
101
- <div className="px-6 pb-6">
102
- <p className="text-gray-600 leading-relaxed whitespace-pre-line" dir="rtl">
103
- {article.excerpt}
104
- </p>
105
- <div className="mt-6">
106
- <span className={`inline-flex items-center ${textColor} font-medium ${textHover} transition-colors`}>
107
- קרא עוד
108
- <ArrowDown className="w-4 h-4 mr-2 rotate-180 group-hover:transform group-hover:-translate-y-1 transition-transform" />
109
- </span>
113
+
114
+ {/* Excerpt and "Read More" - Hidden when expanded in inline mode */}
115
+ {!(articleOpenType === 'inline' && isExpanded) && (
116
+ <div className="px-6 pb-6">
117
+ <p className="text-gray-600 leading-relaxed whitespace-pre-line" dir="rtl">
118
+ {article.excerpt}
119
+ </p>
120
+ <div className="mt-6">
121
+ <span className={`inline-flex items-center ${textColor} font-medium ${textHover} transition-colors`}>
122
+ קרא עוד
123
+ <ArrowDown className="w-4 h-4 mr-2 rotate-180 group-hover:transform group-hover:-translate-y-1 transition-transform" />
124
+ </span>
125
+ </div>
110
126
  </div>
111
- </div>
127
+ )}
128
+
129
+ {/* Full Content - Only shown when expanded in inline mode */}
130
+ {articleOpenType === 'inline' && isExpanded && (
131
+ <div className="px-6 pb-6 border-t border-gray-200">
132
+ <div className="prose prose-lg max-w-none">
133
+ <ArticleFormatter text={article.content} />
134
+ </div>
135
+ <div className="mt-6">
136
+ <span className={`inline-flex items-center ${textColor} font-medium ${textHover} transition-colors`}>
137
+ סגור
138
+ <ArrowDown className="w-4 h-4 mr-2 group-hover:transform group-hover:translate-y-1 transition-transform" />
139
+ </span>
140
+ </div>
141
+ </div>
142
+ )}
112
143
  </div>
113
144
  </motion.div>
114
145
  );
@@ -118,66 +149,67 @@ const ArticlesList = ({
118
149
  </section>
119
150
 
120
151
  {/* Article Modal */}
121
- <AnimatePresence>
122
- {selectedArticle && (
123
- <div className="fixed inset-0 z-50 flex items-center justify-center supports-[height:100dvh]:h-[100dvh]">
124
- {/* Backdrop */}
125
- <motion.div
126
- initial={{ opacity: 0 }}
127
- animate={{ opacity: 1 }}
128
- exit={{ opacity: 0 }}
129
- transition={{ duration: 0.2 }}
130
- className="absolute inset-0 bg-black bg-opacity-50 backdrop-blur-sm"
131
- onClick={() => setSelectedArticle(null)}
132
- />
133
-
134
- {/* Modal Content */}
135
- <motion.div
136
- initial={{ opacity: 0, scale: 0.9, y: 20 }}
137
- animate={{ opacity: 1, scale: 1, y: 0 }}
138
- exit={{ opacity: 0, scale: 0.9, y: 20 }}
139
- transition={{ type: "spring", stiffness: 300, damping: 30 }}
140
- className="relative w-full max-w-4xl mx-4 max-h-[90vh] bg-white rounded-xl shadow-2xl overflow-hidden"
141
- onClick={(e) => e.stopPropagation()}
142
- >
143
- {/* Close Button */}
144
- <button
152
+ {articleOpenType === 'modal' && (
153
+ <AnimatePresence>
154
+ {selectedArticle && (
155
+ <div className="fixed inset-0 z-50 flex items-center justify-center supports-[height:100dvh]:h-[100dvh]">
156
+ {/* Backdrop */}
157
+ <motion.div
158
+ initial={{ opacity: 0 }}
159
+ animate={{ opacity: 1 }}
160
+ exit={{ opacity: 0 }}
161
+ transition={{ duration: 0.2 }}
162
+ className="absolute inset-0 bg-black bg-opacity-50 backdrop-blur-sm"
145
163
  onClick={() => setSelectedArticle(null)}
146
- className="absolute top-4 left-4 z-10 bg-white hover:bg-gray-100 text-gray-700 p-2 rounded-full shadow-lg transition-colors duration-200"
147
- aria-label="סגור"
164
+ />
165
+
166
+ {/* Modal Content */}
167
+ <motion.div
168
+ initial={{ opacity: 0, scale: 0.9, y: 20 }}
169
+ animate={{ opacity: 1, scale: 1, y: 0 }}
170
+ exit={{ opacity: 0, scale: 0.9, y: 20 }}
171
+ transition={{ type: "spring", stiffness: 300, damping: 30 }}
172
+ className="relative w-full max-w-4xl mx-4 max-h-[90vh] bg-white rounded-xl shadow-2xl overflow-hidden"
173
+ onClick={(e) => e.stopPropagation()}
148
174
  >
149
- <X size={24} />
150
- </button>
151
-
152
- {/* Scrollable Content */}
153
- <div className="overflow-y-auto max-h-[90vh] p-8 md:p-12" dir="rtl">
154
- {/* Article Header */}
155
- <div className="mb-8">
156
- <div className="flex items-center gap-4 mb-6">
157
- <div className="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-full flex items-center justify-center flex-shrink-0">
158
- {selectedArticle.icon ? (
159
- <selectedArticle.icon className="w-8 h-8 text-white" />
160
- ) : (
161
- <BookOpen className="w-8 h-8 text-white" />
162
- )}
175
+ {/* Close Button */}
176
+ <button
177
+ onClick={() => setSelectedArticle(null)}
178
+ className="absolute top-4 left-4 z-10 bg-white hover:bg-gray-100 text-gray-700 p-2 rounded-full shadow-lg transition-colors duration-200"
179
+ aria-label="סגור"
180
+ >
181
+ <X size={24} />
182
+ </button>
183
+
184
+ {/* Scrollable Content */}
185
+ <div className="overflow-y-auto max-h-[90vh] p-8 md:p-12" dir="rtl">
186
+ {/* Article Header */}
187
+ <div className="mb-8">
188
+ <div className="flex items-center gap-4 mb-6">
189
+ <div className="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-full flex items-center justify-center flex-shrink-0">
190
+ {selectedArticle.icon ? (
191
+ <selectedArticle.icon className="w-8 h-8 text-white" />
192
+ ) : (
193
+ <BookOpen className="w-8 h-8 text-white" />
194
+ )}
195
+ </div>
196
+ <h2 className="text-3xl md:text-4xl font-bold text-green-900">
197
+ {selectedArticle.title}
198
+ </h2>
163
199
  </div>
164
- <h2 className="text-3xl md:text-4xl font-bold text-green-900">
165
- {selectedArticle.title}
166
- </h2>
200
+ <div className="w-20 h-1 bg-gradient-to-r from-green-500 to-sky-400"></div>
167
201
  </div>
168
- <div className="w-20 h-1 bg-gradient-to-r from-green-500 to-sky-400"></div>
169
- </div>
170
202
 
171
- {/* Article Content */}
172
- <div className="prose prose-lg max-w-none">
173
- <ArticleFormatter text={selectedArticle.content} />
203
+ {/* Article Content */}
204
+ <div className="prose prose-lg max-w-none">
205
+ <ArticleFormatter text={selectedArticle.content} />
206
+ </div>
174
207
  </div>
175
- </div>
176
- </motion.div>
177
- </div>
178
- )}
179
- </AnimatePresence>
180
-
208
+ </motion.div>
209
+ </div>
210
+ )}
211
+ </AnimatePresence>
212
+ )}
181
213
  {/* Custom Styles */}
182
214
  <style jsx>{`
183
215
  .from-primary {
@@ -202,7 +234,7 @@ const ArticleFormatter = ({ text }) => {
202
234
  {sections.map((section, index) => {
203
235
  // Find the first newline to separate a potential heading from its paragraph
204
236
  const firstNewlineIndex = section.indexOf('\n');
205
-
237
+
206
238
  let heading = '';
207
239
  let paragraph = '';
208
240
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codesinger0/shared-components",
3
- "version": "1.1.56",
3
+ "version": "1.1.57",
4
4
  "description": "Shared React components for customer projects",
5
5
  "main": "dist/index.js",
6
6
  "files": [