frontend-hamroun 1.2.75 → 1.2.77
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/dist/batch/package.json +16 -0
- package/dist/client-router/package.json +16 -0
- package/dist/component/package.json +16 -0
- package/dist/context/package.json +16 -0
- package/dist/event-bus/package.json +16 -0
- package/dist/forms/package.json +16 -0
- package/dist/hooks/package.json +16 -0
- package/dist/jsx-runtime/package.json +16 -0
- package/dist/lifecycle-events/package.json +16 -0
- package/dist/package.json +71 -0
- package/dist/render-component/package.json +16 -0
- package/dist/renderer/package.json +16 -0
- package/dist/router/package.json +16 -0
- package/dist/server/package.json +17 -0
- package/dist/server/src/client-router.d.ts +60 -0
- package/dist/server/src/client-router.js +210 -0
- package/dist/server/src/client-router.js.map +1 -0
- package/dist/server/src/component.js +1 -1
- package/dist/server/src/event-bus.d.ts +23 -0
- package/dist/server/src/event-bus.js +75 -0
- package/dist/server/src/event-bus.js.map +1 -0
- package/dist/server/src/forms.d.ts +40 -0
- package/dist/server/src/forms.js +148 -0
- package/dist/server/src/forms.js.map +1 -0
- package/dist/server/src/hooks.js +2 -2
- package/dist/server/src/index.js +19 -11
- package/dist/server/src/lifecycle-events.d.ts +108 -0
- package/dist/server/src/lifecycle-events.js +177 -0
- package/dist/server/src/lifecycle-events.js.map +1 -0
- package/dist/server/src/renderComponent.js +1 -1
- package/dist/server/src/renderer.js +3 -3
- package/dist/server/src/router.d.ts +55 -0
- package/dist/server/src/router.js +166 -0
- package/dist/server/src/router.js.map +1 -0
- package/dist/server/src/server/index.d.ts +75 -2
- package/dist/server/src/server/index.js +224 -8
- package/dist/server/src/server/index.js.map +1 -1
- package/dist/server/src/server/server.js +1 -1
- package/dist/server/src/server/templates.d.ts +28 -0
- package/dist/server/src/server/templates.js +204 -0
- package/dist/server/src/server/templates.js.map +1 -0
- package/dist/server/src/server/utils.d.ts +70 -0
- package/dist/server/src/server/utils.js +156 -0
- package/dist/server/src/server/utils.js.map +1 -0
- package/dist/server/src/server-renderer.js +1 -1
- package/dist/server/src/store.d.ts +41 -0
- package/dist/server/src/store.js +99 -0
- package/dist/server/src/store.js.map +1 -0
- package/dist/server/src/utils.d.ts +46 -0
- package/dist/server/src/utils.js +144 -0
- package/dist/server/src/utils.js.map +1 -0
- package/dist/server/tsconfig.server.tsbuildinfo +1 -1
- package/dist/server-renderer/package.json +16 -0
- package/dist/store/package.json +16 -0
- package/dist/types/package.json +16 -0
- package/dist/utils/package.json +16 -0
- package/dist/vdom/package.json +16 -0
- package/dist/wasm/package.json +16 -0
- package/package.json +14 -13
- package/templates/complete-app/build.js +284 -0
- package/templates/complete-app/package.json +40 -0
- package/templates/complete-app/public/styles.css +345 -0
- package/templates/complete-app/src/api/index.js +31 -0
- package/templates/complete-app/src/client.js +93 -0
- package/templates/complete-app/src/components/App.js +66 -0
- package/templates/complete-app/src/components/Footer.js +19 -0
- package/templates/complete-app/src/components/Header.js +38 -0
- package/templates/complete-app/src/pages/About.js +59 -0
- package/templates/complete-app/src/pages/Home.js +54 -0
- package/templates/complete-app/src/pages/WasmDemo.js +136 -0
- package/templates/complete-app/src/server.js +186 -0
- package/templates/complete-app/src/wasm/build.bat +16 -0
- package/templates/complete-app/src/wasm/build.sh +16 -0
- package/templates/complete-app/src/wasm/example.go +101 -0
- package/templates/fullstack-app/build/main.css +225 -15
- package/templates/fullstack-app/build/main.css.map +2 -2
- package/templates/fullstack-app/build/main.js +657 -372
- package/templates/fullstack-app/build/main.js.map +4 -4
- package/templates/fullstack-app/build.ts +3 -4
- package/templates/fullstack-app/public/styles.css +222 -15
- package/templates/fullstack-app/server.ts +46 -12
- package/templates/fullstack-app/src/components/ClientHome.tsx +0 -0
- package/templates/fullstack-app/src/components/ErrorBoundary.tsx +36 -0
- package/templates/fullstack-app/src/components/Layout.tsx +23 -26
- package/templates/fullstack-app/src/components/StateDemo.tsx +207 -0
- package/templates/fullstack-app/src/components/UserList.tsx +30 -13
- package/templates/fullstack-app/src/data/api.ts +173 -38
- package/templates/fullstack-app/src/main.tsx +88 -154
- package/templates/fullstack-app/src/middleware.ts +28 -0
- package/templates/fullstack-app/src/pages/404.tsx +28 -0
- package/templates/fullstack-app/src/pages/[id].tsx +0 -0
- package/templates/fullstack-app/src/pages/_app.tsx +11 -0
- package/templates/fullstack-app/src/pages/_document.tsx +25 -0
- package/templates/fullstack-app/src/pages/_error.tsx +45 -0
- package/templates/fullstack-app/src/pages/about.tsx +71 -0
- package/templates/fullstack-app/src/pages/api/users/[id].ts +73 -0
- package/templates/fullstack-app/src/pages/api/users/index.ts +43 -0
- package/templates/fullstack-app/src/pages/index.tsx +97 -20
- package/templates/fullstack-app/src/pages/users/[id].tsx +153 -0
- package/templates/fullstack-app/src/pages/wasm-demo.tsx +1 -0
- package/templates/go/example.go +99 -86
- package/templates/go-wasm-app/babel.config.js +8 -2
- package/templates/go-wasm-app/build.config.js +62 -0
- package/templates/go-wasm-app/build.js +218 -0
- package/templates/go-wasm-app/package.json +21 -12
- package/templates/go-wasm-app/server.js +59 -510
- package/templates/go-wasm-app/src/app.js +173 -0
- package/templates/go-wasm-app/vite.config.js +16 -5
- package/templates/ssr-template/client.js +54 -26
- package/templates/ssr-template/server.js +5 -28
- package/templates/ssr-template/vite.config.js +21 -5
- package/dist/server/wasm.d.ts +0 -7
- package/dist/wasm.d.ts +0 -37
@@ -460,13 +460,19 @@ video {
|
|
460
460
|
max-width: 1536px;
|
461
461
|
}
|
462
462
|
}
|
463
|
+
.m-1 {
|
464
|
+
margin: 0.25rem;
|
465
|
+
}
|
466
|
+
.mx-4 {
|
467
|
+
margin-left: 1rem;
|
468
|
+
margin-right: 1rem;
|
469
|
+
}
|
463
470
|
.mx-auto {
|
464
471
|
margin-left: auto;
|
465
472
|
margin-right: auto;
|
466
473
|
}
|
467
|
-
.
|
468
|
-
margin-
|
469
|
-
margin-bottom: 1rem;
|
474
|
+
.mb-1 {
|
475
|
+
margin-bottom: 0.25rem;
|
470
476
|
}
|
471
477
|
.mb-2 {
|
472
478
|
margin-bottom: 0.5rem;
|
@@ -486,12 +492,24 @@ video {
|
|
486
492
|
.mr-2 {
|
487
493
|
margin-right: 0.5rem;
|
488
494
|
}
|
489
|
-
.mt-
|
490
|
-
margin-top:
|
495
|
+
.mt-2 {
|
496
|
+
margin-top: 0.5rem;
|
497
|
+
}
|
498
|
+
.mt-3 {
|
499
|
+
margin-top: 0.75rem;
|
500
|
+
}
|
501
|
+
.mt-4 {
|
502
|
+
margin-top: 1rem;
|
503
|
+
}
|
504
|
+
.mt-6 {
|
505
|
+
margin-top: 1.5rem;
|
491
506
|
}
|
492
507
|
.mt-8 {
|
493
508
|
margin-top: 2rem;
|
494
509
|
}
|
510
|
+
.block {
|
511
|
+
display: block;
|
512
|
+
}
|
495
513
|
.inline-block {
|
496
514
|
display: inline-block;
|
497
515
|
}
|
@@ -501,11 +519,38 @@ video {
|
|
501
519
|
.table {
|
502
520
|
display: table;
|
503
521
|
}
|
522
|
+
.grid {
|
523
|
+
display: grid;
|
524
|
+
}
|
525
|
+
.h-4 {
|
526
|
+
height: 1rem;
|
527
|
+
}
|
528
|
+
.h-40 {
|
529
|
+
height: 10rem;
|
530
|
+
}
|
504
531
|
.h-5 {
|
505
532
|
height: 1.25rem;
|
506
533
|
}
|
507
|
-
.
|
508
|
-
|
534
|
+
.h-8 {
|
535
|
+
height: 2rem;
|
536
|
+
}
|
537
|
+
.max-h-24 {
|
538
|
+
max-height: 6rem;
|
539
|
+
}
|
540
|
+
.max-h-96 {
|
541
|
+
max-height: 24rem;
|
542
|
+
}
|
543
|
+
.min-h-screen {
|
544
|
+
min-height: 100vh;
|
545
|
+
}
|
546
|
+
.w-1\/2 {
|
547
|
+
width: 50%;
|
548
|
+
}
|
549
|
+
.w-1\/4 {
|
550
|
+
width: 25%;
|
551
|
+
}
|
552
|
+
.w-3\/4 {
|
553
|
+
width: 75%;
|
509
554
|
}
|
510
555
|
.w-5 {
|
511
556
|
width: 1.25rem;
|
@@ -516,8 +561,25 @@ video {
|
|
516
561
|
.max-w-4xl {
|
517
562
|
max-width: 56rem;
|
518
563
|
}
|
519
|
-
.
|
520
|
-
|
564
|
+
.flex-grow {
|
565
|
+
flex-grow: 1;
|
566
|
+
}
|
567
|
+
@keyframes pulse {
|
568
|
+
50% {
|
569
|
+
opacity: .5;
|
570
|
+
}
|
571
|
+
}
|
572
|
+
.animate-pulse {
|
573
|
+
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
574
|
+
}
|
575
|
+
.list-disc {
|
576
|
+
list-style-type: disc;
|
577
|
+
}
|
578
|
+
.grid-cols-3 {
|
579
|
+
grid-template-columns: repeat(3, minmax(0, 1fr));
|
580
|
+
}
|
581
|
+
.flex-col {
|
582
|
+
flex-direction: column;
|
521
583
|
}
|
522
584
|
.items-center {
|
523
585
|
align-items: center;
|
@@ -525,6 +587,9 @@ video {
|
|
525
587
|
.justify-between {
|
526
588
|
justify-content: space-between;
|
527
589
|
}
|
590
|
+
.gap-2 {
|
591
|
+
gap: 0.5rem;
|
592
|
+
}
|
528
593
|
.space-x-6 > :not([hidden]) ~ :not([hidden]) {
|
529
594
|
--tw-space-x-reverse: 0;
|
530
595
|
margin-right: calc(1.5rem * var(--tw-space-x-reverse));
|
@@ -535,15 +600,27 @@ video {
|
|
535
600
|
margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse)));
|
536
601
|
margin-bottom: calc(0.5rem * var(--tw-space-y-reverse));
|
537
602
|
}
|
603
|
+
.space-y-4 > :not([hidden]) ~ :not([hidden]) {
|
604
|
+
--tw-space-y-reverse: 0;
|
605
|
+
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
|
606
|
+
margin-bottom: calc(1rem * var(--tw-space-y-reverse));
|
607
|
+
}
|
538
608
|
.divide-y > :not([hidden]) ~ :not([hidden]) {
|
539
609
|
--tw-divide-y-reverse: 0;
|
540
610
|
border-top-width: calc(1px * calc(1 - var(--tw-divide-y-reverse)));
|
541
611
|
border-bottom-width: calc(1px * var(--tw-divide-y-reverse));
|
542
612
|
}
|
613
|
+
.divide-gray-100 > :not([hidden]) ~ :not([hidden]) {
|
614
|
+
--tw-divide-opacity: 1;
|
615
|
+
border-color: rgb(243 244 246 / var(--tw-divide-opacity, 1));
|
616
|
+
}
|
543
617
|
.divide-gray-200 > :not([hidden]) ~ :not([hidden]) {
|
544
618
|
--tw-divide-opacity: 1;
|
545
619
|
border-color: rgb(229 231 235 / var(--tw-divide-opacity, 1));
|
546
620
|
}
|
621
|
+
.self-center {
|
622
|
+
align-self: center;
|
623
|
+
}
|
547
624
|
.overflow-auto {
|
548
625
|
overflow: auto;
|
549
626
|
}
|
@@ -553,6 +630,12 @@ video {
|
|
553
630
|
.overflow-x-auto {
|
554
631
|
overflow-x: auto;
|
555
632
|
}
|
633
|
+
.overflow-y-auto {
|
634
|
+
overflow-y: auto;
|
635
|
+
}
|
636
|
+
.rounded {
|
637
|
+
border-radius: 0.25rem;
|
638
|
+
}
|
556
639
|
.rounded-lg {
|
557
640
|
border-radius: 0.5rem;
|
558
641
|
}
|
@@ -576,6 +659,18 @@ video {
|
|
576
659
|
--tw-border-opacity: 1;
|
577
660
|
border-color: rgb(229 231 235 / var(--tw-border-opacity, 1));
|
578
661
|
}
|
662
|
+
.border-red-200 {
|
663
|
+
--tw-border-opacity: 1;
|
664
|
+
border-color: rgb(254 202 202 / var(--tw-border-opacity, 1));
|
665
|
+
}
|
666
|
+
.border-red-500 {
|
667
|
+
--tw-border-opacity: 1;
|
668
|
+
border-color: rgb(239 68 68 / var(--tw-border-opacity, 1));
|
669
|
+
}
|
670
|
+
.border-yellow-200 {
|
671
|
+
--tw-border-opacity: 1;
|
672
|
+
border-color: rgb(254 240 138 / var(--tw-border-opacity, 1));
|
673
|
+
}
|
579
674
|
.bg-blue-50 {
|
580
675
|
--tw-bg-opacity: 1;
|
581
676
|
background-color: rgb(239 246 255 / var(--tw-bg-opacity, 1));
|
@@ -588,14 +683,41 @@ video {
|
|
588
683
|
--tw-bg-opacity: 1;
|
589
684
|
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
590
685
|
}
|
686
|
+
.bg-gray-200 {
|
687
|
+
--tw-bg-opacity: 1;
|
688
|
+
background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));
|
689
|
+
}
|
591
690
|
.bg-gray-50 {
|
592
691
|
--tw-bg-opacity: 1;
|
593
692
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
594
693
|
}
|
694
|
+
.bg-gray-800 {
|
695
|
+
--tw-bg-opacity: 1;
|
696
|
+
background-color: rgb(31 41 55 / var(--tw-bg-opacity, 1));
|
697
|
+
}
|
698
|
+
.bg-green-50 {
|
699
|
+
--tw-bg-opacity: 1;
|
700
|
+
background-color: rgb(240 253 244 / var(--tw-bg-opacity, 1));
|
701
|
+
}
|
702
|
+
.bg-red-50 {
|
703
|
+
--tw-bg-opacity: 1;
|
704
|
+
background-color: rgb(254 242 242 / var(--tw-bg-opacity, 1));
|
705
|
+
}
|
706
|
+
.bg-red-600 {
|
707
|
+
--tw-bg-opacity: 1;
|
708
|
+
background-color: rgb(220 38 38 / var(--tw-bg-opacity, 1));
|
709
|
+
}
|
595
710
|
.bg-white {
|
596
711
|
--tw-bg-opacity: 1;
|
597
712
|
background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
|
598
713
|
}
|
714
|
+
.bg-yellow-50 {
|
715
|
+
--tw-bg-opacity: 1;
|
716
|
+
background-color: rgb(254 252 232 / var(--tw-bg-opacity, 1));
|
717
|
+
}
|
718
|
+
.p-2 {
|
719
|
+
padding: 0.5rem;
|
720
|
+
}
|
599
721
|
.p-4 {
|
600
722
|
padding: 1rem;
|
601
723
|
}
|
@@ -605,6 +727,14 @@ video {
|
|
605
727
|
.p-8 {
|
606
728
|
padding: 2rem;
|
607
729
|
}
|
730
|
+
.px-2 {
|
731
|
+
padding-left: 0.5rem;
|
732
|
+
padding-right: 0.5rem;
|
733
|
+
}
|
734
|
+
.px-3 {
|
735
|
+
padding-left: 0.75rem;
|
736
|
+
padding-right: 0.75rem;
|
737
|
+
}
|
608
738
|
.px-4 {
|
609
739
|
padding-left: 1rem;
|
610
740
|
padding-right: 1rem;
|
@@ -613,10 +743,18 @@ video {
|
|
613
743
|
padding-left: 1.5rem;
|
614
744
|
padding-right: 1.5rem;
|
615
745
|
}
|
746
|
+
.py-1 {
|
747
|
+
padding-top: 0.25rem;
|
748
|
+
padding-bottom: 0.25rem;
|
749
|
+
}
|
616
750
|
.py-12 {
|
617
751
|
padding-top: 3rem;
|
618
752
|
padding-bottom: 3rem;
|
619
753
|
}
|
754
|
+
.py-2 {
|
755
|
+
padding-top: 0.5rem;
|
756
|
+
padding-bottom: 0.5rem;
|
757
|
+
}
|
620
758
|
.py-3 {
|
621
759
|
padding-top: 0.75rem;
|
622
760
|
padding-bottom: 0.75rem;
|
@@ -625,12 +763,22 @@ video {
|
|
625
763
|
padding-top: 1rem;
|
626
764
|
padding-bottom: 1rem;
|
627
765
|
}
|
766
|
+
.py-6 {
|
767
|
+
padding-top: 1.5rem;
|
768
|
+
padding-bottom: 1.5rem;
|
769
|
+
}
|
628
770
|
.py-8 {
|
629
771
|
padding-top: 2rem;
|
630
772
|
padding-bottom: 2rem;
|
631
773
|
}
|
632
|
-
.
|
633
|
-
padding-
|
774
|
+
.pb-4 {
|
775
|
+
padding-bottom: 1rem;
|
776
|
+
}
|
777
|
+
.pl-6 {
|
778
|
+
padding-left: 1.5rem;
|
779
|
+
}
|
780
|
+
.pt-4 {
|
781
|
+
padding-top: 1rem;
|
634
782
|
}
|
635
783
|
.text-left {
|
636
784
|
text-align: left;
|
@@ -638,14 +786,14 @@ video {
|
|
638
786
|
.text-center {
|
639
787
|
text-align: center;
|
640
788
|
}
|
789
|
+
.text-2xl {
|
790
|
+
font-size: 1.5rem;
|
791
|
+
line-height: 2rem;
|
792
|
+
}
|
641
793
|
.text-3xl {
|
642
794
|
font-size: 1.875rem;
|
643
795
|
line-height: 2.25rem;
|
644
796
|
}
|
645
|
-
.text-4xl {
|
646
|
-
font-size: 2.25rem;
|
647
|
-
line-height: 2.5rem;
|
648
|
-
}
|
649
797
|
.text-lg {
|
650
798
|
font-size: 1.125rem;
|
651
799
|
line-height: 1.75rem;
|
@@ -658,6 +806,10 @@ video {
|
|
658
806
|
font-size: 1.25rem;
|
659
807
|
line-height: 1.75rem;
|
660
808
|
}
|
809
|
+
.text-xs {
|
810
|
+
font-size: 0.75rem;
|
811
|
+
line-height: 1rem;
|
812
|
+
}
|
661
813
|
.font-bold {
|
662
814
|
font-weight: 700;
|
663
815
|
}
|
@@ -688,6 +840,14 @@ video {
|
|
688
840
|
--tw-text-opacity: 1;
|
689
841
|
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
|
690
842
|
}
|
843
|
+
.text-gray-100 {
|
844
|
+
--tw-text-opacity: 1;
|
845
|
+
color: rgb(243 244 246 / var(--tw-text-opacity, 1));
|
846
|
+
}
|
847
|
+
.text-gray-400 {
|
848
|
+
--tw-text-opacity: 1;
|
849
|
+
color: rgb(156 163 175 / var(--tw-text-opacity, 1));
|
850
|
+
}
|
691
851
|
.text-gray-500 {
|
692
852
|
--tw-text-opacity: 1;
|
693
853
|
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
|
@@ -712,10 +872,30 @@ video {
|
|
712
872
|
--tw-text-opacity: 1;
|
713
873
|
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
|
714
874
|
}
|
875
|
+
.text-red-600 {
|
876
|
+
--tw-text-opacity: 1;
|
877
|
+
color: rgb(220 38 38 / var(--tw-text-opacity, 1));
|
878
|
+
}
|
879
|
+
.text-red-700 {
|
880
|
+
--tw-text-opacity: 1;
|
881
|
+
color: rgb(185 28 28 / var(--tw-text-opacity, 1));
|
882
|
+
}
|
883
|
+
.text-red-800 {
|
884
|
+
--tw-text-opacity: 1;
|
885
|
+
color: rgb(153 27 27 / var(--tw-text-opacity, 1));
|
886
|
+
}
|
715
887
|
.text-white {
|
716
888
|
--tw-text-opacity: 1;
|
717
889
|
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
|
718
890
|
}
|
891
|
+
.text-yellow-600 {
|
892
|
+
--tw-text-opacity: 1;
|
893
|
+
color: rgb(202 138 4 / var(--tw-text-opacity, 1));
|
894
|
+
}
|
895
|
+
.text-yellow-700 {
|
896
|
+
--tw-text-opacity: 1;
|
897
|
+
color: rgb(161 98 7 / var(--tw-text-opacity, 1));
|
898
|
+
}
|
719
899
|
.underline {
|
720
900
|
text-decoration-line: underline;
|
721
901
|
}
|
@@ -729,6 +909,14 @@ video {
|
|
729
909
|
--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
|
730
910
|
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
731
911
|
}
|
912
|
+
.shadow-sm {
|
913
|
+
--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
914
|
+
--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);
|
915
|
+
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
|
916
|
+
}
|
917
|
+
.filter {
|
918
|
+
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
919
|
+
}
|
732
920
|
.transition-colors {
|
733
921
|
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
734
922
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
@@ -755,14 +943,33 @@ body {
|
|
755
943
|
--tw-bg-opacity: 1;
|
756
944
|
background-color: rgb(29 78 216 / var(--tw-bg-opacity, 1));
|
757
945
|
}
|
946
|
+
.hover\:bg-gray-300:hover {
|
947
|
+
--tw-bg-opacity: 1;
|
948
|
+
background-color: rgb(209 213 219 / var(--tw-bg-opacity, 1));
|
949
|
+
}
|
758
950
|
.hover\:bg-gray-50:hover {
|
759
951
|
--tw-bg-opacity: 1;
|
760
952
|
background-color: rgb(249 250 251 / var(--tw-bg-opacity, 1));
|
761
953
|
}
|
954
|
+
.hover\:bg-red-700:hover {
|
955
|
+
--tw-bg-opacity: 1;
|
956
|
+
background-color: rgb(185 28 28 / var(--tw-bg-opacity, 1));
|
957
|
+
}
|
958
|
+
.hover\:text-blue-100:hover {
|
959
|
+
--tw-text-opacity: 1;
|
960
|
+
color: rgb(219 234 254 / var(--tw-text-opacity, 1));
|
961
|
+
}
|
762
962
|
.hover\:text-blue-800:hover {
|
763
963
|
--tw-text-opacity: 1;
|
764
964
|
color: rgb(30 64 175 / var(--tw-text-opacity, 1));
|
765
965
|
}
|
966
|
+
.hover\:text-red-600:hover {
|
967
|
+
--tw-text-opacity: 1;
|
968
|
+
color: rgb(220 38 38 / var(--tw-text-opacity, 1));
|
969
|
+
}
|
766
970
|
.hover\:underline:hover {
|
767
971
|
text-decoration-line: underline;
|
972
|
+
}
|
973
|
+
.disabled\:opacity-50:disabled {
|
974
|
+
opacity: 0.5;
|
768
975
|
}
|
@@ -2,7 +2,7 @@ import express, { Request, Response, NextFunction } from 'express';
|
|
2
2
|
import path from 'path';
|
3
3
|
import { fileURLToPath } from 'url';
|
4
4
|
import fs from 'fs/promises';
|
5
|
-
import { existsSync } from 'fs';
|
5
|
+
import { existsSync, PathLike } from 'fs';
|
6
6
|
import dotenv from 'dotenv';
|
7
7
|
import { createServer } from 'http';
|
8
8
|
import { Server as SocketServer } from 'socket.io';
|
@@ -82,7 +82,7 @@ app.get('/api/users/:id', (req, res) => {
|
|
82
82
|
});
|
83
83
|
|
84
84
|
// Setup esbuild
|
85
|
-
let esbuildContext;
|
85
|
+
let esbuildContext: esbuild.BuildContext<{ entryPoints: string[]; bundle: true; format: "esm"; outdir: string; sourcemap: boolean; minify: boolean; jsx: "transform"; jsxFactory: string; jsxFragment: string; external: string[]; define: { 'process.env.NODE_ENV': string; }; loader: { '.tsx': "tsx"; '.ts': "ts"; '.jsx': "jsx"; '.js': "js"; '.css': "css"; '.json': "json"; '.png': "file"; '.jpg': "file"; '.svg': "file"; }; plugins: { name: string; setup(build: esbuild.PluginBuild): void; }[]; }>;
|
86
86
|
|
87
87
|
async function setupEsbuild() {
|
88
88
|
const buildDir = path.join(__dirname, 'build');
|
@@ -101,7 +101,7 @@ async function setupEsbuild() {
|
|
101
101
|
// Create a plugin to process CSS with Tailwind
|
102
102
|
postcssPlugin = {
|
103
103
|
name: 'postcss-tailwind',
|
104
|
-
setup(build) {
|
104
|
+
setup(build: esbuild.PluginBuild) {
|
105
105
|
build.onLoad({ filter: /\.css$/ }, async (args) => {
|
106
106
|
const css = await fs.readFile(args.path, 'utf8');
|
107
107
|
try {
|
@@ -116,11 +116,11 @@ async function setupEsbuild() {
|
|
116
116
|
|
117
117
|
return {
|
118
118
|
contents: result.css,
|
119
|
-
loader: 'css'
|
119
|
+
loader: 'css' as esbuild.Loader
|
120
120
|
};
|
121
121
|
} catch (error) {
|
122
122
|
console.error('Error processing CSS with Tailwind:', error);
|
123
|
-
return { contents: css, loader: 'css' };
|
123
|
+
return { contents: css, loader: 'css' as esbuild.Loader };
|
124
124
|
}
|
125
125
|
});
|
126
126
|
}
|
@@ -209,7 +209,7 @@ if (isDev) {
|
|
209
209
|
// Determine content type based on file extension
|
210
210
|
const ext = path.extname(filePath);
|
211
211
|
let contentType = 'application/javascript';
|
212
|
-
let loader
|
212
|
+
let loader = 'js';
|
213
213
|
|
214
214
|
switch (ext) {
|
215
215
|
case '.ts':
|
@@ -233,7 +233,7 @@ if (isDev) {
|
|
233
233
|
|
234
234
|
// Transform the file with esbuild
|
235
235
|
const result = await esbuild.transform(source, {
|
236
|
-
loader,
|
236
|
+
loader: loader as esbuild.Loader,
|
237
237
|
sourcemap: 'inline',
|
238
238
|
jsxFactory: 'jsx',
|
239
239
|
jsxFragment: 'Fragment'
|
@@ -249,7 +249,7 @@ if (isDev) {
|
|
249
249
|
}
|
250
250
|
|
251
251
|
// Helper function to check if file exists
|
252
|
-
async function fileExists(filepath:
|
252
|
+
async function fileExists(filepath: PathLike) {
|
253
253
|
try {
|
254
254
|
await fs.access(filepath);
|
255
255
|
return true;
|
@@ -258,8 +258,30 @@ async function fileExists(filepath: string): Promise<boolean> {
|
|
258
258
|
}
|
259
259
|
}
|
260
260
|
|
261
|
+
// Import server utilities directly without WASM functionality
|
262
|
+
import { renderToString } from 'frontend-hamroun';
|
263
|
+
|
264
|
+
// Simple renderComponent implementation
|
265
|
+
async function renderComponent(Component: (arg0: {}) => any, props = {}) {
|
266
|
+
try {
|
267
|
+
// Create HTML string from component
|
268
|
+
const html = renderToString(Component(props));
|
269
|
+
return {
|
270
|
+
html,
|
271
|
+
success: true
|
272
|
+
};
|
273
|
+
} catch (error) {
|
274
|
+
console.error('Error rendering component:', error);
|
275
|
+
return {
|
276
|
+
html: `<div class="error">Error rendering component</div>`,
|
277
|
+
success: false,
|
278
|
+
error
|
279
|
+
};
|
280
|
+
}
|
281
|
+
}
|
282
|
+
|
261
283
|
// SSR handler for all routes except /api and static files
|
262
|
-
app.get('*', async (req
|
284
|
+
app.get('*', async (req, res, next) => {
|
263
285
|
// Skip API routes, static assets, and build/src files
|
264
286
|
if (req.path.startsWith('/api/') ||
|
265
287
|
req.path.startsWith('/build/') ||
|
@@ -323,7 +345,7 @@ app.get('*', async (req: Request, res: Response, next: NextFunction) => {
|
|
323
345
|
}
|
324
346
|
</style>
|
325
347
|
<script>
|
326
|
-
window.__INITIAL_STATE__ =
|
348
|
+
window.__INITIAL_STATE__ = ${JSON.stringify(initialState)};
|
327
349
|
</script>
|
328
350
|
</head>
|
329
351
|
<body>
|
@@ -386,8 +408,8 @@ io.on('connection', (socket) => {
|
|
386
408
|
|
387
409
|
// Handle file changes for live reload in development
|
388
410
|
if (isDev) {
|
389
|
-
const
|
390
|
-
const watcher =
|
411
|
+
const { watch } = await import('chokidar');
|
412
|
+
const watcher = watch([
|
391
413
|
path.join(__dirname, 'src/**/*'),
|
392
414
|
path.join(__dirname, 'public/**/*')
|
393
415
|
]);
|
@@ -417,6 +439,18 @@ if (isDev) {
|
|
417
439
|
console.log('[Watcher] File watching enabled for development');
|
418
440
|
}
|
419
441
|
|
442
|
+
// API routes
|
443
|
+
app.get('/api/posts', (req, res) => {
|
444
|
+
const { authorId } = req.query;
|
445
|
+
|
446
|
+
if (authorId) {
|
447
|
+
const filteredPosts = store.posts.filter(p => p.authorId === parseInt( authorId as string));
|
448
|
+
return res.json(filteredPosts);
|
449
|
+
}
|
450
|
+
|
451
|
+
res.json(store.posts);
|
452
|
+
});
|
453
|
+
|
420
454
|
// Start the server
|
421
455
|
httpServer.listen(PORT, () => {
|
422
456
|
console.log(`Server running at http://localhost:${PORT}`);
|
File without changes
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import { jsx, useState, useEffect, useErrorBoundary } from 'frontend-hamroun';
|
2
|
+
|
3
|
+
interface ErrorBoundaryProps {
|
4
|
+
children: any;
|
5
|
+
fallback?: (error: Error, reset: () => void) => any;
|
6
|
+
}
|
7
|
+
|
8
|
+
export function ErrorBoundary({ children, fallback }: ErrorBoundaryProps) {
|
9
|
+
const [error, resetError] = useErrorBoundary();
|
10
|
+
|
11
|
+
if (error) {
|
12
|
+
if (fallback) {
|
13
|
+
return fallback(error, resetError);
|
14
|
+
}
|
15
|
+
|
16
|
+
return (
|
17
|
+
<div className="error-boundary p-4 border border-red-500 rounded bg-red-50">
|
18
|
+
<h3 className="text-lg font-medium text-red-800 mb-2">Something went wrong</h3>
|
19
|
+
<p className="text-red-600 mb-2">{error.message}</p>
|
20
|
+
<button
|
21
|
+
onClick={resetError}
|
22
|
+
className="px-3 py-1 bg-red-600 text-white rounded hover:bg-red-700"
|
23
|
+
>
|
24
|
+
Try again
|
25
|
+
</button>
|
26
|
+
{process.env.NODE_ENV !== 'production' && (
|
27
|
+
<pre className="mt-3 text-xs overflow-auto p-2 bg-gray-100">
|
28
|
+
{error.stack}
|
29
|
+
</pre>
|
30
|
+
)}
|
31
|
+
</div>
|
32
|
+
);
|
33
|
+
}
|
34
|
+
|
35
|
+
return children;
|
36
|
+
}
|
@@ -1,44 +1,41 @@
|
|
1
1
|
import { jsx } from 'frontend-hamroun';
|
2
|
-
import AppConfig from '../config';
|
3
2
|
|
4
|
-
|
3
|
+
interface LayoutProps {
|
5
4
|
children: any;
|
6
5
|
title?: string;
|
7
|
-
showNavigation?: boolean;
|
8
6
|
}
|
9
7
|
|
10
|
-
export default function Layout({ children, title =
|
11
|
-
const { navigation } = AppConfig;
|
12
|
-
|
8
|
+
export default function Layout({ children, title = 'Frontend Hamroun App' }: LayoutProps) {
|
13
9
|
return (
|
14
|
-
<div className="
|
15
|
-
<header className="
|
16
|
-
<
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
<div className="min-h-screen flex flex-col bg-gray-50">
|
11
|
+
<header className="bg-blue-600 text-white">
|
12
|
+
<div className="container mx-auto px-4 py-4 flex justify-between items-center">
|
13
|
+
<h1 className="text-xl font-bold">
|
14
|
+
<a href="/" className="hover:text-blue-100">
|
15
|
+
{title}
|
16
|
+
</a>
|
17
|
+
</h1>
|
18
|
+
|
19
|
+
<nav>
|
20
20
|
<ul className="flex space-x-6">
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
href={item.path}
|
25
|
-
className="text-blue-600 hover:text-blue-800 hover:underline transition-colors font-medium"
|
26
|
-
>
|
27
|
-
{item.label}
|
28
|
-
</a>
|
29
|
-
</li>
|
30
|
-
))}
|
21
|
+
<li><a href="/" className="hover:text-blue-100">Home</a></li>
|
22
|
+
<li><a href="/about" className="hover:text-blue-100">About</a></li>
|
23
|
+
{/* WASM demo link removed */}
|
31
24
|
</ul>
|
32
25
|
</nav>
|
33
|
-
|
26
|
+
</div>
|
34
27
|
</header>
|
35
28
|
|
36
|
-
<main className="
|
29
|
+
<main className="flex-grow container mx-auto px-4 py-8">
|
37
30
|
{children}
|
38
31
|
</main>
|
39
32
|
|
40
|
-
<footer className="
|
41
|
-
<
|
33
|
+
<footer className="bg-gray-800 text-white">
|
34
|
+
<div className="container mx-auto px-4 py-6">
|
35
|
+
<p className="text-center text-gray-400">
|
36
|
+
© {new Date().getFullYear()} Frontend Hamroun App. All rights reserved.
|
37
|
+
</p>
|
38
|
+
</div>
|
42
39
|
</footer>
|
43
40
|
</div>
|
44
41
|
);
|