funuicss 3.6.16 → 3.6.18

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/cors.json ADDED
@@ -0,0 +1,8 @@
1
+ [
2
+ {
3
+ "origin": ["*"],
4
+ "method": ["GET", "HEAD", "DELETE", "POST", "PUT"],
5
+ "maxAgeSeconds": 3600,
6
+ "responseHeader": ["Content-Type"]
7
+ }
8
+ ]
package/css/fun.css CHANGED
@@ -220,126 +220,167 @@
220
220
 
221
221
 
222
222
 
223
+ /* fonts scalling */
223
224
  :root {
224
- /* BUTTON VARIABLES */
225
- --btn-font-size: var(--text-base);
226
- --btn-font-weight: 500;
227
- --btn-padding-x: var(--space-4);
228
- --btn-padding-y: var(--space-2);
229
- --btn-border-radius: var(--radius-lg);
230
- --btn-border-width: 1px;
231
- --btn-min-height: 2.5rem;
232
- --btn-gap: var(--space-2); /* for icon spacing */
225
+ /* ===== Font Scale - Perfect Fourth (1.333 ratio) ===== */
226
+ --font-size-smaller: 0.75rem; /* 12px */
227
+ --font-size-small: 0.875rem; /* 14px */
228
+ --font-size-base: 1rem; /* 16px - Base */
229
+ --font-size-big: 1.25rem; /* 20px */
230
+ --font-size-bigger: 1.5rem; /* 24px */
231
+ --font-size-h6: 1rem; /* 16px */
232
+ --font-size-h5: 1.25rem; /* 20px */
233
+ --font-size-h4: 1.5rem; /* 24px */
234
+ --font-size-h3: 1.75rem; /* 28px */
235
+ --font-size-h2: 2rem; /* 32px */
236
+ --font-size-h1: 2.5rem; /* 40px */
237
+ --font-size-jumbo: 3rem; /* 48px */
238
+
239
+ /* ===== Line Height Scale ===== */
240
+ --line-height-tight: 1.2;
241
+ --line-height-normal: 1.5;
242
+ --line-height-relaxed: 1.75;
243
+ --line-height-loose: 2;
244
+
245
+ /* Element-specific line heights */
246
+ --line-height-smaller: var(--line-height-normal);
247
+ --line-height-small: var(--line-height-normal);
248
+ --line-height-body: var(--line-height-normal);
249
+ --line-height-big: var(--line-height-normal);
250
+ --line-height-bigger: var(--line-height-normal);
251
+ --line-height-h6: var(--line-height-normal);
252
+ --line-height-h5: var(--line-height-normal);
253
+ --line-height-h4: var(--line-height-normal);
254
+ --line-height-h3: var(--line-height-normal);
255
+ --line-height-h2: var(--line-height-tight);
256
+ --line-height-h1: var(--line-height-tight);
257
+ --line-height-jumbo: var(--line-height-tight);
258
+
259
+ /* ===== Font Weights ===== */
260
+ --font-weight-thin: 100;
261
+ --font-weight-extra-light: 200;
262
+ --font-weight-light: 300;
263
+ --font-weight-normal: 400;
264
+ --font-weight-medium: 500;
265
+ --font-weight-semibold: 600;
266
+ --font-weight-bold: 700;
267
+ --font-weight-extra-bold: 800;
268
+ --font-weight-black: 900;
269
+
270
+ /* Element-specific font weights */
271
+ --font-weight-smaller: var(--font-weight-normal);
272
+ --font-weight-small: var(--font-weight-normal);
273
+ --font-weight-body: var(--font-weight-normal);
274
+ --font-weight-big: var(--font-weight-normal);
275
+ --font-weight-bigger: var(--font-weight-normal);
276
+ --font-weight-h6: var(--font-weight-medium);
277
+ --font-weight-h5: var(--font-weight-medium);
278
+ --font-weight-h4: var(--font-weight-medium);
279
+ --font-weight-h3: var(--font-weight-semibold);
280
+ --font-weight-h2: var(--font-weight-semibold);
281
+ --font-weight-h1: var(--font-weight-bold);
282
+ --font-weight-jumbo: var(--font-weight-bold);
283
+
284
+ /* ===== Text Decoration ===== */
285
+ --text-decoration-none: none;
286
+ --text-decoration-underline: underline;
287
+ --text-decoration-overline: overline;
288
+ --text-decoration-line-through: line-through;
289
+
290
+ /* Element-specific text decoration */
291
+ --text-decoration-smaller: var(--text-decoration-none);
292
+ --text-decoration-small: var(--text-decoration-none);
293
+ --text-decoration-body: var(--text-decoration-none);
294
+ --text-decoration-big: var(--text-decoration-none);
295
+ --text-decoration-bigger: var(--text-decoration-none);
296
+ --text-decoration-h6: var(--text-decoration-none);
297
+ --text-decoration-h5: var(--text-decoration-none);
298
+ --text-decoration-h4: var(--text-decoration-none);
299
+ --text-decoration-h3: var(--text-decoration-none);
300
+ --text-decoration-h2: var(--text-decoration-none);
301
+ --text-decoration-h1: var(--text-decoration-none);
302
+ --text-decoration-jumbo: var(--text-decoration-none);
303
+
304
+ /* ===== Font Style ===== */
305
+ --font-style-normal: normal;
306
+ --font-style-italic: italic;
307
+ --font-style-oblique: oblique;
308
+
309
+ /* Element-specific font styles */
310
+ --font-style-smaller: var(--font-style-normal);
311
+ --font-style-small: var(--font-style-normal);
312
+ --font-style-body: var(--font-style-normal);
313
+ --font-style-big: var(--font-style-normal);
314
+ --font-style-bigger: var(--font-style-normal);
315
+ --font-style-h6: var(--font-style-normal);
316
+ --font-style-h5: var(--font-style-normal);
317
+ --font-style-h4: var(--font-style-normal);
318
+ --font-style-h3: var(--font-style-normal);
319
+ --font-style-h2: var(--font-style-normal);
320
+ --font-style-h1: var(--font-style-normal);
321
+ --font-style-jumbo: var(--font-style-normal);
322
+
323
+ /* ===== Text Transform ===== */
324
+ --text-transform-none: none;
325
+ --text-transform-uppercase: uppercase;
326
+ --text-transform-lowercase: lowercase;
327
+ --text-transform-capitalize: capitalize;
328
+
329
+ /* Element-specific text transforms */
330
+ --text-transform-smaller: var(--text-transform-none);
331
+ --text-transform-small: var(--text-transform-none);
332
+ --text-transform-body: var(--text-transform-none);
333
+ --text-transform-big: var(--text-transform-none);
334
+ --text-transform-bigger: var(--text-transform-none);
335
+ --text-transform-h6: var(--text-transform-none);
336
+ --text-transform-h5: var(--text-transform-none);
337
+ --text-transform-h4: var(--text-transform-none);
338
+ --text-transform-h3: var(--text-transform-none);
339
+ --text-transform-h2: var(--text-transform-none);
340
+ --text-transform-h1: var(--text-transform-none);
341
+ --text-transform-jumbo: var(--text-transform-none);
342
+
343
+ /* ===== Letter Spacing ===== */
344
+ --letter-spacing-tighter: -0.05em;
345
+ --letter-spacing-tight: -0.025em;
346
+ --letter-spacing-normal: 0em;
347
+ --letter-spacing-wide: 0.025em;
348
+ --letter-spacing-wider: 0.05em;
349
+ --letter-spacing-widest: 0.1em;
350
+
351
+ /* Element-specific letter spacing */
352
+ --letter-spacing-smaller: var(--letter-spacing-normal);
353
+ --letter-spacing-small: var(--letter-spacing-normal);
354
+ --letter-spacing-body: var(--letter-spacing-normal);
355
+ --letter-spacing-big: var(--letter-spacing-normal);
356
+ --letter-spacing-bigger: var(--letter-spacing-normal);
357
+ --letter-spacing-h6: var(--letter-spacing-normal);
358
+ --letter-spacing-h5: var(--letter-spacing-normal);
359
+ --letter-spacing-h4: var(--letter-spacing-normal);
360
+ --letter-spacing-h3: var(--letter-spacing-normal);
361
+ --letter-spacing-h2: var(--letter-spacing-tight);
362
+ --letter-spacing-h1: var(--letter-spacing-tight);
363
+ --letter-spacing-jumbo: var(--letter-spacing-tight);
364
+
365
+ /* ===== Word Spacing ===== */
366
+ --word-spacing-tight: -0.05em;
367
+ --word-spacing-normal: 0em;
368
+ --word-spacing-wide: 0.05em;
369
+ --word-spacing-wider: 0.1em;
370
+
371
+ /* ===== Responsive Typography Scales ===== */
372
+ /* Mobile-first scale (base) */
373
+ --scale-mobile: 1.2;
233
374
 
234
- /* Button States */
235
- --btn-hover-scale: 1.02;
236
- --btn-active-scale: 0.98;
237
- --btn-disabled-opacity: 0.5;
375
+ /* Tablet scale */
376
+ --scale-tablet: 1.25;
238
377
 
239
- /* Button Variants */
240
- --btn-primary-bg: var(--primary);
241
- --btn-primary-text: var(--white);
242
- --btn-primary-hover: var(--primary600);
243
-
244
- --btn-secondary-bg: var(--secondary);
245
- --btn-secondary-text: var(--white);
246
- --btn-secondary-hover: var(--secondary600);
247
-
248
- --btn-outlined-border: var(--primary);
249
- --btn-outlined-text: var(--primary);
250
- --btn-outlined-hover-bg: var(--primary50);
251
-
252
- /* INPUT VARIABLES */
253
- --input-font-size: var(--text-base);
254
- --input-padding-x: var(--space-4);
255
- --input-padding-y: var(--space-3);
256
- --input-border-radius: var(--radius-lg);
257
- --input-border-width: var(--inputBorder);
258
- --input-border-color: var(--borderColor);
259
- --input-bg: var(--white);
260
- --input-text-color: var(--text-color);
261
- --input-placeholder-color: var(--muted);
262
- --input-min-height: var(--inputButtonHeight);
263
-
264
- /* Input States */
265
- --input-focus-border: var(--primary);
266
- --input-focus-ring: 0 0 0 3px var(--primary200);
267
- --input-error-border: var(--error);
268
- --input-error-ring: 0 0 0 3px var(--error200);
269
- --input-disabled-bg: var(--lighter);
270
- --input-disabled-opacity: 0.6;
271
-
272
- /* CARD VARIABLES */
273
- --card-bg: var(--cardBg);
274
- --card-border: var(--border);
275
- --card-border-radius: var(--borderRadius);
276
- --card-padding: var(--space-6);
277
- --card-shadow: var(--card);
278
- --card-hover-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
279
-
280
- /* LINK VARIABLES */
281
- --link-color: var(--linkColor);
282
- --link-hover-color: var(--primary);
283
- --link-underline: none;
284
- --link-hover-underline: underline;
285
- --link-font-weight: 400;
286
-
287
- /* BADGE/TAG VARIABLES */
288
- --badge-font-size: var(--text-xs);
289
- --badge-padding-x: var(--space-2);
290
- --badge-padding-y: var(--space-1);
291
- --badge-border-radius: var(--radius-full);
292
- --badge-font-weight: 500;
293
-
294
- /* MODAL/DIALOG VARIABLES */
295
- --modal-backdrop: rgba(0, 0, 0, 0.5);
296
- --modal-bg: var(--white);
297
- --modal-border-radius: var(--radius-2xl);
298
- --modal-padding: var(--space-8);
299
- --modal-max-width: 32rem;
300
- --modal-shadow: 0 25px 50px rgba(0, 0, 0, 0.25);
301
-
302
- /* DROPDOWN/SELECT VARIABLES */
303
- --dropdown-bg: var(--white);
304
- --dropdown-border: var(--border);
305
- --dropdown-border-radius: var(--radius-lg);
306
- --dropdown-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
307
- --dropdown-item-padding: var(--space-3) var(--space-4);
308
- --dropdown-item-hover-bg: var(--lighter);
309
-
310
- /* SWITCH/TOGGLE VARIABLES */
311
- --switch-width: 2.75rem;
312
- --switch-height: 1.5rem;
313
- --switch-bg: var(--borderColor);
314
- --switch-active-bg: var(--primary);
315
- --switch-thumb-size: 1.25rem;
316
-
317
- /* CHECKBOX/RADIO VARIABLES */
318
- --checkbox-size: 1.25rem;
319
- --checkbox-border: var(--borderColor);
320
- --checkbox-checked-bg: var(--primary);
321
- --checkbox-checked-border: var(--primary);
322
- --checkbox-border-radius: var(--radius);
323
-
324
- /* TOOLTIP VARIABLES */
325
- --tooltip-bg: var(--dark);
326
- --tooltip-text: var(--white);
327
- --tooltip-padding: var(--space-2) var(--space-3);
328
- --tooltip-border-radius: var(--radius);
329
- --tooltip-font-size: var(--text-sm);
330
-
331
- /* AVATAR VARIABLES */
332
- --avatar-size: 2.5rem;
333
- --avatar-border-radius: var(--radius-full);
334
- --avatar-border: 2px solid var(--white);
335
-
336
- /* DIVIDER VARIABLES */
337
- --divider-color: var(--borderColor);
338
- --divider-width: 1px;
339
- --divider-margin: var(--space-4) 0;
378
+ /* Desktop scale */
379
+ --scale-desktop: 1.333;
340
380
  }
341
381
 
342
382
 
383
+
343
384
  /* For WebKit browsers (Chrome, Edge, Brave, Safari) */
344
385
  ::-webkit-scrollbar {
345
386
  width: 10px;
@@ -580,23 +621,34 @@ body {
580
621
  font-weight: 900;
581
622
  }
582
623
 
583
- /* Additional responsive/animated sizes */
584
624
  .text-big {
585
- font-size: calc(1.375rem + 2vw); /* Responsive scaling */
586
- line-height: 80%;
587
- font-weight: 900;
625
+ font-size: var(--font-size-big);
626
+ line-height: var(--line-height-big);
627
+ font-weight: var(--font-weight-big);
628
+ font-style: var(--font-style-big);
629
+ text-decoration: var(--text-decoration-big);
630
+ text-transform: var(--text-transform-big);
631
+ letter-spacing: var(--letter-spacing-big);
588
632
  }
589
633
 
590
634
  .text-bigger {
591
- font-size: calc(1.375rem + 2.5vw);
592
- line-height: 80% ;
593
- font-weight: 900;
635
+ font-size: var(--font-size-bigger);
636
+ line-height: var(--line-height-bigger);
637
+ font-weight: var(--font-weight-bigger);
638
+ font-style: var(--font-style-bigger);
639
+ text-decoration: var(--text-decoration-bigger);
640
+ text-transform: var(--text-transform-bigger);
641
+ letter-spacing: var(--letter-spacing-bigger);
594
642
  }
595
643
 
596
644
  .text-jumbo {
597
- font-size: calc(1.375rem + 5vw);
598
- line-height: 70%;
599
- font-weight: 900;
645
+ font-size: var(--font-size-jumbo);
646
+ line-height: var(--line-height-jumbo);
647
+ font-weight: var(--font-weight-jumbo);
648
+ font-style: var(--font-style-jumbo);
649
+ text-decoration: var(--text-decoration-jumbo);
650
+ text-transform: var(--text-transform-jumbo);
651
+ letter-spacing: var(--letter-spacing-jumbo);
600
652
  }
601
653
  .important{
602
654
  font-weight: 700;
@@ -604,13 +656,23 @@ body {
604
656
  }
605
657
  /* Mini sizes */
606
658
  .text-small {
607
- font-size: var(--smallFont);
608
- line-height: 1.25rem;
659
+ font-size: var(--font-size-small);
660
+ line-height: var(--line-height-small);
661
+ font-weight: var(--font-weight-small);
662
+ font-style: var(--font-style-small);
663
+ text-decoration: var(--text-decoration-small);
664
+ text-transform: var(--text-transform-small);
665
+ letter-spacing: var(--letter-spacing-small);
609
666
  }
610
667
 
611
668
  .text-smaller {
612
- font-size: var(--smallerFont);
613
- line-height: 1.125rem;
669
+ font-size: var(--font-size-smaller);
670
+ line-height: var(--line-height-smaller);
671
+ font-weight: var(--font-weight-smaller);
672
+ font-style: var(--font-style-smaller);
673
+ text-decoration: var(--text-decoration-smaller);
674
+ text-transform: var(--text-transform-smaller);
675
+ letter-spacing: var(--letter-spacing-smaller);
614
676
  }
615
677
 
616
678
  .text-minified , .text-md{
@@ -646,39 +708,82 @@ h1,
646
708
  }
647
709
 
648
710
  h1, .h1 {
649
- font-size: var(--text-5xl);
650
- line-height: var(--leading-none);
651
- font-weight: 900;
711
+ font-size: var(--font-size-h1);
712
+ line-height: var(--line-height-h1);
713
+ font-weight: var(--font-weight-h1);
714
+ font-style: var(--font-style-h1);
715
+ text-decoration: var(--text-decoration-h1);
716
+ text-transform: var(--text-transform-h1);
717
+ letter-spacing: var(--letter-spacing-h1);
652
718
  }
653
719
 
654
720
  h2, .h2 {
655
- font-size: var(--text-4xl);
656
- line-height: var(--leading-4xl);
657
- font-weight: 900;
721
+ font-size: var(--font-size-h2);
722
+ line-height: var(--line-height-h2);
723
+ font-weight: var(--font-weight-h2);
724
+ font-style: var(--font-style-h2);
725
+ text-decoration: var(--text-decoration-h2);
726
+ text-transform: var(--text-transform-h2);
727
+ letter-spacing: var(--letter-spacing-h2);
658
728
  }
659
729
 
660
730
  h3, .h3 {
661
- font-size: var(--text-3xl);
662
- line-height: var(--leading-3xl);
663
- font-weight: 700;
731
+ font-size: var(--font-size-h3);
732
+ line-height: var(--line-height-h3);
733
+ font-weight: var(--font-weight-h3);
734
+ font-style: var(--font-style-h3);
735
+ text-decoration: var(--text-decoration-h3);
736
+ text-transform: var(--text-transform-h3);
737
+ letter-spacing: var(--letter-spacing-h3);
664
738
  }
665
739
 
666
740
  h4, .h4 {
667
- font-size: var(--text-2xl);
668
- line-height: var(--leading-2xl);
669
- font-weight: 600;
741
+ font-size: var(--font-size-h4);
742
+ line-height: var(--line-height-h4);
743
+ font-weight: var(--font-weight-h4);
744
+ font-style: var(--font-style-h4);
745
+ text-decoration: var(--text-decoration-h4);
746
+ text-transform: var(--text-transform-h4);
747
+ letter-spacing: var(--letter-spacing-h4);
670
748
  }
671
749
 
672
750
  h5, .h5 {
673
- font-size: var(--text-xl);
674
- line-height: var(--leading-xl);
675
- font-weight: 500;
751
+ font-size: var(--font-size-h5);
752
+ line-height: var(--line-height-h5);
753
+ font-weight: var(--font-weight-h5);
754
+ font-style: var(--font-style-h5);
755
+ text-decoration: var(--text-decoration-h5);
756
+ text-transform: var(--text-transform-h5);
757
+ letter-spacing: var(--letter-spacing-h5);
676
758
  }
677
759
 
678
760
  h6, .h6 {
679
- font-size: var(--text-base);
680
- line-height: var(--leading-normal);
681
- font-weight: 500;
761
+ font-size: var(--font-size-h6);
762
+ line-height: var(--line-height-h6);
763
+ font-weight: var(--font-weight-h6);
764
+ font-style: var(--font-style-h6);
765
+ text-decoration: var(--text-decoration-h6);
766
+ text-transform: var(--text-transform-h6);
767
+ letter-spacing: var(--letter-spacing-h6);
768
+ }
769
+
770
+ /* ===== Responsive Typography ===== */
771
+ @media (min-width: 768px) {
772
+ :root {
773
+ --font-size-h1: calc(2.5rem * var(--scale-tablet));
774
+ --font-size-h2: calc(2rem * var(--scale-tablet));
775
+ --font-size-h3: calc(1.75rem * var(--scale-tablet));
776
+ --font-size-jumbo: calc(3rem * var(--scale-tablet));
777
+ }
778
+ }
779
+
780
+ @media (min-width: 1024px) {
781
+ :root {
782
+ --font-size-h1: calc(2.5rem * var(--scale-desktop));
783
+ --font-size-h2: calc(2rem * var(--scale-desktop));
784
+ --font-size-h3: calc(1.75rem * var(--scale-desktop));
785
+ --font-size-jumbo: calc(3rem * var(--scale-desktop));
786
+ }
682
787
  }
683
788
 
684
789
 
@@ -1969,8 +2074,6 @@ border-radius: var(--borderRadius);
1969
2074
 
1970
2075
 
1971
2076
 
1972
-
1973
-
1974
2077
  .dropup:hover .drop-menu {
1975
2078
  display: block;
1976
2079
  z-index: 1;
@@ -2050,7 +2153,6 @@ border-radius: var(--borderRadius);
2050
2153
  pointer-events: none;
2051
2154
  transition: all 0.2s ease;
2052
2155
  background-color: transparent;
2053
- padding: 0 0.25rem;
2054
2156
  z-index: 1;
2055
2157
  font-weight: 500;
2056
2158
  }
@@ -2066,7 +2168,7 @@ border-radius: var(--borderRadius);
2066
2168
  transform: translateY(0);
2067
2169
  line-height: 1;
2068
2170
  }
2069
- .floating-label.label-left{left: 2.5rem ;}
2171
+ .floating-label.label-left{left: 2rem ;}
2070
2172
  /* Label status colors */
2071
2173
  .floating-label.label-success.active {
2072
2174
  color: var(--success);
@@ -2097,14 +2199,6 @@ border-radius: var(--borderRadius);
2097
2199
  background-color: transparent;
2098
2200
  }
2099
2201
 
2100
- /* For textarea */
2101
- textarea ~ .floating-label {
2102
- top: 1.2rem;
2103
- }
2104
-
2105
- textarea ~ .floating-label.active {
2106
- top: 0.35rem;
2107
- }
2108
2202
 
2109
2203
  /* Status Input Styles */
2110
2204
  .input.success-input,
@@ -2157,8 +2251,7 @@ textarea {
2157
2251
  border-radius: var(--radius) !important;
2158
2252
  height: fit-content !important;
2159
2253
  min-height: 4rem;
2160
- padding-top: 1.4rem;
2161
- padding-bottom: 0.6rem;
2254
+ padding-top: 0.8rem !important;
2162
2255
  }
2163
2256
 
2164
2257
  /* Reset padding when there's no label for textarea */
package/gsutil ADDED
File without changes
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "3.6.16",
2
+ "version": "3.6.18",
3
3
  "name": "funuicss",
4
4
  "description": "React and Next.js component UI Library for creating Easy and good looking websites with fewer lines of code. Elevate your web development experience with our cutting-edge React/Next.js component UI Library. Craft stunning websites effortlessly, boasting both seamless functionality and aesthetic appeal—all achieved with minimal lines of code. Unleash the power of simplicity and style in your projects!",
5
5
  "main": "index.js",
@@ -62,8 +62,7 @@ var pi_1 = require("react-icons/pi");
62
62
  var componentUtils_1 = require("../../utils/componentUtils");
63
63
  var getDynamicIcon_1 = require("../../utils/getDynamicIcon");
64
64
  function Button(_a) {
65
- var _b;
66
- var _c = _a.variant, variant = _c === void 0 ? '' : _c, color = _a.color, bg = _a.bg, funcss = _a.funcss, startIcon = _a.startIcon, endIcon = _a.endIcon, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, prefix = _a.prefix, suffix = _a.suffix, iconSize = _a.iconSize, _d = _a.iconLineHeight, iconLineHeight = _d === void 0 ? 0 : _d, text = _a.text, rounded = _a.rounded, raised = _a.raised, height = _a.height, width = _a.width, float = _a.float, hoverUp = _a.hoverUp, fullWidth = _a.fullWidth, outlined = _a.outlined, small = _a.small, hoverless = _a.hoverless, smaller = _a.smaller, big = _a.big, bigger = _a.bigger, jumbo = _a.jumbo, flat = _a.flat, hoverNone = _a.hoverNone, fillAnimation = _a.fillAnimation, fillDirection = _a.fillDirection, fillTextColor = _a.fillTextColor, outlineSize = _a.outlineSize, isLoading = _a.isLoading, status = _a.status, bold = _a.bold, children = _a.children, style = _a.style, url = _a.url, onClick = _a.onClick, rest = __rest(_a, ["variant", "color", "bg", "funcss", "startIcon", "endIcon", "stringPrefix", "stringSuffix", "prefix", "suffix", "iconSize", "iconLineHeight", "text", "rounded", "raised", "height", "width", "float", "hoverUp", "fullWidth", "outlined", "small", "hoverless", "smaller", "big", "bigger", "jumbo", "flat", "hoverNone", "fillAnimation", "fillDirection", "fillTextColor", "outlineSize", "isLoading", "status", "bold", "children", "style", "url", "onClick"]);
65
+ var _b = _a.variant, variant = _b === void 0 ? '' : _b, color = _a.color, bg = _a.bg, funcss = _a.funcss, startIcon = _a.startIcon, endIcon = _a.endIcon, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, prefix = _a.prefix, suffix = _a.suffix, iconSize = _a.iconSize, _c = _a.iconLineHeight, iconLineHeight = _c === void 0 ? 0 : _c, text = _a.text, rounded = _a.rounded, raised = _a.raised, height = _a.height, width = _a.width, float = _a.float, hoverUp = _a.hoverUp, fullWidth = _a.fullWidth, outlined = _a.outlined, small = _a.small, hoverless = _a.hoverless, smaller = _a.smaller, big = _a.big, bigger = _a.bigger, jumbo = _a.jumbo, flat = _a.flat, hoverNone = _a.hoverNone, fillAnimation = _a.fillAnimation, fillDirection = _a.fillDirection, fillTextColor = _a.fillTextColor, outlineSize = _a.outlineSize, isLoading = _a.isLoading, status = _a.status, bold = _a.bold, children = _a.children, style = _a.style, url = _a.url, onClick = _a.onClick, rest = __rest(_a, ["variant", "color", "bg", "funcss", "startIcon", "endIcon", "stringPrefix", "stringSuffix", "prefix", "suffix", "iconSize", "iconLineHeight", "text", "rounded", "raised", "height", "width", "float", "hoverUp", "fullWidth", "outlined", "small", "hoverless", "smaller", "big", "bigger", "jumbo", "flat", "hoverNone", "fillAnimation", "fillDirection", "fillTextColor", "outlineSize", "isLoading", "status", "bold", "children", "style", "url", "onClick"]);
67
66
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Button', variant).mergeWithLocal;
68
67
  var mergedProps = mergeWithLocal(__assign({ color: color, bg: bg, funcss: funcss, text: text, rounded: rounded, raised: raised, height: height, width: width, float: float, hoverUp: hoverUp, fullWidth: fullWidth, outlined: outlined, small: small, hoverless: hoverless, smaller: smaller, big: big, bigger: bigger, jumbo: jumbo, flat: flat, hoverNone: hoverNone, fillAnimation: fillAnimation, fillDirection: fillDirection, fillTextColor: fillTextColor, outlineSize: outlineSize, isLoading: isLoading, status: status, bold: bold }, rest)).props;
69
68
  var final = {
@@ -91,17 +90,28 @@ function Button(_a) {
91
90
  fillTextColor: mergedProps.fillTextColor,
92
91
  funcss: mergedProps.funcss,
93
92
  };
94
- var _e = (0, react_1.useState)(null), prefixNode = _e[0], setPrefixNode = _e[1];
95
- var _f = (0, react_1.useState)(null), suffixNode = _f[0], setSuffixNode = _f[1];
93
+ var _d = (0, react_1.useState)(null), prefixNode = _d[0], setPrefixNode = _d[1];
94
+ var _e = (0, react_1.useState)(null), suffixNode = _e[0], setSuffixNode = _e[1];
96
95
  function isReactElement(node) {
97
96
  return react_1.default.isValidElement(node);
98
97
  }
98
+ // FIX: Clear icons when stringPrefix/stringSuffix are empty or undefined
99
99
  (0, react_1.useEffect)(function () {
100
- if (stringPrefix)
100
+ if (stringPrefix) {
101
101
  (0, getDynamicIcon_1.getDynamicIcon)(stringPrefix).then(function (node) { return setPrefixNode(node); });
102
- if (stringSuffix)
102
+ }
103
+ else {
104
+ setPrefixNode(null); // Clear when empty
105
+ }
106
+ }, [stringPrefix]);
107
+ (0, react_1.useEffect)(function () {
108
+ if (stringSuffix) {
103
109
  (0, getDynamicIcon_1.getDynamicIcon)(stringSuffix).then(function (node) { return setSuffixNode(node); });
104
- }, [stringPrefix, stringSuffix]);
110
+ }
111
+ else {
112
+ setSuffixNode(null); // Clear when empty
113
+ }
114
+ }, [stringSuffix]);
105
115
  var textColorClass = final.bg
106
116
  ? final.color
107
117
  ? final.color
@@ -111,6 +121,8 @@ function Button(_a) {
111
121
  ? 'white'
112
122
  : final.bg.replace(/[0-9]/g, '')
113
123
  : final.color;
124
+ // Determine background: status takes priority over bg prop
125
+ var effectiveBg = final.status ? final.status : final.bg;
114
126
  var classNames = [
115
127
  'button',
116
128
  "text-".concat(textColorClass),
@@ -128,8 +140,8 @@ function Button(_a) {
128
140
  final.bigger ? 'biggerBtn' : '',
129
141
  final.jumbo ? 'jumboBtn' : '',
130
142
  final.outlined
131
- ? "outlined outline-".concat(final.bg || '', " text-").concat(final.color ? final.color : (_b = final.bg) === null || _b === void 0 ? void 0 : _b.replace(/[0-9]/g, ''))
132
- : final.bg || '',
143
+ ? "outlined outline-".concat(effectiveBg || '', " text-").concat(final.color ? final.color : effectiveBg === null || effectiveBg === void 0 ? void 0 : effectiveBg.replace(/[0-9]/g, ''))
144
+ : effectiveBg || '',
133
145
  "".concat(final.fillAnimation ? "".concat(final.fillTextColor ? "hover-text-".concat(final.fillTextColor) : '', " button-fill fill-").concat(final.fillDirection || 'left') : ''),
134
146
  ].join(' ');
135
147
  var iconWrapperStyle = {
@@ -140,19 +152,18 @@ function Button(_a) {
140
152
  };
141
153
  return (react_1.default.createElement("span", null,
142
154
  react_1.default.createElement("button", __assign({ className: "".concat(classNames, " ").concat((startIcon || endIcon || prefix || suffix || prefixNode || suffixNode || final.status || final.isLoading) ? 'iconic' : ''), style: __assign({ height: mergedProps.height || '', width: mergedProps.fullWidth ? '100%' : mergedProps.width || '', borderRadius: final.flat ? '0rem' : '' }, style), onClick: onClick || (url ? function () { return (window.location.href = url); } : undefined) }, mergedProps),
143
- final.isLoading && (react_1.default.createElement("span", { className: "btn_left_icon rotate", style: iconWrapperStyle },
144
- react_1.default.createElement(pi_1.PiSpinner, { size: iconSize }))),
145
- final.status && (react_1.default.createElement("span", { className: "btn_left_icon", style: iconWrapperStyle },
155
+ final.isLoading ? (react_1.default.createElement("span", { className: "btn_left_icon rotate", style: iconWrapperStyle },
156
+ react_1.default.createElement(pi_1.PiSpinner, { size: iconSize }))) : (react_1.default.createElement(react_1.default.Fragment, null, final.status ? (react_1.default.createElement("span", { className: "btn_left_icon", style: iconWrapperStyle },
146
157
  final.status === 'success' && react_1.default.createElement(pi_1.PiCheck, { size: iconSize }),
147
158
  final.status === 'info' && react_1.default.createElement(pi_1.PiInfo, { size: iconSize }),
148
159
  final.status === 'warning' && react_1.default.createElement(pi_1.PiWarning, { size: iconSize }),
149
- final.status === 'danger' && react_1.default.createElement(pi_1.PiX, { size: iconSize }))),
150
- final.fillAnimation && react_1.default.createElement("span", { className: "button_fill_span ".concat(final.bg) }),
160
+ final.status === 'danger' && react_1.default.createElement(pi_1.PiX, { size: iconSize }))) : (
161
+ /* Otherwise show regular start icons */
151
162
  (prefix || startIcon || prefixNode) && (react_1.default.createElement("span", { className: "btn_left_icon", style: iconWrapperStyle }, isReactElement(startIcon) ? react_1.default.cloneElement(startIcon, { size: iconSize })
152
163
  : isReactElement(prefix) ? react_1.default.cloneElement(prefix, { size: iconSize })
153
164
  : isReactElement(prefixNode) ? react_1.default.cloneElement(prefixNode, { size: iconSize })
154
- : prefix || startIcon || prefixNode // fallback for string/number, rendered as-is
155
- )),
165
+ : prefix || startIcon || prefixNode))))),
166
+ final.fillAnimation && react_1.default.createElement("span", { className: "button_fill_span ".concat(effectiveBg) }),
156
167
  final.text ? final.text : children,
157
168
  (suffix || endIcon || suffixNode) && (react_1.default.createElement("span", { className: "btn_right_icon", style: iconWrapperStyle }, isReactElement(endIcon) ? react_1.default.cloneElement(endIcon, { size: iconSize })
158
169
  : isReactElement(suffix) ? react_1.default.cloneElement(suffix, { size: iconSize })
@@ -19,6 +19,8 @@ interface BaseInputProps {
19
19
  endIcon?: React.ReactNode;
20
20
  prefix?: React.ReactNode;
21
21
  suffix?: React.ReactNode;
22
+ stringPrefix?: string;
23
+ stringSuffix?: string;
22
24
  iconicBg?: string;
23
25
  variant?: string;
24
26
  label?: string;
package/ui/input/Input.js CHANGED
@@ -65,6 +65,7 @@ var pi_1 = require("react-icons/pi");
65
65
  var Button_1 = __importDefault(require("../button/Button"));
66
66
  var theme_1 = require("../theme/theme");
67
67
  var componentUtils_1 = require("../../utils/componentUtils");
68
+ var getDynamicIcon_1 = require("../../utils/getDynamicIcon");
68
69
  // Status icons mapping
69
70
  var statusIcons = {
70
71
  success: react_1.default.createElement(pi_1.PiCheckCircle, null),
@@ -83,10 +84,9 @@ var generateInputClasses = function (_a) {
83
84
  var borderClass = bordered ? 'borderedInput' : borderless ? 'borderless' : (!bordered && !borderless ? 'borderedInput' : '');
84
85
  return "\n ".concat(statusClass, "\n ").concat(roundedClass, "\n ").concat(bgClass, "\n ").concat(funcss || '', "\n ").concat(flatClass, "\n ").concat(cornerClass, "\n ").concat(borderClass, "\n ").concat(additionalClasses, "\n input\n ").trim().replace(/\s+/g, ' ');
85
86
  };
86
- // Iconic Input Wrapper Component - Updated to support both prefix/suffix and startIcon/endIcon
87
+ // Iconic Input Wrapper Component
87
88
  var IconicInputWrapper = function (_a) {
88
89
  var startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, iconicBg = _a.iconicBg, funcss = _a.funcss, children = _a.children;
89
- // Use prefix/suffix if provided, otherwise fall back to startIcon/endIcon
90
90
  var effectiveStartIcon = prefix !== undefined ? prefix : startIcon;
91
91
  var effectiveEndIcon = suffix !== undefined ? suffix : endIcon;
92
92
  if (!effectiveStartIcon && !effectiveEndIcon) {
@@ -114,15 +114,35 @@ var InputContainer = function (_a) {
114
114
  };
115
115
  // Text Input Component
116
116
  var TextInput = function (_a) {
117
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, _b = _a.fullWidth, fullWidth = _b === void 0 ? true : _b, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, iconicBg = _a.iconicBg, _c = _a.type, type = _c === void 0 ? 'text' : _c, label = _a.label, helperText = _a.helperText, _d = _a.variant, variant = _d === void 0 ? '' : _d, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "iconicBg", "type", "label", "helperText", "variant"]);
117
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, _b = _a.fullWidth, fullWidth = _b === void 0 ? true : _b, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, iconicBg = _a.iconicBg, _c = _a.type, type = _c === void 0 ? 'text' : _c, label = _a.label, helperText = _a.helperText, _d = _a.variant, variant = _d === void 0 ? '' : _d, placeholder = _a.placeholder, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "stringPrefix", "stringSuffix", "iconicBg", "type", "label", "helperText", "variant", "placeholder"]);
118
118
  var _e = (0, react_1.useState)(false), isFocused = _e[0], setIsFocused = _e[1];
119
119
  var _f = (0, react_1.useState)(value || defaultValue || ''), inputValue = _f[0], setInputValue = _f[1];
120
+ var _g = (0, react_1.useState)(null), prefixNode = _g[0], setPrefixNode = _g[1];
121
+ var _h = (0, react_1.useState)(null), suffixNode = _h[0], setSuffixNode = _h[1];
120
122
  var inputRef = (0, react_1.useRef)(null);
121
123
  (0, react_1.useEffect)(function () {
122
124
  if (value !== undefined) {
123
125
  setInputValue(value);
124
126
  }
125
127
  }, [value]);
128
+ // Handle stringPrefix
129
+ (0, react_1.useEffect)(function () {
130
+ if (stringPrefix) {
131
+ (0, getDynamicIcon_1.getDynamicIcon)(stringPrefix).then(function (node) { return setPrefixNode(node); });
132
+ }
133
+ else {
134
+ setPrefixNode(null);
135
+ }
136
+ }, [stringPrefix]);
137
+ // Handle stringSuffix
138
+ (0, react_1.useEffect)(function () {
139
+ if (stringSuffix) {
140
+ (0, getDynamicIcon_1.getDynamicIcon)(stringSuffix).then(function (node) { return setSuffixNode(node); });
141
+ }
142
+ else {
143
+ setSuffixNode(null);
144
+ }
145
+ }, [stringSuffix]);
126
146
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
127
147
  var mergedProps = mergeWithLocal({
128
148
  status: status,
@@ -169,23 +189,47 @@ var TextInput = function (_a) {
169
189
  if (rest.onBlur)
170
190
  rest.onBlur(e);
171
191
  };
172
- var inputElement = (react_1.default.createElement("input", __assign({ ref: inputRef, id: id, name: name, className: className, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, defaultValue: defaultValue, type: type, placeholder: !label ? rest.placeholder : '', style: style, value: value }, rest)));
173
- var wrappedInput = (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, prefix: mergedProps.prefix, suffix: mergedProps.suffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, inputElement));
174
- return (react_1.default.createElement(InputContainer, { startIcon: startIcon, prefix: prefix, label: label, status: mergedProps.status, helperText: helperText, isFocused: isFocused, hasValue: !!inputValue, fullWidth: mergedProps.fullWidth, id: id }, wrappedInput));
192
+ // Determine effective icons: stringPrefix/stringSuffix take priority
193
+ var effectivePrefix = prefixNode || mergedProps.prefix || mergedProps.startIcon;
194
+ var effectiveSuffix = suffixNode || mergedProps.suffix || mergedProps.endIcon;
195
+ // Show placeholder only when label is active (focused or has value)
196
+ var showPlaceholder = placeholder && label && (isFocused || !!inputValue);
197
+ var inputElement = (react_1.default.createElement("input", __assign({ ref: inputRef, id: id, name: name, className: className, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, defaultValue: defaultValue, type: type, placeholder: showPlaceholder ? placeholder : (!label ? placeholder : ''), style: style, value: value }, rest)));
198
+ var wrappedInput = (react_1.default.createElement(IconicInputWrapper, { startIcon: effectivePrefix, endIcon: effectiveSuffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, inputElement));
199
+ return (react_1.default.createElement(InputContainer, { startIcon: effectivePrefix, label: label, status: mergedProps.status, helperText: helperText, isFocused: isFocused, hasValue: !!inputValue, fullWidth: mergedProps.fullWidth, id: id }, wrappedInput));
175
200
  };
176
201
  exports.TextInput = TextInput;
177
202
  // Select Component
178
203
  var SelectInput = function (_a) {
179
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, iconicBg = _a.iconicBg, _b = _a.options, options = _b === void 0 ? [] : _b, label = _a.label, helperText = _a.helperText, _c = _a.variant, variant = _c === void 0 ? '' : _c, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "iconicBg", "options", "label", "helperText", "variant"]);
204
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, iconicBg = _a.iconicBg, _b = _a.options, options = _b === void 0 ? [] : _b, label = _a.label, helperText = _a.helperText, _c = _a.variant, variant = _c === void 0 ? '' : _c, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "stringPrefix", "stringSuffix", "iconicBg", "options", "label", "helperText", "variant"]);
180
205
  var _d = (0, react_1.useState)(false), isFocused = _d[0], setIsFocused = _d[1];
181
206
  var _e = (0, react_1.useState)(value || defaultValue || ''), selectValue = _e[0], setSelectValue = _e[1];
207
+ var _f = (0, react_1.useState)(null), prefixNode = _f[0], setPrefixNode = _f[1];
208
+ var _g = (0, react_1.useState)(null), suffixNode = _g[0], setSuffixNode = _g[1];
182
209
  (0, react_1.useEffect)(function () {
183
210
  if (value !== undefined) {
184
211
  setSelectValue(value);
185
212
  }
186
213
  }, [value]);
187
- // For select inputs, label should always be active when there's a label
188
- var selectHasValue = true; // Always true for select to keep label at top
214
+ // Handle stringPrefix
215
+ (0, react_1.useEffect)(function () {
216
+ if (stringPrefix) {
217
+ (0, getDynamicIcon_1.getDynamicIcon)(stringPrefix).then(function (node) { return setPrefixNode(node); });
218
+ }
219
+ else {
220
+ setPrefixNode(null);
221
+ }
222
+ }, [stringPrefix]);
223
+ // Handle stringSuffix
224
+ (0, react_1.useEffect)(function () {
225
+ if (stringSuffix) {
226
+ (0, getDynamicIcon_1.getDynamicIcon)(stringSuffix).then(function (node) { return setSuffixNode(node); });
227
+ }
228
+ else {
229
+ setSuffixNode(null);
230
+ }
231
+ }, [stringSuffix]);
232
+ var selectHasValue = true;
189
233
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
190
234
  var mergedProps = mergeWithLocal({
191
235
  status: status,
@@ -232,21 +276,43 @@ var SelectInput = function (_a) {
232
276
  if (rest.onBlur)
233
277
  rest.onBlur(e);
234
278
  };
279
+ var effectivePrefix = prefixNode || mergedProps.prefix || mergedProps.startIcon;
280
+ var effectiveSuffix = suffixNode || mergedProps.suffix || mergedProps.endIcon;
235
281
  var selectElement = (react_1.default.createElement("select", __assign({ id: id, name: name, className: className, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, defaultValue: defaultValue, value: value, style: style }, rest), options.map(function (option) { return (react_1.default.createElement("option", { key: option.value, value: option.value }, option.text)); })));
236
- var wrappedSelect = (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, prefix: mergedProps.prefix, suffix: mergedProps.suffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, selectElement));
237
- return (react_1.default.createElement(InputContainer, { startIcon: startIcon, prefix: prefix, label: label, status: mergedProps.status, helperText: helperText, isFocused: isFocused, hasValue: selectHasValue, fullWidth: mergedProps.fullWidth, id: id }, wrappedSelect));
282
+ var wrappedSelect = (react_1.default.createElement(IconicInputWrapper, { startIcon: effectivePrefix, endIcon: effectiveSuffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, selectElement));
283
+ return (react_1.default.createElement(InputContainer, { startIcon: effectivePrefix, label: label, status: mergedProps.status, helperText: helperText, isFocused: isFocused, hasValue: selectHasValue, fullWidth: mergedProps.fullWidth, id: id }, wrappedSelect));
238
284
  };
239
285
  exports.SelectInput = SelectInput;
240
286
  // Textarea Component
241
287
  var TextareaInput = function (_a) {
242
- var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, iconicBg = _a.iconicBg, label = _a.label, helperText = _a.helperText, _b = _a.rows, rows = _b === void 0 ? 2 : _b, _c = _a.variant, variant = _c === void 0 ? '' : _c, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "iconicBg", "label", "helperText", "rows", "variant"]);
288
+ var id = _a.id, name = _a.name, value = _a.value, defaultValue = _a.defaultValue, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, bordered = _a.bordered, borderless = _a.borderless, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, iconicBg = _a.iconicBg, label = _a.label, helperText = _a.helperText, _b = _a.rows, rows = _b === void 0 ? 2 : _b, _c = _a.variant, variant = _c === void 0 ? '' : _c, placeholder = _a.placeholder, rest = __rest(_a, ["id", "name", "value", "defaultValue", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "bordered", "borderless", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "stringPrefix", "stringSuffix", "iconicBg", "label", "helperText", "rows", "variant", "placeholder"]);
243
289
  var _d = (0, react_1.useState)(false), isFocused = _d[0], setIsFocused = _d[1];
244
290
  var _e = (0, react_1.useState)(value || defaultValue || ''), textValue = _e[0], setTextValue = _e[1];
291
+ var _f = (0, react_1.useState)(null), prefixNode = _f[0], setPrefixNode = _f[1];
292
+ var _g = (0, react_1.useState)(null), suffixNode = _g[0], setSuffixNode = _g[1];
245
293
  (0, react_1.useEffect)(function () {
246
294
  if (value !== undefined) {
247
295
  setTextValue(value);
248
296
  }
249
297
  }, [value]);
298
+ // Handle stringPrefix
299
+ (0, react_1.useEffect)(function () {
300
+ if (stringPrefix) {
301
+ (0, getDynamicIcon_1.getDynamicIcon)(stringPrefix).then(function (node) { return setPrefixNode(node); });
302
+ }
303
+ else {
304
+ setPrefixNode(null);
305
+ }
306
+ }, [stringPrefix]);
307
+ // Handle stringSuffix
308
+ (0, react_1.useEffect)(function () {
309
+ if (stringSuffix) {
310
+ (0, getDynamicIcon_1.getDynamicIcon)(stringSuffix).then(function (node) { return setSuffixNode(node); });
311
+ }
312
+ else {
313
+ setSuffixNode(null);
314
+ }
315
+ }, [stringSuffix]);
250
316
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
251
317
  var mergedProps = mergeWithLocal({
252
318
  status: status,
@@ -293,15 +359,39 @@ var TextareaInput = function (_a) {
293
359
  if (rest.onBlur)
294
360
  rest.onBlur(e);
295
361
  };
296
- var textareaElement = (react_1.default.createElement("textarea", __assign({ id: id, name: name, className: className, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, defaultValue: defaultValue, placeholder: !label ? rest.placeholder : '', style: style, value: value, rows: rows }, rest)));
297
- var wrappedTextarea = (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, prefix: mergedProps.prefix, suffix: mergedProps.suffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, textareaElement));
298
- return (react_1.default.createElement(InputContainer, { startIcon: startIcon, prefix: prefix, label: label, status: mergedProps.status, helperText: helperText, isFocused: isFocused, hasValue: !!textValue, fullWidth: mergedProps.fullWidth, id: id }, wrappedTextarea));
362
+ var effectivePrefix = prefixNode || mergedProps.prefix || mergedProps.startIcon;
363
+ var effectiveSuffix = suffixNode || mergedProps.suffix || mergedProps.endIcon;
364
+ // Show placeholder only when label is active (focused or has value)
365
+ var showPlaceholder = placeholder && label && (isFocused || !!textValue);
366
+ var textareaElement = (react_1.default.createElement("textarea", __assign({ id: id, name: name, className: className, onChange: handleChange, onFocus: handleFocus, onBlur: handleBlur, defaultValue: defaultValue, placeholder: showPlaceholder ? placeholder : (!label ? placeholder : ''), style: style, value: value, rows: rows }, rest)));
367
+ var wrappedTextarea = (react_1.default.createElement(IconicInputWrapper, { startIcon: effectivePrefix, endIcon: effectiveSuffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, textareaElement));
368
+ return (react_1.default.createElement(InputContainer, { startIcon: effectivePrefix, label: label, status: mergedProps.status, helperText: helperText, isFocused: isFocused, hasValue: !!textValue, fullWidth: mergedProps.fullWidth, id: id }, wrappedTextarea));
299
369
  };
300
370
  exports.TextareaInput = TextareaInput;
301
371
  // File Input Component
302
372
  var FileInput = function (_a) {
303
- var _b = _a.id, id = _b === void 0 ? 'fileInput' : _b, name = _a.name, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, iconicBg = _a.iconicBg, _c = _a.label, label = _c === void 0 ? 'Upload File' : _c, helperText = _a.helperText, icon = _a.icon, extra = _a.extra, button = _a.button, btn = _a.btn, value = _a.value, _d = _a.variant, variant = _d === void 0 ? '' : _d, rest = __rest(_a, ["id", "name", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "iconicBg", "label", "helperText", "icon", "extra", "button", "btn", "value", "variant"]);
373
+ var _b = _a.id, id = _b === void 0 ? 'fileInput' : _b, name = _a.name, onChange = _a.onChange, status = _a.status, funcss = _a.funcss, bg = _a.bg, fullWidth = _a.fullWidth, flat = _a.flat, rounded = _a.rounded, leftRounded = _a.leftRounded, rightRounded = _a.rightRounded, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, iconicBg = _a.iconicBg, _c = _a.label, label = _c === void 0 ? 'Upload File' : _c, helperText = _a.helperText, icon = _a.icon, extra = _a.extra, button = _a.button, btn = _a.btn, value = _a.value, _d = _a.variant, variant = _d === void 0 ? '' : _d, rest = __rest(_a, ["id", "name", "onChange", "status", "funcss", "bg", "fullWidth", "flat", "rounded", "leftRounded", "rightRounded", "startIcon", "endIcon", "prefix", "suffix", "stringPrefix", "stringSuffix", "iconicBg", "label", "helperText", "icon", "extra", "button", "btn", "value", "variant"]);
304
374
  var _e = (0, react_1.useState)(''), fileName = _e[0], setFileName = _e[1];
375
+ var _f = (0, react_1.useState)(null), prefixNode = _f[0], setPrefixNode = _f[1];
376
+ var _g = (0, react_1.useState)(null), suffixNode = _g[0], setSuffixNode = _g[1];
377
+ // Handle stringPrefix
378
+ (0, react_1.useEffect)(function () {
379
+ if (stringPrefix) {
380
+ (0, getDynamicIcon_1.getDynamicIcon)(stringPrefix).then(function (node) { return setPrefixNode(node); });
381
+ }
382
+ else {
383
+ setPrefixNode(null);
384
+ }
385
+ }, [stringPrefix]);
386
+ // Handle stringSuffix
387
+ (0, react_1.useEffect)(function () {
388
+ if (stringSuffix) {
389
+ (0, getDynamicIcon_1.getDynamicIcon)(stringSuffix).then(function (node) { return setSuffixNode(node); });
390
+ }
391
+ else {
392
+ setSuffixNode(null);
393
+ }
394
+ }, [stringSuffix]);
305
395
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
306
396
  var mergedProps = mergeWithLocal({
307
397
  status: status,
@@ -330,6 +420,8 @@ var FileInput = function (_a) {
330
420
  if (onChange)
331
421
  onChange(e);
332
422
  };
423
+ var effectivePrefix = prefixNode || mergedProps.prefix || mergedProps.startIcon;
424
+ var effectiveSuffix = suffixNode || mergedProps.suffix || mergedProps.endIcon;
333
425
  if (btn) {
334
426
  var className = generateInputClasses({
335
427
  status: mergedProps.status,
@@ -347,8 +439,8 @@ var FileInput = function (_a) {
347
439
  var fileInputElement = (react_1.default.createElement("div", { className: "fileInput" },
348
440
  button || (react_1.default.createElement(Button_1.default, { funcss: mergedProps.funcss, startIcon: icon || react_1.default.createElement(pi_1.PiCloudArrowUp, null), bg: "primary", fullWidth: true, raised: true }, fileName || label)),
349
441
  react_1.default.createElement("input", __assign({ id: id, name: name, className: className, onChange: handleChange, type: "file", style: style, value: value }, rest))));
350
- var wrappedFileInput = (react_1.default.createElement(IconicInputWrapper, { startIcon: mergedProps.startIcon, endIcon: mergedProps.endIcon, prefix: mergedProps.prefix, suffix: mergedProps.suffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, fileInputElement));
351
- return (react_1.default.createElement(InputContainer, { startIcon: startIcon, prefix: prefix, label: undefined, status: mergedProps.status, helperText: helperText, isFocused: false, hasValue: !!fileName, fullWidth: mergedProps.fullWidth, id: id }, wrappedFileInput));
442
+ var wrappedFileInput = (react_1.default.createElement(IconicInputWrapper, { startIcon: effectivePrefix, endIcon: effectiveSuffix, iconicBg: mergedProps.iconicBg, funcss: mergedProps.funcss }, fileInputElement));
443
+ return (react_1.default.createElement(InputContainer, { startIcon: effectivePrefix, label: undefined, status: mergedProps.status, helperText: helperText, isFocused: false, hasValue: !!fileName, fullWidth: mergedProps.fullWidth, id: id }, wrappedFileInput));
352
444
  }
353
445
  var uploadElement = (react_1.default.createElement("div", { className: "_upload_container" },
354
446
  react_1.default.createElement("label", { htmlFor: id, className: "_upload_label" },
@@ -362,14 +454,14 @@ var FileInput = function (_a) {
362
454
  } }, fileName || label),
363
455
  extra && react_1.default.createElement("div", { className: "text-small opacity-3" }, extra)),
364
456
  react_1.default.createElement("input", __assign({ onChange: handleChange, type: "file", id: id, className: "_upload_input" }, rest))));
365
- return (react_1.default.createElement(InputContainer, { startIcon: startIcon, prefix: prefix, label: undefined, status: mergedProps.status, helperText: helperText, isFocused: false, hasValue: !!fileName, fullWidth: mergedProps.fullWidth, id: id }, uploadElement));
457
+ return (react_1.default.createElement(InputContainer, { startIcon: effectivePrefix, label: undefined, status: mergedProps.status, helperText: helperText, isFocused: false, hasValue: !!fileName, fullWidth: mergedProps.fullWidth, id: id }, uploadElement));
366
458
  };
367
459
  exports.FileInput = FileInput;
368
460
  var Input = function (_a) {
369
- var select = _a.select, multiline = _a.multiline, file = _a.file, noBorder = _a.noBorder, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, iconicBg = _a.iconicBg, _b = _a.variant, variant = _b === void 0 ? '' : _b, props = __rest(_a, ["select", "multiline", "file", "noBorder", "startIcon", "endIcon", "prefix", "suffix", "iconicBg", "variant"]);
461
+ var select = _a.select, multiline = _a.multiline, file = _a.file, noBorder = _a.noBorder, startIcon = _a.startIcon, endIcon = _a.endIcon, prefix = _a.prefix, suffix = _a.suffix, stringPrefix = _a.stringPrefix, stringSuffix = _a.stringSuffix, iconicBg = _a.iconicBg, _b = _a.variant, variant = _b === void 0 ? '' : _b, props = __rest(_a, ["select", "multiline", "file", "noBorder", "startIcon", "endIcon", "prefix", "suffix", "stringPrefix", "stringSuffix", "iconicBg", "variant"]);
370
462
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Input', variant).mergeWithLocal;
371
463
  var mergedProps = mergeWithLocal(__assign(__assign({}, props), { startIcon: startIcon, endIcon: endIcon, prefix: prefix, suffix: suffix, iconicBg: iconicBg })).props;
372
- var inputProps = __assign(__assign(__assign({}, props), mergedProps), { variant: variant, borderless: noBorder !== undefined ? noBorder : (props.borderless !== undefined ? props.borderless : mergedProps.borderless) });
464
+ var inputProps = __assign(__assign(__assign({}, props), mergedProps), { variant: variant, stringPrefix: stringPrefix, stringSuffix: stringSuffix, borderless: noBorder !== undefined ? noBorder : (props.borderless !== undefined ? props.borderless : mergedProps.borderless) });
373
465
  if (select) {
374
466
  return react_1.default.createElement(exports.SelectInput, __assign({}, inputProps));
375
467
  }
package/ui/theme/theme.js CHANGED
@@ -74,11 +74,6 @@ exports.useGlobalConfig = exports.useColors = exports.useComponentConfig = expor
74
74
  var react_1 = __importStar(require("react"));
75
75
  var themes_1 = require("./themes");
76
76
  var darkenUtils_1 = require("./darkenUtils");
77
- var firestore_1 = require("firebase/firestore");
78
- var db;
79
- if (typeof window !== 'undefined') {
80
- db = require('../../utils/Firebase').default;
81
- }
82
77
  var ThemeContext = (0, react_1.createContext)({
83
78
  variant: 'standard',
84
79
  setVariant: function () { },
@@ -96,7 +91,6 @@ var useTheme = function () {
96
91
  return context;
97
92
  };
98
93
  exports.useTheme = useTheme;
99
- // Backward compatibility
100
94
  var useVariant = function () {
101
95
  var _a = (0, exports.useTheme)(), variant = _a.variant, setVariant = _a.setVariant;
102
96
  return { variant: variant, setVariant: setVariant };
@@ -107,6 +101,7 @@ exports.useVariant = useVariant;
107
101
  /* -------------------------------------------------------------------------- */
108
102
  var CACHE_KEY = 'funui_theme_cache';
109
103
  var CACHE_EXPIRY = 1000 * 60 * 60; // 1 hour
104
+ var POLL_INTERVAL = 5 * 60 * 1000; // Check for updates every 5 minutes
110
105
  var getThemeFromCache = function (projectId) {
111
106
  if (typeof window === 'undefined')
112
107
  return null;
@@ -135,6 +130,7 @@ var saveThemeToCache = function (projectId, data) {
135
130
  projectId: projectId,
136
131
  data: data,
137
132
  timestamp: Date.now(),
133
+ version: data.version || Date.now(),
138
134
  };
139
135
  localStorage.setItem("".concat(CACHE_KEY, "_").concat(projectId), JSON.stringify(cache));
140
136
  }
@@ -143,49 +139,56 @@ var saveThemeToCache = function (projectId, data) {
143
139
  }
144
140
  };
145
141
  /* -------------------------------------------------------------------------- */
146
- /* SINGLETON LISTENER */
142
+ /* CDN THEME LOADER (NO TOKEN!) */
147
143
  /* -------------------------------------------------------------------------- */
148
- var activeListener = null;
149
- var currentProjectId = null;
150
- var listenerSubscribers = new Set();
151
- var subscribeToTheme = function (projectId, callback) {
152
- listenerSubscribers.add(callback);
153
- // If listener already exists for this project, just subscribe
154
- if (currentProjectId === projectId && activeListener) {
155
- return function () {
156
- listenerSubscribers.delete(callback);
157
- };
158
- }
159
- // Clean up old listener if project changed
160
- if (activeListener && currentProjectId !== projectId) {
161
- activeListener();
162
- activeListener = null;
163
- currentProjectId = null;
164
- }
165
- // Create new listener
166
- var docRef = (0, firestore_1.doc)(db, 'Projects', projectId);
167
- currentProjectId = projectId;
168
- var unsubscribe = (0, firestore_1.onSnapshot)(docRef, function (snapshot) {
169
- var data = snapshot.data();
170
- if (!data)
171
- return;
172
- // Save to cache
173
- saveThemeToCache(projectId, data);
174
- // Notify all subscribers
175
- listenerSubscribers.forEach(function (cb) { return cb(data); });
176
- }, function (error) {
177
- console.error('Theme listener error:', error);
178
- });
179
- activeListener = unsubscribe;
180
- return function () {
181
- listenerSubscribers.delete(callback);
182
- if (listenerSubscribers.size === 0 && activeListener) {
183
- activeListener();
184
- activeListener = null;
185
- currentProjectId = null;
144
+ var loadThemeFromCDN = function (projectId) { return __awaiter(void 0, void 0, void 0, function () {
145
+ var publicResponse, data, error_1, publicUrl, response, data, error_2;
146
+ return __generator(this, function (_a) {
147
+ switch (_a.label) {
148
+ case 0:
149
+ _a.trys.push([0, 4, , 5]);
150
+ return [4 /*yield*/, fetch("/funui.json", {
151
+ cache: 'no-cache',
152
+ })];
153
+ case 1:
154
+ publicResponse = _a.sent();
155
+ if (!publicResponse.ok) return [3 /*break*/, 3];
156
+ return [4 /*yield*/, publicResponse.json()];
157
+ case 2:
158
+ data = _a.sent();
159
+ console.log('✅ Loaded theme from public folder');
160
+ return [2 /*return*/, data];
161
+ case 3: return [3 /*break*/, 5];
162
+ case 4:
163
+ error_1 = _a.sent();
164
+ console.log('No theme in public folder, checking Firebase Storage...');
165
+ return [3 /*break*/, 5];
166
+ case 5:
167
+ _a.trys.push([5, 10, , 11]);
168
+ publicUrl = "https://firebasestorage.googleapis.com/v0/b/funui-4bcd1.firebasestorage.app/o/themes%2F".concat(projectId, ".json?alt=media");
169
+ return [4 /*yield*/, fetch(publicUrl, {
170
+ cache: 'no-cache',
171
+ })];
172
+ case 6:
173
+ response = _a.sent();
174
+ if (!response.ok) return [3 /*break*/, 8];
175
+ return [4 /*yield*/, response.json()];
176
+ case 7:
177
+ data = _a.sent();
178
+ console.log('✅ Loaded theme from Firebase Storage (public CDN)');
179
+ return [2 /*return*/, data];
180
+ case 8:
181
+ console.error('Firebase Storage fetch failed:', response.status, response.statusText);
182
+ _a.label = 9;
183
+ case 9: return [3 /*break*/, 11];
184
+ case 10:
185
+ error_2 = _a.sent();
186
+ console.error('Error loading from Firebase Storage:', error_2);
187
+ return [3 /*break*/, 11];
188
+ case 11: return [2 /*return*/, null];
186
189
  }
187
- };
188
- };
190
+ });
191
+ }); };
189
192
  /* -------------------------------------------------------------------------- */
190
193
  /* COMPONENT */
191
194
  /* -------------------------------------------------------------------------- */
@@ -197,6 +200,7 @@ var ThemeProvider = function (_a) {
197
200
  var _g = (0, react_1.useState)(true), isLoading = _g[0], setIsLoading = _g[1];
198
201
  var _h = (0, react_1.useState)(true), isInitialLoad = _h[0], setIsInitialLoad = _h[1];
199
202
  var _j = (0, react_1.useState)(null), error = _j[0], setError = _j[1];
203
+ var _k = (0, react_1.useState)(null), currentVersion = _k[0], setCurrentVersion = _k[1];
200
204
  /* -------------------------- Apply base theme --------------------------- */
201
205
  (0, react_1.useEffect)(function () {
202
206
  var root = document.documentElement;
@@ -218,7 +222,7 @@ var ThemeProvider = function (_a) {
218
222
  });
219
223
  }
220
224
  }, [theme]);
221
- /* ---------------------- Firebase Theme Sync ----------------------- */
225
+ /* ---------------------- CDN Theme Sync (No Token!) ----------------------- */
222
226
  (0, react_1.useEffect)(function () {
223
227
  if (typeof window === 'undefined' || !projectId) {
224
228
  setIsLoading(false);
@@ -226,34 +230,51 @@ var ThemeProvider = function (_a) {
226
230
  return;
227
231
  }
228
232
  var root = document.documentElement;
229
- // Step 1: Try to load from cache immediately
233
+ var pollTimer;
234
+ // Step 1: Load from cache immediately
230
235
  var cachedTheme = getThemeFromCache(projectId);
231
236
  if (cachedTheme) {
232
237
  applyThemeData(cachedTheme, root);
238
+ setCurrentVersion(cachedTheme.version || null);
233
239
  setIsLoading(false);
234
- // Still initialLoad true, but we have cached data to show
240
+ console.log('✅ Using cached theme');
235
241
  }
236
- // Step 2: Fetch fresh data (doesn't block render if we have cache)
237
- var fetchInitialData = function () { return __awaiter(void 0, void 0, void 0, function () {
238
- var docRef, snapshot, data, err_1;
242
+ // Step 2: Fetch from CDN
243
+ var fetchFromCDN = function () { return __awaiter(void 0, void 0, void 0, function () {
244
+ var cdnTheme, newVersion, err_1;
239
245
  return __generator(this, function (_a) {
240
246
  switch (_a.label) {
241
247
  case 0:
242
248
  _a.trys.push([0, 2, 3, 4]);
243
- docRef = (0, firestore_1.doc)(db, 'Projects', projectId);
244
- return [4 /*yield*/, (0, firestore_1.getDoc)(docRef)];
249
+ return [4 /*yield*/, loadThemeFromCDN(projectId)];
245
250
  case 1:
246
- snapshot = _a.sent();
247
- if (snapshot.exists()) {
248
- data = snapshot.data();
249
- applyThemeData(data, root);
250
- saveThemeToCache(projectId, data);
251
+ cdnTheme = _a.sent();
252
+ if (cdnTheme) {
253
+ newVersion = cdnTheme.version || Date.now();
254
+ if (!currentVersion || newVersion !== currentVersion) {
255
+ applyThemeData(cdnTheme, root);
256
+ saveThemeToCache(projectId, cdnTheme);
257
+ setCurrentVersion(newVersion);
258
+ console.log('✅ Theme updated from CDN');
259
+ }
260
+ else {
261
+ console.log('✓ Theme unchanged');
262
+ }
263
+ setError(null);
264
+ }
265
+ else {
266
+ console.warn('⚠️ No theme found in CDN');
267
+ if (!cachedTheme) {
268
+ setError('Theme not found');
269
+ }
251
270
  }
252
271
  return [3 /*break*/, 4];
253
272
  case 2:
254
273
  err_1 = _a.sent();
255
- console.error('Error fetching initial theme:', err_1);
256
- setError('Failed to load theme');
274
+ console.error('Error loading theme from CDN:', err_1);
275
+ if (!cachedTheme) {
276
+ setError('Failed to load theme');
277
+ }
257
278
  return [3 /*break*/, 4];
258
279
  case 3:
259
280
  setIsLoading(false);
@@ -263,21 +284,21 @@ var ThemeProvider = function (_a) {
263
284
  }
264
285
  });
265
286
  }); };
266
- // Only fetch if no cache
267
287
  if (!cachedTheme) {
268
- fetchInitialData();
288
+ fetchFromCDN();
269
289
  }
270
290
  else {
271
- // We have cache, mark as loaded after short delay
272
291
  setTimeout(function () { return setIsInitialLoad(false); }, 100);
292
+ fetchFromCDN();
273
293
  }
274
- // Step 3: Subscribe to real-time updates
275
- var unsubscribe = subscribeToTheme(projectId, function (data) {
276
- applyThemeData(data, root);
277
- });
278
- return unsubscribe;
279
- }, [projectId]);
280
- /* Helper function to apply theme data */
294
+ // Step 3: Poll for updates every 5 minutes
295
+ pollTimer = setInterval(function () {
296
+ fetchFromCDN();
297
+ }, POLL_INTERVAL);
298
+ return function () {
299
+ clearInterval(pollTimer);
300
+ };
301
+ }, [projectId, currentVersion]);
281
302
  var applyThemeData = function (data, root) {
282
303
  var _a;
283
304
  var config = (_a = data.theme_config) !== null && _a !== void 0 ? _a : {};
@@ -285,13 +306,11 @@ var ThemeProvider = function (_a) {
285
306
  setVariant(newVariant);
286
307
  setThemeConfig(config);
287
308
  setProjectData(data);
288
- // Apply CSS variables
289
309
  Object.entries(config).forEach(function (_a) {
290
310
  var key = _a[0], value = _a[1];
291
311
  root.style.setProperty(key.startsWith('--') ? key : "--".concat(key), String(value));
292
312
  });
293
313
  };
294
- /* Memoize context value to prevent unnecessary re-renders */
295
314
  var contextValue = (0, react_1.useMemo)(function () { return ({
296
315
  variant: variant,
297
316
  setVariant: setVariant,
@@ -301,40 +320,32 @@ var ThemeProvider = function (_a) {
301
320
  isInitialLoad: isInitialLoad,
302
321
  error: error,
303
322
  }); }, [variant, themeConfig, projectData, isLoading, isInitialLoad, error]);
304
- /* ------------------------------- Render ------------------------------- */
305
323
  return (react_1.default.createElement(ThemeContext.Provider, { value: contextValue },
306
324
  react_1.default.createElement("div", { className: "theme-".concat(theme, " ").concat(funcss), style: {
307
325
  backgroundColor: 'var(--page-bg)',
308
326
  color: 'var(--text-color)',
309
327
  minHeight: minHeight,
310
- // Smooth transition when theme changes
311
328
  transition: isInitialLoad ? 'none' : 'background-color 0.3s ease, color 0.3s ease',
312
329
  } }, children)));
313
330
  };
314
331
  exports.default = ThemeProvider;
315
- /* -------------------------------------------------------------------------- */
316
- /* HELPER HOOKS */
317
- /* -------------------------------------------------------------------------- */
318
- // Hook to get specific theme values
332
+ // Helper hooks
319
333
  var useThemeValue = function (key) {
320
334
  var themeConfig = (0, exports.useTheme)().themeConfig;
321
335
  return themeConfig[key];
322
336
  };
323
337
  exports.useThemeValue = useThemeValue;
324
- // Hook to get component-specific config
325
338
  var useComponentConfig = function (componentName) {
326
339
  var _a;
327
340
  var projectData = (0, exports.useTheme)().projectData;
328
341
  return ((_a = projectData === null || projectData === void 0 ? void 0 : projectData.components) === null || _a === void 0 ? void 0 : _a[componentName]) || {};
329
342
  };
330
343
  exports.useComponentConfig = useComponentConfig;
331
- // Hook to get colors
332
344
  var useColors = function () {
333
345
  var projectData = (0, exports.useTheme)().projectData;
334
346
  return (projectData === null || projectData === void 0 ? void 0 : projectData.colors) || {};
335
347
  };
336
348
  exports.useColors = useColors;
337
- // Hook to get global config
338
349
  var useGlobalConfig = function () {
339
350
  var projectData = (0, exports.useTheme)().projectData;
340
351
  return (projectData === null || projectData === void 0 ? void 0 : projectData.global) || {};