@bookklik/senangstart-icons 1.0.3
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/LICENSE.md +21 -0
- package/README.md +40 -0
- package/dist/senangstart-icon.min.js +2 -0
- package/dist/senangstart-icon.min.js.map +1 -0
- package/dist/senangstart.min.css +2 -0
- package/dist/senangstart.min.css.map +1 -0
- package/index.html +479 -0
- package/package.json +31 -0
- package/scripts/build-svgs.js +51 -0
- package/src/icons.json +1444 -0
- package/src/index.js +9 -0
- package/src/ss-icon.js +62 -0
- package/src/ss-loader.js +64 -0
- package/src/style.css +12 -0
- package/ss.png +0 -0
- package/ss.svg +1 -0
- package/webpack.config.js +68 -0
package/index.html
ADDED
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en" class="scroll-smooth">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>SenangStart Icons | Curated icons designed for Starters</title>
|
|
7
|
+
|
|
8
|
+
<link rel="apple-touch-icon" sizes="180x180" href="ss.png" />
|
|
9
|
+
<link rel="shortcut icon" href="ss.png" type="image/x-icon" />
|
|
10
|
+
|
|
11
|
+
<!-- Google Fonts: Outfit -->
|
|
12
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
13
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
14
|
+
<link
|
|
15
|
+
href="https://fonts.googleapis.com/css2?family=Outfit:wght@100..900&display=swap"
|
|
16
|
+
rel="stylesheet"
|
|
17
|
+
/>
|
|
18
|
+
|
|
19
|
+
<!-- SenangStart Styles/Scripts -->
|
|
20
|
+
<link rel="stylesheet" href="dist/senangstart.min.css" />
|
|
21
|
+
<script src="dist/senangstart-icon.min.js"></script>
|
|
22
|
+
|
|
23
|
+
<!-- Senangwebs Jot -->
|
|
24
|
+
<link
|
|
25
|
+
rel="stylesheet"
|
|
26
|
+
href="https://unpkg.com/senangwebs-jot@latest/dist/swj.css"
|
|
27
|
+
/>
|
|
28
|
+
<script src="https://unpkg.com/senangwebs-jot@latest/dist/swj.js"></script>
|
|
29
|
+
|
|
30
|
+
<!-- Senangwebs Modals -->
|
|
31
|
+
<link
|
|
32
|
+
rel="stylesheet"
|
|
33
|
+
href="https://unpkg.com/senangwebs-modals@latest/dist/swm.css"
|
|
34
|
+
/>
|
|
35
|
+
<script src="https://unpkg.com/senangwebs-modals@latest/dist/swm.js"></script>
|
|
36
|
+
|
|
37
|
+
<!-- Alpine.js -->
|
|
38
|
+
<script src="https://unpkg.com/alpinejs@3.x.x/dist/cdn.min.js"></script>
|
|
39
|
+
|
|
40
|
+
<!-- Tailwind CSS -->
|
|
41
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
42
|
+
<script>
|
|
43
|
+
tailwind.config = {
|
|
44
|
+
theme: {
|
|
45
|
+
extend: {
|
|
46
|
+
fontFamily: {
|
|
47
|
+
sans: ["Outfit", "sans-serif"],
|
|
48
|
+
},
|
|
49
|
+
colors: {
|
|
50
|
+
brand: {
|
|
51
|
+
600: "#2563EB",
|
|
52
|
+
700: "#1D4ED8",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
</script>
|
|
59
|
+
|
|
60
|
+
<style type="text/tailwindcss">
|
|
61
|
+
@layer base {
|
|
62
|
+
body {
|
|
63
|
+
@apply antialiased text-slate-900 bg-slate-50;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@layer components {
|
|
68
|
+
#search-container input {
|
|
69
|
+
@apply w-full max-w-xl px-5 py-3.5 text-base text-slate-900 bg-white border border-slate-200 rounded-full shadow-sm outline-none transition-all duration-200 placeholder:text-slate-400;
|
|
70
|
+
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cg%3E%3Cpath d='M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z' /%3E%3C/g%3E%3C/svg%3E");
|
|
71
|
+
background-repeat: no-repeat;
|
|
72
|
+
background-position: right 1rem center;
|
|
73
|
+
background-size: 1.25rem;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#search-container input:focus {
|
|
77
|
+
@apply border-brand-600 ring-4 ring-blue-500/10;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.swi-pagination-list {
|
|
81
|
+
@apply flex flex-wrap justify-center items-center gap-2 list-none p-0 mt-12;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.swi-pagination-btn {
|
|
85
|
+
@apply flex items-center justify-center min-w-[2.5rem] h-10 px-3 text-sm font-medium text-slate-600 bg-white border border-slate-200 rounded-lg transition-all duration-200 hover:border-brand-600 hover:text-brand-600;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.swi-pagination-item.swi-active .swi-pagination-btn {
|
|
89
|
+
@apply z-10 bg-brand-600 text-white border-brand-600 shadow-md shadow-blue-500/20 pointer-events-none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.swi-pagination-item.swi-disabled .swi-pagination-btn {
|
|
93
|
+
@apply opacity-50 cursor-not-allowed bg-slate-50 text-slate-400 hover:border-slate-200 hover:text-slate-400;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.swj-button {
|
|
97
|
+
@apply bg-brand-600 text-white;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.swj-btn .swj-button {
|
|
101
|
+
@apply w-full;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
</style>
|
|
105
|
+
</head>
|
|
106
|
+
<body class="flex flex-col min-h-screen">
|
|
107
|
+
<header class="w-full h-16 lg:h-24 bg-white">
|
|
108
|
+
<nav class="fixed z-50 w-full p-6" x-data="{ isOpen: false }">
|
|
109
|
+
<div
|
|
110
|
+
class="max-w-7xl mx-auto flex w-full flex-col rounded-xl bg-white bg-opacity-80 p-2 backdrop-blur backdrop-filter lg:flex-row border border-slate-200"
|
|
111
|
+
>
|
|
112
|
+
<div class="flex h-12 items-center">
|
|
113
|
+
<a href="https://senangstart.com/" target="_blank"
|
|
114
|
+
><img src="ss.svg" class="h-8 pl-2"
|
|
115
|
+
/></a>
|
|
116
|
+
<div class="flex-grow lg:hidden"></div>
|
|
117
|
+
<div
|
|
118
|
+
x-on:click="isOpen = !isOpen"
|
|
119
|
+
x-on:click.outside="isOpen = false"
|
|
120
|
+
class="flex w-12 h-12 cursor-pointer flex items-center justify-center lg:hidden text-3xl"
|
|
121
|
+
>
|
|
122
|
+
<i class="ss ss-bars-3" :class="!isOpen ? '' : 'hidden'"></i>
|
|
123
|
+
<i class="ss ss-x-mark" :class="isOpen ? '' : 'hidden'"></i>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
<div
|
|
127
|
+
:class="isOpen ? '' : 'hidden'"
|
|
128
|
+
class="flex-grow flex-col justify-end pt-4 lg:flex lg:flex-row lg:pt-0"
|
|
129
|
+
>
|
|
130
|
+
<a
|
|
131
|
+
href="#all-icons"
|
|
132
|
+
class="-mx-2 flex h-12 items-center px-6 lg:mx-0"
|
|
133
|
+
>Icons</a
|
|
134
|
+
>
|
|
135
|
+
<a
|
|
136
|
+
href="https://github.com/bookklik-technologies/senangstart-icons"
|
|
137
|
+
target="_blank"
|
|
138
|
+
class="-mx-2 flex h-12 items-center px-6 lg:mx-0"
|
|
139
|
+
>Github
|
|
140
|
+
<i class="ss ss-arrow-top-right-on-square ml-1" thickness="2"></i>
|
|
141
|
+
</a>
|
|
142
|
+
<a
|
|
143
|
+
href="#installation"
|
|
144
|
+
class="mx-4 mb-4 mt-4 flex h-12 items-center justify-center rounded-lg bg-blue-600 px-6 text-white lg:mb-0 lg:ml-4 lg:mr-0 lg:mt-0"
|
|
145
|
+
>Install</a
|
|
146
|
+
>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
</nav>
|
|
150
|
+
</header>
|
|
151
|
+
|
|
152
|
+
<main class="flex-grow">
|
|
153
|
+
<div class="bg-white border-b border-slate-100 pb-12 pt-16 px-6">
|
|
154
|
+
<div class="max-w-4xl mx-auto text-center">
|
|
155
|
+
<h1
|
|
156
|
+
class="text-4xl md:text-5xl font-semibold text-slate-900 tracking-tight mb-4"
|
|
157
|
+
>
|
|
158
|
+
Icons for
|
|
159
|
+
<span class="text-brand-600"
|
|
160
|
+
>Senang<span class="font-normal">Start</span></span
|
|
161
|
+
>.
|
|
162
|
+
</h1>
|
|
163
|
+
<p class="text-lg text-slate-500 mb-8 max-w-2xl mx-auto">
|
|
164
|
+
Curated icons designed for Starters.
|
|
165
|
+
</p>
|
|
166
|
+
|
|
167
|
+
<div
|
|
168
|
+
class="max-w-4xl mx-auto flex flex-col md:flex-row md:flex-row justify-center items-center gap-8"
|
|
169
|
+
>
|
|
170
|
+
<div
|
|
171
|
+
id="search-container"
|
|
172
|
+
class="flex flex-col md:flex-row justify-center items-center flex-grow max-w-xl"
|
|
173
|
+
>
|
|
174
|
+
<input type="text" placeholder="Search icons..." />
|
|
175
|
+
</div>
|
|
176
|
+
<div class="flex justify-center items-center gap-4">
|
|
177
|
+
<label
|
|
178
|
+
for="thickness-slider"
|
|
179
|
+
class="text-sm font-medium text-slate-700"
|
|
180
|
+
>Thickness</label
|
|
181
|
+
>
|
|
182
|
+
|
|
183
|
+
<input
|
|
184
|
+
id="thickness-slider"
|
|
185
|
+
type="range"
|
|
186
|
+
min="1"
|
|
187
|
+
max="4"
|
|
188
|
+
step="0.1"
|
|
189
|
+
value="2.2"
|
|
190
|
+
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-blue-600"
|
|
191
|
+
/>
|
|
192
|
+
<span
|
|
193
|
+
id="thickness-value"
|
|
194
|
+
class="text-xs font-mono w-16 text-slate-500 bg-slate-100 px-1.5 py-0.5 rounded"
|
|
195
|
+
>2.2</span
|
|
196
|
+
>
|
|
197
|
+
</div>
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
|
|
202
|
+
<div id="all-icons" class="max-w-7xl mx-auto px-6 py-12">
|
|
203
|
+
<div class="senangstart-icons">
|
|
204
|
+
<div
|
|
205
|
+
id="icons-container"
|
|
206
|
+
class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-4"
|
|
207
|
+
>
|
|
208
|
+
<!-- Icons injected here -->
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
<div id="pagination-container">
|
|
212
|
+
<!-- Pagination injected here -->
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
</div>
|
|
216
|
+
|
|
217
|
+
<section
|
|
218
|
+
id="installation"
|
|
219
|
+
class="bg-white border-t border-slate-200 py-16 lg:py-24"
|
|
220
|
+
>
|
|
221
|
+
<div class="max-w-7xl mx-auto px-6">
|
|
222
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-20">
|
|
223
|
+
<div>
|
|
224
|
+
<h2 class="text-3xl font-bold text-slate-900 tracking-tight mb-6">
|
|
225
|
+
Quick Installation
|
|
226
|
+
</h2>
|
|
227
|
+
<p class="text-slate-600 mb-8 leading-relaxed">
|
|
228
|
+
Choose how you want to include SenangStart Icons in your
|
|
229
|
+
project. Use NPM for module bundlers or the CDN for quick
|
|
230
|
+
prototyping.
|
|
231
|
+
</p>
|
|
232
|
+
|
|
233
|
+
<div class="mb-8">
|
|
234
|
+
<div class="flex items-center justify-between mb-3">
|
|
235
|
+
<span class="text-sm font-semibold text-slate-900"
|
|
236
|
+
>Install via NPM</span
|
|
237
|
+
>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="relative group">
|
|
240
|
+
<div
|
|
241
|
+
class="absolute inset-y-0 left-0 w-1 bg-brand-600 rounded-l-lg"
|
|
242
|
+
></div>
|
|
243
|
+
<pre
|
|
244
|
+
class="bg-slate-900 text-slate-50 p-5 rounded-r-lg rounded-l-md overflow-x-auto font-mono text-sm shadow-xl"
|
|
245
|
+
><code data-swj-id="code-install" data-swj-value>npm install senangstart-icons</code></pre>
|
|
246
|
+
</div>
|
|
247
|
+
<div class="flex justify-end w-full mt-2">
|
|
248
|
+
<button
|
|
249
|
+
type="button"
|
|
250
|
+
class="absolute inset-y-0 top-2 right-2 w-8 h-8 bg-brand-600 rounded flex items-center justify-center"
|
|
251
|
+
data-swj-copy="code-install"
|
|
252
|
+
></button>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
|
|
256
|
+
<div>
|
|
257
|
+
<div class="flex items-center justify-between mb-3">
|
|
258
|
+
<span class="text-sm font-semibold text-slate-900"
|
|
259
|
+
>CDN Link</span
|
|
260
|
+
>
|
|
261
|
+
<span
|
|
262
|
+
class="text-xs text-brand-600 bg-blue-50 px-2 py-0.5 rounded border border-blue-100"
|
|
263
|
+
>Recommended for static sites</span
|
|
264
|
+
>
|
|
265
|
+
</div>
|
|
266
|
+
<div class="relative group">
|
|
267
|
+
<div
|
|
268
|
+
class="absolute inset-y-0 left-0 w-1 bg-slate-600 rounded-l-lg"
|
|
269
|
+
></div>
|
|
270
|
+
<pre
|
|
271
|
+
class="bg-slate-900 text-slate-50 p-5 rounded-r-lg rounded-l-md overflow-x-auto font-mono text-sm shadow-xl"
|
|
272
|
+
><code><link rel="stylesheet" href="https://cdn.example.com/senangstart.min.css" />
|
|
273
|
+
<script src="https://cdn.example.com/senangstart-icon.min.js"></script></code></pre>
|
|
274
|
+
</div>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<div
|
|
279
|
+
class="bg-slate-50 rounded-2xl border border-slate-200 p-8 lg:p-10 flex flex-col justify-center"
|
|
280
|
+
>
|
|
281
|
+
<h2 class="text-2xl font-bold text-slate-900 mb-6">How to use</h2>
|
|
282
|
+
<p class="text-slate-600 mb-8">
|
|
283
|
+
Simply use the
|
|
284
|
+
<code
|
|
285
|
+
class="text-brand-700 bg-blue-100 px-1.5 py-0.5 rounded font-mono text-sm"
|
|
286
|
+
>ss-icon</code
|
|
287
|
+
>
|
|
288
|
+
custom element and pass the icon name to the
|
|
289
|
+
<code
|
|
290
|
+
class="text-brand-700 bg-blue-100 px-1.5 py-0.5 rounded font-mono text-sm"
|
|
291
|
+
>icon</code
|
|
292
|
+
>
|
|
293
|
+
attribute.
|
|
294
|
+
</p>
|
|
295
|
+
|
|
296
|
+
<div
|
|
297
|
+
class="bg-white rounded-xl shadow-sm border border-slate-200 overflow-hidden mb-6"
|
|
298
|
+
>
|
|
299
|
+
<div
|
|
300
|
+
class="bg-slate-100 px-4 py-2 border-b border-slate-200 flex items-center gap-2"
|
|
301
|
+
>
|
|
302
|
+
<div class="w-3 h-3 rounded-full bg-red-400"></div>
|
|
303
|
+
<div class="w-3 h-3 rounded-full bg-amber-400"></div>
|
|
304
|
+
<div class="w-3 h-3 rounded-full bg-green-400"></div>
|
|
305
|
+
</div>
|
|
306
|
+
<div class="p-8 flex items-center justify-evenly gap-6">
|
|
307
|
+
<div class="flex flex-col items-center gap-3 mt-auto">
|
|
308
|
+
<i class="ss ss-save text-blue-600 text-4xl"></i>
|
|
309
|
+
<span class="text-xs text-slate-400 font-mono"
|
|
310
|
+
>Icon: Save</span
|
|
311
|
+
>
|
|
312
|
+
</div>
|
|
313
|
+
<div class="flex flex-col items-center gap-3 mt-auto">
|
|
314
|
+
<ss-icon icon="home"></ss-icon>
|
|
315
|
+
<span class="text-xs text-slate-400 font-mono"
|
|
316
|
+
>Size: Default</span
|
|
317
|
+
>
|
|
318
|
+
</div>
|
|
319
|
+
<div class="flex flex-col items-center gap-3">
|
|
320
|
+
<ss-icon
|
|
321
|
+
icon="heart"
|
|
322
|
+
thickness="4"
|
|
323
|
+
class="text-brand-600 w-12 h-12"
|
|
324
|
+
></ss-icon>
|
|
325
|
+
<span class="text-xs text-slate-400 font-mono"
|
|
326
|
+
>Size: 48px</span
|
|
327
|
+
>
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
|
|
332
|
+
<div class="relative">
|
|
333
|
+
<pre
|
|
334
|
+
class="bg-slate-900 text-slate-50 p-4 rounded-lg overflow-x-auto font-mono text-sm leading-relaxed"
|
|
335
|
+
><code><span class="text-slate-500"><!-- Basic Usage --></span>
|
|
336
|
+
<i class="ss ss-save text-blue-600 text-4xl"></i>
|
|
337
|
+
<ss-icon icon="home"></ss-icon>
|
|
338
|
+
|
|
339
|
+
<span class="text-slate-500"><!-- With Tailwind Classes --></span>
|
|
340
|
+
<ss-icon icon="heart" thickness="4" class="text-brand-600 w-12 h-12"></ss-icon></code></pre>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
</section>
|
|
346
|
+
</main>
|
|
347
|
+
|
|
348
|
+
<!-- Footer -->
|
|
349
|
+
<footer class="bg-white border-t border-slate-200 py-8 mt-auto">
|
|
350
|
+
<div
|
|
351
|
+
class="max-w-7xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center gap-4"
|
|
352
|
+
>
|
|
353
|
+
<p class="text-sm text-slate-500">
|
|
354
|
+
Created with by
|
|
355
|
+
<a href="https://bookklik.com/" target="_blank" class="text-brand-600"
|
|
356
|
+
>Bookklik Technologies<i
|
|
357
|
+
class="ss ss-arrow-top-right-on-square ml-1"
|
|
358
|
+
thickness="2"
|
|
359
|
+
></i
|
|
360
|
+
></a>
|
|
361
|
+
</p>
|
|
362
|
+
<div class="flex gap-6">
|
|
363
|
+
<a
|
|
364
|
+
href="https://senangstart.com/license"
|
|
365
|
+
class="text-sm text-slate-400 hover:text-slate-900"
|
|
366
|
+
>License</a
|
|
367
|
+
>
|
|
368
|
+
<a
|
|
369
|
+
href="https://senangstart.com/privacy_policy"
|
|
370
|
+
class="text-sm text-slate-400 hover:text-slate-900"
|
|
371
|
+
>Privacy</a
|
|
372
|
+
>
|
|
373
|
+
</div>
|
|
374
|
+
</div>
|
|
375
|
+
</footer>
|
|
376
|
+
|
|
377
|
+
<script src="https://unpkg.com/senangwebs-index@latest/dist/swi.js"></script>
|
|
378
|
+
<script>
|
|
379
|
+
let currentThickness = 2.2;
|
|
380
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
381
|
+
const icons = "./src/icons.json";
|
|
382
|
+
|
|
383
|
+
const swi = new SenangWebsIndex({
|
|
384
|
+
container: "#icons-container",
|
|
385
|
+
data: icons,
|
|
386
|
+
itemTemplate: (item) => {
|
|
387
|
+
// Polished Card Template
|
|
388
|
+
return `
|
|
389
|
+
<div class="group relative flex flex-col items-center justify-between p-4 bg-white border border-slate-200 rounded-xl cursor-pointer transition-all duration-300 hover:border-brand-600 hover:shadow-lg hover:shadow-blue-500/10 aspect-square" onclick="iconDetails('${item.name}', '${item.slug}', '${item.tags}')">
|
|
390
|
+
<div class="flex-grow flex items-center justify-center mb-2 text-slate-700 transition-colors duration-300 group-hover:text-brand-600">
|
|
391
|
+
<ss-icon icon="${item.slug}" thickness="${currentThickness}" class="w-12 h-12"></ss-icon>
|
|
392
|
+
</div>
|
|
393
|
+
|
|
394
|
+
<div class="w-full text-center">
|
|
395
|
+
<div class=" max-w-full">
|
|
396
|
+
<code class="block text-[12px] leading-tight text-slate-400 bg-slate-50 border border-slate-100 rounded px-1.5 py-0.5 font-mono truncate transition-colors group-hover:text-brand-600 group-hover:bg-blue-50 group-hover:border-blue-100">
|
|
397
|
+
${item.slug}
|
|
398
|
+
</code>
|
|
399
|
+
</div>
|
|
400
|
+
</div>
|
|
401
|
+
|
|
402
|
+
</div>
|
|
403
|
+
`;
|
|
404
|
+
},
|
|
405
|
+
search: {
|
|
406
|
+
enabled: true,
|
|
407
|
+
selector: "#search-container",
|
|
408
|
+
searchKey: "tags",
|
|
409
|
+
},
|
|
410
|
+
pagination: {
|
|
411
|
+
enabled: true,
|
|
412
|
+
selector: "#pagination-container",
|
|
413
|
+
itemsPerPage: 48,
|
|
414
|
+
},
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
const thicknessSlider = document.getElementById("thickness-slider");
|
|
418
|
+
const thicknessValue = document.getElementById("thickness-value");
|
|
419
|
+
|
|
420
|
+
thicknessSlider.addEventListener("input", (e) => {
|
|
421
|
+
currentThickness = e.target.value;
|
|
422
|
+
thicknessValue.textContent = currentThickness;
|
|
423
|
+
|
|
424
|
+
// Update all currently visible icons
|
|
425
|
+
const icons = document.querySelectorAll("#icons-container ss-icon");
|
|
426
|
+
icons.forEach((icon) => {
|
|
427
|
+
icon.setAttribute("thickness", currentThickness);
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const targetDiv = document.getElementById("icons-container");
|
|
433
|
+
const config = { childList: true, subtree: true, characterData: true };
|
|
434
|
+
const callback = function (mutationsList, observer) {
|
|
435
|
+
for (const mutation of mutationsList) {
|
|
436
|
+
if (
|
|
437
|
+
mutation.type === "childList" ||
|
|
438
|
+
mutation.type === "characterData"
|
|
439
|
+
) {
|
|
440
|
+
SWJ.refresh();
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
};
|
|
444
|
+
const observer = new MutationObserver(callback);
|
|
445
|
+
observer.observe(targetDiv, config);
|
|
446
|
+
|
|
447
|
+
function iconDetails(name, slug, tags) {
|
|
448
|
+
let thickness = currentThickness;
|
|
449
|
+
SWM.createModal({
|
|
450
|
+
title: `${name}`,
|
|
451
|
+
content: `<div class="flex flex-col justify-center items-center lg:flex-row gap-4 w-full py-2">
|
|
452
|
+
<div class="bg-slate-50 border border-slate-200 p-4 rounded-lg text-7xl aspect-square w-48 flex items-center justify-center">
|
|
453
|
+
<ss-icon icon="${slug}" thickness="${thickness}"></ss-icon>
|
|
454
|
+
</div>
|
|
455
|
+
<div class="flex flex-col gap-2 justify-between flex-grow lg:h-48">
|
|
456
|
+
<div class="relative group">
|
|
457
|
+
<div class="absolute inset-y-0 left-0 w-1 bg-brand-600 rounded-l-lg"></div>
|
|
458
|
+
<pre class="bg-slate-900 text-slate-50 p-5 rounded-r-lg rounded-l-md overflow-x-auto font-mono text-sm shadow-xl max-w-[calc(100vw-4rem)]"><code><ss-icon icon="${slug}" thickness="${thickness}"></ss-icon>
|
|
459
|
+
<i class="ss ss-${slug}"></i></code></pre>
|
|
460
|
+
</div>
|
|
461
|
+
<div class="text-xs text-slate-400 mb-auto">tags: ${tags}</div>
|
|
462
|
+
<textarea id="copy-code-${slug}" class="w-0 h-0" data-swj-id="copy-code-${slug}" data-swj-value><ss-icon icon="${slug}" thickness="${thickness}"></ss-icon></textarea>
|
|
463
|
+
<div class="flex items-center justify-center lg:justify-end">
|
|
464
|
+
<button
|
|
465
|
+
type="button"
|
|
466
|
+
class="bg-brand-600 rounded flex items-center justify-center text-white px-2 py-1"
|
|
467
|
+
data-swj-copy="copy-code-${slug}"
|
|
468
|
+
>Copy</button>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
</div>`,
|
|
472
|
+
position: "top",
|
|
473
|
+
zIndex: "50",
|
|
474
|
+
});
|
|
475
|
+
SWJ.refresh();
|
|
476
|
+
}
|
|
477
|
+
</script>
|
|
478
|
+
</body>
|
|
479
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bookklik/senangstart-icons",
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "Curated Starter icons designed for web projects.",
|
|
5
|
+
"main": "dist/senangstart-icon.min.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build:svg": "node scripts/build-svgs.js",
|
|
8
|
+
"build": "npm run build:svg && webpack --mode production",
|
|
9
|
+
"build:watch": "npm run build:svg && webpack --mode production --watch",
|
|
10
|
+
"dev": "npm run build:svg && webpack --mode development --watch",
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"icons",
|
|
15
|
+
"svg",
|
|
16
|
+
"web-components"
|
|
17
|
+
],
|
|
18
|
+
"author": "a-hakim",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@babel/core": "^7.23.0",
|
|
22
|
+
"@babel/preset-env": "^7.23.0",
|
|
23
|
+
"babel-loader": "^9.1.3",
|
|
24
|
+
"css-loader": "^6.8.1",
|
|
25
|
+
"css-minimizer-webpack-plugin": "^5.0.1",
|
|
26
|
+
"mini-css-extract-plugin": "^2.7.6",
|
|
27
|
+
"terser-webpack-plugin": "^5.3.9",
|
|
28
|
+
"webpack": "^5.89.0",
|
|
29
|
+
"webpack-cli": "^5.1.4"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const fs = require("fs");
|
|
2
|
+
const path = require("path");
|
|
3
|
+
|
|
4
|
+
const iconsPath = path.resolve(__dirname, "../src/icons.json");
|
|
5
|
+
const svgDir = path.resolve(__dirname, "../src/svg");
|
|
6
|
+
|
|
7
|
+
// Read icons.json
|
|
8
|
+
const icons = JSON.parse(fs.readFileSync(iconsPath, "utf8"));
|
|
9
|
+
|
|
10
|
+
// Ensure svg directory exists
|
|
11
|
+
if (!fs.existsSync(svgDir)) {
|
|
12
|
+
fs.mkdirSync(svgDir, { recursive: true });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const iconExports = [];
|
|
16
|
+
|
|
17
|
+
icons.forEach((icon) => {
|
|
18
|
+
const { slug, src, viewBox, fill, stroke, strokeWidth } = icon;
|
|
19
|
+
|
|
20
|
+
// Default values
|
|
21
|
+
const vBox = viewBox || "0 0 24 24";
|
|
22
|
+
const fl = fill || "none";
|
|
23
|
+
const strk = stroke || "currentColor";
|
|
24
|
+
const strkWidth = strokeWidth || "2";
|
|
25
|
+
|
|
26
|
+
// Create SVG content
|
|
27
|
+
const svgContent = `<svg viewBox="${vBox}" fill="${fl}" stroke="${strk}" stroke-width="${strkWidth}" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg">
|
|
28
|
+
<g><path d="${src}" /></g>
|
|
29
|
+
</svg>`;
|
|
30
|
+
|
|
31
|
+
// Write SVG file
|
|
32
|
+
const svgFilePath = path.join(svgDir, `${slug}.svg`);
|
|
33
|
+
fs.writeFileSync(svgFilePath, svgContent);
|
|
34
|
+
console.log(`Generated ${slug}.svg`);
|
|
35
|
+
|
|
36
|
+
// Add to exports
|
|
37
|
+
// Convert slug to camelCase or valid identifier if needed, but for now using slug as key in object
|
|
38
|
+
// Since we want to export an object mapping slugs to svg content (via webpack asset/source)
|
|
39
|
+
iconExports.push(`"${slug}": require("./${slug}.svg")`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Generate index.js
|
|
43
|
+
const indexContent = `const icons = {
|
|
44
|
+
${iconExports.join(",\n ")}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default icons;
|
|
48
|
+
`;
|
|
49
|
+
|
|
50
|
+
fs.writeFileSync(path.join(svgDir, "index.js"), indexContent);
|
|
51
|
+
console.log("Generated src/svg/index.js");
|