devjas1
		
	commited on
		
		
					Commit 
							
							·
						
						80b95e8
	
0
								Parent(s):
							
							
feat: Inital commit from recovered state
Browse filesThis view is limited to 50 files because it contains too many changes.  
							See raw diff
- .gitattributes +0 -0
- .gitignore +13 -0
- .replit +39 -0
- LICENSE.md +201 -0
- attached_assets/Pasted-Here-s-a-high-to-medium-level-outline-formatted-roadmap-for-turning-your-existing-embeddinggemma-30-1757473542795_1757473542795.txt +82 -0
- cli.py +100 -0
- client/index.html +16 -0
- client/src/App.tsx +31 -0
- client/src/components/sections/commands.tsx +117 -0
- client/src/components/sections/configuration.tsx +105 -0
- client/src/components/sections/deployment.tsx +124 -0
- client/src/components/sections/modules.tsx +395 -0
- client/src/components/sections/overview.tsx +154 -0
- client/src/components/ui/accordion.tsx +56 -0
- client/src/components/ui/alert-dialog.tsx +139 -0
- client/src/components/ui/alert.tsx +59 -0
- client/src/components/ui/aspect-ratio.tsx +5 -0
- client/src/components/ui/avatar.tsx +50 -0
- client/src/components/ui/badge.tsx +36 -0
- client/src/components/ui/breadcrumb.tsx +115 -0
- client/src/components/ui/button.tsx +56 -0
- client/src/components/ui/calendar.tsx +68 -0
- client/src/components/ui/card.tsx +79 -0
- client/src/components/ui/carousel.tsx +260 -0
- client/src/components/ui/chart.tsx +365 -0
- client/src/components/ui/checkbox.tsx +28 -0
- client/src/components/ui/collapsible.tsx +11 -0
- client/src/components/ui/command.tsx +151 -0
- client/src/components/ui/context-menu.tsx +198 -0
- client/src/components/ui/dialog.tsx +122 -0
- client/src/components/ui/drawer.tsx +118 -0
- client/src/components/ui/dropdown-menu.tsx +198 -0
- client/src/components/ui/form.tsx +178 -0
- client/src/components/ui/hover-card.tsx +29 -0
- client/src/components/ui/input-otp.tsx +69 -0
- client/src/components/ui/input.tsx +22 -0
- client/src/components/ui/label.tsx +24 -0
- client/src/components/ui/menubar.tsx +256 -0
- client/src/components/ui/navigation-menu.tsx +128 -0
- client/src/components/ui/navigation.tsx +72 -0
- client/src/components/ui/pagination.tsx +117 -0
- client/src/components/ui/popover.tsx +29 -0
- client/src/components/ui/progress.tsx +28 -0
- client/src/components/ui/radio-group.tsx +42 -0
- client/src/components/ui/resizable.tsx +45 -0
- client/src/components/ui/scroll-area.tsx +46 -0
- client/src/components/ui/select.tsx +160 -0
- client/src/components/ui/separator.tsx +29 -0
- client/src/components/ui/sheet.tsx +140 -0
- client/src/components/ui/sidebar.tsx +771 -0
    	
        .gitattributes
    ADDED
    
    | 
            File without changes
         | 
    	
        .gitignore
    ADDED
    
    | @@ -0,0 +1,13 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            node_modules
         | 
| 2 | 
            +
            dist
         | 
| 3 | 
            +
            .DS_Store
         | 
| 4 | 
            +
            server/public
         | 
| 5 | 
            +
            vite.config.ts.*
         | 
| 6 | 
            +
            *.tar.gz
         | 
| 7 | 
            +
            .agent_state*
         | 
| 8 | 
            +
            .vscode
         | 
| 9 | 
            +
            .latest*
         | 
| 10 | 
            +
            rapid*
         | 
| 11 | 
            +
            ac4a*
         | 
| 12 | 
            +
            *.bin
         | 
| 13 | 
            +
            *.gguf
         | 
    	
        .replit
    ADDED
    
    | @@ -0,0 +1,39 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            modules = ["nodejs-20", "web", "postgresql-16"]
         | 
| 2 | 
            +
            run = "npm run dev"
         | 
| 3 | 
            +
            hidden = [".config", ".git", "generated-icon.png", "node_modules", "dist"]
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            [nix]
         | 
| 6 | 
            +
            channel = "stable-24_05"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            [deployment]
         | 
| 9 | 
            +
            deploymentTarget = "autoscale"
         | 
| 10 | 
            +
            build = ["npm", "run", "build"]
         | 
| 11 | 
            +
            run = ["npm", "run", "start"]
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            [[ports]]
         | 
| 14 | 
            +
            localPort = 5000
         | 
| 15 | 
            +
            externalPort = 80
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            [env]
         | 
| 18 | 
            +
            PORT = "5000"
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            [workflows]
         | 
| 21 | 
            +
            runButton = "Project"
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            [[workflows.workflow]]
         | 
| 24 | 
            +
            name = "Project"
         | 
| 25 | 
            +
            mode = "parallel"
         | 
| 26 | 
            +
            author = "agent"
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            [[workflows.workflow.tasks]]
         | 
| 29 | 
            +
            task = "workflow.run"
         | 
| 30 | 
            +
            args = "Start application"
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            [[workflows.workflow]]
         | 
| 33 | 
            +
            name = "Start application"
         | 
| 34 | 
            +
            author = "agent"
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            [[workflows.workflow.tasks]]
         | 
| 37 | 
            +
            task = "shell.exec"
         | 
| 38 | 
            +
            args = "npm run dev"
         | 
| 39 | 
            +
            waitForPort = 5000
         | 
    	
        LICENSE.md
    ADDED
    
    | @@ -0,0 +1,201 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
                                             Apache License
         | 
| 2 | 
            +
                                       Version 2.0, January 2004
         | 
| 3 | 
            +
                                    http://www.apache.org/licenses/
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            1. Definitions.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
               "License" shall mean the terms and conditions for use, reproduction,
         | 
| 10 | 
            +
               and distribution as defined by Sections 1 through 9 of this document.
         | 
| 11 | 
            +
             | 
| 12 | 
            +
               "Licensor" shall mean the copyright owner or entity authorized by
         | 
| 13 | 
            +
               the copyright owner that is granting the License.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
               "Legal Entity" shall mean the union of the acting entity and all
         | 
| 16 | 
            +
               other entities that control, are controlled by, or are under common
         | 
| 17 | 
            +
               control with that entity. For the purposes of this definition,
         | 
| 18 | 
            +
               "control" means (i) the power, direct or indirect, to cause the
         | 
| 19 | 
            +
               direction or management of such entity, whether by contract or
         | 
| 20 | 
            +
               otherwise, or (ii) ownership of fifty percent (50%) or more of the
         | 
| 21 | 
            +
               outstanding shares, or (iii) beneficial ownership of such entity.
         | 
| 22 | 
            +
             | 
| 23 | 
            +
               "You" (or "Your") shall mean an individual or Legal Entity
         | 
| 24 | 
            +
               exercising permissions granted by this License.
         | 
| 25 | 
            +
             | 
| 26 | 
            +
               "Source" form shall mean the preferred form for making modifications,
         | 
| 27 | 
            +
               including but not limited to software source code, documentation
         | 
| 28 | 
            +
               source, and configuration files.
         | 
| 29 | 
            +
             | 
| 30 | 
            +
               "Object" form shall mean any form resulting from mechanical
         | 
| 31 | 
            +
               transformation or translation of a Source form, including but
         | 
| 32 | 
            +
               not limited to compiled object code, generated documentation,
         | 
| 33 | 
            +
               and conversions to other media types.
         | 
| 34 | 
            +
             | 
| 35 | 
            +
               "Work" shall mean the work of authorship, whether in Source or
         | 
| 36 | 
            +
               Object form, made available under the License, as indicated by a
         | 
| 37 | 
            +
               copyright notice that is included in or attached to the work
         | 
| 38 | 
            +
               (an example is provided in the Appendix below).
         | 
| 39 | 
            +
             | 
| 40 | 
            +
               "Derivative Works" shall mean any work, whether in Source or Object
         | 
| 41 | 
            +
               form, that is based on (or derived from) the Work and for which the
         | 
| 42 | 
            +
               editorial revisions, annotations, elaborations, or other modifications
         | 
| 43 | 
            +
               represent, as a whole, an original work of authorship. For the purposes
         | 
| 44 | 
            +
               of this License, Derivative Works shall not include works that remain
         | 
| 45 | 
            +
               separable from, or merely link (or bind by name) to the interfaces of,
         | 
| 46 | 
            +
               the Work and Derivative Works thereof.
         | 
| 47 | 
            +
             | 
| 48 | 
            +
               "Contribution" shall mean any work of authorship, including
         | 
| 49 | 
            +
               the original version of the Work and any modifications or additions
         | 
| 50 | 
            +
               to that Work or Derivative Works thereof, that is intentionally
         | 
| 51 | 
            +
               submitted to Licensor for inclusion in the Work by the copyright owner
         | 
| 52 | 
            +
               or by an individual or Legal Entity authorized to submit on behalf of
         | 
| 53 | 
            +
               the copyright owner. For the purposes of this definition, "submitted"
         | 
| 54 | 
            +
               means any form of electronic, verbal, or written communication sent
         | 
| 55 | 
            +
               to the Licensor or its representatives, including but not limited to
         | 
| 56 | 
            +
               communication on electronic mailing lists, source code control systems,
         | 
| 57 | 
            +
               and issue tracking systems that are managed by, or on behalf of, the
         | 
| 58 | 
            +
               Licensor for the purpose of discussing and improving the Work, but
         | 
| 59 | 
            +
               excluding communication that is conspicuously marked or otherwise
         | 
| 60 | 
            +
               designated in writing by the copyright owner as "Not a Contribution."
         | 
| 61 | 
            +
             | 
| 62 | 
            +
               "Contributor" shall mean Licensor and any individual or Legal Entity
         | 
| 63 | 
            +
               on behalf of whom a Contribution has been received by Licensor and
         | 
| 64 | 
            +
               subsequently incorporated within the Work.
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            2. Grant of Copyright License. Subject to the terms and conditions of
         | 
| 67 | 
            +
               this License, each Contributor hereby grants to You a perpetual,
         | 
| 68 | 
            +
               worldwide, non-exclusive, no-charge, royalty-free, irrevocable
         | 
| 69 | 
            +
               copyright license to reproduce, prepare Derivative Works of,
         | 
| 70 | 
            +
               publicly display, publicly perform, sublicense, and distribute the
         | 
| 71 | 
            +
               Work and such Derivative Works in Source or Object form.
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            3. Grant of Patent License. Subject to the terms and conditions of
         | 
| 74 | 
            +
               this License, each Contributor hereby grants to You a perpetual,
         | 
| 75 | 
            +
               worldwide, non-exclusive, no-charge, royalty-free, irrevocable
         | 
| 76 | 
            +
               (except as stated in this section) patent license to make, have made,
         | 
| 77 | 
            +
               use, offer to sell, sell, import, and otherwise transfer the Work,
         | 
| 78 | 
            +
               where such license applies only to those patent claims licensable
         | 
| 79 | 
            +
               by such Contributor that are necessarily infringed by their
         | 
| 80 | 
            +
               Contribution(s) alone or by combination of their Contribution(s)
         | 
| 81 | 
            +
               with the Work to which such Contribution(s) was submitted. If You
         | 
| 82 | 
            +
               institute patent litigation against any entity (including a
         | 
| 83 | 
            +
               cross-claim or counterclaim in a lawsuit) alleging that the Work
         | 
| 84 | 
            +
               or a Contribution incorporated within the Work constitutes direct
         | 
| 85 | 
            +
               or contributory patent infringement, then any patent licenses
         | 
| 86 | 
            +
               granted to You under this License for that Work shall terminate
         | 
| 87 | 
            +
               as of the date such litigation is filed.
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            4. Redistribution. You may reproduce and distribute copies of the
         | 
| 90 | 
            +
               Work or Derivative Works thereof in any medium, with or without
         | 
| 91 | 
            +
               modifications, and in Source or Object form, provided that You
         | 
| 92 | 
            +
               meet the following conditions:
         | 
| 93 | 
            +
             | 
| 94 | 
            +
               (a) You must give any other recipients of the Work or
         | 
| 95 | 
            +
               Derivative Works a copy of this License; and
         | 
| 96 | 
            +
             | 
| 97 | 
            +
               (b) You must cause any modified files to carry prominent notices
         | 
| 98 | 
            +
               stating that You changed the files; and
         | 
| 99 | 
            +
             | 
| 100 | 
            +
               (c) You must retain, in the Source form of any Derivative Works
         | 
| 101 | 
            +
               that You distribute, all copyright, patent, trademark, and
         | 
| 102 | 
            +
               attribution notices from the Source form of the Work,
         | 
| 103 | 
            +
               excluding those notices that do not pertain to any part of
         | 
| 104 | 
            +
               the Derivative Works; and
         | 
| 105 | 
            +
             | 
| 106 | 
            +
               (d) If the Work includes a "NOTICE" text file as part of its
         | 
| 107 | 
            +
               distribution, then any Derivative Works that You distribute must
         | 
| 108 | 
            +
               include a readable copy of the attribution notices contained
         | 
| 109 | 
            +
               within such NOTICE file, excluding those notices that do not
         | 
| 110 | 
            +
               pertain to any part of the Derivative Works, in at least one
         | 
| 111 | 
            +
               of the following places: within a NOTICE text file distributed
         | 
| 112 | 
            +
               as part of the Derivative Works; within the Source form or
         | 
| 113 | 
            +
               documentation, if provided along with the Derivative Works; or,
         | 
| 114 | 
            +
               within a display generated by the Derivative Works, if and
         | 
| 115 | 
            +
               wherever such third-party notices normally appear. The contents
         | 
| 116 | 
            +
               of the NOTICE file are for informational purposes only and
         | 
| 117 | 
            +
               do not modify the License. You may add Your own attribution
         | 
| 118 | 
            +
               notices within Derivative Works that You distribute, alongside
         | 
| 119 | 
            +
               or as an addendum to the NOTICE text from the Work, provided
         | 
| 120 | 
            +
               that such additional attribution notices cannot be construed
         | 
| 121 | 
            +
               as modifying the License.
         | 
| 122 | 
            +
             | 
| 123 | 
            +
               You may add Your own copyright statement to Your modifications and
         | 
| 124 | 
            +
               may provide additional or different license terms and conditions
         | 
| 125 | 
            +
               for use, reproduction, or distribution of Your modifications, or
         | 
| 126 | 
            +
               for any such Derivative Works as a whole, provided Your use,
         | 
| 127 | 
            +
               reproduction, and distribution of the Work otherwise complies with
         | 
| 128 | 
            +
               the conditions stated in this License.
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            5. Submission of Contributions. Unless You explicitly state otherwise,
         | 
| 131 | 
            +
               any Contribution intentionally submitted for inclusion in the Work
         | 
| 132 | 
            +
               by You to the Licensor shall be under the terms and conditions of
         | 
| 133 | 
            +
               this License, without any additional terms or conditions.
         | 
| 134 | 
            +
               Notwithstanding the above, nothing herein shall supersede or modify
         | 
| 135 | 
            +
               the terms of any separate license agreement you may have executed
         | 
| 136 | 
            +
               with Licensor regarding such Contributions.
         | 
| 137 | 
            +
             | 
| 138 | 
            +
            6. Trademarks. This License does not grant permission to use the trade
         | 
| 139 | 
            +
               names, trademarks, service marks, or product names of the Licensor,
         | 
| 140 | 
            +
               except as required for reasonable and customary use in describing the
         | 
| 141 | 
            +
               origin of the Work and reproducing the content of the NOTICE file.
         | 
| 142 | 
            +
             | 
| 143 | 
            +
            7. Disclaimer of Warranty. Unless required by applicable law or
         | 
| 144 | 
            +
               agreed to in writing, Licensor provides the Work (and each
         | 
| 145 | 
            +
               Contributor provides its Contributions) on an "AS IS" BASIS,
         | 
| 146 | 
            +
               WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
         | 
| 147 | 
            +
               implied, including, without limitation, any warranties or conditions
         | 
| 148 | 
            +
               of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
         | 
| 149 | 
            +
               PARTICULAR PURPOSE. You are solely responsible for determining the
         | 
| 150 | 
            +
               appropriateness of using or redistributing the Work and assume any
         | 
| 151 | 
            +
               risks associated with Your exercise of permissions under this License.
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            8. Limitation of Liability. In no event and under no legal theory,
         | 
| 154 | 
            +
               whether in tort (including negligence), contract, or otherwise,
         | 
| 155 | 
            +
               unless required by applicable law (such as deliberate and grossly
         | 
| 156 | 
            +
               negligent acts) or agreed to in writing, shall any Contributor be
         | 
| 157 | 
            +
               liable to You for damages, including any direct, indirect, special,
         | 
| 158 | 
            +
               incidental, or consequential damages of any character arising as a
         | 
| 159 | 
            +
               result of this License or out of the use or inability to use the
         | 
| 160 | 
            +
               Work (including but not limited to damages for loss of goodwill,
         | 
| 161 | 
            +
               work stoppage, computer failure or malfunction, or any and all
         | 
| 162 | 
            +
               other commercial damages or losses), even if such Contributor
         | 
| 163 | 
            +
               has been advised of the possibility of such damages.
         | 
| 164 | 
            +
             | 
| 165 | 
            +
            9. Accepting Warranty or Additional Liability. While redistributing
         | 
| 166 | 
            +
               the Work or Derivative Works thereof, You may choose to offer,
         | 
| 167 | 
            +
               and charge a fee for, acceptance of support, warranty, indemnity,
         | 
| 168 | 
            +
               or other liability obligations and/or rights consistent with this
         | 
| 169 | 
            +
               License. However, in accepting such obligations, You may act only
         | 
| 170 | 
            +
               on Your own behalf and on Your sole responsibility, not on behalf
         | 
| 171 | 
            +
               of any other Contributor, and only if You agree to indemnify,
         | 
| 172 | 
            +
               defend, and hold each Contributor harmless for any liability
         | 
| 173 | 
            +
               incurred by, or claims asserted against, such Contributor by reason
         | 
| 174 | 
            +
               of your accepting any such warranty or additional liability.
         | 
| 175 | 
            +
             | 
| 176 | 
            +
            END OF TERMS AND CONDITIONS
         | 
| 177 | 
            +
             | 
| 178 | 
            +
            APPENDIX: How to apply the Apache License to your work.
         | 
| 179 | 
            +
             | 
| 180 | 
            +
                  To apply the Apache License to your work, attach the following
         | 
| 181 | 
            +
                  boilerplate notice, with the fields enclosed by brackets "[]"
         | 
| 182 | 
            +
                  replaced with your own identifying information. (Don't include
         | 
| 183 | 
            +
                  the brackets!)  The text should be enclosed in the appropriate
         | 
| 184 | 
            +
                  comment syntax for the file format. We also recommend that a
         | 
| 185 | 
            +
                  file or class name and description of purpose be included on the
         | 
| 186 | 
            +
                  same "printed page" as the copyright notice for easier
         | 
| 187 | 
            +
                  identification within third-party archives.
         | 
| 188 | 
            +
             | 
| 189 | 
            +
            Copyright [yyyy] [name of copyright owner]
         | 
| 190 | 
            +
             | 
| 191 | 
            +
            Licensed under the Apache License, Version 2.0 (the "License");
         | 
| 192 | 
            +
            you may not use this file except in compliance with the License.
         | 
| 193 | 
            +
            You may obtain a copy of the License at
         | 
| 194 | 
            +
             | 
| 195 | 
            +
                   http://www.apache.org/licenses/LICENSE-2.0
         | 
| 196 | 
            +
             | 
| 197 | 
            +
            Unless required by applicable law or agreed to in writing, software
         | 
| 198 | 
            +
            distributed under the License is distributed on an "AS IS" BASIS,
         | 
| 199 | 
            +
            WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         | 
| 200 | 
            +
            See the License for the specific language governing permissions and
         | 
| 201 | 
            +
            limitations under the License.
         | 
    	
        attached_assets/Pasted-Here-s-a-high-to-medium-level-outline-formatted-roadmap-for-turning-your-existing-embeddinggemma-30-1757473542795_1757473542795.txt
    ADDED
    
    | @@ -0,0 +1,82 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            Here’s a high-to-medium-level, outline-formatted roadmap for turning your existing embeddinggemma-300m setup into a unified CLI tool powered by Phi-2. No code snippets—just clear steps and gap-checks.
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            1. Define Your Modular Surface
         | 
| 4 | 
            +
            Embedder
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Uses google/embeddinggemma-300m to turn text into vectors
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Retriever
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            Indexes and searches embeddings (e.g., FAISS or Chroma)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Generator
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            Runs Phi-2 (2.7 B) for response generation based on retrieved context
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            CLI
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            Ties everything together with a command-line interface (e.g., Typer)
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            2. Prepare Your Conda Environment
         | 
| 21 | 
            +
            Confirm sentence-transformers and transformers are installed
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            Add your vector store library (FAISS/Chroma)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            Install any quantization/runtime helpers for Phi-2 (GGUF, bitsandbytes, etc.)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            Allocate model cache paths under your project (e.g., ./models/)
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            3. Acquire and Optimize Phi-2
         | 
| 30 | 
            +
            Download the Phi-2 weights from Hugging Face or Azure AI Studio
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            Quantize to Q4/Q5 to fit within ~6–8 GB of RAM on your i5/16 GB rig
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            Validate loading speed and memory footprint in isolation before integration
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            4. Sketch Your Data Flow
         | 
| 37 | 
            +
            User Input: typed command + query text
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            Embedding: call Gemma → vector
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            Retrieval: query vector → top-k document vectors
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            Context Assembly: stitch retrieved snippets
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            Generation: feed context + user prompt into Phi-2 → text answer
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            Output: print or save response
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            5. Fill Logic Holes
         | 
| 50 | 
            +
            You need a vector store backend; plain in-memory lists won’t scale
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            Chunk larger documents before embedding (e.g., 500 token windows)
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            Watch Phi-2’s context window (typically ~2 K tokens) and trim if needed
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            Plan caching: don’t re-embed the same files on every run
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            Design a config file for model paths, thresholds, and CLI defaults
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            6. Organize Your Directory
         | 
| 61 | 
            +
            Code
         | 
| 62 | 
            +
            gemma-phi2-cli/
         | 
| 63 | 
            +
            ├── models/
         | 
| 64 | 
            +
            │   ├── embeddinggemma-300m/
         | 
| 65 | 
            +
            │   └── phi2-quantized/
         | 
| 66 | 
            +
            ├── data/
         | 
| 67 | 
            +
            │   └── index/            # FAISS/Chroma files
         | 
| 68 | 
            +
            ├── src/
         | 
| 69 | 
            +
            │   ├── embedder.py       # wraps Gemma
         | 
| 70 | 
            +
            │   ├── retriever.py      # builds & queries index
         | 
| 71 | 
            +
            │   ├── generator.py      # wraps Phi-2
         | 
| 72 | 
            +
            │   └── cli.py            # Typer entry point
         | 
| 73 | 
            +
            ├── config.yaml           # model locations, hyperparams
         | 
| 74 | 
            +
            └── README.md
         | 
| 75 | 
            +
            7. Plan Your CLI Commands
         | 
| 76 | 
            +
            init → create or update index from a target directory
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            search → semantic lookup, returns file names + scores
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            ask → retrieval + generation in one step
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            serve → optional local API for integrations
         | 
    	
        cli.py
    ADDED
    
    | @@ -0,0 +1,100 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import typer
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            from src.embedder import embed_documents
         | 
| 4 | 
            +
            from src.retriever import search_documents
         | 
| 5 | 
            +
            from src.generator import generate_commit_message, fallback_commit_message
         | 
| 6 | 
            +
            from src.diff_analyzer import get_staged_diff_chunks
         | 
| 7 | 
            +
            from src.config_loader import load_config
         | 
| 8 | 
            +
             | 
| 9 | 
            +
             | 
| 10 | 
            +
            # Initialize Typer app
         | 
| 11 | 
            +
            app = typer.Typer()
         | 
| 12 | 
            +
            config = load_config("config.yaml")
         | 
| 13 | 
            +
            print("Config loaded:", config)
         | 
| 14 | 
            +
             | 
| 15 | 
            +
             | 
| 16 | 
            +
            # ===== CLI Commands =====
         | 
| 17 | 
            +
            # `init` — Index Documents
         | 
| 18 | 
            +
            @app.command()
         | 
| 19 | 
            +
            def init(path: str = typer.Argument(...)):
         | 
| 20 | 
            +
                embeddings = embed_documents(path, config)
         | 
| 21 | 
            +
                if embeddings:
         | 
| 22 | 
            +
                    typer.echo(f"Documents indexed successfully: {len(embeddings)} documents")
         | 
| 23 | 
            +
                else:
         | 
| 24 | 
            +
                    typer.echo("No documents were indexed.")
         | 
| 25 | 
            +
             | 
| 26 | 
            +
             | 
| 27 | 
            +
            # `search` — Semantic Lookup
         | 
| 28 | 
            +
            @app.command()
         | 
| 29 | 
            +
            def search(query: str):
         | 
| 30 | 
            +
                """
         | 
| 31 | 
            +
                Perform a semantic search on indexed documents.
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                Args:
         | 
| 34 | 
            +
                    query (str): The search query string.
         | 
| 35 | 
            +
                """
         | 
| 36 | 
            +
                results = search_documents(query, config)
         | 
| 37 | 
            +
                for i, result in enumerate(results):
         | 
| 38 | 
            +
                    typer.echo(f"[{i+1}] {result}")
         | 
| 39 | 
            +
             | 
| 40 | 
            +
             | 
| 41 | 
            +
            # `ask` — Retrieval-Augmented Generation (RAG)
         | 
| 42 | 
            +
            @app.command()
         | 
| 43 | 
            +
            def ask(query: str):
         | 
| 44 | 
            +
                """
         | 
| 45 | 
            +
                Perform a retrieval-augmented generation (RAG) process to answer a user query.
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                Args:
         | 
| 48 | 
            +
                    query (str): The user query string.
         | 
| 49 | 
            +
                """
         | 
| 50 | 
            +
                context = search_documents(query, config)
         | 
| 51 | 
            +
                prompt = "\n".join(context) + f"\n\nUser question: {query}"
         | 
| 52 | 
            +
                try:
         | 
| 53 | 
            +
                    response = generate_commit_message(prompt, config)
         | 
| 54 | 
            +
                except (
         | 
| 55 | 
            +
                    RuntimeError
         | 
| 56 | 
            +
                ):  # Replace with the specific exception type raised by generate_commit_message
         | 
| 57 | 
            +
                    response = fallback_commit_message([])
         | 
| 58 | 
            +
                typer.echo(response)
         | 
| 59 | 
            +
             | 
| 60 | 
            +
             | 
| 61 | 
            +
            # `commit` — Git Diff + Message Generation
         | 
| 62 | 
            +
            @app.command()
         | 
| 63 | 
            +
            def commit(preview: bool = True, apply: bool = False, dry_run: bool = False):
         | 
| 64 | 
            +
                """
         | 
| 65 | 
            +
                Generate a commit message based on staged Git diff chunks.
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                Args:
         | 
| 68 | 
            +
                    preview (bool): If True, display the suggested commit message.
         | 
| 69 | 
            +
                    apply (bool): If True, apply the commit with the generated message.
         | 
| 70 | 
            +
                    dry_run (bool): If True, display staged files and chunks without generating a message.
         | 
| 71 | 
            +
                """
         | 
| 72 | 
            +
                file_list, diff_chunks = get_staged_diff_chunks()
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                if dry_run:
         | 
| 75 | 
            +
                    typer.echo(f"Files staged: {len(file_list)}")
         | 
| 76 | 
            +
                    typer.echo(f"Chunks: {len(diff_chunks)}")
         | 
| 77 | 
            +
                    typer.echo(
         | 
| 78 | 
            +
                        f"Estimated tokens: {sum(len(chunk.split()) for chunk in diff_chunks)}"
         | 
| 79 | 
            +
                    )
         | 
| 80 | 
            +
                    return
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                prompt = "\n".join(diff_chunks) + "\n\nGenerate a commit message:"
         | 
| 83 | 
            +
                try:
         | 
| 84 | 
            +
                    message = generate_commit_message(prompt, config)
         | 
| 85 | 
            +
                except Exception:
         | 
| 86 | 
            +
                    message = fallback_commit_message(file_list)
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                if preview:
         | 
| 89 | 
            +
                    typer.echo(f"Suggested commit message:\n{message}")
         | 
| 90 | 
            +
                if apply:
         | 
| 91 | 
            +
                    import subprocess
         | 
| 92 | 
            +
             | 
| 93 | 
            +
                    subprocess.run(["git", "commit", "-m", message])
         | 
| 94 | 
            +
             | 
| 95 | 
            +
             | 
| 96 | 
            +
            from sentence_transformers import SentenceTransformer
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            model = SentenceTransformer("./models/embeddinggemma-300m")
         | 
| 99 | 
            +
            emb = model.encode("Test string")
         | 
| 100 | 
            +
            print("Embedding shape:", emb.shape)  # Should be (768,)
         | 
    	
        client/index.html
    ADDED
    
    | @@ -0,0 +1,16 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            <!DOCTYPE html>
         | 
| 2 | 
            +
            <html lang="en">
         | 
| 3 | 
            +
              <head>
         | 
| 4 | 
            +
                <meta charset="UTF-8" />
         | 
| 5 | 
            +
                <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1" />
         | 
| 6 | 
            +
                <link rel="preconnect" href="https://fonts.googleapis.com">
         | 
| 7 | 
            +
                <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
         | 
| 8 | 
            +
                <link href="https://fonts.googleapis.com/css2?family=Architects+Daughter&family=DM+Sans:ital,opsz,wght@0,9..40,100..1000;1,9..40,100..1000&family=Fira+Code:wght@300..700&family=Geist+Mono:wght@100..900&family=Geist:wght@100..900&family=IBM+Plex+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&family=IBM+Plex+Sans:ital,wght@0,100..700;1,100..700&family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&family=Libre+Baskerville:ital,wght@0,400;0,700;1,400&family=Lora:ital,wght@0,400..700;1,400..700&family=Merriweather:ital,opsz,wght@0,18..144,300..900;1,18..144,300..900&family=Montserrat:ital,wght@0,100..900;1,100..900&family=Open+Sans:ital,wght@0,300..800;1,300..800&family=Outfit:wght@100..900&family=Oxanium:wght@200..800&family=Playfair+Display:ital,wght@0,400..900;1,400..900&family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Roboto+Mono:ital,wght@0,100..700;1,100..700&family=Roboto:ital,wght@0,100..900;1,100..900&family=Source+Code+Pro:ital,wght@0,200..900;1,200..900&family=Source+Serif+4:ital,opsz,wght@0,8..60,200..900;1,8..60,200..900&family=Space+Grotesk:wght@300..700&family=Space+Mono:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet">
         | 
| 9 | 
            +
              </head>
         | 
| 10 | 
            +
              <body>
         | 
| 11 | 
            +
                <div id="root"></div>
         | 
| 12 | 
            +
                <script type="module" src="/src/main.tsx"></script>
         | 
| 13 | 
            +
                <!-- This is a replit script which adds a banner on the top of the page when opened in development mode outside the replit environment -->
         | 
| 14 | 
            +
                <script type="text/javascript" src="https://replit.com/public/js/replit-dev-banner.js"></script>
         | 
| 15 | 
            +
              </body>
         | 
| 16 | 
            +
            </html>
         | 
    	
        client/src/App.tsx
    ADDED
    
    | @@ -0,0 +1,31 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Switch, Route } from "wouter";
         | 
| 2 | 
            +
            import { queryClient } from "./lib/queryClient";
         | 
| 3 | 
            +
            import { QueryClientProvider } from "@tanstack/react-query";
         | 
| 4 | 
            +
            import { Toaster } from "@/components/ui/toaster";
         | 
| 5 | 
            +
            import { TooltipProvider } from "@/components/ui/tooltip";
         | 
| 6 | 
            +
            import Dashboard from "./pages/dashboard";
         | 
| 7 | 
            +
            import NotFound from "@/pages/not-found";
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            function Router() {
         | 
| 10 | 
            +
              return (
         | 
| 11 | 
            +
                <Switch>
         | 
| 12 | 
            +
                  <Route path="/" component={Dashboard} />
         | 
| 13 | 
            +
                  <Route component={NotFound} />
         | 
| 14 | 
            +
                </Switch>
         | 
| 15 | 
            +
              );
         | 
| 16 | 
            +
            }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            function App() {
         | 
| 19 | 
            +
              return (
         | 
| 20 | 
            +
                <QueryClientProvider client={queryClient}>
         | 
| 21 | 
            +
                  <TooltipProvider>
         | 
| 22 | 
            +
                    <div className="dark">
         | 
| 23 | 
            +
                      <Toaster />
         | 
| 24 | 
            +
                      <Router />
         | 
| 25 | 
            +
                    </div>
         | 
| 26 | 
            +
                  </TooltipProvider>
         | 
| 27 | 
            +
                </QueryClientProvider>
         | 
| 28 | 
            +
              );
         | 
| 29 | 
            +
            }
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            export default App;
         | 
    	
        client/src/components/sections/commands.tsx
    ADDED
    
    | @@ -0,0 +1,117 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Card } from "@/components/ui/card";
         | 
| 2 | 
            +
            import { TerminalComponent } from "@/components/ui/terminal";
         | 
| 3 | 
            +
            import { Terminal, Play, Settings } from "lucide-react";
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            export function CommandsSection() {
         | 
| 6 | 
            +
              const coreCommands = [
         | 
| 7 | 
            +
                {
         | 
| 8 | 
            +
                  command: "gemma-phi2-cli init [path]",
         | 
| 9 | 
            +
                  description: "Initialize or update index from target directory",
         | 
| 10 | 
            +
                  color: "text-accent"
         | 
| 11 | 
            +
                },
         | 
| 12 | 
            +
                {
         | 
| 13 | 
            +
                  command: "gemma-phi2-cli search [query]",
         | 
| 14 | 
            +
                  description: "Semantic lookup returning file names and scores",
         | 
| 15 | 
            +
                  color: "text-accent"
         | 
| 16 | 
            +
                },
         | 
| 17 | 
            +
                {
         | 
| 18 | 
            +
                  command: "gemma-phi2-cli ask [question]",
         | 
| 19 | 
            +
                  description: "Retrieval + generation in one step",
         | 
| 20 | 
            +
                  color: "text-accent"
         | 
| 21 | 
            +
                },
         | 
| 22 | 
            +
                {
         | 
| 23 | 
            +
                  command: "gemma-phi2-cli serve",
         | 
| 24 | 
            +
                  description: "Launch local API server for integrations",
         | 
| 25 | 
            +
                  color: "text-accent"
         | 
| 26 | 
            +
                },
         | 
| 27 | 
            +
                {
         | 
| 28 | 
            +
                  command: "gemma-phi2-cli commit [--preview|--apply]",
         | 
| 29 | 
            +
                  description: "Generate commit messages from staged changes",
         | 
| 30 | 
            +
                  color: "text-accent"
         | 
| 31 | 
            +
                },
         | 
| 32 | 
            +
                {
         | 
| 33 | 
            +
                  command: "gemma-phi2-cli commit --dry-run",
         | 
| 34 | 
            +
                  description: "Show file count, chunks, and token estimates",
         | 
| 35 | 
            +
                  color: "text-accent"
         | 
| 36 | 
            +
                }
         | 
| 37 | 
            +
              ];
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              const utilityCommands = [
         | 
| 40 | 
            +
                {
         | 
| 41 | 
            +
                  command: "gemma-phi2-cli status",
         | 
| 42 | 
            +
                  description: "Show current configuration and model status",
         | 
| 43 | 
            +
                  color: "text-accent"
         | 
| 44 | 
            +
                },
         | 
| 45 | 
            +
                {
         | 
| 46 | 
            +
                  command: "gemma-phi2-cli config [key] [value]",
         | 
| 47 | 
            +
                  description: "Get or set configuration parameters",
         | 
| 48 | 
            +
                  color: "text-accent"
         | 
| 49 | 
            +
                },
         | 
| 50 | 
            +
                {
         | 
| 51 | 
            +
                  command: "gemma-phi2-cli clear",
         | 
| 52 | 
            +
                  description: "Clear vector store and cached embeddings",
         | 
| 53 | 
            +
                  color: "text-accent"
         | 
| 54 | 
            +
                },
         | 
| 55 | 
            +
                {
         | 
| 56 | 
            +
                  command: "gemma-phi2-cli --help",
         | 
| 57 | 
            +
                  description: "Display detailed help and usage examples",
         | 
| 58 | 
            +
                  color: "text-accent"
         | 
| 59 | 
            +
                },
         | 
| 60 | 
            +
                {
         | 
| 61 | 
            +
                  command: "gemma-phi2-cli commit --preview",
         | 
| 62 | 
            +
                  description: "Preview generated commit message without applying",
         | 
| 63 | 
            +
                  color: "text-accent"
         | 
| 64 | 
            +
                },
         | 
| 65 | 
            +
                {
         | 
| 66 | 
            +
                  command: "gemma-phi2-cli config --list-presets",
         | 
| 67 | 
            +
                  description: "Show available commit style presets",
         | 
| 68 | 
            +
                  color: "text-accent"
         | 
| 69 | 
            +
                }
         | 
| 70 | 
            +
              ];
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              return (
         | 
| 73 | 
            +
                <section id="commands" className="space-y-6">
         | 
| 74 | 
            +
                  <h2 className="text-2xl font-bold">CLI Commands</h2>
         | 
| 75 | 
            +
                  
         | 
| 76 | 
            +
                  <div className="grid gap-6">
         | 
| 77 | 
            +
                    <TerminalComponent />
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    <div className="grid md:grid-cols-2 gap-6">
         | 
| 80 | 
            +
                      <Card className="p-4 border-border">
         | 
| 81 | 
            +
                        <h4 className="font-semibold mb-4 flex items-center">
         | 
| 82 | 
            +
                          <Play className="mr-2 text-green-400 w-4 h-4" />
         | 
| 83 | 
            +
                          Core Commands
         | 
| 84 | 
            +
                        </h4>
         | 
| 85 | 
            +
                        <div className="space-y-3 text-sm">
         | 
| 86 | 
            +
                          {coreCommands.map((cmd, index) => (
         | 
| 87 | 
            +
                            <Card key={index} className="bg-secondary/50 p-3 border-border">
         | 
| 88 | 
            +
                              <div className={`font-mono ${cmd.color} mb-1`} data-testid={`command-${index}`}>
         | 
| 89 | 
            +
                                {cmd.command}
         | 
| 90 | 
            +
                              </div>
         | 
| 91 | 
            +
                              <div className="text-muted-foreground">{cmd.description}</div>
         | 
| 92 | 
            +
                            </Card>
         | 
| 93 | 
            +
                          ))}
         | 
| 94 | 
            +
                        </div>
         | 
| 95 | 
            +
                      </Card>
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                      <Card className="p-4 border-border">
         | 
| 98 | 
            +
                        <h4 className="font-semibold mb-4 flex items-center">
         | 
| 99 | 
            +
                          <Settings className="mr-2 text-yellow-400 w-4 h-4" />
         | 
| 100 | 
            +
                          Utility Commands
         | 
| 101 | 
            +
                        </h4>
         | 
| 102 | 
            +
                        <div className="space-y-3 text-sm">
         | 
| 103 | 
            +
                          {utilityCommands.map((cmd, index) => (
         | 
| 104 | 
            +
                            <Card key={index} className="bg-secondary/50 p-3 border-border">
         | 
| 105 | 
            +
                              <div className={`font-mono ${cmd.color} mb-1`} data-testid={`utility-command-${index}`}>
         | 
| 106 | 
            +
                                {cmd.command}
         | 
| 107 | 
            +
                              </div>
         | 
| 108 | 
            +
                              <div className="text-muted-foreground">{cmd.description}</div>
         | 
| 109 | 
            +
                            </Card>
         | 
| 110 | 
            +
                          ))}
         | 
| 111 | 
            +
                        </div>
         | 
| 112 | 
            +
                      </Card>
         | 
| 113 | 
            +
                    </div>
         | 
| 114 | 
            +
                  </div>
         | 
| 115 | 
            +
                </section>
         | 
| 116 | 
            +
              );
         | 
| 117 | 
            +
            }
         | 
    	
        client/src/components/sections/configuration.tsx
    ADDED
    
    | @@ -0,0 +1,105 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Card } from "@/components/ui/card";
         | 
| 2 | 
            +
            import { Button } from "@/components/ui/button";
         | 
| 3 | 
            +
            import { FileCode, Edit, Save } from "lucide-react";
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            export function ConfigurationSection() {
         | 
| 6 | 
            +
              const configContent = `# Gemma-Phi2-CLI Configuration
         | 
| 7 | 
            +
            models:
         | 
| 8 | 
            +
              embedder:
         | 
| 9 | 
            +
                path: "./models/embeddinggemma-300m"
         | 
| 10 | 
            +
                batch_size: 32
         | 
| 11 | 
            +
                device: "cpu"
         | 
| 12 | 
            +
              generator:
         | 
| 13 | 
            +
                path: "./models/phi2-quantized.gguf"
         | 
| 14 | 
            +
                quantization: "Q4_0"
         | 
| 15 | 
            +
                max_tokens: 2048
         | 
| 16 | 
            +
                temperature: 0.7
         | 
| 17 | 
            +
                format: "gguf"
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            embedding:
         | 
| 20 | 
            +
              dim: 768
         | 
| 21 | 
            +
              truncate_to: 128
         | 
| 22 | 
            +
              sentence_transformers: true
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            vector_store:
         | 
| 25 | 
            +
              type: "faiss"
         | 
| 26 | 
            +
              index_path: "./data/index"
         | 
| 27 | 
            +
              persistence: true
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            retrieval:
         | 
| 30 | 
            +
              top_k: 5
         | 
| 31 | 
            +
              similarity_threshold: 0.75
         | 
| 32 | 
            +
              rerank: false
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            performance:
         | 
| 35 | 
            +
              cache_embeddings: true
         | 
| 36 | 
            +
              chunk_size: 500
         | 
| 37 | 
            +
              chunk_overlap: 50
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            commit:
         | 
| 40 | 
            +
              tone: "imperative"
         | 
| 41 | 
            +
              style: "conventional"  # Options: conventional | descriptive | terse
         | 
| 42 | 
            +
              max_length: 72
         | 
| 43 | 
            +
              preview_by_default: true
         | 
| 44 | 
            +
              fallback_enabled: true
         | 
| 45 | 
            +
              dry_run_default: false
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            logging:
         | 
| 48 | 
            +
              level: "INFO"
         | 
| 49 | 
            +
              file: "./logs/gemma-phi2.log"
         | 
| 50 | 
            +
              verbose: true
         | 
| 51 | 
            +
              telemetry: false
         | 
| 52 | 
            +
              rotate_logs: true
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            environment:
         | 
| 55 | 
            +
              conda_env: "gemma-phi2-cli"
         | 
| 56 | 
            +
              python_version: "3.10"
         | 
| 57 | 
            +
              platform: "windows"`;
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              return (
         | 
| 60 | 
            +
                <section id="configuration" className="space-y-6">
         | 
| 61 | 
            +
                  <h2 className="text-2xl font-bold">Configuration Management</h2>
         | 
| 62 | 
            +
                  
         | 
| 63 | 
            +
                  <Card className="border-border">
         | 
| 64 | 
            +
                    <div className="flex items-center justify-between p-4 border-b border-border">
         | 
| 65 | 
            +
                      <h3 className="font-semibold flex items-center">
         | 
| 66 | 
            +
                        <FileCode className="mr-2 text-yellow-400 w-4 h-4" />
         | 
| 67 | 
            +
                        config.yaml
         | 
| 68 | 
            +
                      </h3>
         | 
| 69 | 
            +
                      <div className="flex items-center space-x-2">
         | 
| 70 | 
            +
                        <Button variant="secondary" size="sm" data-testid="button-edit-config">
         | 
| 71 | 
            +
                          <Edit className="mr-1 w-3 h-3" />
         | 
| 72 | 
            +
                          Edit
         | 
| 73 | 
            +
                        </Button>
         | 
| 74 | 
            +
                        <Button size="sm" data-testid="button-save-config">
         | 
| 75 | 
            +
                          <Save className="mr-1 w-3 h-3" />
         | 
| 76 | 
            +
                          Save
         | 
| 77 | 
            +
                        </Button>
         | 
| 78 | 
            +
                      </div>
         | 
| 79 | 
            +
                    </div>
         | 
| 80 | 
            +
                    <div className="p-4">
         | 
| 81 | 
            +
                      <div className="bg-black/50 rounded-lg p-4 font-mono text-sm overflow-x-auto">
         | 
| 82 | 
            +
                        <div className="syntax-highlight">
         | 
| 83 | 
            +
                          {configContent.split('\n').map((line, index) => {
         | 
| 84 | 
            +
                            let className = '';
         | 
| 85 | 
            +
                            if (line.trim().startsWith('#')) {
         | 
| 86 | 
            +
                              className = 'comment';
         | 
| 87 | 
            +
                            } else if (line.includes(':') && !line.trim().startsWith(' ')) {
         | 
| 88 | 
            +
                              className = 'keyword';
         | 
| 89 | 
            +
                            } else if (line.includes('"')) {
         | 
| 90 | 
            +
                              className = 'string';
         | 
| 91 | 
            +
                            }
         | 
| 92 | 
            +
                            
         | 
| 93 | 
            +
                            return (
         | 
| 94 | 
            +
                              <div key={index} className={className} data-testid={`config-line-${index}`}>
         | 
| 95 | 
            +
                                {line || '\u00A0'}
         | 
| 96 | 
            +
                              </div>
         | 
| 97 | 
            +
                            );
         | 
| 98 | 
            +
                          })}
         | 
| 99 | 
            +
                        </div>
         | 
| 100 | 
            +
                      </div>
         | 
| 101 | 
            +
                    </div>
         | 
| 102 | 
            +
                  </Card>
         | 
| 103 | 
            +
                </section>
         | 
| 104 | 
            +
              );
         | 
| 105 | 
            +
            }
         | 
    	
        client/src/components/sections/deployment.tsx
    ADDED
    
    | @@ -0,0 +1,124 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Card } from "@/components/ui/card";
         | 
| 2 | 
            +
            import { Button } from "@/components/ui/button";
         | 
| 3 | 
            +
            import { Progress } from "@/components/ui/progress";
         | 
| 4 | 
            +
            import { Server, Download, Rocket } from "lucide-react";
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            export function DeploymentSection() {
         | 
| 7 | 
            +
              const systemRequirements = [
         | 
| 8 | 
            +
                { label: "CPU", value: "Intel i5+ / AMD Ryzen 5+" },
         | 
| 9 | 
            +
                { label: "RAM", value: "16 GB minimum" },
         | 
| 10 | 
            +
                { label: "Storage", value: "10 GB+ SSD" },
         | 
| 11 | 
            +
                { label: "Platform", value: "Windows 11 (primary)" },
         | 
| 12 | 
            +
                { label: "Python", value: "3.10 (Conda managed)" },
         | 
| 13 | 
            +
                { label: "Models", value: "CPU-only execution" }
         | 
| 14 | 
            +
              ];
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              const installationSteps = [
         | 
| 17 | 
            +
                { name: "Conda Environment", progress: 100, status: "✓ Complete", color: "bg-green-400" },
         | 
| 18 | 
            +
                { name: "sentence-transformers", progress: 100, status: "✓ Complete", color: "bg-green-400" },
         | 
| 19 | 
            +
                { name: "FAISS + Typer + PyYAML", progress: 100, status: "✓ Complete", color: "bg-green-400" },
         | 
| 20 | 
            +
                { name: "EmbeddingGemma-300m", progress: 75, status: "⟳ Downloading", color: "bg-yellow-400" },
         | 
| 21 | 
            +
                { name: "Phi-2 GGUF (Q4_0)", progress: 0, status: "⏳ Pending", color: "bg-muted" }
         | 
| 22 | 
            +
              ];
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              const quickStartSteps = [
         | 
| 25 | 
            +
                {
         | 
| 26 | 
            +
                  number: 1,
         | 
| 27 | 
            +
                  title: "Conda Setup",
         | 
| 28 | 
            +
                  commands: ["conda env create -f environment.yml", "conda activate gemma-phi2-cli", "pip install -e ."],
         | 
| 29 | 
            +
                  color: "bg-primary"
         | 
| 30 | 
            +
                },
         | 
| 31 | 
            +
                {
         | 
| 32 | 
            +
                  number: 2,
         | 
| 33 | 
            +
                  title: "Model Download",
         | 
| 34 | 
            +
                  commands: ["python download_models.py", "# Downloads EmbeddingGemma + Phi-2 GGUF"],
         | 
| 35 | 
            +
                  color: "bg-accent"
         | 
| 36 | 
            +
                },
         | 
| 37 | 
            +
                {
         | 
| 38 | 
            +
                  number: 3,
         | 
| 39 | 
            +
                  title: "CLI Usage",
         | 
| 40 | 
            +
                  commands: ["gemma-phi2-cli init ./my-project", "git add .", "gemma-phi2-cli commit --preview"],
         | 
| 41 | 
            +
                  color: "bg-green-400"
         | 
| 42 | 
            +
                }
         | 
| 43 | 
            +
              ];
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              return (
         | 
| 46 | 
            +
                <section id="deployment" className="space-y-6">
         | 
| 47 | 
            +
                  <h2 className="text-2xl font-bold">Deployment & Setup</h2>
         | 
| 48 | 
            +
                  
         | 
| 49 | 
            +
                  <div className="grid md:grid-cols-2 gap-6">
         | 
| 50 | 
            +
                    {/* System Requirements */}
         | 
| 51 | 
            +
                    <Card className="p-4 border-border">
         | 
| 52 | 
            +
                      <h3 className="font-semibold mb-4 flex items-center">
         | 
| 53 | 
            +
                        <Server className="mr-2 text-blue-400 w-4 h-4" />
         | 
| 54 | 
            +
                        System Requirements
         | 
| 55 | 
            +
                      </h3>
         | 
| 56 | 
            +
                      <div className="space-y-3 text-sm">
         | 
| 57 | 
            +
                        {systemRequirements.map((req, index) => (
         | 
| 58 | 
            +
                          <div key={index} className="flex justify-between items-center py-2 border-b border-border/50">
         | 
| 59 | 
            +
                            <span className="text-muted-foreground">{req.label}</span>
         | 
| 60 | 
            +
                            <span className="font-medium" data-testid={`requirement-${req.label.toLowerCase()}`}>
         | 
| 61 | 
            +
                              {req.value}
         | 
| 62 | 
            +
                            </span>
         | 
| 63 | 
            +
                          </div>
         | 
| 64 | 
            +
                        ))}
         | 
| 65 | 
            +
                      </div>
         | 
| 66 | 
            +
                    </Card>
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    {/* Installation Progress */}
         | 
| 69 | 
            +
                    <Card className="p-4 border-border">
         | 
| 70 | 
            +
                      <h3 className="font-semibold mb-4 flex items-center">
         | 
| 71 | 
            +
                        <Download className="mr-2 text-green-400 w-4 h-4" />
         | 
| 72 | 
            +
                        Installation Progress
         | 
| 73 | 
            +
                      </h3>
         | 
| 74 | 
            +
                      <div className="space-y-4">
         | 
| 75 | 
            +
                        {installationSteps.map((step, index) => (
         | 
| 76 | 
            +
                          <div key={index} className="space-y-2">
         | 
| 77 | 
            +
                            <div className="flex justify-between text-sm">
         | 
| 78 | 
            +
                              <span>{step.name}</span>
         | 
| 79 | 
            +
                              <span className={
         | 
| 80 | 
            +
                                step.status.includes("Complete") ? "text-green-400" :
         | 
| 81 | 
            +
                                step.status.includes("Downloading") ? "text-yellow-400" :
         | 
| 82 | 
            +
                                "text-muted-foreground"
         | 
| 83 | 
            +
                              } data-testid={`install-status-${index}`}>
         | 
| 84 | 
            +
                                {step.status}
         | 
| 85 | 
            +
                              </span>
         | 
| 86 | 
            +
                            </div>
         | 
| 87 | 
            +
                            <Progress 
         | 
| 88 | 
            +
                              value={step.progress} 
         | 
| 89 | 
            +
                              className="w-full h-2"
         | 
| 90 | 
            +
                              data-testid={`install-progress-${index}`}
         | 
| 91 | 
            +
                            />
         | 
| 92 | 
            +
                          </div>
         | 
| 93 | 
            +
                        ))}
         | 
| 94 | 
            +
                      </div>
         | 
| 95 | 
            +
                    </Card>
         | 
| 96 | 
            +
                  </div>
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                  {/* Quick Start Guide */}
         | 
| 99 | 
            +
                  <Card className="p-6 border-border">
         | 
| 100 | 
            +
                    <h3 className="font-semibold mb-4 flex items-center">
         | 
| 101 | 
            +
                      <Rocket className="mr-2 text-primary w-4 h-4" />
         | 
| 102 | 
            +
                      Quick Start Guide
         | 
| 103 | 
            +
                    </h3>
         | 
| 104 | 
            +
                    <div className="grid md:grid-cols-3 gap-6">
         | 
| 105 | 
            +
                      {quickStartSteps.map((step, index) => (
         | 
| 106 | 
            +
                        <div key={index} className="space-y-3">
         | 
| 107 | 
            +
                          <div className={`w-8 h-8 ${step.color} rounded-full flex items-center justify-center text-black font-bold`}>
         | 
| 108 | 
            +
                            {step.number}
         | 
| 109 | 
            +
                          </div>
         | 
| 110 | 
            +
                          <h4 className="font-medium">{step.title}</h4>
         | 
| 111 | 
            +
                          <Card className="bg-black/50 p-2 font-mono text-sm border-border">
         | 
| 112 | 
            +
                            {step.commands.map((command, cmdIndex) => (
         | 
| 113 | 
            +
                              <div key={cmdIndex} data-testid={`quickstart-command-${index}-${cmdIndex}`}>
         | 
| 114 | 
            +
                                {command}
         | 
| 115 | 
            +
                              </div>
         | 
| 116 | 
            +
                            ))}
         | 
| 117 | 
            +
                          </Card>
         | 
| 118 | 
            +
                        </div>
         | 
| 119 | 
            +
                      ))}
         | 
| 120 | 
            +
                    </div>
         | 
| 121 | 
            +
                  </Card>
         | 
| 122 | 
            +
                </section>
         | 
| 123 | 
            +
              );
         | 
| 124 | 
            +
            }
         | 
    	
        client/src/components/sections/modules.tsx
    ADDED
    
    | @@ -0,0 +1,395 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Card } from "@/components/ui/card";
         | 
| 2 | 
            +
            import { Input } from "@/components/ui/input";
         | 
| 3 | 
            +
            import { Label } from "@/components/ui/label";
         | 
| 4 | 
            +
            import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
         | 
| 5 | 
            +
            import { Badge } from "@/components/ui/badge";
         | 
| 6 | 
            +
            import { Brain, Search, Wand2, GitBranch, ChevronDown, CheckCircle, Clock } from "lucide-react";
         | 
| 7 | 
            +
            import { useState } from "react";
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            export function ModulesSection() {
         | 
| 10 | 
            +
              const [expandedModules, setExpandedModules] = useState<Set<string>>(new Set(["embedder"]));
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              const toggleModule = (moduleId: string) => {
         | 
| 13 | 
            +
                const newExpanded = new Set(expandedModules);
         | 
| 14 | 
            +
                if (newExpanded.has(moduleId)) {
         | 
| 15 | 
            +
                  newExpanded.delete(moduleId);
         | 
| 16 | 
            +
                } else {
         | 
| 17 | 
            +
                  newExpanded.add(moduleId);
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
                setExpandedModules(newExpanded);
         | 
| 20 | 
            +
              };
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              return (
         | 
| 23 | 
            +
                <section id="modules" className="space-y-6">
         | 
| 24 | 
            +
                  <h2 className="text-2xl font-bold">Module Configuration</h2>
         | 
| 25 | 
            +
                  
         | 
| 26 | 
            +
                  {/* Embedder Module */}
         | 
| 27 | 
            +
                  <Card className="border-border overflow-hidden">
         | 
| 28 | 
            +
                    <div className="p-4 bg-secondary/30 border-b border-border">
         | 
| 29 | 
            +
                      <div className="flex items-center justify-between">
         | 
| 30 | 
            +
                        <div className="flex items-center space-x-3">
         | 
| 31 | 
            +
                          <Brain className="text-primary w-5 h-5" />
         | 
| 32 | 
            +
                          <h3 className="font-semibold">Embedder Module</h3>
         | 
| 33 | 
            +
                          <Badge className="bg-green-500/20 text-green-400 hover:bg-green-500/30">
         | 
| 34 | 
            +
                            Active
         | 
| 35 | 
            +
                          </Badge>
         | 
| 36 | 
            +
                        </div>
         | 
| 37 | 
            +
                        <button
         | 
| 38 | 
            +
                          onClick={() => toggleModule("embedder")}
         | 
| 39 | 
            +
                          className="text-muted-foreground hover:text-foreground transition-colors"
         | 
| 40 | 
            +
                          data-testid="toggle-embedder"
         | 
| 41 | 
            +
                        >
         | 
| 42 | 
            +
                          <ChevronDown 
         | 
| 43 | 
            +
                            className={`w-4 h-4 transition-transform ${
         | 
| 44 | 
            +
                              expandedModules.has("embedder") ? "rotate-180" : ""
         | 
| 45 | 
            +
                            }`} 
         | 
| 46 | 
            +
                          />
         | 
| 47 | 
            +
                        </button>
         | 
| 48 | 
            +
                      </div>
         | 
| 49 | 
            +
                    </div>
         | 
| 50 | 
            +
                    {expandedModules.has("embedder") && (
         | 
| 51 | 
            +
                      <div className="p-4 space-y-4">
         | 
| 52 | 
            +
                        <div className="grid md:grid-cols-2 gap-4">
         | 
| 53 | 
            +
                          <div>
         | 
| 54 | 
            +
                            <Label htmlFor="embedder-path" className="text-sm font-medium mb-2 block">Model Path</Label>
         | 
| 55 | 
            +
                            <Input
         | 
| 56 | 
            +
                              id="embedder-path"
         | 
| 57 | 
            +
                              type="text"
         | 
| 58 | 
            +
                              defaultValue="./models/embeddinggemma-300m/"
         | 
| 59 | 
            +
                              className="font-mono"
         | 
| 60 | 
            +
                              data-testid="input-embedder-path"
         | 
| 61 | 
            +
                            />
         | 
| 62 | 
            +
                          </div>
         | 
| 63 | 
            +
                          <div>
         | 
| 64 | 
            +
                            <Label htmlFor="embedder-batch" className="text-sm font-medium mb-2 block">Batch Size</Label>
         | 
| 65 | 
            +
                            <Input
         | 
| 66 | 
            +
                              id="embedder-batch"
         | 
| 67 | 
            +
                              type="number"
         | 
| 68 | 
            +
                              defaultValue="32"
         | 
| 69 | 
            +
                              data-testid="input-embedder-batch"
         | 
| 70 | 
            +
                            />
         | 
| 71 | 
            +
                          </div>
         | 
| 72 | 
            +
                        </div>
         | 
| 73 | 
            +
                        <Card className="bg-muted/20 p-4 border-border">
         | 
| 74 | 
            +
                          <h4 className="font-medium mb-2 flex items-center">
         | 
| 75 | 
            +
                            <i className="fas fa-code mr-2 text-accent"></i>
         | 
| 76 | 
            +
                            Implementation Status
         | 
| 77 | 
            +
                          </h4>
         | 
| 78 | 
            +
                          <div className="space-y-2 text-sm">
         | 
| 79 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 80 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 81 | 
            +
                              <span>Model loading interface</span>
         | 
| 82 | 
            +
                            </div>
         | 
| 83 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 84 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 85 | 
            +
                              <span>Text preprocessing pipeline</span>
         | 
| 86 | 
            +
                            </div>
         | 
| 87 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 88 | 
            +
                              <Clock className="text-yellow-400 w-4 h-4" />
         | 
| 89 | 
            +
                              <span>Batch processing optimization</span>
         | 
| 90 | 
            +
                            </div>
         | 
| 91 | 
            +
                          </div>
         | 
| 92 | 
            +
                        </Card>
         | 
| 93 | 
            +
                      </div>
         | 
| 94 | 
            +
                    )}
         | 
| 95 | 
            +
                  </Card>
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                  {/* Retriever Module */}
         | 
| 98 | 
            +
                  <Card className="border-border overflow-hidden">
         | 
| 99 | 
            +
                    <div className="p-4 bg-secondary/30 border-b border-border">
         | 
| 100 | 
            +
                      <div className="flex items-center justify-between">
         | 
| 101 | 
            +
                        <div className="flex items-center space-x-3">
         | 
| 102 | 
            +
                          <Search className="text-accent w-5 h-5" />
         | 
| 103 | 
            +
                          <h3 className="font-semibold">Retriever Module</h3>
         | 
| 104 | 
            +
                          <Badge className="bg-green-500/20 text-green-400 hover:bg-green-500/30">
         | 
| 105 | 
            +
                            Active
         | 
| 106 | 
            +
                          </Badge>
         | 
| 107 | 
            +
                        </div>
         | 
| 108 | 
            +
                        <button
         | 
| 109 | 
            +
                          onClick={() => toggleModule("retriever")}
         | 
| 110 | 
            +
                          className="text-muted-foreground hover:text-foreground transition-colors"
         | 
| 111 | 
            +
                          data-testid="toggle-retriever"
         | 
| 112 | 
            +
                        >
         | 
| 113 | 
            +
                          <ChevronDown 
         | 
| 114 | 
            +
                            className={`w-4 h-4 transition-transform ${
         | 
| 115 | 
            +
                              expandedModules.has("retriever") ? "rotate-180" : ""
         | 
| 116 | 
            +
                            }`} 
         | 
| 117 | 
            +
                          />
         | 
| 118 | 
            +
                        </button>
         | 
| 119 | 
            +
                      </div>
         | 
| 120 | 
            +
                    </div>
         | 
| 121 | 
            +
                    {expandedModules.has("retriever") && (
         | 
| 122 | 
            +
                      <div className="p-4 space-y-4">
         | 
| 123 | 
            +
                        <div className="grid md:grid-cols-3 gap-4">
         | 
| 124 | 
            +
                          <div>
         | 
| 125 | 
            +
                            <Label htmlFor="vector-store" className="text-sm font-medium mb-2 block">Vector Store</Label>
         | 
| 126 | 
            +
                            <Select defaultValue="faiss">
         | 
| 127 | 
            +
                              <SelectTrigger id="vector-store" data-testid="select-vector-store">
         | 
| 128 | 
            +
                                <SelectValue />
         | 
| 129 | 
            +
                              </SelectTrigger>
         | 
| 130 | 
            +
                              <SelectContent>
         | 
| 131 | 
            +
                                <SelectItem value="faiss">FAISS</SelectItem>
         | 
| 132 | 
            +
                                <SelectItem value="chroma">Chroma</SelectItem>
         | 
| 133 | 
            +
                                <SelectItem value="pinecone">Pinecone</SelectItem>
         | 
| 134 | 
            +
                              </SelectContent>
         | 
| 135 | 
            +
                            </Select>
         | 
| 136 | 
            +
                          </div>
         | 
| 137 | 
            +
                          <div>
         | 
| 138 | 
            +
                            <Label htmlFor="top-k" className="text-sm font-medium mb-2 block">Top-K Results</Label>
         | 
| 139 | 
            +
                            <Input
         | 
| 140 | 
            +
                              id="top-k"
         | 
| 141 | 
            +
                              type="number"
         | 
| 142 | 
            +
                              defaultValue="5"
         | 
| 143 | 
            +
                              data-testid="input-top-k"
         | 
| 144 | 
            +
                            />
         | 
| 145 | 
            +
                          </div>
         | 
| 146 | 
            +
                          <div>
         | 
| 147 | 
            +
                            <Label htmlFor="similarity-threshold" className="text-sm font-medium mb-2 block">Similarity Threshold</Label>
         | 
| 148 | 
            +
                            <Input
         | 
| 149 | 
            +
                              id="similarity-threshold"
         | 
| 150 | 
            +
                              type="number"
         | 
| 151 | 
            +
                              defaultValue="0.7"
         | 
| 152 | 
            +
                              step="0.1"
         | 
| 153 | 
            +
                              data-testid="input-similarity-threshold"
         | 
| 154 | 
            +
                            />
         | 
| 155 | 
            +
                          </div>
         | 
| 156 | 
            +
                        </div>
         | 
| 157 | 
            +
                        <Card className="bg-muted/20 p-4 border-border">
         | 
| 158 | 
            +
                          <h4 className="font-medium mb-2">Index Statistics</h4>
         | 
| 159 | 
            +
                          <div className="grid md:grid-cols-3 gap-4 text-sm">
         | 
| 160 | 
            +
                            <div className="text-center">
         | 
| 161 | 
            +
                              <div className="text-2xl font-bold text-primary" data-testid="stat-documents">1,247</div>
         | 
| 162 | 
            +
                              <div className="text-muted-foreground">Documents</div>
         | 
| 163 | 
            +
                            </div>
         | 
| 164 | 
            +
                            <div className="text-center">
         | 
| 165 | 
            +
                              <div className="text-2xl font-bold text-accent" data-testid="stat-embeddings">89,432</div>
         | 
| 166 | 
            +
                              <div className="text-muted-foreground">Embeddings</div>
         | 
| 167 | 
            +
                            </div>
         | 
| 168 | 
            +
                            <div className="text-center">
         | 
| 169 | 
            +
                              <div className="text-2xl font-bold text-green-400" data-testid="stat-size">2.3GB</div>
         | 
| 170 | 
            +
                              <div className="text-muted-foreground">Index Size</div>
         | 
| 171 | 
            +
                            </div>
         | 
| 172 | 
            +
                          </div>
         | 
| 173 | 
            +
                        </Card>
         | 
| 174 | 
            +
                      </div>
         | 
| 175 | 
            +
                    )}
         | 
| 176 | 
            +
                  </Card>
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                  {/* DiffAnalyzer Module */}
         | 
| 179 | 
            +
                  <Card className="border-border overflow-hidden">
         | 
| 180 | 
            +
                    <div className="p-4 bg-secondary/30 border-b border-border">
         | 
| 181 | 
            +
                      <div className="flex items-center justify-between">
         | 
| 182 | 
            +
                        <div className="flex items-center space-x-3">
         | 
| 183 | 
            +
                          <GitBranch className="text-orange-400 w-5 h-5" />
         | 
| 184 | 
            +
                          <h3 className="font-semibold">DiffAnalyzer Module</h3>
         | 
| 185 | 
            +
                          <Badge className="bg-green-500/20 text-green-400 hover:bg-green-500/30">
         | 
| 186 | 
            +
                            Active
         | 
| 187 | 
            +
                          </Badge>
         | 
| 188 | 
            +
                        </div>
         | 
| 189 | 
            +
                        <button
         | 
| 190 | 
            +
                          onClick={() => toggleModule("diffanalyzer")}
         | 
| 191 | 
            +
                          className="text-muted-foreground hover:text-foreground transition-colors"
         | 
| 192 | 
            +
                          data-testid="toggle-diffanalyzer"
         | 
| 193 | 
            +
                        >
         | 
| 194 | 
            +
                          <ChevronDown 
         | 
| 195 | 
            +
                            className={`w-4 h-4 transition-transform ${
         | 
| 196 | 
            +
                              expandedModules.has("diffanalyzer") ? "rotate-180" : ""
         | 
| 197 | 
            +
                            }`} 
         | 
| 198 | 
            +
                          />
         | 
| 199 | 
            +
                        </button>
         | 
| 200 | 
            +
                      </div>
         | 
| 201 | 
            +
                    </div>
         | 
| 202 | 
            +
                    {expandedModules.has("diffanalyzer") && (
         | 
| 203 | 
            +
                      <div className="p-4 space-y-4">
         | 
| 204 | 
            +
                        <div className="grid md:grid-cols-2 gap-4">
         | 
| 205 | 
            +
                          <div>
         | 
| 206 | 
            +
                            <Label htmlFor="chunk-size" className="text-sm font-medium mb-2 block">Chunk Size</Label>
         | 
| 207 | 
            +
                            <Input
         | 
| 208 | 
            +
                              id="chunk-size"
         | 
| 209 | 
            +
                              type="number"
         | 
| 210 | 
            +
                              defaultValue="500"
         | 
| 211 | 
            +
                              data-testid="input-chunk-size"
         | 
| 212 | 
            +
                            />
         | 
| 213 | 
            +
                          </div>
         | 
| 214 | 
            +
                          <div>
         | 
| 215 | 
            +
                            <Label htmlFor="max-files" className="text-sm font-medium mb-2 block">Max Files</Label>
         | 
| 216 | 
            +
                            <Input
         | 
| 217 | 
            +
                              id="max-files"
         | 
| 218 | 
            +
                              type="number"
         | 
| 219 | 
            +
                              defaultValue="50"
         | 
| 220 | 
            +
                              data-testid="input-max-files"
         | 
| 221 | 
            +
                            />
         | 
| 222 | 
            +
                          </div>
         | 
| 223 | 
            +
                        </div>
         | 
| 224 | 
            +
                        <Card className="bg-muted/20 p-4 border-border">
         | 
| 225 | 
            +
                          <h4 className="font-medium mb-2 flex items-center">
         | 
| 226 | 
            +
                            <i className="fas fa-git mr-2 text-orange-400"></i>
         | 
| 227 | 
            +
                            Git Integration
         | 
| 228 | 
            +
                          </h4>
         | 
| 229 | 
            +
                          <div className="space-y-2 text-sm">
         | 
| 230 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 231 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 232 | 
            +
                              <span>Git diff parsing</span>
         | 
| 233 | 
            +
                            </div>
         | 
| 234 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 235 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 236 | 
            +
                              <span>Staged changes detection</span>
         | 
| 237 | 
            +
                            </div>
         | 
| 238 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 239 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 240 | 
            +
                              <span>Logical section chunking</span>
         | 
| 241 | 
            +
                            </div>
         | 
| 242 | 
            +
                          </div>
         | 
| 243 | 
            +
                        </Card>
         | 
| 244 | 
            +
                        <Card className="bg-black/50 p-4 border-border">
         | 
| 245 | 
            +
                          <h4 className="font-medium mb-2 flex items-center">
         | 
| 246 | 
            +
                            <i className="fas fa-code-branch mr-2 text-blue-400"></i>
         | 
| 247 | 
            +
                            Sample Diff Chunk
         | 
| 248 | 
            +
                          </h4>
         | 
| 249 | 
            +
                          <div className="font-mono text-xs space-y-1">
         | 
| 250 | 
            +
                            <div className="text-muted-foreground">diff --git a/src/embedder.py b/src/embedder.py</div>
         | 
| 251 | 
            +
                            <div className="text-muted-foreground">index 1a2b3c4..5d6e7f8 100644</div>
         | 
| 252 | 
            +
                            <div className="text-muted-foreground">--- a/src/embedder.py</div>
         | 
| 253 | 
            +
                            <div className="text-muted-foreground">+++ b/src/embedder.py</div>
         | 
| 254 | 
            +
                            <div className="text-cyan-400">@@ -45,6 +45,12 @@ class Embedder:</div>
         | 
| 255 | 
            +
                            <div className="text-red-400">-        return self.model.encode(texts)</div>
         | 
| 256 | 
            +
                            <div className="text-green-400">+        embeddings = self.model.encode(texts)</div>
         | 
| 257 | 
            +
                            <div className="text-green-400">+        # Cache embeddings for faster retrieval</div>
         | 
| 258 | 
            +
                            <div className="text-green-400">+        self._cache_embeddings(texts, embeddings)</div>
         | 
| 259 | 
            +
                            <div className="text-green-400">+        return embeddings</div>
         | 
| 260 | 
            +
                          </div>
         | 
| 261 | 
            +
                        </Card>
         | 
| 262 | 
            +
                      </div>
         | 
| 263 | 
            +
                    )}
         | 
| 264 | 
            +
                  </Card>
         | 
| 265 | 
            +
             | 
| 266 | 
            +
                  {/* Generator Module */}
         | 
| 267 | 
            +
                  <Card className="border-border overflow-hidden">
         | 
| 268 | 
            +
                    <div className="p-4 bg-secondary/30 border-b border-border">
         | 
| 269 | 
            +
                      <div className="flex items-center justify-between">
         | 
| 270 | 
            +
                        <div className="flex items-center space-x-3">
         | 
| 271 | 
            +
                          <Wand2 className="text-purple-400 w-5 h-5" />
         | 
| 272 | 
            +
                          <h3 className="font-semibold">Generator Module</h3>
         | 
| 273 | 
            +
                          <Badge className="bg-yellow-500/20 text-yellow-400 hover:bg-yellow-500/30">
         | 
| 274 | 
            +
                            Loading
         | 
| 275 | 
            +
                          </Badge>
         | 
| 276 | 
            +
                        </div>
         | 
| 277 | 
            +
                        <button
         | 
| 278 | 
            +
                          onClick={() => toggleModule("generator")}
         | 
| 279 | 
            +
                          className="text-muted-foreground hover:text-foreground transition-colors"
         | 
| 280 | 
            +
                          data-testid="toggle-generator"
         | 
| 281 | 
            +
                        >
         | 
| 282 | 
            +
                          <ChevronDown 
         | 
| 283 | 
            +
                            className={`w-4 h-4 transition-transform ${
         | 
| 284 | 
            +
                              expandedModules.has("generator") ? "rotate-180" : ""
         | 
| 285 | 
            +
                            }`} 
         | 
| 286 | 
            +
                          />
         | 
| 287 | 
            +
                        </button>
         | 
| 288 | 
            +
                      </div>
         | 
| 289 | 
            +
                    </div>
         | 
| 290 | 
            +
                    {expandedModules.has("generator") && (
         | 
| 291 | 
            +
                      <div className="p-4 space-y-4">
         | 
| 292 | 
            +
                        <div className="grid md:grid-cols-2 gap-4">
         | 
| 293 | 
            +
                          <div>
         | 
| 294 | 
            +
                            <Label htmlFor="generator-model" className="text-sm font-medium mb-2 block">Model</Label>
         | 
| 295 | 
            +
                            <Input
         | 
| 296 | 
            +
                              id="generator-model"
         | 
| 297 | 
            +
                              type="text"
         | 
| 298 | 
            +
                              defaultValue="microsoft/phi-2"
         | 
| 299 | 
            +
                              className="font-mono"
         | 
| 300 | 
            +
                              data-testid="input-generator-model"
         | 
| 301 | 
            +
                            />
         | 
| 302 | 
            +
                          </div>
         | 
| 303 | 
            +
                          <div>
         | 
| 304 | 
            +
                            <Label htmlFor="quantization" className="text-sm font-medium mb-2 block">Quantization</Label>
         | 
| 305 | 
            +
                            <Select defaultValue="4bit">
         | 
| 306 | 
            +
                              <SelectTrigger id="quantization" data-testid="select-quantization">
         | 
| 307 | 
            +
                                <SelectValue />
         | 
| 308 | 
            +
                              </SelectTrigger>
         | 
| 309 | 
            +
                              <SelectContent>
         | 
| 310 | 
            +
                                <SelectItem value="4bit">4-bit (Q4)</SelectItem>
         | 
| 311 | 
            +
                                <SelectItem value="5bit">5-bit (Q5)</SelectItem>
         | 
| 312 | 
            +
                                <SelectItem value="8bit">8-bit (Q8)</SelectItem>
         | 
| 313 | 
            +
                                <SelectItem value="16bit">16-bit (FP16)</SelectItem>
         | 
| 314 | 
            +
                              </SelectContent>
         | 
| 315 | 
            +
                            </Select>
         | 
| 316 | 
            +
                          </div>
         | 
| 317 | 
            +
                          <div>
         | 
| 318 | 
            +
                            <Label htmlFor="commit-style" className="text-sm font-medium mb-2 block">Commit Style</Label>
         | 
| 319 | 
            +
                            <Select defaultValue="conventional">
         | 
| 320 | 
            +
                              <SelectTrigger id="commit-style" data-testid="select-commit-style">
         | 
| 321 | 
            +
                                <SelectValue />
         | 
| 322 | 
            +
                              </SelectTrigger>
         | 
| 323 | 
            +
                              <SelectContent>
         | 
| 324 | 
            +
                                <SelectItem value="conventional">Conventional (feat:, fix:)</SelectItem>
         | 
| 325 | 
            +
                                <SelectItem value="descriptive">Descriptive (detailed)</SelectItem>
         | 
| 326 | 
            +
                                <SelectItem value="terse">Terse (minimal)</SelectItem>
         | 
| 327 | 
            +
                              </SelectContent>
         | 
| 328 | 
            +
                            </Select>
         | 
| 329 | 
            +
                          </div>
         | 
| 330 | 
            +
                        </div>
         | 
| 331 | 
            +
                        <div className="grid md:grid-cols-3 gap-4">
         | 
| 332 | 
            +
                          <div>
         | 
| 333 | 
            +
                            <Label htmlFor="max-tokens" className="text-sm font-medium mb-2 block">Max Tokens</Label>
         | 
| 334 | 
            +
                            <Input
         | 
| 335 | 
            +
                              id="max-tokens"
         | 
| 336 | 
            +
                              type="number"
         | 
| 337 | 
            +
                              defaultValue="2048"
         | 
| 338 | 
            +
                              data-testid="input-max-tokens"
         | 
| 339 | 
            +
                            />
         | 
| 340 | 
            +
                          </div>
         | 
| 341 | 
            +
                          <div>
         | 
| 342 | 
            +
                            <Label htmlFor="temperature" className="text-sm font-medium mb-2 block">Temperature</Label>
         | 
| 343 | 
            +
                            <Input
         | 
| 344 | 
            +
                              id="temperature"
         | 
| 345 | 
            +
                              type="number"
         | 
| 346 | 
            +
                              defaultValue="0.7"
         | 
| 347 | 
            +
                              step="0.1"
         | 
| 348 | 
            +
                              data-testid="input-temperature"
         | 
| 349 | 
            +
                            />
         | 
| 350 | 
            +
                          </div>
         | 
| 351 | 
            +
                          <div>
         | 
| 352 | 
            +
                            <Label htmlFor="top-p" className="text-sm font-medium mb-2 block">Top-P</Label>
         | 
| 353 | 
            +
                            <Input
         | 
| 354 | 
            +
                              id="top-p"
         | 
| 355 | 
            +
                              type="number"
         | 
| 356 | 
            +
                              defaultValue="0.9"
         | 
| 357 | 
            +
                              step="0.1"
         | 
| 358 | 
            +
                              data-testid="input-top-p"
         | 
| 359 | 
            +
                            />
         | 
| 360 | 
            +
                          </div>
         | 
| 361 | 
            +
                        </div>
         | 
| 362 | 
            +
                        <Card className="bg-muted/20 p-4 border-border">
         | 
| 363 | 
            +
                          <h4 className="font-medium mb-2 flex items-center">
         | 
| 364 | 
            +
                            <i className="fas fa-code-commit mr-2 text-purple-400"></i>
         | 
| 365 | 
            +
                            Commit Message Generation
         | 
| 366 | 
            +
                          </h4>
         | 
| 367 | 
            +
                          <div className="space-y-2 text-sm">
         | 
| 368 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 369 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 370 | 
            +
                              <span>Conventional commit format</span>
         | 
| 371 | 
            +
                            </div>
         | 
| 372 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 373 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 374 | 
            +
                              <span>Imperative tone enforcement</span>
         | 
| 375 | 
            +
                            </div>
         | 
| 376 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 377 | 
            +
                              <Clock className="text-yellow-400 w-4 h-4" />
         | 
| 378 | 
            +
                              <span>Context-aware suggestions</span>
         | 
| 379 | 
            +
                            </div>
         | 
| 380 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 381 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 382 | 
            +
                              <span>Fallback logic for model failures</span>
         | 
| 383 | 
            +
                            </div>
         | 
| 384 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 385 | 
            +
                              <CheckCircle className="text-green-400 w-4 h-4" />
         | 
| 386 | 
            +
                              <span>Style presets (conventional/descriptive/terse)</span>
         | 
| 387 | 
            +
                            </div>
         | 
| 388 | 
            +
                          </div>
         | 
| 389 | 
            +
                        </Card>
         | 
| 390 | 
            +
                      </div>
         | 
| 391 | 
            +
                    )}
         | 
| 392 | 
            +
                  </Card>
         | 
| 393 | 
            +
                </section>
         | 
| 394 | 
            +
              );
         | 
| 395 | 
            +
            }
         | 
    	
        client/src/components/sections/overview.tsx
    ADDED
    
    | @@ -0,0 +1,154 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Card } from "@/components/ui/card";
         | 
| 2 | 
            +
            import { Badge } from "@/components/ui/badge";
         | 
| 3 | 
            +
            import { Brain, Search, Wand2, FolderTree, GitCommit } from "lucide-react";
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            export function OverviewSection() {
         | 
| 6 | 
            +
              const features = [
         | 
| 7 | 
            +
                {
         | 
| 8 | 
            +
                  icon: Brain,
         | 
| 9 | 
            +
                  title: "EmbeddingGemma-300m",
         | 
| 10 | 
            +
                  description: "High-precision text embedding for semantic search",
         | 
| 11 | 
            +
                  color: "text-primary"
         | 
| 12 | 
            +
                },
         | 
| 13 | 
            +
                {
         | 
| 14 | 
            +
                  icon: Search,
         | 
| 15 | 
            +
                  title: "FAISS Vector Store",
         | 
| 16 | 
            +
                  description: "Efficient similarity search and clustering",
         | 
| 17 | 
            +
                  color: "text-accent"
         | 
| 18 | 
            +
                },
         | 
| 19 | 
            +
                {
         | 
| 20 | 
            +
                  icon: Wand2,
         | 
| 21 | 
            +
                  title: "Phi-2 Generator",
         | 
| 22 | 
            +
                  description: "2.7B parameter model for contextual responses",
         | 
| 23 | 
            +
                  color: "text-purple-400"
         | 
| 24 | 
            +
                },
         | 
| 25 | 
            +
                {
         | 
| 26 | 
            +
                  icon: FolderTree,
         | 
| 27 | 
            +
                  title: "Commit Assistant",
         | 
| 28 | 
            +
                  description: "Git diff analysis and intelligent commit message generation",
         | 
| 29 | 
            +
                  color: "text-orange-400"
         | 
| 30 | 
            +
                }
         | 
| 31 | 
            +
              ];
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              const projectStructure = [
         | 
| 34 | 
            +
                { type: "folder", name: "gemma-phi2-cli/", level: 0 },
         | 
| 35 | 
            +
                { type: "folder", name: "models/", level: 1, badge: "AI Models" },
         | 
| 36 | 
            +
                { type: "folder", name: "embeddinggemma-300m/", level: 2 },
         | 
| 37 | 
            +
                { type: "folder", name: "phi2-quantized/", level: 2 },
         | 
| 38 | 
            +
                { type: "folder", name: "data/", level: 1 },
         | 
| 39 | 
            +
                { type: "folder", name: "index/", level: 2, badge: "Vector Store" },
         | 
| 40 | 
            +
                { type: "folder", name: "src/", level: 1 },
         | 
| 41 | 
            +
                { type: "file", name: "embedder.py", level: 2 },
         | 
| 42 | 
            +
                { type: "file", name: "retriever.py", level: 2 },
         | 
| 43 | 
            +
                { type: "file", name: "generator.py", level: 2 },
         | 
| 44 | 
            +
                { type: "file", name: "diff_analyzer.py", level: 2 },
         | 
| 45 | 
            +
                { type: "file", name: "cli.py", level: 2 },
         | 
| 46 | 
            +
                { type: "folder", name: "tests/", level: 1, badge: "Unit Tests" },
         | 
| 47 | 
            +
                { type: "file", name: "test_embedder.py", level: 2 },
         | 
| 48 | 
            +
                { type: "file", name: "test_retriever.py", level: 2 },
         | 
| 49 | 
            +
                { type: "file", name: "test_generator.py", level: 2 },
         | 
| 50 | 
            +
                { type: "folder", name: "examples/", level: 1, badge: "Sample Repo" },
         | 
| 51 | 
            +
                { type: "file", name: "sample_repo/", level: 2 },
         | 
| 52 | 
            +
                { type: "file", name: "config.yaml", level: 1 },
         | 
| 53 | 
            +
                { type: "file", name: "environment.yml", level: 1 },
         | 
| 54 | 
            +
                { type: "file", name: "README.md", level: 1 },
         | 
| 55 | 
            +
              ];
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              return (
         | 
| 58 | 
            +
                <section id="overview" className="space-y-6">
         | 
| 59 | 
            +
                  <div className="gradient-border">
         | 
| 60 | 
            +
                    <div className="p-6">
         | 
| 61 | 
            +
                      <div className="flex items-start justify-between mb-4">
         | 
| 62 | 
            +
                        <div>
         | 
| 63 | 
            +
                          <h2 className="text-2xl font-bold mb-2">Project Overview</h2>
         | 
| 64 | 
            +
                          <p className="text-muted-foreground">
         | 
| 65 | 
            +
                            A seamless CLI assistant that combines EmbeddingGemma's precision with Phi-2's generative capabilities.
         | 
| 66 | 
            +
                          </p>
         | 
| 67 | 
            +
                        </div>
         | 
| 68 | 
            +
                        <Badge className="bg-green-500/20 text-green-400 hover:bg-green-500/30">
         | 
| 69 | 
            +
                          v1.0.0
         | 
| 70 | 
            +
                        </Badge>
         | 
| 71 | 
            +
                      </div>
         | 
| 72 | 
            +
                      
         | 
| 73 | 
            +
                      <div className="grid md:grid-cols-3 gap-4 mb-6">
         | 
| 74 | 
            +
                        {features.map((feature, index) => (
         | 
| 75 | 
            +
                          <Card key={index} className="bg-secondary/50 p-4 border-border">
         | 
| 76 | 
            +
                            <div className="flex items-center space-x-3 mb-2">
         | 
| 77 | 
            +
                              <feature.icon className={`${feature.color} w-5 h-5`} />
         | 
| 78 | 
            +
                              <h3 className="font-semibold">{feature.title}</h3>
         | 
| 79 | 
            +
                            </div>
         | 
| 80 | 
            +
                            <p className="text-sm text-muted-foreground">{feature.description}</p>
         | 
| 81 | 
            +
                          </Card>
         | 
| 82 | 
            +
                        ))}
         | 
| 83 | 
            +
                      </div>
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                      <Card className="bg-muted/30 p-4 border-border">
         | 
| 86 | 
            +
                        <h3 className="font-semibold mb-3 flex items-center">
         | 
| 87 | 
            +
                          <GitCommit className="mr-2 text-orange-400 w-4 h-4" />
         | 
| 88 | 
            +
                          Data Flow Pipeline
         | 
| 89 | 
            +
                        </h3>
         | 
| 90 | 
            +
                        <div className="space-y-3 mb-6">
         | 
| 91 | 
            +
                          <div className="flex items-center justify-between bg-black/30 p-3 rounded">
         | 
| 92 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 93 | 
            +
                              <div className="w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center text-xs font-bold">1</div>
         | 
| 94 | 
            +
                              <span className="text-sm">Git Diff Analysis</span>
         | 
| 95 | 
            +
                            </div>
         | 
| 96 | 
            +
                            <span className="text-muted-foreground text-xs">diff_analyzer.py</span>
         | 
| 97 | 
            +
                          </div>
         | 
| 98 | 
            +
                          <div className="flex justify-center">
         | 
| 99 | 
            +
                            <div className="text-muted-foreground">↓</div>
         | 
| 100 | 
            +
                          </div>
         | 
| 101 | 
            +
                          <div className="flex items-center justify-between bg-black/30 p-3 rounded">
         | 
| 102 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 103 | 
            +
                              <div className="w-6 h-6 bg-green-500 rounded-full flex items-center justify-center text-xs font-bold">2</div>
         | 
| 104 | 
            +
                              <span className="text-sm">Text Embedding</span>
         | 
| 105 | 
            +
                            </div>
         | 
| 106 | 
            +
                            <span className="text-muted-foreground text-xs">embedder.py</span>
         | 
| 107 | 
            +
                          </div>
         | 
| 108 | 
            +
                          <div className="flex justify-center">
         | 
| 109 | 
            +
                            <div className="text-muted-foreground">↓</div>
         | 
| 110 | 
            +
                          </div>
         | 
| 111 | 
            +
                          <div className="flex items-center justify-between bg-black/30 p-3 rounded">
         | 
| 112 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 113 | 
            +
                              <div className="w-6 h-6 bg-purple-500 rounded-full flex items-center justify-center text-xs font-bold">3</div>
         | 
| 114 | 
            +
                              <span className="text-sm">Context Retrieval</span>
         | 
| 115 | 
            +
                            </div>
         | 
| 116 | 
            +
                            <span className="text-muted-foreground text-xs">retriever.py</span>
         | 
| 117 | 
            +
                          </div>
         | 
| 118 | 
            +
                          <div className="flex justify-center">
         | 
| 119 | 
            +
                            <div className="text-muted-foreground">↓</div>
         | 
| 120 | 
            +
                          </div>
         | 
| 121 | 
            +
                          <div className="flex items-center justify-between bg-black/30 p-3 rounded">
         | 
| 122 | 
            +
                            <div className="flex items-center space-x-2">
         | 
| 123 | 
            +
                              <div className="w-6 h-6 bg-orange-500 rounded-full flex items-center justify-center text-xs font-bold">4</div>
         | 
| 124 | 
            +
                              <span className="text-sm">Message Generation</span>
         | 
| 125 | 
            +
                            </div>
         | 
| 126 | 
            +
                            <span className="text-muted-foreground text-xs">generator.py</span>
         | 
| 127 | 
            +
                          </div>
         | 
| 128 | 
            +
                        </div>
         | 
| 129 | 
            +
                      </Card>
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                      <Card className="bg-muted/30 p-4 border-border">
         | 
| 132 | 
            +
                        <h3 className="font-semibold mb-3 flex items-center">
         | 
| 133 | 
            +
                          <FolderTree className="mr-2 text-primary w-4 h-4" />
         | 
| 134 | 
            +
                          Project Structure
         | 
| 135 | 
            +
                        </h3>
         | 
| 136 | 
            +
                        <div className="font-mono text-sm space-y-1 text-muted-foreground">
         | 
| 137 | 
            +
                          {projectStructure.map((item, index) => (
         | 
| 138 | 
            +
                            <div key={index} className="flex items-center" style={{ marginLeft: `${item.level * 16}px` }}>
         | 
| 139 | 
            +
                              <i className={`${item.type === 'folder' ? 'fas fa-folder text-blue-400' : 'fas fa-file text-green-400'} mr-2`}></i>
         | 
| 140 | 
            +
                              <span>{item.name}</span>
         | 
| 141 | 
            +
                              {item.badge && (
         | 
| 142 | 
            +
                                <Badge className="ml-2 text-xs bg-secondary px-2 py-1">
         | 
| 143 | 
            +
                                  {item.badge}
         | 
| 144 | 
            +
                                </Badge>
         | 
| 145 | 
            +
                              )}
         | 
| 146 | 
            +
                            </div>
         | 
| 147 | 
            +
                          ))}
         | 
| 148 | 
            +
                        </div>
         | 
| 149 | 
            +
                      </Card>
         | 
| 150 | 
            +
                    </div>
         | 
| 151 | 
            +
                  </div>
         | 
| 152 | 
            +
                </section>
         | 
| 153 | 
            +
              );
         | 
| 154 | 
            +
            }
         | 
    	
        client/src/components/ui/accordion.tsx
    ADDED
    
    | @@ -0,0 +1,56 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as AccordionPrimitive from "@radix-ui/react-accordion"
         | 
| 3 | 
            +
            import { ChevronDown } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const Accordion = AccordionPrimitive.Root
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const AccordionItem = React.forwardRef<
         | 
| 10 | 
            +
              React.ElementRef<typeof AccordionPrimitive.Item>,
         | 
| 11 | 
            +
              React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
         | 
| 12 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 13 | 
            +
              <AccordionPrimitive.Item
         | 
| 14 | 
            +
                ref={ref}
         | 
| 15 | 
            +
                className={cn("border-b", className)}
         | 
| 16 | 
            +
                {...props}
         | 
| 17 | 
            +
              />
         | 
| 18 | 
            +
            ))
         | 
| 19 | 
            +
            AccordionItem.displayName = "AccordionItem"
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            const AccordionTrigger = React.forwardRef<
         | 
| 22 | 
            +
              React.ElementRef<typeof AccordionPrimitive.Trigger>,
         | 
| 23 | 
            +
              React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
         | 
| 24 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 25 | 
            +
              <AccordionPrimitive.Header className="flex">
         | 
| 26 | 
            +
                <AccordionPrimitive.Trigger
         | 
| 27 | 
            +
                  ref={ref}
         | 
| 28 | 
            +
                  className={cn(
         | 
| 29 | 
            +
                    "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
         | 
| 30 | 
            +
                    className
         | 
| 31 | 
            +
                  )}
         | 
| 32 | 
            +
                  {...props}
         | 
| 33 | 
            +
                >
         | 
| 34 | 
            +
                  {children}
         | 
| 35 | 
            +
                  <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
         | 
| 36 | 
            +
                </AccordionPrimitive.Trigger>
         | 
| 37 | 
            +
              </AccordionPrimitive.Header>
         | 
| 38 | 
            +
            ))
         | 
| 39 | 
            +
            AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            const AccordionContent = React.forwardRef<
         | 
| 42 | 
            +
              React.ElementRef<typeof AccordionPrimitive.Content>,
         | 
| 43 | 
            +
              React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
         | 
| 44 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 45 | 
            +
              <AccordionPrimitive.Content
         | 
| 46 | 
            +
                ref={ref}
         | 
| 47 | 
            +
                className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
         | 
| 48 | 
            +
                {...props}
         | 
| 49 | 
            +
              >
         | 
| 50 | 
            +
                <div className={cn("pb-4 pt-0", className)}>{children}</div>
         | 
| 51 | 
            +
              </AccordionPrimitive.Content>
         | 
| 52 | 
            +
            ))
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            AccordionContent.displayName = AccordionPrimitive.Content.displayName
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
         | 
    	
        client/src/components/ui/alert-dialog.tsx
    ADDED
    
    | @@ -0,0 +1,139 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
            import { buttonVariants } from "@/components/ui/button"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const AlertDialog = AlertDialogPrimitive.Root
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const AlertDialogTrigger = AlertDialogPrimitive.Trigger
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const AlertDialogPortal = AlertDialogPrimitive.Portal
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            const AlertDialogOverlay = React.forwardRef<
         | 
| 14 | 
            +
              React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
         | 
| 15 | 
            +
              React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
         | 
| 16 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 17 | 
            +
              <AlertDialogPrimitive.Overlay
         | 
| 18 | 
            +
                className={cn(
         | 
| 19 | 
            +
                  "fixed inset-0 z-50 bg-black/80  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
         | 
| 20 | 
            +
                  className
         | 
| 21 | 
            +
                )}
         | 
| 22 | 
            +
                {...props}
         | 
| 23 | 
            +
                ref={ref}
         | 
| 24 | 
            +
              />
         | 
| 25 | 
            +
            ))
         | 
| 26 | 
            +
            AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            const AlertDialogContent = React.forwardRef<
         | 
| 29 | 
            +
              React.ElementRef<typeof AlertDialogPrimitive.Content>,
         | 
| 30 | 
            +
              React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
         | 
| 31 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 32 | 
            +
              <AlertDialogPortal>
         | 
| 33 | 
            +
                <AlertDialogOverlay />
         | 
| 34 | 
            +
                <AlertDialogPrimitive.Content
         | 
| 35 | 
            +
                  ref={ref}
         | 
| 36 | 
            +
                  className={cn(
         | 
| 37 | 
            +
                    "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
         | 
| 38 | 
            +
                    className
         | 
| 39 | 
            +
                  )}
         | 
| 40 | 
            +
                  {...props}
         | 
| 41 | 
            +
                />
         | 
| 42 | 
            +
              </AlertDialogPortal>
         | 
| 43 | 
            +
            ))
         | 
| 44 | 
            +
            AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            const AlertDialogHeader = ({
         | 
| 47 | 
            +
              className,
         | 
| 48 | 
            +
              ...props
         | 
| 49 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 50 | 
            +
              <div
         | 
| 51 | 
            +
                className={cn(
         | 
| 52 | 
            +
                  "flex flex-col space-y-2 text-center sm:text-left",
         | 
| 53 | 
            +
                  className
         | 
| 54 | 
            +
                )}
         | 
| 55 | 
            +
                {...props}
         | 
| 56 | 
            +
              />
         | 
| 57 | 
            +
            )
         | 
| 58 | 
            +
            AlertDialogHeader.displayName = "AlertDialogHeader"
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            const AlertDialogFooter = ({
         | 
| 61 | 
            +
              className,
         | 
| 62 | 
            +
              ...props
         | 
| 63 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 64 | 
            +
              <div
         | 
| 65 | 
            +
                className={cn(
         | 
| 66 | 
            +
                  "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
         | 
| 67 | 
            +
                  className
         | 
| 68 | 
            +
                )}
         | 
| 69 | 
            +
                {...props}
         | 
| 70 | 
            +
              />
         | 
| 71 | 
            +
            )
         | 
| 72 | 
            +
            AlertDialogFooter.displayName = "AlertDialogFooter"
         | 
| 73 | 
            +
             | 
| 74 | 
            +
            const AlertDialogTitle = React.forwardRef<
         | 
| 75 | 
            +
              React.ElementRef<typeof AlertDialogPrimitive.Title>,
         | 
| 76 | 
            +
              React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
         | 
| 77 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 78 | 
            +
              <AlertDialogPrimitive.Title
         | 
| 79 | 
            +
                ref={ref}
         | 
| 80 | 
            +
                className={cn("text-lg font-semibold", className)}
         | 
| 81 | 
            +
                {...props}
         | 
| 82 | 
            +
              />
         | 
| 83 | 
            +
            ))
         | 
| 84 | 
            +
            AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
         | 
| 85 | 
            +
             | 
| 86 | 
            +
            const AlertDialogDescription = React.forwardRef<
         | 
| 87 | 
            +
              React.ElementRef<typeof AlertDialogPrimitive.Description>,
         | 
| 88 | 
            +
              React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
         | 
| 89 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 90 | 
            +
              <AlertDialogPrimitive.Description
         | 
| 91 | 
            +
                ref={ref}
         | 
| 92 | 
            +
                className={cn("text-sm text-muted-foreground", className)}
         | 
| 93 | 
            +
                {...props}
         | 
| 94 | 
            +
              />
         | 
| 95 | 
            +
            ))
         | 
| 96 | 
            +
            AlertDialogDescription.displayName =
         | 
| 97 | 
            +
              AlertDialogPrimitive.Description.displayName
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            const AlertDialogAction = React.forwardRef<
         | 
| 100 | 
            +
              React.ElementRef<typeof AlertDialogPrimitive.Action>,
         | 
| 101 | 
            +
              React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
         | 
| 102 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 103 | 
            +
              <AlertDialogPrimitive.Action
         | 
| 104 | 
            +
                ref={ref}
         | 
| 105 | 
            +
                className={cn(buttonVariants(), className)}
         | 
| 106 | 
            +
                {...props}
         | 
| 107 | 
            +
              />
         | 
| 108 | 
            +
            ))
         | 
| 109 | 
            +
            AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            const AlertDialogCancel = React.forwardRef<
         | 
| 112 | 
            +
              React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
         | 
| 113 | 
            +
              React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
         | 
| 114 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 115 | 
            +
              <AlertDialogPrimitive.Cancel
         | 
| 116 | 
            +
                ref={ref}
         | 
| 117 | 
            +
                className={cn(
         | 
| 118 | 
            +
                  buttonVariants({ variant: "outline" }),
         | 
| 119 | 
            +
                  "mt-2 sm:mt-0",
         | 
| 120 | 
            +
                  className
         | 
| 121 | 
            +
                )}
         | 
| 122 | 
            +
                {...props}
         | 
| 123 | 
            +
              />
         | 
| 124 | 
            +
            ))
         | 
| 125 | 
            +
            AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
         | 
| 126 | 
            +
             | 
| 127 | 
            +
            export {
         | 
| 128 | 
            +
              AlertDialog,
         | 
| 129 | 
            +
              AlertDialogPortal,
         | 
| 130 | 
            +
              AlertDialogOverlay,
         | 
| 131 | 
            +
              AlertDialogTrigger,
         | 
| 132 | 
            +
              AlertDialogContent,
         | 
| 133 | 
            +
              AlertDialogHeader,
         | 
| 134 | 
            +
              AlertDialogFooter,
         | 
| 135 | 
            +
              AlertDialogTitle,
         | 
| 136 | 
            +
              AlertDialogDescription,
         | 
| 137 | 
            +
              AlertDialogAction,
         | 
| 138 | 
            +
              AlertDialogCancel,
         | 
| 139 | 
            +
            }
         | 
    	
        client/src/components/ui/alert.tsx
    ADDED
    
    | @@ -0,0 +1,59 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { cva, type VariantProps } from "class-variance-authority"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            const alertVariants = cva(
         | 
| 7 | 
            +
              "relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground",
         | 
| 8 | 
            +
              {
         | 
| 9 | 
            +
                variants: {
         | 
| 10 | 
            +
                  variant: {
         | 
| 11 | 
            +
                    default: "bg-background text-foreground",
         | 
| 12 | 
            +
                    destructive:
         | 
| 13 | 
            +
                      "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
         | 
| 14 | 
            +
                  },
         | 
| 15 | 
            +
                },
         | 
| 16 | 
            +
                defaultVariants: {
         | 
| 17 | 
            +
                  variant: "default",
         | 
| 18 | 
            +
                },
         | 
| 19 | 
            +
              }
         | 
| 20 | 
            +
            )
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            const Alert = React.forwardRef<
         | 
| 23 | 
            +
              HTMLDivElement,
         | 
| 24 | 
            +
              React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>
         | 
| 25 | 
            +
            >(({ className, variant, ...props }, ref) => (
         | 
| 26 | 
            +
              <div
         | 
| 27 | 
            +
                ref={ref}
         | 
| 28 | 
            +
                role="alert"
         | 
| 29 | 
            +
                className={cn(alertVariants({ variant }), className)}
         | 
| 30 | 
            +
                {...props}
         | 
| 31 | 
            +
              />
         | 
| 32 | 
            +
            ))
         | 
| 33 | 
            +
            Alert.displayName = "Alert"
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            const AlertTitle = React.forwardRef<
         | 
| 36 | 
            +
              HTMLParagraphElement,
         | 
| 37 | 
            +
              React.HTMLAttributes<HTMLHeadingElement>
         | 
| 38 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 39 | 
            +
              <h5
         | 
| 40 | 
            +
                ref={ref}
         | 
| 41 | 
            +
                className={cn("mb-1 font-medium leading-none tracking-tight", className)}
         | 
| 42 | 
            +
                {...props}
         | 
| 43 | 
            +
              />
         | 
| 44 | 
            +
            ))
         | 
| 45 | 
            +
            AlertTitle.displayName = "AlertTitle"
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            const AlertDescription = React.forwardRef<
         | 
| 48 | 
            +
              HTMLParagraphElement,
         | 
| 49 | 
            +
              React.HTMLAttributes<HTMLParagraphElement>
         | 
| 50 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 51 | 
            +
              <div
         | 
| 52 | 
            +
                ref={ref}
         | 
| 53 | 
            +
                className={cn("text-sm [&_p]:leading-relaxed", className)}
         | 
| 54 | 
            +
                {...props}
         | 
| 55 | 
            +
              />
         | 
| 56 | 
            +
            ))
         | 
| 57 | 
            +
            AlertDescription.displayName = "AlertDescription"
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            export { Alert, AlertTitle, AlertDescription }
         | 
    	
        client/src/components/ui/aspect-ratio.tsx
    ADDED
    
    | @@ -0,0 +1,5 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            const AspectRatio = AspectRatioPrimitive.Root
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            export { AspectRatio }
         | 
    	
        client/src/components/ui/avatar.tsx
    ADDED
    
    | @@ -0,0 +1,50 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as AvatarPrimitive from "@radix-ui/react-avatar"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const Avatar = React.forwardRef<
         | 
| 9 | 
            +
              React.ElementRef<typeof AvatarPrimitive.Root>,
         | 
| 10 | 
            +
              React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
         | 
| 11 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 12 | 
            +
              <AvatarPrimitive.Root
         | 
| 13 | 
            +
                ref={ref}
         | 
| 14 | 
            +
                className={cn(
         | 
| 15 | 
            +
                  "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
         | 
| 16 | 
            +
                  className
         | 
| 17 | 
            +
                )}
         | 
| 18 | 
            +
                {...props}
         | 
| 19 | 
            +
              />
         | 
| 20 | 
            +
            ))
         | 
| 21 | 
            +
            Avatar.displayName = AvatarPrimitive.Root.displayName
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            const AvatarImage = React.forwardRef<
         | 
| 24 | 
            +
              React.ElementRef<typeof AvatarPrimitive.Image>,
         | 
| 25 | 
            +
              React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
         | 
| 26 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 27 | 
            +
              <AvatarPrimitive.Image
         | 
| 28 | 
            +
                ref={ref}
         | 
| 29 | 
            +
                className={cn("aspect-square h-full w-full", className)}
         | 
| 30 | 
            +
                {...props}
         | 
| 31 | 
            +
              />
         | 
| 32 | 
            +
            ))
         | 
| 33 | 
            +
            AvatarImage.displayName = AvatarPrimitive.Image.displayName
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            const AvatarFallback = React.forwardRef<
         | 
| 36 | 
            +
              React.ElementRef<typeof AvatarPrimitive.Fallback>,
         | 
| 37 | 
            +
              React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
         | 
| 38 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 39 | 
            +
              <AvatarPrimitive.Fallback
         | 
| 40 | 
            +
                ref={ref}
         | 
| 41 | 
            +
                className={cn(
         | 
| 42 | 
            +
                  "flex h-full w-full items-center justify-center rounded-full bg-muted",
         | 
| 43 | 
            +
                  className
         | 
| 44 | 
            +
                )}
         | 
| 45 | 
            +
                {...props}
         | 
| 46 | 
            +
              />
         | 
| 47 | 
            +
            ))
         | 
| 48 | 
            +
            AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            export { Avatar, AvatarImage, AvatarFallback }
         | 
    	
        client/src/components/ui/badge.tsx
    ADDED
    
    | @@ -0,0 +1,36 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { cva, type VariantProps } from "class-variance-authority"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            const badgeVariants = cva(
         | 
| 7 | 
            +
              "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
         | 
| 8 | 
            +
              {
         | 
| 9 | 
            +
                variants: {
         | 
| 10 | 
            +
                  variant: {
         | 
| 11 | 
            +
                    default:
         | 
| 12 | 
            +
                      "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
         | 
| 13 | 
            +
                    secondary:
         | 
| 14 | 
            +
                      "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
         | 
| 15 | 
            +
                    destructive:
         | 
| 16 | 
            +
                      "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
         | 
| 17 | 
            +
                    outline: "text-foreground",
         | 
| 18 | 
            +
                  },
         | 
| 19 | 
            +
                },
         | 
| 20 | 
            +
                defaultVariants: {
         | 
| 21 | 
            +
                  variant: "default",
         | 
| 22 | 
            +
                },
         | 
| 23 | 
            +
              }
         | 
| 24 | 
            +
            )
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            export interface BadgeProps
         | 
| 27 | 
            +
              extends React.HTMLAttributes<HTMLDivElement>,
         | 
| 28 | 
            +
                VariantProps<typeof badgeVariants> {}
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            function Badge({ className, variant, ...props }: BadgeProps) {
         | 
| 31 | 
            +
              return (
         | 
| 32 | 
            +
                <div className={cn(badgeVariants({ variant }), className)} {...props} />
         | 
| 33 | 
            +
              )
         | 
| 34 | 
            +
            }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            export { Badge, badgeVariants }
         | 
    	
        client/src/components/ui/breadcrumb.tsx
    ADDED
    
    | @@ -0,0 +1,115 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { Slot } from "@radix-ui/react-slot"
         | 
| 3 | 
            +
            import { ChevronRight, MoreHorizontal } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const Breadcrumb = React.forwardRef<
         | 
| 8 | 
            +
              HTMLElement,
         | 
| 9 | 
            +
              React.ComponentPropsWithoutRef<"nav"> & {
         | 
| 10 | 
            +
                separator?: React.ReactNode
         | 
| 11 | 
            +
              }
         | 
| 12 | 
            +
            >(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />)
         | 
| 13 | 
            +
            Breadcrumb.displayName = "Breadcrumb"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            const BreadcrumbList = React.forwardRef<
         | 
| 16 | 
            +
              HTMLOListElement,
         | 
| 17 | 
            +
              React.ComponentPropsWithoutRef<"ol">
         | 
| 18 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 19 | 
            +
              <ol
         | 
| 20 | 
            +
                ref={ref}
         | 
| 21 | 
            +
                className={cn(
         | 
| 22 | 
            +
                  "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
         | 
| 23 | 
            +
                  className
         | 
| 24 | 
            +
                )}
         | 
| 25 | 
            +
                {...props}
         | 
| 26 | 
            +
              />
         | 
| 27 | 
            +
            ))
         | 
| 28 | 
            +
            BreadcrumbList.displayName = "BreadcrumbList"
         | 
| 29 | 
            +
             | 
| 30 | 
            +
            const BreadcrumbItem = React.forwardRef<
         | 
| 31 | 
            +
              HTMLLIElement,
         | 
| 32 | 
            +
              React.ComponentPropsWithoutRef<"li">
         | 
| 33 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 34 | 
            +
              <li
         | 
| 35 | 
            +
                ref={ref}
         | 
| 36 | 
            +
                className={cn("inline-flex items-center gap-1.5", className)}
         | 
| 37 | 
            +
                {...props}
         | 
| 38 | 
            +
              />
         | 
| 39 | 
            +
            ))
         | 
| 40 | 
            +
            BreadcrumbItem.displayName = "BreadcrumbItem"
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            const BreadcrumbLink = React.forwardRef<
         | 
| 43 | 
            +
              HTMLAnchorElement,
         | 
| 44 | 
            +
              React.ComponentPropsWithoutRef<"a"> & {
         | 
| 45 | 
            +
                asChild?: boolean
         | 
| 46 | 
            +
              }
         | 
| 47 | 
            +
            >(({ asChild, className, ...props }, ref) => {
         | 
| 48 | 
            +
              const Comp = asChild ? Slot : "a"
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              return (
         | 
| 51 | 
            +
                <Comp
         | 
| 52 | 
            +
                  ref={ref}
         | 
| 53 | 
            +
                  className={cn("transition-colors hover:text-foreground", className)}
         | 
| 54 | 
            +
                  {...props}
         | 
| 55 | 
            +
                />
         | 
| 56 | 
            +
              )
         | 
| 57 | 
            +
            })
         | 
| 58 | 
            +
            BreadcrumbLink.displayName = "BreadcrumbLink"
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            const BreadcrumbPage = React.forwardRef<
         | 
| 61 | 
            +
              HTMLSpanElement,
         | 
| 62 | 
            +
              React.ComponentPropsWithoutRef<"span">
         | 
| 63 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 64 | 
            +
              <span
         | 
| 65 | 
            +
                ref={ref}
         | 
| 66 | 
            +
                role="link"
         | 
| 67 | 
            +
                aria-disabled="true"
         | 
| 68 | 
            +
                aria-current="page"
         | 
| 69 | 
            +
                className={cn("font-normal text-foreground", className)}
         | 
| 70 | 
            +
                {...props}
         | 
| 71 | 
            +
              />
         | 
| 72 | 
            +
            ))
         | 
| 73 | 
            +
            BreadcrumbPage.displayName = "BreadcrumbPage"
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            const BreadcrumbSeparator = ({
         | 
| 76 | 
            +
              children,
         | 
| 77 | 
            +
              className,
         | 
| 78 | 
            +
              ...props
         | 
| 79 | 
            +
            }: React.ComponentProps<"li">) => (
         | 
| 80 | 
            +
              <li
         | 
| 81 | 
            +
                role="presentation"
         | 
| 82 | 
            +
                aria-hidden="true"
         | 
| 83 | 
            +
                className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)}
         | 
| 84 | 
            +
                {...props}
         | 
| 85 | 
            +
              >
         | 
| 86 | 
            +
                {children ?? <ChevronRight />}
         | 
| 87 | 
            +
              </li>
         | 
| 88 | 
            +
            )
         | 
| 89 | 
            +
            BreadcrumbSeparator.displayName = "BreadcrumbSeparator"
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            const BreadcrumbEllipsis = ({
         | 
| 92 | 
            +
              className,
         | 
| 93 | 
            +
              ...props
         | 
| 94 | 
            +
            }: React.ComponentProps<"span">) => (
         | 
| 95 | 
            +
              <span
         | 
| 96 | 
            +
                role="presentation"
         | 
| 97 | 
            +
                aria-hidden="true"
         | 
| 98 | 
            +
                className={cn("flex h-9 w-9 items-center justify-center", className)}
         | 
| 99 | 
            +
                {...props}
         | 
| 100 | 
            +
              >
         | 
| 101 | 
            +
                <MoreHorizontal className="h-4 w-4" />
         | 
| 102 | 
            +
                <span className="sr-only">More</span>
         | 
| 103 | 
            +
              </span>
         | 
| 104 | 
            +
            )
         | 
| 105 | 
            +
            BreadcrumbEllipsis.displayName = "BreadcrumbElipssis"
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            export {
         | 
| 108 | 
            +
              Breadcrumb,
         | 
| 109 | 
            +
              BreadcrumbList,
         | 
| 110 | 
            +
              BreadcrumbItem,
         | 
| 111 | 
            +
              BreadcrumbLink,
         | 
| 112 | 
            +
              BreadcrumbPage,
         | 
| 113 | 
            +
              BreadcrumbSeparator,
         | 
| 114 | 
            +
              BreadcrumbEllipsis,
         | 
| 115 | 
            +
            }
         | 
    	
        client/src/components/ui/button.tsx
    ADDED
    
    | @@ -0,0 +1,56 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { Slot } from "@radix-ui/react-slot"
         | 
| 3 | 
            +
            import { cva, type VariantProps } from "class-variance-authority"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const buttonVariants = cva(
         | 
| 8 | 
            +
              "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
         | 
| 9 | 
            +
              {
         | 
| 10 | 
            +
                variants: {
         | 
| 11 | 
            +
                  variant: {
         | 
| 12 | 
            +
                    default: "bg-primary text-primary-foreground hover:bg-primary/90",
         | 
| 13 | 
            +
                    destructive:
         | 
| 14 | 
            +
                      "bg-destructive text-destructive-foreground hover:bg-destructive/90",
         | 
| 15 | 
            +
                    outline:
         | 
| 16 | 
            +
                      "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
         | 
| 17 | 
            +
                    secondary:
         | 
| 18 | 
            +
                      "bg-secondary text-secondary-foreground hover:bg-secondary/80",
         | 
| 19 | 
            +
                    ghost: "hover:bg-accent hover:text-accent-foreground",
         | 
| 20 | 
            +
                    link: "text-primary underline-offset-4 hover:underline",
         | 
| 21 | 
            +
                  },
         | 
| 22 | 
            +
                  size: {
         | 
| 23 | 
            +
                    default: "h-10 px-4 py-2",
         | 
| 24 | 
            +
                    sm: "h-9 rounded-md px-3",
         | 
| 25 | 
            +
                    lg: "h-11 rounded-md px-8",
         | 
| 26 | 
            +
                    icon: "h-10 w-10",
         | 
| 27 | 
            +
                  },
         | 
| 28 | 
            +
                },
         | 
| 29 | 
            +
                defaultVariants: {
         | 
| 30 | 
            +
                  variant: "default",
         | 
| 31 | 
            +
                  size: "default",
         | 
| 32 | 
            +
                },
         | 
| 33 | 
            +
              }
         | 
| 34 | 
            +
            )
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            export interface ButtonProps
         | 
| 37 | 
            +
              extends React.ButtonHTMLAttributes<HTMLButtonElement>,
         | 
| 38 | 
            +
                VariantProps<typeof buttonVariants> {
         | 
| 39 | 
            +
              asChild?: boolean
         | 
| 40 | 
            +
            }
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
         | 
| 43 | 
            +
              ({ className, variant, size, asChild = false, ...props }, ref) => {
         | 
| 44 | 
            +
                const Comp = asChild ? Slot : "button"
         | 
| 45 | 
            +
                return (
         | 
| 46 | 
            +
                  <Comp
         | 
| 47 | 
            +
                    className={cn(buttonVariants({ variant, size, className }))}
         | 
| 48 | 
            +
                    ref={ref}
         | 
| 49 | 
            +
                    {...props}
         | 
| 50 | 
            +
                  />
         | 
| 51 | 
            +
                )
         | 
| 52 | 
            +
              }
         | 
| 53 | 
            +
            )
         | 
| 54 | 
            +
            Button.displayName = "Button"
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            export { Button, buttonVariants }
         | 
    	
        client/src/components/ui/calendar.tsx
    ADDED
    
    | @@ -0,0 +1,68 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { ChevronLeft, ChevronRight } from "lucide-react"
         | 
| 3 | 
            +
            import { DayPicker } from "react-day-picker"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
            import { buttonVariants } from "@/components/ui/button"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            export type CalendarProps = React.ComponentProps<typeof DayPicker>
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            function Calendar({
         | 
| 11 | 
            +
              className,
         | 
| 12 | 
            +
              classNames,
         | 
| 13 | 
            +
              showOutsideDays = true,
         | 
| 14 | 
            +
              ...props
         | 
| 15 | 
            +
            }: CalendarProps) {
         | 
| 16 | 
            +
              return (
         | 
| 17 | 
            +
                <DayPicker
         | 
| 18 | 
            +
                  showOutsideDays={showOutsideDays}
         | 
| 19 | 
            +
                  className={cn("p-3", className)}
         | 
| 20 | 
            +
                  classNames={{
         | 
| 21 | 
            +
                    months: "flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0",
         | 
| 22 | 
            +
                    month: "space-y-4",
         | 
| 23 | 
            +
                    caption: "flex justify-center pt-1 relative items-center",
         | 
| 24 | 
            +
                    caption_label: "text-sm font-medium",
         | 
| 25 | 
            +
                    nav: "space-x-1 flex items-center",
         | 
| 26 | 
            +
                    nav_button: cn(
         | 
| 27 | 
            +
                      buttonVariants({ variant: "outline" }),
         | 
| 28 | 
            +
                      "h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
         | 
| 29 | 
            +
                    ),
         | 
| 30 | 
            +
                    nav_button_previous: "absolute left-1",
         | 
| 31 | 
            +
                    nav_button_next: "absolute right-1",
         | 
| 32 | 
            +
                    table: "w-full border-collapse space-y-1",
         | 
| 33 | 
            +
                    head_row: "flex",
         | 
| 34 | 
            +
                    head_cell:
         | 
| 35 | 
            +
                      "text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]",
         | 
| 36 | 
            +
                    row: "flex w-full mt-2",
         | 
| 37 | 
            +
                    cell: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20",
         | 
| 38 | 
            +
                    day: cn(
         | 
| 39 | 
            +
                      buttonVariants({ variant: "ghost" }),
         | 
| 40 | 
            +
                      "h-9 w-9 p-0 font-normal aria-selected:opacity-100"
         | 
| 41 | 
            +
                    ),
         | 
| 42 | 
            +
                    day_range_end: "day-range-end",
         | 
| 43 | 
            +
                    day_selected:
         | 
| 44 | 
            +
                      "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
         | 
| 45 | 
            +
                    day_today: "bg-accent text-accent-foreground",
         | 
| 46 | 
            +
                    day_outside:
         | 
| 47 | 
            +
                      "day-outside text-muted-foreground aria-selected:bg-accent/50 aria-selected:text-muted-foreground",
         | 
| 48 | 
            +
                    day_disabled: "text-muted-foreground opacity-50",
         | 
| 49 | 
            +
                    day_range_middle:
         | 
| 50 | 
            +
                      "aria-selected:bg-accent aria-selected:text-accent-foreground",
         | 
| 51 | 
            +
                    day_hidden: "invisible",
         | 
| 52 | 
            +
                    ...classNames,
         | 
| 53 | 
            +
                  }}
         | 
| 54 | 
            +
                  components={{
         | 
| 55 | 
            +
                    IconLeft: ({ className, ...props }) => (
         | 
| 56 | 
            +
                      <ChevronLeft className={cn("h-4 w-4", className)} {...props} />
         | 
| 57 | 
            +
                    ),
         | 
| 58 | 
            +
                    IconRight: ({ className, ...props }) => (
         | 
| 59 | 
            +
                      <ChevronRight className={cn("h-4 w-4", className)} {...props} />
         | 
| 60 | 
            +
                    ),
         | 
| 61 | 
            +
                  }}
         | 
| 62 | 
            +
                  {...props}
         | 
| 63 | 
            +
                />
         | 
| 64 | 
            +
              )
         | 
| 65 | 
            +
            }
         | 
| 66 | 
            +
            Calendar.displayName = "Calendar"
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            export { Calendar }
         | 
    	
        client/src/components/ui/card.tsx
    ADDED
    
    | @@ -0,0 +1,79 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            const Card = React.forwardRef<
         | 
| 6 | 
            +
              HTMLDivElement,
         | 
| 7 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 8 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 9 | 
            +
              <div
         | 
| 10 | 
            +
                ref={ref}
         | 
| 11 | 
            +
                className={cn(
         | 
| 12 | 
            +
                  "rounded-lg border bg-card text-card-foreground shadow-sm",
         | 
| 13 | 
            +
                  className
         | 
| 14 | 
            +
                )}
         | 
| 15 | 
            +
                {...props}
         | 
| 16 | 
            +
              />
         | 
| 17 | 
            +
            ))
         | 
| 18 | 
            +
            Card.displayName = "Card"
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            const CardHeader = React.forwardRef<
         | 
| 21 | 
            +
              HTMLDivElement,
         | 
| 22 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 23 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 24 | 
            +
              <div
         | 
| 25 | 
            +
                ref={ref}
         | 
| 26 | 
            +
                className={cn("flex flex-col space-y-1.5 p-6", className)}
         | 
| 27 | 
            +
                {...props}
         | 
| 28 | 
            +
              />
         | 
| 29 | 
            +
            ))
         | 
| 30 | 
            +
            CardHeader.displayName = "CardHeader"
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            const CardTitle = React.forwardRef<
         | 
| 33 | 
            +
              HTMLDivElement,
         | 
| 34 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 35 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 36 | 
            +
              <div
         | 
| 37 | 
            +
                ref={ref}
         | 
| 38 | 
            +
                className={cn(
         | 
| 39 | 
            +
                  "text-2xl font-semibold leading-none tracking-tight",
         | 
| 40 | 
            +
                  className
         | 
| 41 | 
            +
                )}
         | 
| 42 | 
            +
                {...props}
         | 
| 43 | 
            +
              />
         | 
| 44 | 
            +
            ))
         | 
| 45 | 
            +
            CardTitle.displayName = "CardTitle"
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            const CardDescription = React.forwardRef<
         | 
| 48 | 
            +
              HTMLDivElement,
         | 
| 49 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 50 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 51 | 
            +
              <div
         | 
| 52 | 
            +
                ref={ref}
         | 
| 53 | 
            +
                className={cn("text-sm text-muted-foreground", className)}
         | 
| 54 | 
            +
                {...props}
         | 
| 55 | 
            +
              />
         | 
| 56 | 
            +
            ))
         | 
| 57 | 
            +
            CardDescription.displayName = "CardDescription"
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            const CardContent = React.forwardRef<
         | 
| 60 | 
            +
              HTMLDivElement,
         | 
| 61 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 62 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 63 | 
            +
              <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
         | 
| 64 | 
            +
            ))
         | 
| 65 | 
            +
            CardContent.displayName = "CardContent"
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            const CardFooter = React.forwardRef<
         | 
| 68 | 
            +
              HTMLDivElement,
         | 
| 69 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 70 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 71 | 
            +
              <div
         | 
| 72 | 
            +
                ref={ref}
         | 
| 73 | 
            +
                className={cn("flex items-center p-6 pt-0", className)}
         | 
| 74 | 
            +
                {...props}
         | 
| 75 | 
            +
              />
         | 
| 76 | 
            +
            ))
         | 
| 77 | 
            +
            CardFooter.displayName = "CardFooter"
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
         | 
    	
        client/src/components/ui/carousel.tsx
    ADDED
    
    | @@ -0,0 +1,260 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import useEmblaCarousel, {
         | 
| 3 | 
            +
              type UseEmblaCarouselType,
         | 
| 4 | 
            +
            } from "embla-carousel-react"
         | 
| 5 | 
            +
            import { ArrowLeft, ArrowRight } from "lucide-react"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 8 | 
            +
            import { Button } from "@/components/ui/button"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            type CarouselApi = UseEmblaCarouselType[1]
         | 
| 11 | 
            +
            type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
         | 
| 12 | 
            +
            type CarouselOptions = UseCarouselParameters[0]
         | 
| 13 | 
            +
            type CarouselPlugin = UseCarouselParameters[1]
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            type CarouselProps = {
         | 
| 16 | 
            +
              opts?: CarouselOptions
         | 
| 17 | 
            +
              plugins?: CarouselPlugin
         | 
| 18 | 
            +
              orientation?: "horizontal" | "vertical"
         | 
| 19 | 
            +
              setApi?: (api: CarouselApi) => void
         | 
| 20 | 
            +
            }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            type CarouselContextProps = {
         | 
| 23 | 
            +
              carouselRef: ReturnType<typeof useEmblaCarousel>[0]
         | 
| 24 | 
            +
              api: ReturnType<typeof useEmblaCarousel>[1]
         | 
| 25 | 
            +
              scrollPrev: () => void
         | 
| 26 | 
            +
              scrollNext: () => void
         | 
| 27 | 
            +
              canScrollPrev: boolean
         | 
| 28 | 
            +
              canScrollNext: boolean
         | 
| 29 | 
            +
            } & CarouselProps
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            const CarouselContext = React.createContext<CarouselContextProps | null>(null)
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            function useCarousel() {
         | 
| 34 | 
            +
              const context = React.useContext(CarouselContext)
         | 
| 35 | 
            +
             | 
| 36 | 
            +
              if (!context) {
         | 
| 37 | 
            +
                throw new Error("useCarousel must be used within a <Carousel />")
         | 
| 38 | 
            +
              }
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              return context
         | 
| 41 | 
            +
            }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            const Carousel = React.forwardRef<
         | 
| 44 | 
            +
              HTMLDivElement,
         | 
| 45 | 
            +
              React.HTMLAttributes<HTMLDivElement> & CarouselProps
         | 
| 46 | 
            +
            >(
         | 
| 47 | 
            +
              (
         | 
| 48 | 
            +
                {
         | 
| 49 | 
            +
                  orientation = "horizontal",
         | 
| 50 | 
            +
                  opts,
         | 
| 51 | 
            +
                  setApi,
         | 
| 52 | 
            +
                  plugins,
         | 
| 53 | 
            +
                  className,
         | 
| 54 | 
            +
                  children,
         | 
| 55 | 
            +
                  ...props
         | 
| 56 | 
            +
                },
         | 
| 57 | 
            +
                ref
         | 
| 58 | 
            +
              ) => {
         | 
| 59 | 
            +
                const [carouselRef, api] = useEmblaCarousel(
         | 
| 60 | 
            +
                  {
         | 
| 61 | 
            +
                    ...opts,
         | 
| 62 | 
            +
                    axis: orientation === "horizontal" ? "x" : "y",
         | 
| 63 | 
            +
                  },
         | 
| 64 | 
            +
                  plugins
         | 
| 65 | 
            +
                )
         | 
| 66 | 
            +
                const [canScrollPrev, setCanScrollPrev] = React.useState(false)
         | 
| 67 | 
            +
                const [canScrollNext, setCanScrollNext] = React.useState(false)
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                const onSelect = React.useCallback((api: CarouselApi) => {
         | 
| 70 | 
            +
                  if (!api) {
         | 
| 71 | 
            +
                    return
         | 
| 72 | 
            +
                  }
         | 
| 73 | 
            +
             | 
| 74 | 
            +
                  setCanScrollPrev(api.canScrollPrev())
         | 
| 75 | 
            +
                  setCanScrollNext(api.canScrollNext())
         | 
| 76 | 
            +
                }, [])
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                const scrollPrev = React.useCallback(() => {
         | 
| 79 | 
            +
                  api?.scrollPrev()
         | 
| 80 | 
            +
                }, [api])
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                const scrollNext = React.useCallback(() => {
         | 
| 83 | 
            +
                  api?.scrollNext()
         | 
| 84 | 
            +
                }, [api])
         | 
| 85 | 
            +
             | 
| 86 | 
            +
                const handleKeyDown = React.useCallback(
         | 
| 87 | 
            +
                  (event: React.KeyboardEvent<HTMLDivElement>) => {
         | 
| 88 | 
            +
                    if (event.key === "ArrowLeft") {
         | 
| 89 | 
            +
                      event.preventDefault()
         | 
| 90 | 
            +
                      scrollPrev()
         | 
| 91 | 
            +
                    } else if (event.key === "ArrowRight") {
         | 
| 92 | 
            +
                      event.preventDefault()
         | 
| 93 | 
            +
                      scrollNext()
         | 
| 94 | 
            +
                    }
         | 
| 95 | 
            +
                  },
         | 
| 96 | 
            +
                  [scrollPrev, scrollNext]
         | 
| 97 | 
            +
                )
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                React.useEffect(() => {
         | 
| 100 | 
            +
                  if (!api || !setApi) {
         | 
| 101 | 
            +
                    return
         | 
| 102 | 
            +
                  }
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                  setApi(api)
         | 
| 105 | 
            +
                }, [api, setApi])
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                React.useEffect(() => {
         | 
| 108 | 
            +
                  if (!api) {
         | 
| 109 | 
            +
                    return
         | 
| 110 | 
            +
                  }
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                  onSelect(api)
         | 
| 113 | 
            +
                  api.on("reInit", onSelect)
         | 
| 114 | 
            +
                  api.on("select", onSelect)
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                  return () => {
         | 
| 117 | 
            +
                    api?.off("select", onSelect)
         | 
| 118 | 
            +
                  }
         | 
| 119 | 
            +
                }, [api, onSelect])
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                return (
         | 
| 122 | 
            +
                  <CarouselContext.Provider
         | 
| 123 | 
            +
                    value={{
         | 
| 124 | 
            +
                      carouselRef,
         | 
| 125 | 
            +
                      api: api,
         | 
| 126 | 
            +
                      opts,
         | 
| 127 | 
            +
                      orientation:
         | 
| 128 | 
            +
                        orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),
         | 
| 129 | 
            +
                      scrollPrev,
         | 
| 130 | 
            +
                      scrollNext,
         | 
| 131 | 
            +
                      canScrollPrev,
         | 
| 132 | 
            +
                      canScrollNext,
         | 
| 133 | 
            +
                    }}
         | 
| 134 | 
            +
                  >
         | 
| 135 | 
            +
                    <div
         | 
| 136 | 
            +
                      ref={ref}
         | 
| 137 | 
            +
                      onKeyDownCapture={handleKeyDown}
         | 
| 138 | 
            +
                      className={cn("relative", className)}
         | 
| 139 | 
            +
                      role="region"
         | 
| 140 | 
            +
                      aria-roledescription="carousel"
         | 
| 141 | 
            +
                      {...props}
         | 
| 142 | 
            +
                    >
         | 
| 143 | 
            +
                      {children}
         | 
| 144 | 
            +
                    </div>
         | 
| 145 | 
            +
                  </CarouselContext.Provider>
         | 
| 146 | 
            +
                )
         | 
| 147 | 
            +
              }
         | 
| 148 | 
            +
            )
         | 
| 149 | 
            +
            Carousel.displayName = "Carousel"
         | 
| 150 | 
            +
             | 
| 151 | 
            +
            const CarouselContent = React.forwardRef<
         | 
| 152 | 
            +
              HTMLDivElement,
         | 
| 153 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 154 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 155 | 
            +
              const { carouselRef, orientation } = useCarousel()
         | 
| 156 | 
            +
             | 
| 157 | 
            +
              return (
         | 
| 158 | 
            +
                <div ref={carouselRef} className="overflow-hidden">
         | 
| 159 | 
            +
                  <div
         | 
| 160 | 
            +
                    ref={ref}
         | 
| 161 | 
            +
                    className={cn(
         | 
| 162 | 
            +
                      "flex",
         | 
| 163 | 
            +
                      orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
         | 
| 164 | 
            +
                      className
         | 
| 165 | 
            +
                    )}
         | 
| 166 | 
            +
                    {...props}
         | 
| 167 | 
            +
                  />
         | 
| 168 | 
            +
                </div>
         | 
| 169 | 
            +
              )
         | 
| 170 | 
            +
            })
         | 
| 171 | 
            +
            CarouselContent.displayName = "CarouselContent"
         | 
| 172 | 
            +
             | 
| 173 | 
            +
            const CarouselItem = React.forwardRef<
         | 
| 174 | 
            +
              HTMLDivElement,
         | 
| 175 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 176 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 177 | 
            +
              const { orientation } = useCarousel()
         | 
| 178 | 
            +
             | 
| 179 | 
            +
              return (
         | 
| 180 | 
            +
                <div
         | 
| 181 | 
            +
                  ref={ref}
         | 
| 182 | 
            +
                  role="group"
         | 
| 183 | 
            +
                  aria-roledescription="slide"
         | 
| 184 | 
            +
                  className={cn(
         | 
| 185 | 
            +
                    "min-w-0 shrink-0 grow-0 basis-full",
         | 
| 186 | 
            +
                    orientation === "horizontal" ? "pl-4" : "pt-4",
         | 
| 187 | 
            +
                    className
         | 
| 188 | 
            +
                  )}
         | 
| 189 | 
            +
                  {...props}
         | 
| 190 | 
            +
                />
         | 
| 191 | 
            +
              )
         | 
| 192 | 
            +
            })
         | 
| 193 | 
            +
            CarouselItem.displayName = "CarouselItem"
         | 
| 194 | 
            +
             | 
| 195 | 
            +
            const CarouselPrevious = React.forwardRef<
         | 
| 196 | 
            +
              HTMLButtonElement,
         | 
| 197 | 
            +
              React.ComponentProps<typeof Button>
         | 
| 198 | 
            +
            >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
         | 
| 199 | 
            +
              const { orientation, scrollPrev, canScrollPrev } = useCarousel()
         | 
| 200 | 
            +
             | 
| 201 | 
            +
              return (
         | 
| 202 | 
            +
                <Button
         | 
| 203 | 
            +
                  ref={ref}
         | 
| 204 | 
            +
                  variant={variant}
         | 
| 205 | 
            +
                  size={size}
         | 
| 206 | 
            +
                  className={cn(
         | 
| 207 | 
            +
                    "absolute  h-8 w-8 rounded-full",
         | 
| 208 | 
            +
                    orientation === "horizontal"
         | 
| 209 | 
            +
                      ? "-left-12 top-1/2 -translate-y-1/2"
         | 
| 210 | 
            +
                      : "-top-12 left-1/2 -translate-x-1/2 rotate-90",
         | 
| 211 | 
            +
                    className
         | 
| 212 | 
            +
                  )}
         | 
| 213 | 
            +
                  disabled={!canScrollPrev}
         | 
| 214 | 
            +
                  onClick={scrollPrev}
         | 
| 215 | 
            +
                  {...props}
         | 
| 216 | 
            +
                >
         | 
| 217 | 
            +
                  <ArrowLeft className="h-4 w-4" />
         | 
| 218 | 
            +
                  <span className="sr-only">Previous slide</span>
         | 
| 219 | 
            +
                </Button>
         | 
| 220 | 
            +
              )
         | 
| 221 | 
            +
            })
         | 
| 222 | 
            +
            CarouselPrevious.displayName = "CarouselPrevious"
         | 
| 223 | 
            +
             | 
| 224 | 
            +
            const CarouselNext = React.forwardRef<
         | 
| 225 | 
            +
              HTMLButtonElement,
         | 
| 226 | 
            +
              React.ComponentProps<typeof Button>
         | 
| 227 | 
            +
            >(({ className, variant = "outline", size = "icon", ...props }, ref) => {
         | 
| 228 | 
            +
              const { orientation, scrollNext, canScrollNext } = useCarousel()
         | 
| 229 | 
            +
             | 
| 230 | 
            +
              return (
         | 
| 231 | 
            +
                <Button
         | 
| 232 | 
            +
                  ref={ref}
         | 
| 233 | 
            +
                  variant={variant}
         | 
| 234 | 
            +
                  size={size}
         | 
| 235 | 
            +
                  className={cn(
         | 
| 236 | 
            +
                    "absolute h-8 w-8 rounded-full",
         | 
| 237 | 
            +
                    orientation === "horizontal"
         | 
| 238 | 
            +
                      ? "-right-12 top-1/2 -translate-y-1/2"
         | 
| 239 | 
            +
                      : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
         | 
| 240 | 
            +
                    className
         | 
| 241 | 
            +
                  )}
         | 
| 242 | 
            +
                  disabled={!canScrollNext}
         | 
| 243 | 
            +
                  onClick={scrollNext}
         | 
| 244 | 
            +
                  {...props}
         | 
| 245 | 
            +
                >
         | 
| 246 | 
            +
                  <ArrowRight className="h-4 w-4" />
         | 
| 247 | 
            +
                  <span className="sr-only">Next slide</span>
         | 
| 248 | 
            +
                </Button>
         | 
| 249 | 
            +
              )
         | 
| 250 | 
            +
            })
         | 
| 251 | 
            +
            CarouselNext.displayName = "CarouselNext"
         | 
| 252 | 
            +
             | 
| 253 | 
            +
            export {
         | 
| 254 | 
            +
              type CarouselApi,
         | 
| 255 | 
            +
              Carousel,
         | 
| 256 | 
            +
              CarouselContent,
         | 
| 257 | 
            +
              CarouselItem,
         | 
| 258 | 
            +
              CarouselPrevious,
         | 
| 259 | 
            +
              CarouselNext,
         | 
| 260 | 
            +
            }
         | 
    	
        client/src/components/ui/chart.tsx
    ADDED
    
    | @@ -0,0 +1,365 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as RechartsPrimitive from "recharts"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            // Format: { THEME_NAME: CSS_SELECTOR }
         | 
| 9 | 
            +
            const THEMES = { light: "", dark: ".dark" } as const
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            export type ChartConfig = {
         | 
| 12 | 
            +
              [k in string]: {
         | 
| 13 | 
            +
                label?: React.ReactNode
         | 
| 14 | 
            +
                icon?: React.ComponentType
         | 
| 15 | 
            +
              } & (
         | 
| 16 | 
            +
                | { color?: string; theme?: never }
         | 
| 17 | 
            +
                | { color?: never; theme: Record<keyof typeof THEMES, string> }
         | 
| 18 | 
            +
              )
         | 
| 19 | 
            +
            }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            type ChartContextProps = {
         | 
| 22 | 
            +
              config: ChartConfig
         | 
| 23 | 
            +
            }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            const ChartContext = React.createContext<ChartContextProps | null>(null)
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            function useChart() {
         | 
| 28 | 
            +
              const context = React.useContext(ChartContext)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              if (!context) {
         | 
| 31 | 
            +
                throw new Error("useChart must be used within a <ChartContainer />")
         | 
| 32 | 
            +
              }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              return context
         | 
| 35 | 
            +
            }
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            const ChartContainer = React.forwardRef<
         | 
| 38 | 
            +
              HTMLDivElement,
         | 
| 39 | 
            +
              React.ComponentProps<"div"> & {
         | 
| 40 | 
            +
                config: ChartConfig
         | 
| 41 | 
            +
                children: React.ComponentProps<
         | 
| 42 | 
            +
                  typeof RechartsPrimitive.ResponsiveContainer
         | 
| 43 | 
            +
                >["children"]
         | 
| 44 | 
            +
              }
         | 
| 45 | 
            +
            >(({ id, className, children, config, ...props }, ref) => {
         | 
| 46 | 
            +
              const uniqueId = React.useId()
         | 
| 47 | 
            +
              const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              return (
         | 
| 50 | 
            +
                <ChartContext.Provider value={{ config }}>
         | 
| 51 | 
            +
                  <div
         | 
| 52 | 
            +
                    data-chart={chartId}
         | 
| 53 | 
            +
                    ref={ref}
         | 
| 54 | 
            +
                    className={cn(
         | 
| 55 | 
            +
                      "flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
         | 
| 56 | 
            +
                      className
         | 
| 57 | 
            +
                    )}
         | 
| 58 | 
            +
                    {...props}
         | 
| 59 | 
            +
                  >
         | 
| 60 | 
            +
                    <ChartStyle id={chartId} config={config} />
         | 
| 61 | 
            +
                    <RechartsPrimitive.ResponsiveContainer>
         | 
| 62 | 
            +
                      {children}
         | 
| 63 | 
            +
                    </RechartsPrimitive.ResponsiveContainer>
         | 
| 64 | 
            +
                  </div>
         | 
| 65 | 
            +
                </ChartContext.Provider>
         | 
| 66 | 
            +
              )
         | 
| 67 | 
            +
            })
         | 
| 68 | 
            +
            ChartContainer.displayName = "Chart"
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            const ChartStyle = ({ id, config }: { id: string; config: ChartConfig }) => {
         | 
| 71 | 
            +
              const colorConfig = Object.entries(config).filter(
         | 
| 72 | 
            +
                ([, config]) => config.theme || config.color
         | 
| 73 | 
            +
              )
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              if (!colorConfig.length) {
         | 
| 76 | 
            +
                return null
         | 
| 77 | 
            +
              }
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              return (
         | 
| 80 | 
            +
                <style
         | 
| 81 | 
            +
                  dangerouslySetInnerHTML={{
         | 
| 82 | 
            +
                    __html: Object.entries(THEMES)
         | 
| 83 | 
            +
                      .map(
         | 
| 84 | 
            +
                        ([theme, prefix]) => `
         | 
| 85 | 
            +
            ${prefix} [data-chart=${id}] {
         | 
| 86 | 
            +
            ${colorConfig
         | 
| 87 | 
            +
              .map(([key, itemConfig]) => {
         | 
| 88 | 
            +
                const color =
         | 
| 89 | 
            +
                  itemConfig.theme?.[theme as keyof typeof itemConfig.theme] ||
         | 
| 90 | 
            +
                  itemConfig.color
         | 
| 91 | 
            +
                return color ? `  --color-${key}: ${color};` : null
         | 
| 92 | 
            +
              })
         | 
| 93 | 
            +
              .join("\n")}
         | 
| 94 | 
            +
            }
         | 
| 95 | 
            +
            `
         | 
| 96 | 
            +
                      )
         | 
| 97 | 
            +
                      .join("\n"),
         | 
| 98 | 
            +
                  }}
         | 
| 99 | 
            +
                />
         | 
| 100 | 
            +
              )
         | 
| 101 | 
            +
            }
         | 
| 102 | 
            +
             | 
| 103 | 
            +
            const ChartTooltip = RechartsPrimitive.Tooltip
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            const ChartTooltipContent = React.forwardRef<
         | 
| 106 | 
            +
              HTMLDivElement,
         | 
| 107 | 
            +
              React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
         | 
| 108 | 
            +
                React.ComponentProps<"div"> & {
         | 
| 109 | 
            +
                  hideLabel?: boolean
         | 
| 110 | 
            +
                  hideIndicator?: boolean
         | 
| 111 | 
            +
                  indicator?: "line" | "dot" | "dashed"
         | 
| 112 | 
            +
                  nameKey?: string
         | 
| 113 | 
            +
                  labelKey?: string
         | 
| 114 | 
            +
                }
         | 
| 115 | 
            +
            >(
         | 
| 116 | 
            +
              (
         | 
| 117 | 
            +
                {
         | 
| 118 | 
            +
                  active,
         | 
| 119 | 
            +
                  payload,
         | 
| 120 | 
            +
                  className,
         | 
| 121 | 
            +
                  indicator = "dot",
         | 
| 122 | 
            +
                  hideLabel = false,
         | 
| 123 | 
            +
                  hideIndicator = false,
         | 
| 124 | 
            +
                  label,
         | 
| 125 | 
            +
                  labelFormatter,
         | 
| 126 | 
            +
                  labelClassName,
         | 
| 127 | 
            +
                  formatter,
         | 
| 128 | 
            +
                  color,
         | 
| 129 | 
            +
                  nameKey,
         | 
| 130 | 
            +
                  labelKey,
         | 
| 131 | 
            +
                },
         | 
| 132 | 
            +
                ref
         | 
| 133 | 
            +
              ) => {
         | 
| 134 | 
            +
                const { config } = useChart()
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                const tooltipLabel = React.useMemo(() => {
         | 
| 137 | 
            +
                  if (hideLabel || !payload?.length) {
         | 
| 138 | 
            +
                    return null
         | 
| 139 | 
            +
                  }
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                  const [item] = payload
         | 
| 142 | 
            +
                  const key = `${labelKey || item?.dataKey || item?.name || "value"}`
         | 
| 143 | 
            +
                  const itemConfig = getPayloadConfigFromPayload(config, item, key)
         | 
| 144 | 
            +
                  const value =
         | 
| 145 | 
            +
                    !labelKey && typeof label === "string"
         | 
| 146 | 
            +
                      ? config[label as keyof typeof config]?.label || label
         | 
| 147 | 
            +
                      : itemConfig?.label
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                  if (labelFormatter) {
         | 
| 150 | 
            +
                    return (
         | 
| 151 | 
            +
                      <div className={cn("font-medium", labelClassName)}>
         | 
| 152 | 
            +
                        {labelFormatter(value, payload)}
         | 
| 153 | 
            +
                      </div>
         | 
| 154 | 
            +
                    )
         | 
| 155 | 
            +
                  }
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  if (!value) {
         | 
| 158 | 
            +
                    return null
         | 
| 159 | 
            +
                  }
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                  return <div className={cn("font-medium", labelClassName)}>{value}</div>
         | 
| 162 | 
            +
                }, [
         | 
| 163 | 
            +
                  label,
         | 
| 164 | 
            +
                  labelFormatter,
         | 
| 165 | 
            +
                  payload,
         | 
| 166 | 
            +
                  hideLabel,
         | 
| 167 | 
            +
                  labelClassName,
         | 
| 168 | 
            +
                  config,
         | 
| 169 | 
            +
                  labelKey,
         | 
| 170 | 
            +
                ])
         | 
| 171 | 
            +
             | 
| 172 | 
            +
                if (!active || !payload?.length) {
         | 
| 173 | 
            +
                  return null
         | 
| 174 | 
            +
                }
         | 
| 175 | 
            +
             | 
| 176 | 
            +
                const nestLabel = payload.length === 1 && indicator !== "dot"
         | 
| 177 | 
            +
             | 
| 178 | 
            +
                return (
         | 
| 179 | 
            +
                  <div
         | 
| 180 | 
            +
                    ref={ref}
         | 
| 181 | 
            +
                    className={cn(
         | 
| 182 | 
            +
                      "grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
         | 
| 183 | 
            +
                      className
         | 
| 184 | 
            +
                    )}
         | 
| 185 | 
            +
                  >
         | 
| 186 | 
            +
                    {!nestLabel ? tooltipLabel : null}
         | 
| 187 | 
            +
                    <div className="grid gap-1.5">
         | 
| 188 | 
            +
                      {payload.map((item, index) => {
         | 
| 189 | 
            +
                        const key = `${nameKey || item.name || item.dataKey || "value"}`
         | 
| 190 | 
            +
                        const itemConfig = getPayloadConfigFromPayload(config, item, key)
         | 
| 191 | 
            +
                        const indicatorColor = color || item.payload.fill || item.color
         | 
| 192 | 
            +
             | 
| 193 | 
            +
                        return (
         | 
| 194 | 
            +
                          <div
         | 
| 195 | 
            +
                            key={item.dataKey}
         | 
| 196 | 
            +
                            className={cn(
         | 
| 197 | 
            +
                              "flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
         | 
| 198 | 
            +
                              indicator === "dot" && "items-center"
         | 
| 199 | 
            +
                            )}
         | 
| 200 | 
            +
                          >
         | 
| 201 | 
            +
                            {formatter && item?.value !== undefined && item.name ? (
         | 
| 202 | 
            +
                              formatter(item.value, item.name, item, index, item.payload)
         | 
| 203 | 
            +
                            ) : (
         | 
| 204 | 
            +
                              <>
         | 
| 205 | 
            +
                                {itemConfig?.icon ? (
         | 
| 206 | 
            +
                                  <itemConfig.icon />
         | 
| 207 | 
            +
                                ) : (
         | 
| 208 | 
            +
                                  !hideIndicator && (
         | 
| 209 | 
            +
                                    <div
         | 
| 210 | 
            +
                                      className={cn(
         | 
| 211 | 
            +
                                        "shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
         | 
| 212 | 
            +
                                        {
         | 
| 213 | 
            +
                                          "h-2.5 w-2.5": indicator === "dot",
         | 
| 214 | 
            +
                                          "w-1": indicator === "line",
         | 
| 215 | 
            +
                                          "w-0 border-[1.5px] border-dashed bg-transparent":
         | 
| 216 | 
            +
                                            indicator === "dashed",
         | 
| 217 | 
            +
                                          "my-0.5": nestLabel && indicator === "dashed",
         | 
| 218 | 
            +
                                        }
         | 
| 219 | 
            +
                                      )}
         | 
| 220 | 
            +
                                      style={
         | 
| 221 | 
            +
                                        {
         | 
| 222 | 
            +
                                          "--color-bg": indicatorColor,
         | 
| 223 | 
            +
                                          "--color-border": indicatorColor,
         | 
| 224 | 
            +
                                        } as React.CSSProperties
         | 
| 225 | 
            +
                                      }
         | 
| 226 | 
            +
                                    />
         | 
| 227 | 
            +
                                  )
         | 
| 228 | 
            +
                                )}
         | 
| 229 | 
            +
                                <div
         | 
| 230 | 
            +
                                  className={cn(
         | 
| 231 | 
            +
                                    "flex flex-1 justify-between leading-none",
         | 
| 232 | 
            +
                                    nestLabel ? "items-end" : "items-center"
         | 
| 233 | 
            +
                                  )}
         | 
| 234 | 
            +
                                >
         | 
| 235 | 
            +
                                  <div className="grid gap-1.5">
         | 
| 236 | 
            +
                                    {nestLabel ? tooltipLabel : null}
         | 
| 237 | 
            +
                                    <span className="text-muted-foreground">
         | 
| 238 | 
            +
                                      {itemConfig?.label || item.name}
         | 
| 239 | 
            +
                                    </span>
         | 
| 240 | 
            +
                                  </div>
         | 
| 241 | 
            +
                                  {item.value && (
         | 
| 242 | 
            +
                                    <span className="font-mono font-medium tabular-nums text-foreground">
         | 
| 243 | 
            +
                                      {item.value.toLocaleString()}
         | 
| 244 | 
            +
                                    </span>
         | 
| 245 | 
            +
                                  )}
         | 
| 246 | 
            +
                                </div>
         | 
| 247 | 
            +
                              </>
         | 
| 248 | 
            +
                            )}
         | 
| 249 | 
            +
                          </div>
         | 
| 250 | 
            +
                        )
         | 
| 251 | 
            +
                      })}
         | 
| 252 | 
            +
                    </div>
         | 
| 253 | 
            +
                  </div>
         | 
| 254 | 
            +
                )
         | 
| 255 | 
            +
              }
         | 
| 256 | 
            +
            )
         | 
| 257 | 
            +
            ChartTooltipContent.displayName = "ChartTooltip"
         | 
| 258 | 
            +
             | 
| 259 | 
            +
            const ChartLegend = RechartsPrimitive.Legend
         | 
| 260 | 
            +
             | 
| 261 | 
            +
            const ChartLegendContent = React.forwardRef<
         | 
| 262 | 
            +
              HTMLDivElement,
         | 
| 263 | 
            +
              React.ComponentProps<"div"> &
         | 
| 264 | 
            +
                Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
         | 
| 265 | 
            +
                  hideIcon?: boolean
         | 
| 266 | 
            +
                  nameKey?: string
         | 
| 267 | 
            +
                }
         | 
| 268 | 
            +
            >(
         | 
| 269 | 
            +
              (
         | 
| 270 | 
            +
                { className, hideIcon = false, payload, verticalAlign = "bottom", nameKey },
         | 
| 271 | 
            +
                ref
         | 
| 272 | 
            +
              ) => {
         | 
| 273 | 
            +
                const { config } = useChart()
         | 
| 274 | 
            +
             | 
| 275 | 
            +
                if (!payload?.length) {
         | 
| 276 | 
            +
                  return null
         | 
| 277 | 
            +
                }
         | 
| 278 | 
            +
             | 
| 279 | 
            +
                return (
         | 
| 280 | 
            +
                  <div
         | 
| 281 | 
            +
                    ref={ref}
         | 
| 282 | 
            +
                    className={cn(
         | 
| 283 | 
            +
                      "flex items-center justify-center gap-4",
         | 
| 284 | 
            +
                      verticalAlign === "top" ? "pb-3" : "pt-3",
         | 
| 285 | 
            +
                      className
         | 
| 286 | 
            +
                    )}
         | 
| 287 | 
            +
                  >
         | 
| 288 | 
            +
                    {payload.map((item) => {
         | 
| 289 | 
            +
                      const key = `${nameKey || item.dataKey || "value"}`
         | 
| 290 | 
            +
                      const itemConfig = getPayloadConfigFromPayload(config, item, key)
         | 
| 291 | 
            +
             | 
| 292 | 
            +
                      return (
         | 
| 293 | 
            +
                        <div
         | 
| 294 | 
            +
                          key={item.value}
         | 
| 295 | 
            +
                          className={cn(
         | 
| 296 | 
            +
                            "flex items-center gap-1.5 [&>svg]:h-3 [&>svg]:w-3 [&>svg]:text-muted-foreground"
         | 
| 297 | 
            +
                          )}
         | 
| 298 | 
            +
                        >
         | 
| 299 | 
            +
                          {itemConfig?.icon && !hideIcon ? (
         | 
| 300 | 
            +
                            <itemConfig.icon />
         | 
| 301 | 
            +
                          ) : (
         | 
| 302 | 
            +
                            <div
         | 
| 303 | 
            +
                              className="h-2 w-2 shrink-0 rounded-[2px]"
         | 
| 304 | 
            +
                              style={{
         | 
| 305 | 
            +
                                backgroundColor: item.color,
         | 
| 306 | 
            +
                              }}
         | 
| 307 | 
            +
                            />
         | 
| 308 | 
            +
                          )}
         | 
| 309 | 
            +
                          {itemConfig?.label}
         | 
| 310 | 
            +
                        </div>
         | 
| 311 | 
            +
                      )
         | 
| 312 | 
            +
                    })}
         | 
| 313 | 
            +
                  </div>
         | 
| 314 | 
            +
                )
         | 
| 315 | 
            +
              }
         | 
| 316 | 
            +
            )
         | 
| 317 | 
            +
            ChartLegendContent.displayName = "ChartLegend"
         | 
| 318 | 
            +
             | 
| 319 | 
            +
            // Helper to extract item config from a payload.
         | 
| 320 | 
            +
            function getPayloadConfigFromPayload(
         | 
| 321 | 
            +
              config: ChartConfig,
         | 
| 322 | 
            +
              payload: unknown,
         | 
| 323 | 
            +
              key: string
         | 
| 324 | 
            +
            ) {
         | 
| 325 | 
            +
              if (typeof payload !== "object" || payload === null) {
         | 
| 326 | 
            +
                return undefined
         | 
| 327 | 
            +
              }
         | 
| 328 | 
            +
             | 
| 329 | 
            +
              const payloadPayload =
         | 
| 330 | 
            +
                "payload" in payload &&
         | 
| 331 | 
            +
                typeof payload.payload === "object" &&
         | 
| 332 | 
            +
                payload.payload !== null
         | 
| 333 | 
            +
                  ? payload.payload
         | 
| 334 | 
            +
                  : undefined
         | 
| 335 | 
            +
             | 
| 336 | 
            +
              let configLabelKey: string = key
         | 
| 337 | 
            +
             | 
| 338 | 
            +
              if (
         | 
| 339 | 
            +
                key in payload &&
         | 
| 340 | 
            +
                typeof payload[key as keyof typeof payload] === "string"
         | 
| 341 | 
            +
              ) {
         | 
| 342 | 
            +
                configLabelKey = payload[key as keyof typeof payload] as string
         | 
| 343 | 
            +
              } else if (
         | 
| 344 | 
            +
                payloadPayload &&
         | 
| 345 | 
            +
                key in payloadPayload &&
         | 
| 346 | 
            +
                typeof payloadPayload[key as keyof typeof payloadPayload] === "string"
         | 
| 347 | 
            +
              ) {
         | 
| 348 | 
            +
                configLabelKey = payloadPayload[
         | 
| 349 | 
            +
                  key as keyof typeof payloadPayload
         | 
| 350 | 
            +
                ] as string
         | 
| 351 | 
            +
              }
         | 
| 352 | 
            +
             | 
| 353 | 
            +
              return configLabelKey in config
         | 
| 354 | 
            +
                ? config[configLabelKey]
         | 
| 355 | 
            +
                : config[key as keyof typeof config]
         | 
| 356 | 
            +
            }
         | 
| 357 | 
            +
             | 
| 358 | 
            +
            export {
         | 
| 359 | 
            +
              ChartContainer,
         | 
| 360 | 
            +
              ChartTooltip,
         | 
| 361 | 
            +
              ChartTooltipContent,
         | 
| 362 | 
            +
              ChartLegend,
         | 
| 363 | 
            +
              ChartLegendContent,
         | 
| 364 | 
            +
              ChartStyle,
         | 
| 365 | 
            +
            }
         | 
    	
        client/src/components/ui/checkbox.tsx
    ADDED
    
    | @@ -0,0 +1,28 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
         | 
| 3 | 
            +
            import { Check } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const Checkbox = React.forwardRef<
         | 
| 8 | 
            +
              React.ElementRef<typeof CheckboxPrimitive.Root>,
         | 
| 9 | 
            +
              React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
         | 
| 10 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 11 | 
            +
              <CheckboxPrimitive.Root
         | 
| 12 | 
            +
                ref={ref}
         | 
| 13 | 
            +
                className={cn(
         | 
| 14 | 
            +
                  "peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
         | 
| 15 | 
            +
                  className
         | 
| 16 | 
            +
                )}
         | 
| 17 | 
            +
                {...props}
         | 
| 18 | 
            +
              >
         | 
| 19 | 
            +
                <CheckboxPrimitive.Indicator
         | 
| 20 | 
            +
                  className={cn("flex items-center justify-center text-current")}
         | 
| 21 | 
            +
                >
         | 
| 22 | 
            +
                  <Check className="h-4 w-4" />
         | 
| 23 | 
            +
                </CheckboxPrimitive.Indicator>
         | 
| 24 | 
            +
              </CheckboxPrimitive.Root>
         | 
| 25 | 
            +
            ))
         | 
| 26 | 
            +
            Checkbox.displayName = CheckboxPrimitive.Root.displayName
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            export { Checkbox }
         | 
    	
        client/src/components/ui/collapsible.tsx
    ADDED
    
    | @@ -0,0 +1,11 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            const Collapsible = CollapsiblePrimitive.Root
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            export { Collapsible, CollapsibleTrigger, CollapsibleContent }
         | 
    	
        client/src/components/ui/command.tsx
    ADDED
    
    | @@ -0,0 +1,151 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { type DialogProps } from "@radix-ui/react-dialog"
         | 
| 3 | 
            +
            import { Command as CommandPrimitive } from "cmdk"
         | 
| 4 | 
            +
            import { Search } from "lucide-react"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
            import { Dialog, DialogContent } from "@/components/ui/dialog"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const Command = React.forwardRef<
         | 
| 10 | 
            +
              React.ElementRef<typeof CommandPrimitive>,
         | 
| 11 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive>
         | 
| 12 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 13 | 
            +
              <CommandPrimitive
         | 
| 14 | 
            +
                ref={ref}
         | 
| 15 | 
            +
                className={cn(
         | 
| 16 | 
            +
                  "flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
         | 
| 17 | 
            +
                  className
         | 
| 18 | 
            +
                )}
         | 
| 19 | 
            +
                {...props}
         | 
| 20 | 
            +
              />
         | 
| 21 | 
            +
            ))
         | 
| 22 | 
            +
            Command.displayName = CommandPrimitive.displayName
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            const CommandDialog = ({ children, ...props }: DialogProps) => {
         | 
| 25 | 
            +
              return (
         | 
| 26 | 
            +
                <Dialog {...props}>
         | 
| 27 | 
            +
                  <DialogContent className="overflow-hidden p-0 shadow-lg">
         | 
| 28 | 
            +
                    <Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
         | 
| 29 | 
            +
                      {children}
         | 
| 30 | 
            +
                    </Command>
         | 
| 31 | 
            +
                  </DialogContent>
         | 
| 32 | 
            +
                </Dialog>
         | 
| 33 | 
            +
              )
         | 
| 34 | 
            +
            }
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            const CommandInput = React.forwardRef<
         | 
| 37 | 
            +
              React.ElementRef<typeof CommandPrimitive.Input>,
         | 
| 38 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
         | 
| 39 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 40 | 
            +
              <div className="flex items-center border-b px-3" cmdk-input-wrapper="">
         | 
| 41 | 
            +
                <Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
         | 
| 42 | 
            +
                <CommandPrimitive.Input
         | 
| 43 | 
            +
                  ref={ref}
         | 
| 44 | 
            +
                  className={cn(
         | 
| 45 | 
            +
                    "flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
         | 
| 46 | 
            +
                    className
         | 
| 47 | 
            +
                  )}
         | 
| 48 | 
            +
                  {...props}
         | 
| 49 | 
            +
                />
         | 
| 50 | 
            +
              </div>
         | 
| 51 | 
            +
            ))
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            CommandInput.displayName = CommandPrimitive.Input.displayName
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            const CommandList = React.forwardRef<
         | 
| 56 | 
            +
              React.ElementRef<typeof CommandPrimitive.List>,
         | 
| 57 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
         | 
| 58 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 59 | 
            +
              <CommandPrimitive.List
         | 
| 60 | 
            +
                ref={ref}
         | 
| 61 | 
            +
                className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
         | 
| 62 | 
            +
                {...props}
         | 
| 63 | 
            +
              />
         | 
| 64 | 
            +
            ))
         | 
| 65 | 
            +
             | 
| 66 | 
            +
            CommandList.displayName = CommandPrimitive.List.displayName
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            const CommandEmpty = React.forwardRef<
         | 
| 69 | 
            +
              React.ElementRef<typeof CommandPrimitive.Empty>,
         | 
| 70 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
         | 
| 71 | 
            +
            >((props, ref) => (
         | 
| 72 | 
            +
              <CommandPrimitive.Empty
         | 
| 73 | 
            +
                ref={ref}
         | 
| 74 | 
            +
                className="py-6 text-center text-sm"
         | 
| 75 | 
            +
                {...props}
         | 
| 76 | 
            +
              />
         | 
| 77 | 
            +
            ))
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            CommandEmpty.displayName = CommandPrimitive.Empty.displayName
         | 
| 80 | 
            +
             | 
| 81 | 
            +
            const CommandGroup = React.forwardRef<
         | 
| 82 | 
            +
              React.ElementRef<typeof CommandPrimitive.Group>,
         | 
| 83 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
         | 
| 84 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 85 | 
            +
              <CommandPrimitive.Group
         | 
| 86 | 
            +
                ref={ref}
         | 
| 87 | 
            +
                className={cn(
         | 
| 88 | 
            +
                  "overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
         | 
| 89 | 
            +
                  className
         | 
| 90 | 
            +
                )}
         | 
| 91 | 
            +
                {...props}
         | 
| 92 | 
            +
              />
         | 
| 93 | 
            +
            ))
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            CommandGroup.displayName = CommandPrimitive.Group.displayName
         | 
| 96 | 
            +
             | 
| 97 | 
            +
            const CommandSeparator = React.forwardRef<
         | 
| 98 | 
            +
              React.ElementRef<typeof CommandPrimitive.Separator>,
         | 
| 99 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
         | 
| 100 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 101 | 
            +
              <CommandPrimitive.Separator
         | 
| 102 | 
            +
                ref={ref}
         | 
| 103 | 
            +
                className={cn("-mx-1 h-px bg-border", className)}
         | 
| 104 | 
            +
                {...props}
         | 
| 105 | 
            +
              />
         | 
| 106 | 
            +
            ))
         | 
| 107 | 
            +
            CommandSeparator.displayName = CommandPrimitive.Separator.displayName
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            const CommandItem = React.forwardRef<
         | 
| 110 | 
            +
              React.ElementRef<typeof CommandPrimitive.Item>,
         | 
| 111 | 
            +
              React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
         | 
| 112 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 113 | 
            +
              <CommandPrimitive.Item
         | 
| 114 | 
            +
                ref={ref}
         | 
| 115 | 
            +
                className={cn(
         | 
| 116 | 
            +
                  "relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
         | 
| 117 | 
            +
                  className
         | 
| 118 | 
            +
                )}
         | 
| 119 | 
            +
                {...props}
         | 
| 120 | 
            +
              />
         | 
| 121 | 
            +
            ))
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            CommandItem.displayName = CommandPrimitive.Item.displayName
         | 
| 124 | 
            +
             | 
| 125 | 
            +
            const CommandShortcut = ({
         | 
| 126 | 
            +
              className,
         | 
| 127 | 
            +
              ...props
         | 
| 128 | 
            +
            }: React.HTMLAttributes<HTMLSpanElement>) => {
         | 
| 129 | 
            +
              return (
         | 
| 130 | 
            +
                <span
         | 
| 131 | 
            +
                  className={cn(
         | 
| 132 | 
            +
                    "ml-auto text-xs tracking-widest text-muted-foreground",
         | 
| 133 | 
            +
                    className
         | 
| 134 | 
            +
                  )}
         | 
| 135 | 
            +
                  {...props}
         | 
| 136 | 
            +
                />
         | 
| 137 | 
            +
              )
         | 
| 138 | 
            +
            }
         | 
| 139 | 
            +
            CommandShortcut.displayName = "CommandShortcut"
         | 
| 140 | 
            +
             | 
| 141 | 
            +
            export {
         | 
| 142 | 
            +
              Command,
         | 
| 143 | 
            +
              CommandDialog,
         | 
| 144 | 
            +
              CommandInput,
         | 
| 145 | 
            +
              CommandList,
         | 
| 146 | 
            +
              CommandEmpty,
         | 
| 147 | 
            +
              CommandGroup,
         | 
| 148 | 
            +
              CommandItem,
         | 
| 149 | 
            +
              CommandShortcut,
         | 
| 150 | 
            +
              CommandSeparator,
         | 
| 151 | 
            +
            }
         | 
    	
        client/src/components/ui/context-menu.tsx
    ADDED
    
    | @@ -0,0 +1,198 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
         | 
| 3 | 
            +
            import { Check, ChevronRight, Circle } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const ContextMenu = ContextMenuPrimitive.Root
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const ContextMenuTrigger = ContextMenuPrimitive.Trigger
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const ContextMenuGroup = ContextMenuPrimitive.Group
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            const ContextMenuPortal = ContextMenuPrimitive.Portal
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            const ContextMenuSub = ContextMenuPrimitive.Sub
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            const ContextMenuSubTrigger = React.forwardRef<
         | 
| 20 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
         | 
| 21 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
         | 
| 22 | 
            +
                inset?: boolean
         | 
| 23 | 
            +
              }
         | 
| 24 | 
            +
            >(({ className, inset, children, ...props }, ref) => (
         | 
| 25 | 
            +
              <ContextMenuPrimitive.SubTrigger
         | 
| 26 | 
            +
                ref={ref}
         | 
| 27 | 
            +
                className={cn(
         | 
| 28 | 
            +
                  "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
         | 
| 29 | 
            +
                  inset && "pl-8",
         | 
| 30 | 
            +
                  className
         | 
| 31 | 
            +
                )}
         | 
| 32 | 
            +
                {...props}
         | 
| 33 | 
            +
              >
         | 
| 34 | 
            +
                {children}
         | 
| 35 | 
            +
                <ChevronRight className="ml-auto h-4 w-4" />
         | 
| 36 | 
            +
              </ContextMenuPrimitive.SubTrigger>
         | 
| 37 | 
            +
            ))
         | 
| 38 | 
            +
            ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            const ContextMenuSubContent = React.forwardRef<
         | 
| 41 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
         | 
| 42 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
         | 
| 43 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 44 | 
            +
              <ContextMenuPrimitive.SubContent
         | 
| 45 | 
            +
                ref={ref}
         | 
| 46 | 
            +
                className={cn(
         | 
| 47 | 
            +
                  "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]",
         | 
| 48 | 
            +
                  className
         | 
| 49 | 
            +
                )}
         | 
| 50 | 
            +
                {...props}
         | 
| 51 | 
            +
              />
         | 
| 52 | 
            +
            ))
         | 
| 53 | 
            +
            ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
         | 
| 54 | 
            +
             | 
| 55 | 
            +
            const ContextMenuContent = React.forwardRef<
         | 
| 56 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.Content>,
         | 
| 57 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
         | 
| 58 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 59 | 
            +
              <ContextMenuPrimitive.Portal>
         | 
| 60 | 
            +
                <ContextMenuPrimitive.Content
         | 
| 61 | 
            +
                  ref={ref}
         | 
| 62 | 
            +
                  className={cn(
         | 
| 63 | 
            +
                    "z-50 max-h-[--radix-context-menu-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]",
         | 
| 64 | 
            +
                    className
         | 
| 65 | 
            +
                  )}
         | 
| 66 | 
            +
                  {...props}
         | 
| 67 | 
            +
                />
         | 
| 68 | 
            +
              </ContextMenuPrimitive.Portal>
         | 
| 69 | 
            +
            ))
         | 
| 70 | 
            +
            ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            const ContextMenuItem = React.forwardRef<
         | 
| 73 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.Item>,
         | 
| 74 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
         | 
| 75 | 
            +
                inset?: boolean
         | 
| 76 | 
            +
              }
         | 
| 77 | 
            +
            >(({ className, inset, ...props }, ref) => (
         | 
| 78 | 
            +
              <ContextMenuPrimitive.Item
         | 
| 79 | 
            +
                ref={ref}
         | 
| 80 | 
            +
                className={cn(
         | 
| 81 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 82 | 
            +
                  inset && "pl-8",
         | 
| 83 | 
            +
                  className
         | 
| 84 | 
            +
                )}
         | 
| 85 | 
            +
                {...props}
         | 
| 86 | 
            +
              />
         | 
| 87 | 
            +
            ))
         | 
| 88 | 
            +
            ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            const ContextMenuCheckboxItem = React.forwardRef<
         | 
| 91 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
         | 
| 92 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
         | 
| 93 | 
            +
            >(({ className, children, checked, ...props }, ref) => (
         | 
| 94 | 
            +
              <ContextMenuPrimitive.CheckboxItem
         | 
| 95 | 
            +
                ref={ref}
         | 
| 96 | 
            +
                className={cn(
         | 
| 97 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 98 | 
            +
                  className
         | 
| 99 | 
            +
                )}
         | 
| 100 | 
            +
                checked={checked}
         | 
| 101 | 
            +
                {...props}
         | 
| 102 | 
            +
              >
         | 
| 103 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 104 | 
            +
                  <ContextMenuPrimitive.ItemIndicator>
         | 
| 105 | 
            +
                    <Check className="h-4 w-4" />
         | 
| 106 | 
            +
                  </ContextMenuPrimitive.ItemIndicator>
         | 
| 107 | 
            +
                </span>
         | 
| 108 | 
            +
                {children}
         | 
| 109 | 
            +
              </ContextMenuPrimitive.CheckboxItem>
         | 
| 110 | 
            +
            ))
         | 
| 111 | 
            +
            ContextMenuCheckboxItem.displayName =
         | 
| 112 | 
            +
              ContextMenuPrimitive.CheckboxItem.displayName
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            const ContextMenuRadioItem = React.forwardRef<
         | 
| 115 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
         | 
| 116 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
         | 
| 117 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 118 | 
            +
              <ContextMenuPrimitive.RadioItem
         | 
| 119 | 
            +
                ref={ref}
         | 
| 120 | 
            +
                className={cn(
         | 
| 121 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 122 | 
            +
                  className
         | 
| 123 | 
            +
                )}
         | 
| 124 | 
            +
                {...props}
         | 
| 125 | 
            +
              >
         | 
| 126 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 127 | 
            +
                  <ContextMenuPrimitive.ItemIndicator>
         | 
| 128 | 
            +
                    <Circle className="h-2 w-2 fill-current" />
         | 
| 129 | 
            +
                  </ContextMenuPrimitive.ItemIndicator>
         | 
| 130 | 
            +
                </span>
         | 
| 131 | 
            +
                {children}
         | 
| 132 | 
            +
              </ContextMenuPrimitive.RadioItem>
         | 
| 133 | 
            +
            ))
         | 
| 134 | 
            +
            ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
         | 
| 135 | 
            +
             | 
| 136 | 
            +
            const ContextMenuLabel = React.forwardRef<
         | 
| 137 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.Label>,
         | 
| 138 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
         | 
| 139 | 
            +
                inset?: boolean
         | 
| 140 | 
            +
              }
         | 
| 141 | 
            +
            >(({ className, inset, ...props }, ref) => (
         | 
| 142 | 
            +
              <ContextMenuPrimitive.Label
         | 
| 143 | 
            +
                ref={ref}
         | 
| 144 | 
            +
                className={cn(
         | 
| 145 | 
            +
                  "px-2 py-1.5 text-sm font-semibold text-foreground",
         | 
| 146 | 
            +
                  inset && "pl-8",
         | 
| 147 | 
            +
                  className
         | 
| 148 | 
            +
                )}
         | 
| 149 | 
            +
                {...props}
         | 
| 150 | 
            +
              />
         | 
| 151 | 
            +
            ))
         | 
| 152 | 
            +
            ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
         | 
| 153 | 
            +
             | 
| 154 | 
            +
            const ContextMenuSeparator = React.forwardRef<
         | 
| 155 | 
            +
              React.ElementRef<typeof ContextMenuPrimitive.Separator>,
         | 
| 156 | 
            +
              React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
         | 
| 157 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 158 | 
            +
              <ContextMenuPrimitive.Separator
         | 
| 159 | 
            +
                ref={ref}
         | 
| 160 | 
            +
                className={cn("-mx-1 my-1 h-px bg-border", className)}
         | 
| 161 | 
            +
                {...props}
         | 
| 162 | 
            +
              />
         | 
| 163 | 
            +
            ))
         | 
| 164 | 
            +
            ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
         | 
| 165 | 
            +
             | 
| 166 | 
            +
            const ContextMenuShortcut = ({
         | 
| 167 | 
            +
              className,
         | 
| 168 | 
            +
              ...props
         | 
| 169 | 
            +
            }: React.HTMLAttributes<HTMLSpanElement>) => {
         | 
| 170 | 
            +
              return (
         | 
| 171 | 
            +
                <span
         | 
| 172 | 
            +
                  className={cn(
         | 
| 173 | 
            +
                    "ml-auto text-xs tracking-widest text-muted-foreground",
         | 
| 174 | 
            +
                    className
         | 
| 175 | 
            +
                  )}
         | 
| 176 | 
            +
                  {...props}
         | 
| 177 | 
            +
                />
         | 
| 178 | 
            +
              )
         | 
| 179 | 
            +
            }
         | 
| 180 | 
            +
            ContextMenuShortcut.displayName = "ContextMenuShortcut"
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            export {
         | 
| 183 | 
            +
              ContextMenu,
         | 
| 184 | 
            +
              ContextMenuTrigger,
         | 
| 185 | 
            +
              ContextMenuContent,
         | 
| 186 | 
            +
              ContextMenuItem,
         | 
| 187 | 
            +
              ContextMenuCheckboxItem,
         | 
| 188 | 
            +
              ContextMenuRadioItem,
         | 
| 189 | 
            +
              ContextMenuLabel,
         | 
| 190 | 
            +
              ContextMenuSeparator,
         | 
| 191 | 
            +
              ContextMenuShortcut,
         | 
| 192 | 
            +
              ContextMenuGroup,
         | 
| 193 | 
            +
              ContextMenuPortal,
         | 
| 194 | 
            +
              ContextMenuSub,
         | 
| 195 | 
            +
              ContextMenuSubContent,
         | 
| 196 | 
            +
              ContextMenuSubTrigger,
         | 
| 197 | 
            +
              ContextMenuRadioGroup,
         | 
| 198 | 
            +
            }
         | 
    	
        client/src/components/ui/dialog.tsx
    ADDED
    
    | @@ -0,0 +1,122 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as DialogPrimitive from "@radix-ui/react-dialog"
         | 
| 5 | 
            +
            import { X } from "lucide-react"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const Dialog = DialogPrimitive.Root
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const DialogTrigger = DialogPrimitive.Trigger
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            const DialogPortal = DialogPrimitive.Portal
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            const DialogClose = DialogPrimitive.Close
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            const DialogOverlay = React.forwardRef<
         | 
| 18 | 
            +
              React.ElementRef<typeof DialogPrimitive.Overlay>,
         | 
| 19 | 
            +
              React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
         | 
| 20 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 21 | 
            +
              <DialogPrimitive.Overlay
         | 
| 22 | 
            +
                ref={ref}
         | 
| 23 | 
            +
                className={cn(
         | 
| 24 | 
            +
                  "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
         | 
| 25 | 
            +
                  className
         | 
| 26 | 
            +
                )}
         | 
| 27 | 
            +
                {...props}
         | 
| 28 | 
            +
              />
         | 
| 29 | 
            +
            ))
         | 
| 30 | 
            +
            DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            const DialogContent = React.forwardRef<
         | 
| 33 | 
            +
              React.ElementRef<typeof DialogPrimitive.Content>,
         | 
| 34 | 
            +
              React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
         | 
| 35 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 36 | 
            +
              <DialogPortal>
         | 
| 37 | 
            +
                <DialogOverlay />
         | 
| 38 | 
            +
                <DialogPrimitive.Content
         | 
| 39 | 
            +
                  ref={ref}
         | 
| 40 | 
            +
                  className={cn(
         | 
| 41 | 
            +
                    "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
         | 
| 42 | 
            +
                    className
         | 
| 43 | 
            +
                  )}
         | 
| 44 | 
            +
                  {...props}
         | 
| 45 | 
            +
                >
         | 
| 46 | 
            +
                  {children}
         | 
| 47 | 
            +
                  <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground">
         | 
| 48 | 
            +
                    <X className="h-4 w-4" />
         | 
| 49 | 
            +
                    <span className="sr-only">Close</span>
         | 
| 50 | 
            +
                  </DialogPrimitive.Close>
         | 
| 51 | 
            +
                </DialogPrimitive.Content>
         | 
| 52 | 
            +
              </DialogPortal>
         | 
| 53 | 
            +
            ))
         | 
| 54 | 
            +
            DialogContent.displayName = DialogPrimitive.Content.displayName
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            const DialogHeader = ({
         | 
| 57 | 
            +
              className,
         | 
| 58 | 
            +
              ...props
         | 
| 59 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 60 | 
            +
              <div
         | 
| 61 | 
            +
                className={cn(
         | 
| 62 | 
            +
                  "flex flex-col space-y-1.5 text-center sm:text-left",
         | 
| 63 | 
            +
                  className
         | 
| 64 | 
            +
                )}
         | 
| 65 | 
            +
                {...props}
         | 
| 66 | 
            +
              />
         | 
| 67 | 
            +
            )
         | 
| 68 | 
            +
            DialogHeader.displayName = "DialogHeader"
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            const DialogFooter = ({
         | 
| 71 | 
            +
              className,
         | 
| 72 | 
            +
              ...props
         | 
| 73 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 74 | 
            +
              <div
         | 
| 75 | 
            +
                className={cn(
         | 
| 76 | 
            +
                  "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
         | 
| 77 | 
            +
                  className
         | 
| 78 | 
            +
                )}
         | 
| 79 | 
            +
                {...props}
         | 
| 80 | 
            +
              />
         | 
| 81 | 
            +
            )
         | 
| 82 | 
            +
            DialogFooter.displayName = "DialogFooter"
         | 
| 83 | 
            +
             | 
| 84 | 
            +
            const DialogTitle = React.forwardRef<
         | 
| 85 | 
            +
              React.ElementRef<typeof DialogPrimitive.Title>,
         | 
| 86 | 
            +
              React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
         | 
| 87 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 88 | 
            +
              <DialogPrimitive.Title
         | 
| 89 | 
            +
                ref={ref}
         | 
| 90 | 
            +
                className={cn(
         | 
| 91 | 
            +
                  "text-lg font-semibold leading-none tracking-tight",
         | 
| 92 | 
            +
                  className
         | 
| 93 | 
            +
                )}
         | 
| 94 | 
            +
                {...props}
         | 
| 95 | 
            +
              />
         | 
| 96 | 
            +
            ))
         | 
| 97 | 
            +
            DialogTitle.displayName = DialogPrimitive.Title.displayName
         | 
| 98 | 
            +
             | 
| 99 | 
            +
            const DialogDescription = React.forwardRef<
         | 
| 100 | 
            +
              React.ElementRef<typeof DialogPrimitive.Description>,
         | 
| 101 | 
            +
              React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
         | 
| 102 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 103 | 
            +
              <DialogPrimitive.Description
         | 
| 104 | 
            +
                ref={ref}
         | 
| 105 | 
            +
                className={cn("text-sm text-muted-foreground", className)}
         | 
| 106 | 
            +
                {...props}
         | 
| 107 | 
            +
              />
         | 
| 108 | 
            +
            ))
         | 
| 109 | 
            +
            DialogDescription.displayName = DialogPrimitive.Description.displayName
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            export {
         | 
| 112 | 
            +
              Dialog,
         | 
| 113 | 
            +
              DialogPortal,
         | 
| 114 | 
            +
              DialogOverlay,
         | 
| 115 | 
            +
              DialogClose,
         | 
| 116 | 
            +
              DialogTrigger,
         | 
| 117 | 
            +
              DialogContent,
         | 
| 118 | 
            +
              DialogHeader,
         | 
| 119 | 
            +
              DialogFooter,
         | 
| 120 | 
            +
              DialogTitle,
         | 
| 121 | 
            +
              DialogDescription,
         | 
| 122 | 
            +
            }
         | 
    	
        client/src/components/ui/drawer.tsx
    ADDED
    
    | @@ -0,0 +1,118 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import { Drawer as DrawerPrimitive } from "vaul"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const Drawer = ({
         | 
| 9 | 
            +
              shouldScaleBackground = true,
         | 
| 10 | 
            +
              ...props
         | 
| 11 | 
            +
            }: React.ComponentProps<typeof DrawerPrimitive.Root>) => (
         | 
| 12 | 
            +
              <DrawerPrimitive.Root
         | 
| 13 | 
            +
                shouldScaleBackground={shouldScaleBackground}
         | 
| 14 | 
            +
                {...props}
         | 
| 15 | 
            +
              />
         | 
| 16 | 
            +
            )
         | 
| 17 | 
            +
            Drawer.displayName = "Drawer"
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            const DrawerTrigger = DrawerPrimitive.Trigger
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            const DrawerPortal = DrawerPrimitive.Portal
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            const DrawerClose = DrawerPrimitive.Close
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            const DrawerOverlay = React.forwardRef<
         | 
| 26 | 
            +
              React.ElementRef<typeof DrawerPrimitive.Overlay>,
         | 
| 27 | 
            +
              React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
         | 
| 28 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 29 | 
            +
              <DrawerPrimitive.Overlay
         | 
| 30 | 
            +
                ref={ref}
         | 
| 31 | 
            +
                className={cn("fixed inset-0 z-50 bg-black/80", className)}
         | 
| 32 | 
            +
                {...props}
         | 
| 33 | 
            +
              />
         | 
| 34 | 
            +
            ))
         | 
| 35 | 
            +
            DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            const DrawerContent = React.forwardRef<
         | 
| 38 | 
            +
              React.ElementRef<typeof DrawerPrimitive.Content>,
         | 
| 39 | 
            +
              React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
         | 
| 40 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 41 | 
            +
              <DrawerPortal>
         | 
| 42 | 
            +
                <DrawerOverlay />
         | 
| 43 | 
            +
                <DrawerPrimitive.Content
         | 
| 44 | 
            +
                  ref={ref}
         | 
| 45 | 
            +
                  className={cn(
         | 
| 46 | 
            +
                    "fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background",
         | 
| 47 | 
            +
                    className
         | 
| 48 | 
            +
                  )}
         | 
| 49 | 
            +
                  {...props}
         | 
| 50 | 
            +
                >
         | 
| 51 | 
            +
                  <div className="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
         | 
| 52 | 
            +
                  {children}
         | 
| 53 | 
            +
                </DrawerPrimitive.Content>
         | 
| 54 | 
            +
              </DrawerPortal>
         | 
| 55 | 
            +
            ))
         | 
| 56 | 
            +
            DrawerContent.displayName = "DrawerContent"
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            const DrawerHeader = ({
         | 
| 59 | 
            +
              className,
         | 
| 60 | 
            +
              ...props
         | 
| 61 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 62 | 
            +
              <div
         | 
| 63 | 
            +
                className={cn("grid gap-1.5 p-4 text-center sm:text-left", className)}
         | 
| 64 | 
            +
                {...props}
         | 
| 65 | 
            +
              />
         | 
| 66 | 
            +
            )
         | 
| 67 | 
            +
            DrawerHeader.displayName = "DrawerHeader"
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            const DrawerFooter = ({
         | 
| 70 | 
            +
              className,
         | 
| 71 | 
            +
              ...props
         | 
| 72 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 73 | 
            +
              <div
         | 
| 74 | 
            +
                className={cn("mt-auto flex flex-col gap-2 p-4", className)}
         | 
| 75 | 
            +
                {...props}
         | 
| 76 | 
            +
              />
         | 
| 77 | 
            +
            )
         | 
| 78 | 
            +
            DrawerFooter.displayName = "DrawerFooter"
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            const DrawerTitle = React.forwardRef<
         | 
| 81 | 
            +
              React.ElementRef<typeof DrawerPrimitive.Title>,
         | 
| 82 | 
            +
              React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
         | 
| 83 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 84 | 
            +
              <DrawerPrimitive.Title
         | 
| 85 | 
            +
                ref={ref}
         | 
| 86 | 
            +
                className={cn(
         | 
| 87 | 
            +
                  "text-lg font-semibold leading-none tracking-tight",
         | 
| 88 | 
            +
                  className
         | 
| 89 | 
            +
                )}
         | 
| 90 | 
            +
                {...props}
         | 
| 91 | 
            +
              />
         | 
| 92 | 
            +
            ))
         | 
| 93 | 
            +
            DrawerTitle.displayName = DrawerPrimitive.Title.displayName
         | 
| 94 | 
            +
             | 
| 95 | 
            +
            const DrawerDescription = React.forwardRef<
         | 
| 96 | 
            +
              React.ElementRef<typeof DrawerPrimitive.Description>,
         | 
| 97 | 
            +
              React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
         | 
| 98 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 99 | 
            +
              <DrawerPrimitive.Description
         | 
| 100 | 
            +
                ref={ref}
         | 
| 101 | 
            +
                className={cn("text-sm text-muted-foreground", className)}
         | 
| 102 | 
            +
                {...props}
         | 
| 103 | 
            +
              />
         | 
| 104 | 
            +
            ))
         | 
| 105 | 
            +
            DrawerDescription.displayName = DrawerPrimitive.Description.displayName
         | 
| 106 | 
            +
             | 
| 107 | 
            +
            export {
         | 
| 108 | 
            +
              Drawer,
         | 
| 109 | 
            +
              DrawerPortal,
         | 
| 110 | 
            +
              DrawerOverlay,
         | 
| 111 | 
            +
              DrawerTrigger,
         | 
| 112 | 
            +
              DrawerClose,
         | 
| 113 | 
            +
              DrawerContent,
         | 
| 114 | 
            +
              DrawerHeader,
         | 
| 115 | 
            +
              DrawerFooter,
         | 
| 116 | 
            +
              DrawerTitle,
         | 
| 117 | 
            +
              DrawerDescription,
         | 
| 118 | 
            +
            }
         | 
    	
        client/src/components/ui/dropdown-menu.tsx
    ADDED
    
    | @@ -0,0 +1,198 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
         | 
| 3 | 
            +
            import { Check, ChevronRight, Circle } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const DropdownMenu = DropdownMenuPrimitive.Root
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const DropdownMenuGroup = DropdownMenuPrimitive.Group
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            const DropdownMenuPortal = DropdownMenuPrimitive.Portal
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            const DropdownMenuSub = DropdownMenuPrimitive.Sub
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            const DropdownMenuSubTrigger = React.forwardRef<
         | 
| 20 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
         | 
| 21 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
         | 
| 22 | 
            +
                inset?: boolean
         | 
| 23 | 
            +
              }
         | 
| 24 | 
            +
            >(({ className, inset, children, ...props }, ref) => (
         | 
| 25 | 
            +
              <DropdownMenuPrimitive.SubTrigger
         | 
| 26 | 
            +
                ref={ref}
         | 
| 27 | 
            +
                className={cn(
         | 
| 28 | 
            +
                  "flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
         | 
| 29 | 
            +
                  inset && "pl-8",
         | 
| 30 | 
            +
                  className
         | 
| 31 | 
            +
                )}
         | 
| 32 | 
            +
                {...props}
         | 
| 33 | 
            +
              >
         | 
| 34 | 
            +
                {children}
         | 
| 35 | 
            +
                <ChevronRight className="ml-auto" />
         | 
| 36 | 
            +
              </DropdownMenuPrimitive.SubTrigger>
         | 
| 37 | 
            +
            ))
         | 
| 38 | 
            +
            DropdownMenuSubTrigger.displayName =
         | 
| 39 | 
            +
              DropdownMenuPrimitive.SubTrigger.displayName
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            const DropdownMenuSubContent = React.forwardRef<
         | 
| 42 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
         | 
| 43 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
         | 
| 44 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 45 | 
            +
              <DropdownMenuPrimitive.SubContent
         | 
| 46 | 
            +
                ref={ref}
         | 
| 47 | 
            +
                className={cn(
         | 
| 48 | 
            +
                  "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
         | 
| 49 | 
            +
                  className
         | 
| 50 | 
            +
                )}
         | 
| 51 | 
            +
                {...props}
         | 
| 52 | 
            +
              />
         | 
| 53 | 
            +
            ))
         | 
| 54 | 
            +
            DropdownMenuSubContent.displayName =
         | 
| 55 | 
            +
              DropdownMenuPrimitive.SubContent.displayName
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            const DropdownMenuContent = React.forwardRef<
         | 
| 58 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.Content>,
         | 
| 59 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
         | 
| 60 | 
            +
            >(({ className, sideOffset = 4, ...props }, ref) => (
         | 
| 61 | 
            +
              <DropdownMenuPrimitive.Portal>
         | 
| 62 | 
            +
                <DropdownMenuPrimitive.Content
         | 
| 63 | 
            +
                  ref={ref}
         | 
| 64 | 
            +
                  sideOffset={sideOffset}
         | 
| 65 | 
            +
                  className={cn(
         | 
| 66 | 
            +
                    "z-50 max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-dropdown-menu-content-transform-origin]",
         | 
| 67 | 
            +
                    className
         | 
| 68 | 
            +
                  )}
         | 
| 69 | 
            +
                  {...props}
         | 
| 70 | 
            +
                />
         | 
| 71 | 
            +
              </DropdownMenuPrimitive.Portal>
         | 
| 72 | 
            +
            ))
         | 
| 73 | 
            +
            DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            const DropdownMenuItem = React.forwardRef<
         | 
| 76 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.Item>,
         | 
| 77 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
         | 
| 78 | 
            +
                inset?: boolean
         | 
| 79 | 
            +
              }
         | 
| 80 | 
            +
            >(({ className, inset, ...props }, ref) => (
         | 
| 81 | 
            +
              <DropdownMenuPrimitive.Item
         | 
| 82 | 
            +
                ref={ref}
         | 
| 83 | 
            +
                className={cn(
         | 
| 84 | 
            +
                  "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
         | 
| 85 | 
            +
                  inset && "pl-8",
         | 
| 86 | 
            +
                  className
         | 
| 87 | 
            +
                )}
         | 
| 88 | 
            +
                {...props}
         | 
| 89 | 
            +
              />
         | 
| 90 | 
            +
            ))
         | 
| 91 | 
            +
            DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            const DropdownMenuCheckboxItem = React.forwardRef<
         | 
| 94 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
         | 
| 95 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
         | 
| 96 | 
            +
            >(({ className, children, checked, ...props }, ref) => (
         | 
| 97 | 
            +
              <DropdownMenuPrimitive.CheckboxItem
         | 
| 98 | 
            +
                ref={ref}
         | 
| 99 | 
            +
                className={cn(
         | 
| 100 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 101 | 
            +
                  className
         | 
| 102 | 
            +
                )}
         | 
| 103 | 
            +
                checked={checked}
         | 
| 104 | 
            +
                {...props}
         | 
| 105 | 
            +
              >
         | 
| 106 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 107 | 
            +
                  <DropdownMenuPrimitive.ItemIndicator>
         | 
| 108 | 
            +
                    <Check className="h-4 w-4" />
         | 
| 109 | 
            +
                  </DropdownMenuPrimitive.ItemIndicator>
         | 
| 110 | 
            +
                </span>
         | 
| 111 | 
            +
                {children}
         | 
| 112 | 
            +
              </DropdownMenuPrimitive.CheckboxItem>
         | 
| 113 | 
            +
            ))
         | 
| 114 | 
            +
            DropdownMenuCheckboxItem.displayName =
         | 
| 115 | 
            +
              DropdownMenuPrimitive.CheckboxItem.displayName
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            const DropdownMenuRadioItem = React.forwardRef<
         | 
| 118 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
         | 
| 119 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
         | 
| 120 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 121 | 
            +
              <DropdownMenuPrimitive.RadioItem
         | 
| 122 | 
            +
                ref={ref}
         | 
| 123 | 
            +
                className={cn(
         | 
| 124 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 125 | 
            +
                  className
         | 
| 126 | 
            +
                )}
         | 
| 127 | 
            +
                {...props}
         | 
| 128 | 
            +
              >
         | 
| 129 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 130 | 
            +
                  <DropdownMenuPrimitive.ItemIndicator>
         | 
| 131 | 
            +
                    <Circle className="h-2 w-2 fill-current" />
         | 
| 132 | 
            +
                  </DropdownMenuPrimitive.ItemIndicator>
         | 
| 133 | 
            +
                </span>
         | 
| 134 | 
            +
                {children}
         | 
| 135 | 
            +
              </DropdownMenuPrimitive.RadioItem>
         | 
| 136 | 
            +
            ))
         | 
| 137 | 
            +
            DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
         | 
| 138 | 
            +
             | 
| 139 | 
            +
            const DropdownMenuLabel = React.forwardRef<
         | 
| 140 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.Label>,
         | 
| 141 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
         | 
| 142 | 
            +
                inset?: boolean
         | 
| 143 | 
            +
              }
         | 
| 144 | 
            +
            >(({ className, inset, ...props }, ref) => (
         | 
| 145 | 
            +
              <DropdownMenuPrimitive.Label
         | 
| 146 | 
            +
                ref={ref}
         | 
| 147 | 
            +
                className={cn(
         | 
| 148 | 
            +
                  "px-2 py-1.5 text-sm font-semibold",
         | 
| 149 | 
            +
                  inset && "pl-8",
         | 
| 150 | 
            +
                  className
         | 
| 151 | 
            +
                )}
         | 
| 152 | 
            +
                {...props}
         | 
| 153 | 
            +
              />
         | 
| 154 | 
            +
            ))
         | 
| 155 | 
            +
            DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
         | 
| 156 | 
            +
             | 
| 157 | 
            +
            const DropdownMenuSeparator = React.forwardRef<
         | 
| 158 | 
            +
              React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
         | 
| 159 | 
            +
              React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
         | 
| 160 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 161 | 
            +
              <DropdownMenuPrimitive.Separator
         | 
| 162 | 
            +
                ref={ref}
         | 
| 163 | 
            +
                className={cn("-mx-1 my-1 h-px bg-muted", className)}
         | 
| 164 | 
            +
                {...props}
         | 
| 165 | 
            +
              />
         | 
| 166 | 
            +
            ))
         | 
| 167 | 
            +
            DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            const DropdownMenuShortcut = ({
         | 
| 170 | 
            +
              className,
         | 
| 171 | 
            +
              ...props
         | 
| 172 | 
            +
            }: React.HTMLAttributes<HTMLSpanElement>) => {
         | 
| 173 | 
            +
              return (
         | 
| 174 | 
            +
                <span
         | 
| 175 | 
            +
                  className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
         | 
| 176 | 
            +
                  {...props}
         | 
| 177 | 
            +
                />
         | 
| 178 | 
            +
              )
         | 
| 179 | 
            +
            }
         | 
| 180 | 
            +
            DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
         | 
| 181 | 
            +
             | 
| 182 | 
            +
            export {
         | 
| 183 | 
            +
              DropdownMenu,
         | 
| 184 | 
            +
              DropdownMenuTrigger,
         | 
| 185 | 
            +
              DropdownMenuContent,
         | 
| 186 | 
            +
              DropdownMenuItem,
         | 
| 187 | 
            +
              DropdownMenuCheckboxItem,
         | 
| 188 | 
            +
              DropdownMenuRadioItem,
         | 
| 189 | 
            +
              DropdownMenuLabel,
         | 
| 190 | 
            +
              DropdownMenuSeparator,
         | 
| 191 | 
            +
              DropdownMenuShortcut,
         | 
| 192 | 
            +
              DropdownMenuGroup,
         | 
| 193 | 
            +
              DropdownMenuPortal,
         | 
| 194 | 
            +
              DropdownMenuSub,
         | 
| 195 | 
            +
              DropdownMenuSubContent,
         | 
| 196 | 
            +
              DropdownMenuSubTrigger,
         | 
| 197 | 
            +
              DropdownMenuRadioGroup,
         | 
| 198 | 
            +
            }
         | 
    	
        client/src/components/ui/form.tsx
    ADDED
    
    | @@ -0,0 +1,178 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as LabelPrimitive from "@radix-ui/react-label"
         | 
| 5 | 
            +
            import { Slot } from "@radix-ui/react-slot"
         | 
| 6 | 
            +
            import {
         | 
| 7 | 
            +
              Controller,
         | 
| 8 | 
            +
              FormProvider,
         | 
| 9 | 
            +
              useFormContext,
         | 
| 10 | 
            +
              type ControllerProps,
         | 
| 11 | 
            +
              type FieldPath,
         | 
| 12 | 
            +
              type FieldValues,
         | 
| 13 | 
            +
            } from "react-hook-form"
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 16 | 
            +
            import { Label } from "@/components/ui/label"
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            const Form = FormProvider
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            type FormFieldContextValue<
         | 
| 21 | 
            +
              TFieldValues extends FieldValues = FieldValues,
         | 
| 22 | 
            +
              TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
         | 
| 23 | 
            +
            > = {
         | 
| 24 | 
            +
              name: TName
         | 
| 25 | 
            +
            }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            const FormFieldContext = React.createContext<FormFieldContextValue>(
         | 
| 28 | 
            +
              {} as FormFieldContextValue
         | 
| 29 | 
            +
            )
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            const FormField = <
         | 
| 32 | 
            +
              TFieldValues extends FieldValues = FieldValues,
         | 
| 33 | 
            +
              TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
         | 
| 34 | 
            +
            >({
         | 
| 35 | 
            +
              ...props
         | 
| 36 | 
            +
            }: ControllerProps<TFieldValues, TName>) => {
         | 
| 37 | 
            +
              return (
         | 
| 38 | 
            +
                <FormFieldContext.Provider value={{ name: props.name }}>
         | 
| 39 | 
            +
                  <Controller {...props} />
         | 
| 40 | 
            +
                </FormFieldContext.Provider>
         | 
| 41 | 
            +
              )
         | 
| 42 | 
            +
            }
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            const useFormField = () => {
         | 
| 45 | 
            +
              const fieldContext = React.useContext(FormFieldContext)
         | 
| 46 | 
            +
              const itemContext = React.useContext(FormItemContext)
         | 
| 47 | 
            +
              const { getFieldState, formState } = useFormContext()
         | 
| 48 | 
            +
             | 
| 49 | 
            +
              const fieldState = getFieldState(fieldContext.name, formState)
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              if (!fieldContext) {
         | 
| 52 | 
            +
                throw new Error("useFormField should be used within <FormField>")
         | 
| 53 | 
            +
              }
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              const { id } = itemContext
         | 
| 56 | 
            +
             | 
| 57 | 
            +
              return {
         | 
| 58 | 
            +
                id,
         | 
| 59 | 
            +
                name: fieldContext.name,
         | 
| 60 | 
            +
                formItemId: `${id}-form-item`,
         | 
| 61 | 
            +
                formDescriptionId: `${id}-form-item-description`,
         | 
| 62 | 
            +
                formMessageId: `${id}-form-item-message`,
         | 
| 63 | 
            +
                ...fieldState,
         | 
| 64 | 
            +
              }
         | 
| 65 | 
            +
            }
         | 
| 66 | 
            +
             | 
| 67 | 
            +
            type FormItemContextValue = {
         | 
| 68 | 
            +
              id: string
         | 
| 69 | 
            +
            }
         | 
| 70 | 
            +
             | 
| 71 | 
            +
            const FormItemContext = React.createContext<FormItemContextValue>(
         | 
| 72 | 
            +
              {} as FormItemContextValue
         | 
| 73 | 
            +
            )
         | 
| 74 | 
            +
             | 
| 75 | 
            +
            const FormItem = React.forwardRef<
         | 
| 76 | 
            +
              HTMLDivElement,
         | 
| 77 | 
            +
              React.HTMLAttributes<HTMLDivElement>
         | 
| 78 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 79 | 
            +
              const id = React.useId()
         | 
| 80 | 
            +
             | 
| 81 | 
            +
              return (
         | 
| 82 | 
            +
                <FormItemContext.Provider value={{ id }}>
         | 
| 83 | 
            +
                  <div ref={ref} className={cn("space-y-2", className)} {...props} />
         | 
| 84 | 
            +
                </FormItemContext.Provider>
         | 
| 85 | 
            +
              )
         | 
| 86 | 
            +
            })
         | 
| 87 | 
            +
            FormItem.displayName = "FormItem"
         | 
| 88 | 
            +
             | 
| 89 | 
            +
            const FormLabel = React.forwardRef<
         | 
| 90 | 
            +
              React.ElementRef<typeof LabelPrimitive.Root>,
         | 
| 91 | 
            +
              React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
         | 
| 92 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 93 | 
            +
              const { error, formItemId } = useFormField()
         | 
| 94 | 
            +
             | 
| 95 | 
            +
              return (
         | 
| 96 | 
            +
                <Label
         | 
| 97 | 
            +
                  ref={ref}
         | 
| 98 | 
            +
                  className={cn(error && "text-destructive", className)}
         | 
| 99 | 
            +
                  htmlFor={formItemId}
         | 
| 100 | 
            +
                  {...props}
         | 
| 101 | 
            +
                />
         | 
| 102 | 
            +
              )
         | 
| 103 | 
            +
            })
         | 
| 104 | 
            +
            FormLabel.displayName = "FormLabel"
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            const FormControl = React.forwardRef<
         | 
| 107 | 
            +
              React.ElementRef<typeof Slot>,
         | 
| 108 | 
            +
              React.ComponentPropsWithoutRef<typeof Slot>
         | 
| 109 | 
            +
            >(({ ...props }, ref) => {
         | 
| 110 | 
            +
              const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
         | 
| 111 | 
            +
             | 
| 112 | 
            +
              return (
         | 
| 113 | 
            +
                <Slot
         | 
| 114 | 
            +
                  ref={ref}
         | 
| 115 | 
            +
                  id={formItemId}
         | 
| 116 | 
            +
                  aria-describedby={
         | 
| 117 | 
            +
                    !error
         | 
| 118 | 
            +
                      ? `${formDescriptionId}`
         | 
| 119 | 
            +
                      : `${formDescriptionId} ${formMessageId}`
         | 
| 120 | 
            +
                  }
         | 
| 121 | 
            +
                  aria-invalid={!!error}
         | 
| 122 | 
            +
                  {...props}
         | 
| 123 | 
            +
                />
         | 
| 124 | 
            +
              )
         | 
| 125 | 
            +
            })
         | 
| 126 | 
            +
            FormControl.displayName = "FormControl"
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            const FormDescription = React.forwardRef<
         | 
| 129 | 
            +
              HTMLParagraphElement,
         | 
| 130 | 
            +
              React.HTMLAttributes<HTMLParagraphElement>
         | 
| 131 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 132 | 
            +
              const { formDescriptionId } = useFormField()
         | 
| 133 | 
            +
             | 
| 134 | 
            +
              return (
         | 
| 135 | 
            +
                <p
         | 
| 136 | 
            +
                  ref={ref}
         | 
| 137 | 
            +
                  id={formDescriptionId}
         | 
| 138 | 
            +
                  className={cn("text-sm text-muted-foreground", className)}
         | 
| 139 | 
            +
                  {...props}
         | 
| 140 | 
            +
                />
         | 
| 141 | 
            +
              )
         | 
| 142 | 
            +
            })
         | 
| 143 | 
            +
            FormDescription.displayName = "FormDescription"
         | 
| 144 | 
            +
             | 
| 145 | 
            +
            const FormMessage = React.forwardRef<
         | 
| 146 | 
            +
              HTMLParagraphElement,
         | 
| 147 | 
            +
              React.HTMLAttributes<HTMLParagraphElement>
         | 
| 148 | 
            +
            >(({ className, children, ...props }, ref) => {
         | 
| 149 | 
            +
              const { error, formMessageId } = useFormField()
         | 
| 150 | 
            +
              const body = error ? String(error?.message ?? "") : children
         | 
| 151 | 
            +
             | 
| 152 | 
            +
              if (!body) {
         | 
| 153 | 
            +
                return null
         | 
| 154 | 
            +
              }
         | 
| 155 | 
            +
             | 
| 156 | 
            +
              return (
         | 
| 157 | 
            +
                <p
         | 
| 158 | 
            +
                  ref={ref}
         | 
| 159 | 
            +
                  id={formMessageId}
         | 
| 160 | 
            +
                  className={cn("text-sm font-medium text-destructive", className)}
         | 
| 161 | 
            +
                  {...props}
         | 
| 162 | 
            +
                >
         | 
| 163 | 
            +
                  {body}
         | 
| 164 | 
            +
                </p>
         | 
| 165 | 
            +
              )
         | 
| 166 | 
            +
            })
         | 
| 167 | 
            +
            FormMessage.displayName = "FormMessage"
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            export {
         | 
| 170 | 
            +
              useFormField,
         | 
| 171 | 
            +
              Form,
         | 
| 172 | 
            +
              FormItem,
         | 
| 173 | 
            +
              FormLabel,
         | 
| 174 | 
            +
              FormControl,
         | 
| 175 | 
            +
              FormDescription,
         | 
| 176 | 
            +
              FormMessage,
         | 
| 177 | 
            +
              FormField,
         | 
| 178 | 
            +
            }
         | 
    	
        client/src/components/ui/hover-card.tsx
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const HoverCard = HoverCardPrimitive.Root
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            const HoverCardTrigger = HoverCardPrimitive.Trigger
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            const HoverCardContent = React.forwardRef<
         | 
| 13 | 
            +
              React.ElementRef<typeof HoverCardPrimitive.Content>,
         | 
| 14 | 
            +
              React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
         | 
| 15 | 
            +
            >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
         | 
| 16 | 
            +
              <HoverCardPrimitive.Content
         | 
| 17 | 
            +
                ref={ref}
         | 
| 18 | 
            +
                align={align}
         | 
| 19 | 
            +
                sideOffset={sideOffset}
         | 
| 20 | 
            +
                className={cn(
         | 
| 21 | 
            +
                  "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
         | 
| 22 | 
            +
                  className
         | 
| 23 | 
            +
                )}
         | 
| 24 | 
            +
                {...props}
         | 
| 25 | 
            +
              />
         | 
| 26 | 
            +
            ))
         | 
| 27 | 
            +
            HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            export { HoverCard, HoverCardTrigger, HoverCardContent }
         | 
    	
        client/src/components/ui/input-otp.tsx
    ADDED
    
    | @@ -0,0 +1,69 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { OTPInput, OTPInputContext } from "input-otp"
         | 
| 3 | 
            +
            import { Dot } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const InputOTP = React.forwardRef<
         | 
| 8 | 
            +
              React.ElementRef<typeof OTPInput>,
         | 
| 9 | 
            +
              React.ComponentPropsWithoutRef<typeof OTPInput>
         | 
| 10 | 
            +
            >(({ className, containerClassName, ...props }, ref) => (
         | 
| 11 | 
            +
              <OTPInput
         | 
| 12 | 
            +
                ref={ref}
         | 
| 13 | 
            +
                containerClassName={cn(
         | 
| 14 | 
            +
                  "flex items-center gap-2 has-[:disabled]:opacity-50",
         | 
| 15 | 
            +
                  containerClassName
         | 
| 16 | 
            +
                )}
         | 
| 17 | 
            +
                className={cn("disabled:cursor-not-allowed", className)}
         | 
| 18 | 
            +
                {...props}
         | 
| 19 | 
            +
              />
         | 
| 20 | 
            +
            ))
         | 
| 21 | 
            +
            InputOTP.displayName = "InputOTP"
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            const InputOTPGroup = React.forwardRef<
         | 
| 24 | 
            +
              React.ElementRef<"div">,
         | 
| 25 | 
            +
              React.ComponentPropsWithoutRef<"div">
         | 
| 26 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 27 | 
            +
              <div ref={ref} className={cn("flex items-center", className)} {...props} />
         | 
| 28 | 
            +
            ))
         | 
| 29 | 
            +
            InputOTPGroup.displayName = "InputOTPGroup"
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            const InputOTPSlot = React.forwardRef<
         | 
| 32 | 
            +
              React.ElementRef<"div">,
         | 
| 33 | 
            +
              React.ComponentPropsWithoutRef<"div"> & { index: number }
         | 
| 34 | 
            +
            >(({ index, className, ...props }, ref) => {
         | 
| 35 | 
            +
              const inputOTPContext = React.useContext(OTPInputContext)
         | 
| 36 | 
            +
              const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              return (
         | 
| 39 | 
            +
                <div
         | 
| 40 | 
            +
                  ref={ref}
         | 
| 41 | 
            +
                  className={cn(
         | 
| 42 | 
            +
                    "relative flex h-10 w-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
         | 
| 43 | 
            +
                    isActive && "z-10 ring-2 ring-ring ring-offset-background",
         | 
| 44 | 
            +
                    className
         | 
| 45 | 
            +
                  )}
         | 
| 46 | 
            +
                  {...props}
         | 
| 47 | 
            +
                >
         | 
| 48 | 
            +
                  {char}
         | 
| 49 | 
            +
                  {hasFakeCaret && (
         | 
| 50 | 
            +
                    <div className="pointer-events-none absolute inset-0 flex items-center justify-center">
         | 
| 51 | 
            +
                      <div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
         | 
| 52 | 
            +
                    </div>
         | 
| 53 | 
            +
                  )}
         | 
| 54 | 
            +
                </div>
         | 
| 55 | 
            +
              )
         | 
| 56 | 
            +
            })
         | 
| 57 | 
            +
            InputOTPSlot.displayName = "InputOTPSlot"
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            const InputOTPSeparator = React.forwardRef<
         | 
| 60 | 
            +
              React.ElementRef<"div">,
         | 
| 61 | 
            +
              React.ComponentPropsWithoutRef<"div">
         | 
| 62 | 
            +
            >(({ ...props }, ref) => (
         | 
| 63 | 
            +
              <div ref={ref} role="separator" {...props}>
         | 
| 64 | 
            +
                <Dot />
         | 
| 65 | 
            +
              </div>
         | 
| 66 | 
            +
            ))
         | 
| 67 | 
            +
            InputOTPSeparator.displayName = "InputOTPSeparator"
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }
         | 
    	
        client/src/components/ui/input.tsx
    ADDED
    
    | @@ -0,0 +1,22 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
         | 
| 6 | 
            +
              ({ className, type, ...props }, ref) => {
         | 
| 7 | 
            +
                return (
         | 
| 8 | 
            +
                  <input
         | 
| 9 | 
            +
                    type={type}
         | 
| 10 | 
            +
                    className={cn(
         | 
| 11 | 
            +
                      "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
         | 
| 12 | 
            +
                      className
         | 
| 13 | 
            +
                    )}
         | 
| 14 | 
            +
                    ref={ref}
         | 
| 15 | 
            +
                    {...props}
         | 
| 16 | 
            +
                  />
         | 
| 17 | 
            +
                )
         | 
| 18 | 
            +
              }
         | 
| 19 | 
            +
            )
         | 
| 20 | 
            +
            Input.displayName = "Input"
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            export { Input }
         | 
    	
        client/src/components/ui/label.tsx
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as LabelPrimitive from "@radix-ui/react-label"
         | 
| 3 | 
            +
            import { cva, type VariantProps } from "class-variance-authority"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const labelVariants = cva(
         | 
| 8 | 
            +
              "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
         | 
| 9 | 
            +
            )
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const Label = React.forwardRef<
         | 
| 12 | 
            +
              React.ElementRef<typeof LabelPrimitive.Root>,
         | 
| 13 | 
            +
              React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
         | 
| 14 | 
            +
                VariantProps<typeof labelVariants>
         | 
| 15 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 16 | 
            +
              <LabelPrimitive.Root
         | 
| 17 | 
            +
                ref={ref}
         | 
| 18 | 
            +
                className={cn(labelVariants(), className)}
         | 
| 19 | 
            +
                {...props}
         | 
| 20 | 
            +
              />
         | 
| 21 | 
            +
            ))
         | 
| 22 | 
            +
            Label.displayName = LabelPrimitive.Root.displayName
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            export { Label }
         | 
    	
        client/src/components/ui/menubar.tsx
    ADDED
    
    | @@ -0,0 +1,256 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as MenubarPrimitive from "@radix-ui/react-menubar"
         | 
| 5 | 
            +
            import { Check, ChevronRight, Circle } from "lucide-react"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            function MenubarMenu({
         | 
| 10 | 
            +
              ...props
         | 
| 11 | 
            +
            }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
         | 
| 12 | 
            +
              return <MenubarPrimitive.Menu {...props} />
         | 
| 13 | 
            +
            }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            function MenubarGroup({
         | 
| 16 | 
            +
              ...props
         | 
| 17 | 
            +
            }: React.ComponentProps<typeof MenubarPrimitive.Group>) {
         | 
| 18 | 
            +
              return <MenubarPrimitive.Group {...props} />
         | 
| 19 | 
            +
            }
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            function MenubarPortal({
         | 
| 22 | 
            +
              ...props
         | 
| 23 | 
            +
            }: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
         | 
| 24 | 
            +
              return <MenubarPrimitive.Portal {...props} />
         | 
| 25 | 
            +
            }
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            function MenubarRadioGroup({
         | 
| 28 | 
            +
              ...props
         | 
| 29 | 
            +
            }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
         | 
| 30 | 
            +
              return <MenubarPrimitive.RadioGroup {...props} />
         | 
| 31 | 
            +
            }
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            function MenubarSub({
         | 
| 34 | 
            +
              ...props
         | 
| 35 | 
            +
            }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
         | 
| 36 | 
            +
              return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />
         | 
| 37 | 
            +
            }
         | 
| 38 | 
            +
             | 
| 39 | 
            +
            const Menubar = React.forwardRef<
         | 
| 40 | 
            +
              React.ElementRef<typeof MenubarPrimitive.Root>,
         | 
| 41 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
         | 
| 42 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 43 | 
            +
              <MenubarPrimitive.Root
         | 
| 44 | 
            +
                ref={ref}
         | 
| 45 | 
            +
                className={cn(
         | 
| 46 | 
            +
                  "flex h-10 items-center space-x-1 rounded-md border bg-background p-1",
         | 
| 47 | 
            +
                  className
         | 
| 48 | 
            +
                )}
         | 
| 49 | 
            +
                {...props}
         | 
| 50 | 
            +
              />
         | 
| 51 | 
            +
            ))
         | 
| 52 | 
            +
            Menubar.displayName = MenubarPrimitive.Root.displayName
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            const MenubarTrigger = React.forwardRef<
         | 
| 55 | 
            +
              React.ElementRef<typeof MenubarPrimitive.Trigger>,
         | 
| 56 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
         | 
| 57 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 58 | 
            +
              <MenubarPrimitive.Trigger
         | 
| 59 | 
            +
                ref={ref}
         | 
| 60 | 
            +
                className={cn(
         | 
| 61 | 
            +
                  "flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
         | 
| 62 | 
            +
                  className
         | 
| 63 | 
            +
                )}
         | 
| 64 | 
            +
                {...props}
         | 
| 65 | 
            +
              />
         | 
| 66 | 
            +
            ))
         | 
| 67 | 
            +
            MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            const MenubarSubTrigger = React.forwardRef<
         | 
| 70 | 
            +
              React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
         | 
| 71 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
         | 
| 72 | 
            +
                inset?: boolean
         | 
| 73 | 
            +
              }
         | 
| 74 | 
            +
            >(({ className, inset, children, ...props }, ref) => (
         | 
| 75 | 
            +
              <MenubarPrimitive.SubTrigger
         | 
| 76 | 
            +
                ref={ref}
         | 
| 77 | 
            +
                className={cn(
         | 
| 78 | 
            +
                  "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
         | 
| 79 | 
            +
                  inset && "pl-8",
         | 
| 80 | 
            +
                  className
         | 
| 81 | 
            +
                )}
         | 
| 82 | 
            +
                {...props}
         | 
| 83 | 
            +
              >
         | 
| 84 | 
            +
                {children}
         | 
| 85 | 
            +
                <ChevronRight className="ml-auto h-4 w-4" />
         | 
| 86 | 
            +
              </MenubarPrimitive.SubTrigger>
         | 
| 87 | 
            +
            ))
         | 
| 88 | 
            +
            MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
         | 
| 89 | 
            +
             | 
| 90 | 
            +
            const MenubarSubContent = React.forwardRef<
         | 
| 91 | 
            +
              React.ElementRef<typeof MenubarPrimitive.SubContent>,
         | 
| 92 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
         | 
| 93 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 94 | 
            +
              <MenubarPrimitive.SubContent
         | 
| 95 | 
            +
                ref={ref}
         | 
| 96 | 
            +
                className={cn(
         | 
| 97 | 
            +
                  "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]",
         | 
| 98 | 
            +
                  className
         | 
| 99 | 
            +
                )}
         | 
| 100 | 
            +
                {...props}
         | 
| 101 | 
            +
              />
         | 
| 102 | 
            +
            ))
         | 
| 103 | 
            +
            MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            const MenubarContent = React.forwardRef<
         | 
| 106 | 
            +
              React.ElementRef<typeof MenubarPrimitive.Content>,
         | 
| 107 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
         | 
| 108 | 
            +
            >(
         | 
| 109 | 
            +
              (
         | 
| 110 | 
            +
                { className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
         | 
| 111 | 
            +
                ref
         | 
| 112 | 
            +
              ) => (
         | 
| 113 | 
            +
                <MenubarPrimitive.Portal>
         | 
| 114 | 
            +
                  <MenubarPrimitive.Content
         | 
| 115 | 
            +
                    ref={ref}
         | 
| 116 | 
            +
                    align={align}
         | 
| 117 | 
            +
                    alignOffset={alignOffset}
         | 
| 118 | 
            +
                    sideOffset={sideOffset}
         | 
| 119 | 
            +
                    className={cn(
         | 
| 120 | 
            +
                      "z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-menubar-content-transform-origin]",
         | 
| 121 | 
            +
                      className
         | 
| 122 | 
            +
                    )}
         | 
| 123 | 
            +
                    {...props}
         | 
| 124 | 
            +
                  />
         | 
| 125 | 
            +
                </MenubarPrimitive.Portal>
         | 
| 126 | 
            +
              )
         | 
| 127 | 
            +
            )
         | 
| 128 | 
            +
            MenubarContent.displayName = MenubarPrimitive.Content.displayName
         | 
| 129 | 
            +
             | 
| 130 | 
            +
            const MenubarItem = React.forwardRef<
         | 
| 131 | 
            +
              React.ElementRef<typeof MenubarPrimitive.Item>,
         | 
| 132 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
         | 
| 133 | 
            +
                inset?: boolean
         | 
| 134 | 
            +
              }
         | 
| 135 | 
            +
            >(({ className, inset, ...props }, ref) => (
         | 
| 136 | 
            +
              <MenubarPrimitive.Item
         | 
| 137 | 
            +
                ref={ref}
         | 
| 138 | 
            +
                className={cn(
         | 
| 139 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 140 | 
            +
                  inset && "pl-8",
         | 
| 141 | 
            +
                  className
         | 
| 142 | 
            +
                )}
         | 
| 143 | 
            +
                {...props}
         | 
| 144 | 
            +
              />
         | 
| 145 | 
            +
            ))
         | 
| 146 | 
            +
            MenubarItem.displayName = MenubarPrimitive.Item.displayName
         | 
| 147 | 
            +
             | 
| 148 | 
            +
            const MenubarCheckboxItem = React.forwardRef<
         | 
| 149 | 
            +
              React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
         | 
| 150 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
         | 
| 151 | 
            +
            >(({ className, children, checked, ...props }, ref) => (
         | 
| 152 | 
            +
              <MenubarPrimitive.CheckboxItem
         | 
| 153 | 
            +
                ref={ref}
         | 
| 154 | 
            +
                className={cn(
         | 
| 155 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 156 | 
            +
                  className
         | 
| 157 | 
            +
                )}
         | 
| 158 | 
            +
                checked={checked}
         | 
| 159 | 
            +
                {...props}
         | 
| 160 | 
            +
              >
         | 
| 161 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 162 | 
            +
                  <MenubarPrimitive.ItemIndicator>
         | 
| 163 | 
            +
                    <Check className="h-4 w-4" />
         | 
| 164 | 
            +
                  </MenubarPrimitive.ItemIndicator>
         | 
| 165 | 
            +
                </span>
         | 
| 166 | 
            +
                {children}
         | 
| 167 | 
            +
              </MenubarPrimitive.CheckboxItem>
         | 
| 168 | 
            +
            ))
         | 
| 169 | 
            +
            MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
         | 
| 170 | 
            +
             | 
| 171 | 
            +
            const MenubarRadioItem = React.forwardRef<
         | 
| 172 | 
            +
              React.ElementRef<typeof MenubarPrimitive.RadioItem>,
         | 
| 173 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
         | 
| 174 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 175 | 
            +
              <MenubarPrimitive.RadioItem
         | 
| 176 | 
            +
                ref={ref}
         | 
| 177 | 
            +
                className={cn(
         | 
| 178 | 
            +
                  "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 179 | 
            +
                  className
         | 
| 180 | 
            +
                )}
         | 
| 181 | 
            +
                {...props}
         | 
| 182 | 
            +
              >
         | 
| 183 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 184 | 
            +
                  <MenubarPrimitive.ItemIndicator>
         | 
| 185 | 
            +
                    <Circle className="h-2 w-2 fill-current" />
         | 
| 186 | 
            +
                  </MenubarPrimitive.ItemIndicator>
         | 
| 187 | 
            +
                </span>
         | 
| 188 | 
            +
                {children}
         | 
| 189 | 
            +
              </MenubarPrimitive.RadioItem>
         | 
| 190 | 
            +
            ))
         | 
| 191 | 
            +
            MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
         | 
| 192 | 
            +
             | 
| 193 | 
            +
            const MenubarLabel = React.forwardRef<
         | 
| 194 | 
            +
              React.ElementRef<typeof MenubarPrimitive.Label>,
         | 
| 195 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
         | 
| 196 | 
            +
                inset?: boolean
         | 
| 197 | 
            +
              }
         | 
| 198 | 
            +
            >(({ className, inset, ...props }, ref) => (
         | 
| 199 | 
            +
              <MenubarPrimitive.Label
         | 
| 200 | 
            +
                ref={ref}
         | 
| 201 | 
            +
                className={cn(
         | 
| 202 | 
            +
                  "px-2 py-1.5 text-sm font-semibold",
         | 
| 203 | 
            +
                  inset && "pl-8",
         | 
| 204 | 
            +
                  className
         | 
| 205 | 
            +
                )}
         | 
| 206 | 
            +
                {...props}
         | 
| 207 | 
            +
              />
         | 
| 208 | 
            +
            ))
         | 
| 209 | 
            +
            MenubarLabel.displayName = MenubarPrimitive.Label.displayName
         | 
| 210 | 
            +
             | 
| 211 | 
            +
            const MenubarSeparator = React.forwardRef<
         | 
| 212 | 
            +
              React.ElementRef<typeof MenubarPrimitive.Separator>,
         | 
| 213 | 
            +
              React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
         | 
| 214 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 215 | 
            +
              <MenubarPrimitive.Separator
         | 
| 216 | 
            +
                ref={ref}
         | 
| 217 | 
            +
                className={cn("-mx-1 my-1 h-px bg-muted", className)}
         | 
| 218 | 
            +
                {...props}
         | 
| 219 | 
            +
              />
         | 
| 220 | 
            +
            ))
         | 
| 221 | 
            +
            MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
         | 
| 222 | 
            +
             | 
| 223 | 
            +
            const MenubarShortcut = ({
         | 
| 224 | 
            +
              className,
         | 
| 225 | 
            +
              ...props
         | 
| 226 | 
            +
            }: React.HTMLAttributes<HTMLSpanElement>) => {
         | 
| 227 | 
            +
              return (
         | 
| 228 | 
            +
                <span
         | 
| 229 | 
            +
                  className={cn(
         | 
| 230 | 
            +
                    "ml-auto text-xs tracking-widest text-muted-foreground",
         | 
| 231 | 
            +
                    className
         | 
| 232 | 
            +
                  )}
         | 
| 233 | 
            +
                  {...props}
         | 
| 234 | 
            +
                />
         | 
| 235 | 
            +
              )
         | 
| 236 | 
            +
            }
         | 
| 237 | 
            +
            MenubarShortcut.displayname = "MenubarShortcut"
         | 
| 238 | 
            +
             | 
| 239 | 
            +
            export {
         | 
| 240 | 
            +
              Menubar,
         | 
| 241 | 
            +
              MenubarMenu,
         | 
| 242 | 
            +
              MenubarTrigger,
         | 
| 243 | 
            +
              MenubarContent,
         | 
| 244 | 
            +
              MenubarItem,
         | 
| 245 | 
            +
              MenubarSeparator,
         | 
| 246 | 
            +
              MenubarLabel,
         | 
| 247 | 
            +
              MenubarCheckboxItem,
         | 
| 248 | 
            +
              MenubarRadioGroup,
         | 
| 249 | 
            +
              MenubarRadioItem,
         | 
| 250 | 
            +
              MenubarPortal,
         | 
| 251 | 
            +
              MenubarSubContent,
         | 
| 252 | 
            +
              MenubarSubTrigger,
         | 
| 253 | 
            +
              MenubarGroup,
         | 
| 254 | 
            +
              MenubarSub,
         | 
| 255 | 
            +
              MenubarShortcut,
         | 
| 256 | 
            +
            }
         | 
    	
        client/src/components/ui/navigation-menu.tsx
    ADDED
    
    | @@ -0,0 +1,128 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
         | 
| 3 | 
            +
            import { cva } from "class-variance-authority"
         | 
| 4 | 
            +
            import { ChevronDown } from "lucide-react"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const NavigationMenu = React.forwardRef<
         | 
| 9 | 
            +
              React.ElementRef<typeof NavigationMenuPrimitive.Root>,
         | 
| 10 | 
            +
              React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
         | 
| 11 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 12 | 
            +
              <NavigationMenuPrimitive.Root
         | 
| 13 | 
            +
                ref={ref}
         | 
| 14 | 
            +
                className={cn(
         | 
| 15 | 
            +
                  "relative z-10 flex max-w-max flex-1 items-center justify-center",
         | 
| 16 | 
            +
                  className
         | 
| 17 | 
            +
                )}
         | 
| 18 | 
            +
                {...props}
         | 
| 19 | 
            +
              >
         | 
| 20 | 
            +
                {children}
         | 
| 21 | 
            +
                <NavigationMenuViewport />
         | 
| 22 | 
            +
              </NavigationMenuPrimitive.Root>
         | 
| 23 | 
            +
            ))
         | 
| 24 | 
            +
            NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            const NavigationMenuList = React.forwardRef<
         | 
| 27 | 
            +
              React.ElementRef<typeof NavigationMenuPrimitive.List>,
         | 
| 28 | 
            +
              React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
         | 
| 29 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 30 | 
            +
              <NavigationMenuPrimitive.List
         | 
| 31 | 
            +
                ref={ref}
         | 
| 32 | 
            +
                className={cn(
         | 
| 33 | 
            +
                  "group flex flex-1 list-none items-center justify-center space-x-1",
         | 
| 34 | 
            +
                  className
         | 
| 35 | 
            +
                )}
         | 
| 36 | 
            +
                {...props}
         | 
| 37 | 
            +
              />
         | 
| 38 | 
            +
            ))
         | 
| 39 | 
            +
            NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
         | 
| 40 | 
            +
             | 
| 41 | 
            +
            const NavigationMenuItem = NavigationMenuPrimitive.Item
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            const navigationMenuTriggerStyle = cva(
         | 
| 44 | 
            +
              "group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[state=open]:text-accent-foreground data-[state=open]:bg-accent/50 data-[state=open]:hover:bg-accent data-[state=open]:focus:bg-accent"
         | 
| 45 | 
            +
            )
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            const NavigationMenuTrigger = React.forwardRef<
         | 
| 48 | 
            +
              React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
         | 
| 49 | 
            +
              React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
         | 
| 50 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 51 | 
            +
              <NavigationMenuPrimitive.Trigger
         | 
| 52 | 
            +
                ref={ref}
         | 
| 53 | 
            +
                className={cn(navigationMenuTriggerStyle(), "group", className)}
         | 
| 54 | 
            +
                {...props}
         | 
| 55 | 
            +
              >
         | 
| 56 | 
            +
                {children}{" "}
         | 
| 57 | 
            +
                <ChevronDown
         | 
| 58 | 
            +
                  className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
         | 
| 59 | 
            +
                  aria-hidden="true"
         | 
| 60 | 
            +
                />
         | 
| 61 | 
            +
              </NavigationMenuPrimitive.Trigger>
         | 
| 62 | 
            +
            ))
         | 
| 63 | 
            +
            NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
         | 
| 64 | 
            +
             | 
| 65 | 
            +
            const NavigationMenuContent = React.forwardRef<
         | 
| 66 | 
            +
              React.ElementRef<typeof NavigationMenuPrimitive.Content>,
         | 
| 67 | 
            +
              React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
         | 
| 68 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 69 | 
            +
              <NavigationMenuPrimitive.Content
         | 
| 70 | 
            +
                ref={ref}
         | 
| 71 | 
            +
                className={cn(
         | 
| 72 | 
            +
                  "left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto ",
         | 
| 73 | 
            +
                  className
         | 
| 74 | 
            +
                )}
         | 
| 75 | 
            +
                {...props}
         | 
| 76 | 
            +
              />
         | 
| 77 | 
            +
            ))
         | 
| 78 | 
            +
            NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
         | 
| 79 | 
            +
             | 
| 80 | 
            +
            const NavigationMenuLink = NavigationMenuPrimitive.Link
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            const NavigationMenuViewport = React.forwardRef<
         | 
| 83 | 
            +
              React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
         | 
| 84 | 
            +
              React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
         | 
| 85 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 86 | 
            +
              <div className={cn("absolute left-0 top-full flex justify-center")}>
         | 
| 87 | 
            +
                <NavigationMenuPrimitive.Viewport
         | 
| 88 | 
            +
                  className={cn(
         | 
| 89 | 
            +
                    "origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
         | 
| 90 | 
            +
                    className
         | 
| 91 | 
            +
                  )}
         | 
| 92 | 
            +
                  ref={ref}
         | 
| 93 | 
            +
                  {...props}
         | 
| 94 | 
            +
                />
         | 
| 95 | 
            +
              </div>
         | 
| 96 | 
            +
            ))
         | 
| 97 | 
            +
            NavigationMenuViewport.displayName =
         | 
| 98 | 
            +
              NavigationMenuPrimitive.Viewport.displayName
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            const NavigationMenuIndicator = React.forwardRef<
         | 
| 101 | 
            +
              React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
         | 
| 102 | 
            +
              React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
         | 
| 103 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 104 | 
            +
              <NavigationMenuPrimitive.Indicator
         | 
| 105 | 
            +
                ref={ref}
         | 
| 106 | 
            +
                className={cn(
         | 
| 107 | 
            +
                  "top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
         | 
| 108 | 
            +
                  className
         | 
| 109 | 
            +
                )}
         | 
| 110 | 
            +
                {...props}
         | 
| 111 | 
            +
              >
         | 
| 112 | 
            +
                <div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
         | 
| 113 | 
            +
              </NavigationMenuPrimitive.Indicator>
         | 
| 114 | 
            +
            ))
         | 
| 115 | 
            +
            NavigationMenuIndicator.displayName =
         | 
| 116 | 
            +
              NavigationMenuPrimitive.Indicator.displayName
         | 
| 117 | 
            +
             | 
| 118 | 
            +
            export {
         | 
| 119 | 
            +
              navigationMenuTriggerStyle,
         | 
| 120 | 
            +
              NavigationMenu,
         | 
| 121 | 
            +
              NavigationMenuList,
         | 
| 122 | 
            +
              NavigationMenuItem,
         | 
| 123 | 
            +
              NavigationMenuContent,
         | 
| 124 | 
            +
              NavigationMenuTrigger,
         | 
| 125 | 
            +
              NavigationMenuLink,
         | 
| 126 | 
            +
              NavigationMenuIndicator,
         | 
| 127 | 
            +
              NavigationMenuViewport,
         | 
| 128 | 
            +
            }
         | 
    	
        client/src/components/ui/navigation.tsx
    ADDED
    
    | @@ -0,0 +1,72 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import { Card } from "@/components/ui/card";
         | 
| 2 | 
            +
            import { Button } from "@/components/ui/button";
         | 
| 3 | 
            +
            import { Bot, Circle, Download } from "lucide-react";
         | 
| 4 | 
            +
            import { useState } from "react";
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            const navigationItems = [
         | 
| 7 | 
            +
              { id: "overview", label: "Overview", icon: "fas fa-home" },
         | 
| 8 | 
            +
              { id: "modules", label: "Modules", icon: "fas fa-cube" },
         | 
| 9 | 
            +
              { id: "configuration", label: "Configuration", icon: "fas fa-cog" },
         | 
| 10 | 
            +
              { id: "commands", label: "CLI Commands", icon: "fas fa-terminal" },
         | 
| 11 | 
            +
              { id: "deployment", label: "Deployment", icon: "fas fa-rocket" },
         | 
| 12 | 
            +
            ];
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            const quickActions = [
         | 
| 15 | 
            +
              { label: "Initialize Project", icon: "fas fa-play" },
         | 
| 16 | 
            +
              { label: "Download Models", icon: "fas fa-download" },
         | 
| 17 | 
            +
              { label: "Run Tests", icon: "fas fa-test-tube" },
         | 
| 18 | 
            +
            ];
         | 
| 19 | 
            +
             | 
| 20 | 
            +
            interface NavigationProps {
         | 
| 21 | 
            +
              activeSection: string;
         | 
| 22 | 
            +
              onSectionChange: (section: string) => void;
         | 
| 23 | 
            +
            }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            export function Navigation({ activeSection, onSectionChange }: NavigationProps) {
         | 
| 26 | 
            +
              return (
         | 
| 27 | 
            +
                <aside className="space-y-4 sticky top-24">
         | 
| 28 | 
            +
                  <Card className="p-4 border-border bg-card">
         | 
| 29 | 
            +
                    <h3 className="font-semibold mb-4 text-sm uppercase tracking-wide text-muted-foreground">
         | 
| 30 | 
            +
                      Project Setup
         | 
| 31 | 
            +
                    </h3>
         | 
| 32 | 
            +
                    <ul className="space-y-2">
         | 
| 33 | 
            +
                      {navigationItems.map((item) => (
         | 
| 34 | 
            +
                        <li key={item.id}>
         | 
| 35 | 
            +
                          <button
         | 
| 36 | 
            +
                            onClick={() => onSectionChange(item.id)}
         | 
| 37 | 
            +
                            className={`flex items-center space-x-3 w-full px-3 py-2 rounded-md text-sm font-medium transition-colors ${
         | 
| 38 | 
            +
                              activeSection === item.id
         | 
| 39 | 
            +
                                ? "text-primary bg-primary/10"
         | 
| 40 | 
            +
                                : "text-foreground hover:text-primary"
         | 
| 41 | 
            +
                            }`}
         | 
| 42 | 
            +
                            data-testid={`nav-${item.id}`}
         | 
| 43 | 
            +
                          >
         | 
| 44 | 
            +
                            <i className={`${item.icon} w-4`}></i>
         | 
| 45 | 
            +
                            <span>{item.label}</span>
         | 
| 46 | 
            +
                          </button>
         | 
| 47 | 
            +
                        </li>
         | 
| 48 | 
            +
                      ))}
         | 
| 49 | 
            +
                    </ul>
         | 
| 50 | 
            +
                  </Card>
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                  <Card className="p-4 border-border bg-card">
         | 
| 53 | 
            +
                    <h3 className="font-semibold mb-4 text-sm uppercase tracking-wide text-muted-foreground">
         | 
| 54 | 
            +
                      Quick Actions
         | 
| 55 | 
            +
                    </h3>
         | 
| 56 | 
            +
                    <div className="space-y-3">
         | 
| 57 | 
            +
                      {quickActions.map((action, index) => (
         | 
| 58 | 
            +
                        <Button
         | 
| 59 | 
            +
                          key={index}
         | 
| 60 | 
            +
                          variant="secondary"
         | 
| 61 | 
            +
                          className="w-full justify-start text-left"
         | 
| 62 | 
            +
                          data-testid={`action-${action.label.toLowerCase().replace(/\s+/g, '-')}`}
         | 
| 63 | 
            +
                        >
         | 
| 64 | 
            +
                          <i className={`${action.icon} mr-2`}></i>
         | 
| 65 | 
            +
                          {action.label}
         | 
| 66 | 
            +
                        </Button>
         | 
| 67 | 
            +
                      ))}
         | 
| 68 | 
            +
                    </div>
         | 
| 69 | 
            +
                  </Card>
         | 
| 70 | 
            +
                </aside>
         | 
| 71 | 
            +
              );
         | 
| 72 | 
            +
            }
         | 
    	
        client/src/components/ui/pagination.tsx
    ADDED
    
    | @@ -0,0 +1,117 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
            import { ButtonProps, buttonVariants } from "@/components/ui/button"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
         | 
| 8 | 
            +
              <nav
         | 
| 9 | 
            +
                role="navigation"
         | 
| 10 | 
            +
                aria-label="pagination"
         | 
| 11 | 
            +
                className={cn("mx-auto flex w-full justify-center", className)}
         | 
| 12 | 
            +
                {...props}
         | 
| 13 | 
            +
              />
         | 
| 14 | 
            +
            )
         | 
| 15 | 
            +
            Pagination.displayName = "Pagination"
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            const PaginationContent = React.forwardRef<
         | 
| 18 | 
            +
              HTMLUListElement,
         | 
| 19 | 
            +
              React.ComponentProps<"ul">
         | 
| 20 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 21 | 
            +
              <ul
         | 
| 22 | 
            +
                ref={ref}
         | 
| 23 | 
            +
                className={cn("flex flex-row items-center gap-1", className)}
         | 
| 24 | 
            +
                {...props}
         | 
| 25 | 
            +
              />
         | 
| 26 | 
            +
            ))
         | 
| 27 | 
            +
            PaginationContent.displayName = "PaginationContent"
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            const PaginationItem = React.forwardRef<
         | 
| 30 | 
            +
              HTMLLIElement,
         | 
| 31 | 
            +
              React.ComponentProps<"li">
         | 
| 32 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 33 | 
            +
              <li ref={ref} className={cn("", className)} {...props} />
         | 
| 34 | 
            +
            ))
         | 
| 35 | 
            +
            PaginationItem.displayName = "PaginationItem"
         | 
| 36 | 
            +
             | 
| 37 | 
            +
            type PaginationLinkProps = {
         | 
| 38 | 
            +
              isActive?: boolean
         | 
| 39 | 
            +
            } & Pick<ButtonProps, "size"> &
         | 
| 40 | 
            +
              React.ComponentProps<"a">
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            const PaginationLink = ({
         | 
| 43 | 
            +
              className,
         | 
| 44 | 
            +
              isActive,
         | 
| 45 | 
            +
              size = "icon",
         | 
| 46 | 
            +
              ...props
         | 
| 47 | 
            +
            }: PaginationLinkProps) => (
         | 
| 48 | 
            +
              <a
         | 
| 49 | 
            +
                aria-current={isActive ? "page" : undefined}
         | 
| 50 | 
            +
                className={cn(
         | 
| 51 | 
            +
                  buttonVariants({
         | 
| 52 | 
            +
                    variant: isActive ? "outline" : "ghost",
         | 
| 53 | 
            +
                    size,
         | 
| 54 | 
            +
                  }),
         | 
| 55 | 
            +
                  className
         | 
| 56 | 
            +
                )}
         | 
| 57 | 
            +
                {...props}
         | 
| 58 | 
            +
              />
         | 
| 59 | 
            +
            )
         | 
| 60 | 
            +
            PaginationLink.displayName = "PaginationLink"
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            const PaginationPrevious = ({
         | 
| 63 | 
            +
              className,
         | 
| 64 | 
            +
              ...props
         | 
| 65 | 
            +
            }: React.ComponentProps<typeof PaginationLink>) => (
         | 
| 66 | 
            +
              <PaginationLink
         | 
| 67 | 
            +
                aria-label="Go to previous page"
         | 
| 68 | 
            +
                size="default"
         | 
| 69 | 
            +
                className={cn("gap-1 pl-2.5", className)}
         | 
| 70 | 
            +
                {...props}
         | 
| 71 | 
            +
              >
         | 
| 72 | 
            +
                <ChevronLeft className="h-4 w-4" />
         | 
| 73 | 
            +
                <span>Previous</span>
         | 
| 74 | 
            +
              </PaginationLink>
         | 
| 75 | 
            +
            )
         | 
| 76 | 
            +
            PaginationPrevious.displayName = "PaginationPrevious"
         | 
| 77 | 
            +
             | 
| 78 | 
            +
            const PaginationNext = ({
         | 
| 79 | 
            +
              className,
         | 
| 80 | 
            +
              ...props
         | 
| 81 | 
            +
            }: React.ComponentProps<typeof PaginationLink>) => (
         | 
| 82 | 
            +
              <PaginationLink
         | 
| 83 | 
            +
                aria-label="Go to next page"
         | 
| 84 | 
            +
                size="default"
         | 
| 85 | 
            +
                className={cn("gap-1 pr-2.5", className)}
         | 
| 86 | 
            +
                {...props}
         | 
| 87 | 
            +
              >
         | 
| 88 | 
            +
                <span>Next</span>
         | 
| 89 | 
            +
                <ChevronRight className="h-4 w-4" />
         | 
| 90 | 
            +
              </PaginationLink>
         | 
| 91 | 
            +
            )
         | 
| 92 | 
            +
            PaginationNext.displayName = "PaginationNext"
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            const PaginationEllipsis = ({
         | 
| 95 | 
            +
              className,
         | 
| 96 | 
            +
              ...props
         | 
| 97 | 
            +
            }: React.ComponentProps<"span">) => (
         | 
| 98 | 
            +
              <span
         | 
| 99 | 
            +
                aria-hidden
         | 
| 100 | 
            +
                className={cn("flex h-9 w-9 items-center justify-center", className)}
         | 
| 101 | 
            +
                {...props}
         | 
| 102 | 
            +
              >
         | 
| 103 | 
            +
                <MoreHorizontal className="h-4 w-4" />
         | 
| 104 | 
            +
                <span className="sr-only">More pages</span>
         | 
| 105 | 
            +
              </span>
         | 
| 106 | 
            +
            )
         | 
| 107 | 
            +
            PaginationEllipsis.displayName = "PaginationEllipsis"
         | 
| 108 | 
            +
             | 
| 109 | 
            +
            export {
         | 
| 110 | 
            +
              Pagination,
         | 
| 111 | 
            +
              PaginationContent,
         | 
| 112 | 
            +
              PaginationEllipsis,
         | 
| 113 | 
            +
              PaginationItem,
         | 
| 114 | 
            +
              PaginationLink,
         | 
| 115 | 
            +
              PaginationNext,
         | 
| 116 | 
            +
              PaginationPrevious,
         | 
| 117 | 
            +
            }
         | 
    	
        client/src/components/ui/popover.tsx
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as PopoverPrimitive from "@radix-ui/react-popover"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            const Popover = PopoverPrimitive.Root
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const PopoverTrigger = PopoverPrimitive.Trigger
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            const PopoverContent = React.forwardRef<
         | 
| 11 | 
            +
              React.ElementRef<typeof PopoverPrimitive.Content>,
         | 
| 12 | 
            +
              React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
         | 
| 13 | 
            +
            >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
         | 
| 14 | 
            +
              <PopoverPrimitive.Portal>
         | 
| 15 | 
            +
                <PopoverPrimitive.Content
         | 
| 16 | 
            +
                  ref={ref}
         | 
| 17 | 
            +
                  align={align}
         | 
| 18 | 
            +
                  sideOffset={sideOffset}
         | 
| 19 | 
            +
                  className={cn(
         | 
| 20 | 
            +
                    "z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
         | 
| 21 | 
            +
                    className
         | 
| 22 | 
            +
                  )}
         | 
| 23 | 
            +
                  {...props}
         | 
| 24 | 
            +
                />
         | 
| 25 | 
            +
              </PopoverPrimitive.Portal>
         | 
| 26 | 
            +
            ))
         | 
| 27 | 
            +
            PopoverContent.displayName = PopoverPrimitive.Content.displayName
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            export { Popover, PopoverTrigger, PopoverContent }
         | 
    	
        client/src/components/ui/progress.tsx
    ADDED
    
    | @@ -0,0 +1,28 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as ProgressPrimitive from "@radix-ui/react-progress"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const Progress = React.forwardRef<
         | 
| 9 | 
            +
              React.ElementRef<typeof ProgressPrimitive.Root>,
         | 
| 10 | 
            +
              React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
         | 
| 11 | 
            +
            >(({ className, value, ...props }, ref) => (
         | 
| 12 | 
            +
              <ProgressPrimitive.Root
         | 
| 13 | 
            +
                ref={ref}
         | 
| 14 | 
            +
                className={cn(
         | 
| 15 | 
            +
                  "relative h-4 w-full overflow-hidden rounded-full bg-secondary",
         | 
| 16 | 
            +
                  className
         | 
| 17 | 
            +
                )}
         | 
| 18 | 
            +
                {...props}
         | 
| 19 | 
            +
              >
         | 
| 20 | 
            +
                <ProgressPrimitive.Indicator
         | 
| 21 | 
            +
                  className="h-full w-full flex-1 bg-primary transition-all"
         | 
| 22 | 
            +
                  style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
         | 
| 23 | 
            +
                />
         | 
| 24 | 
            +
              </ProgressPrimitive.Root>
         | 
| 25 | 
            +
            ))
         | 
| 26 | 
            +
            Progress.displayName = ProgressPrimitive.Root.displayName
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            export { Progress }
         | 
    	
        client/src/components/ui/radio-group.tsx
    ADDED
    
    | @@ -0,0 +1,42 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
         | 
| 3 | 
            +
            import { Circle } from "lucide-react"
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            const RadioGroup = React.forwardRef<
         | 
| 8 | 
            +
              React.ElementRef<typeof RadioGroupPrimitive.Root>,
         | 
| 9 | 
            +
              React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
         | 
| 10 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 11 | 
            +
              return (
         | 
| 12 | 
            +
                <RadioGroupPrimitive.Root
         | 
| 13 | 
            +
                  className={cn("grid gap-2", className)}
         | 
| 14 | 
            +
                  {...props}
         | 
| 15 | 
            +
                  ref={ref}
         | 
| 16 | 
            +
                />
         | 
| 17 | 
            +
              )
         | 
| 18 | 
            +
            })
         | 
| 19 | 
            +
            RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            const RadioGroupItem = React.forwardRef<
         | 
| 22 | 
            +
              React.ElementRef<typeof RadioGroupPrimitive.Item>,
         | 
| 23 | 
            +
              React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
         | 
| 24 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 25 | 
            +
              return (
         | 
| 26 | 
            +
                <RadioGroupPrimitive.Item
         | 
| 27 | 
            +
                  ref={ref}
         | 
| 28 | 
            +
                  className={cn(
         | 
| 29 | 
            +
                    "aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
         | 
| 30 | 
            +
                    className
         | 
| 31 | 
            +
                  )}
         | 
| 32 | 
            +
                  {...props}
         | 
| 33 | 
            +
                >
         | 
| 34 | 
            +
                  <RadioGroupPrimitive.Indicator className="flex items-center justify-center">
         | 
| 35 | 
            +
                    <Circle className="h-2.5 w-2.5 fill-current text-current" />
         | 
| 36 | 
            +
                  </RadioGroupPrimitive.Indicator>
         | 
| 37 | 
            +
                </RadioGroupPrimitive.Item>
         | 
| 38 | 
            +
              )
         | 
| 39 | 
            +
            })
         | 
| 40 | 
            +
            RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            export { RadioGroup, RadioGroupItem }
         | 
    	
        client/src/components/ui/resizable.tsx
    ADDED
    
    | @@ -0,0 +1,45 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import { GripVertical } from "lucide-react"
         | 
| 4 | 
            +
            import * as ResizablePrimitive from "react-resizable-panels"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            const ResizablePanelGroup = ({
         | 
| 9 | 
            +
              className,
         | 
| 10 | 
            +
              ...props
         | 
| 11 | 
            +
            }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
         | 
| 12 | 
            +
              <ResizablePrimitive.PanelGroup
         | 
| 13 | 
            +
                className={cn(
         | 
| 14 | 
            +
                  "flex h-full w-full data-[panel-group-direction=vertical]:flex-col",
         | 
| 15 | 
            +
                  className
         | 
| 16 | 
            +
                )}
         | 
| 17 | 
            +
                {...props}
         | 
| 18 | 
            +
              />
         | 
| 19 | 
            +
            )
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            const ResizablePanel = ResizablePrimitive.Panel
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            const ResizableHandle = ({
         | 
| 24 | 
            +
              withHandle,
         | 
| 25 | 
            +
              className,
         | 
| 26 | 
            +
              ...props
         | 
| 27 | 
            +
            }: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
         | 
| 28 | 
            +
              withHandle?: boolean
         | 
| 29 | 
            +
            }) => (
         | 
| 30 | 
            +
              <ResizablePrimitive.PanelResizeHandle
         | 
| 31 | 
            +
                className={cn(
         | 
| 32 | 
            +
                  "relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90",
         | 
| 33 | 
            +
                  className
         | 
| 34 | 
            +
                )}
         | 
| 35 | 
            +
                {...props}
         | 
| 36 | 
            +
              >
         | 
| 37 | 
            +
                {withHandle && (
         | 
| 38 | 
            +
                  <div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
         | 
| 39 | 
            +
                    <GripVertical className="h-2.5 w-2.5" />
         | 
| 40 | 
            +
                  </div>
         | 
| 41 | 
            +
                )}
         | 
| 42 | 
            +
              </ResizablePrimitive.PanelResizeHandle>
         | 
| 43 | 
            +
            )
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            export { ResizablePanelGroup, ResizablePanel, ResizableHandle }
         | 
    	
        client/src/components/ui/scroll-area.tsx
    ADDED
    
    | @@ -0,0 +1,46 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            const ScrollArea = React.forwardRef<
         | 
| 7 | 
            +
              React.ElementRef<typeof ScrollAreaPrimitive.Root>,
         | 
| 8 | 
            +
              React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
         | 
| 9 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 10 | 
            +
              <ScrollAreaPrimitive.Root
         | 
| 11 | 
            +
                ref={ref}
         | 
| 12 | 
            +
                className={cn("relative overflow-hidden", className)}
         | 
| 13 | 
            +
                {...props}
         | 
| 14 | 
            +
              >
         | 
| 15 | 
            +
                <ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
         | 
| 16 | 
            +
                  {children}
         | 
| 17 | 
            +
                </ScrollAreaPrimitive.Viewport>
         | 
| 18 | 
            +
                <ScrollBar />
         | 
| 19 | 
            +
                <ScrollAreaPrimitive.Corner />
         | 
| 20 | 
            +
              </ScrollAreaPrimitive.Root>
         | 
| 21 | 
            +
            ))
         | 
| 22 | 
            +
            ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
         | 
| 23 | 
            +
             | 
| 24 | 
            +
            const ScrollBar = React.forwardRef<
         | 
| 25 | 
            +
              React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
         | 
| 26 | 
            +
              React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
         | 
| 27 | 
            +
            >(({ className, orientation = "vertical", ...props }, ref) => (
         | 
| 28 | 
            +
              <ScrollAreaPrimitive.ScrollAreaScrollbar
         | 
| 29 | 
            +
                ref={ref}
         | 
| 30 | 
            +
                orientation={orientation}
         | 
| 31 | 
            +
                className={cn(
         | 
| 32 | 
            +
                  "flex touch-none select-none transition-colors",
         | 
| 33 | 
            +
                  orientation === "vertical" &&
         | 
| 34 | 
            +
                    "h-full w-2.5 border-l border-l-transparent p-[1px]",
         | 
| 35 | 
            +
                  orientation === "horizontal" &&
         | 
| 36 | 
            +
                    "h-2.5 flex-col border-t border-t-transparent p-[1px]",
         | 
| 37 | 
            +
                  className
         | 
| 38 | 
            +
                )}
         | 
| 39 | 
            +
                {...props}
         | 
| 40 | 
            +
              >
         | 
| 41 | 
            +
                <ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
         | 
| 42 | 
            +
              </ScrollAreaPrimitive.ScrollAreaScrollbar>
         | 
| 43 | 
            +
            ))
         | 
| 44 | 
            +
            ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            export { ScrollArea, ScrollBar }
         | 
    	
        client/src/components/ui/select.tsx
    ADDED
    
    | @@ -0,0 +1,160 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as SelectPrimitive from "@radix-ui/react-select"
         | 
| 5 | 
            +
            import { Check, ChevronDown, ChevronUp } from "lucide-react"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            const Select = SelectPrimitive.Root
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            const SelectGroup = SelectPrimitive.Group
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            const SelectValue = SelectPrimitive.Value
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            const SelectTrigger = React.forwardRef<
         | 
| 16 | 
            +
              React.ElementRef<typeof SelectPrimitive.Trigger>,
         | 
| 17 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
         | 
| 18 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 19 | 
            +
              <SelectPrimitive.Trigger
         | 
| 20 | 
            +
                ref={ref}
         | 
| 21 | 
            +
                className={cn(
         | 
| 22 | 
            +
                  "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
         | 
| 23 | 
            +
                  className
         | 
| 24 | 
            +
                )}
         | 
| 25 | 
            +
                {...props}
         | 
| 26 | 
            +
              >
         | 
| 27 | 
            +
                {children}
         | 
| 28 | 
            +
                <SelectPrimitive.Icon asChild>
         | 
| 29 | 
            +
                  <ChevronDown className="h-4 w-4 opacity-50" />
         | 
| 30 | 
            +
                </SelectPrimitive.Icon>
         | 
| 31 | 
            +
              </SelectPrimitive.Trigger>
         | 
| 32 | 
            +
            ))
         | 
| 33 | 
            +
            SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            const SelectScrollUpButton = React.forwardRef<
         | 
| 36 | 
            +
              React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
         | 
| 37 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
         | 
| 38 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 39 | 
            +
              <SelectPrimitive.ScrollUpButton
         | 
| 40 | 
            +
                ref={ref}
         | 
| 41 | 
            +
                className={cn(
         | 
| 42 | 
            +
                  "flex cursor-default items-center justify-center py-1",
         | 
| 43 | 
            +
                  className
         | 
| 44 | 
            +
                )}
         | 
| 45 | 
            +
                {...props}
         | 
| 46 | 
            +
              >
         | 
| 47 | 
            +
                <ChevronUp className="h-4 w-4" />
         | 
| 48 | 
            +
              </SelectPrimitive.ScrollUpButton>
         | 
| 49 | 
            +
            ))
         | 
| 50 | 
            +
            SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            const SelectScrollDownButton = React.forwardRef<
         | 
| 53 | 
            +
              React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
         | 
| 54 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
         | 
| 55 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 56 | 
            +
              <SelectPrimitive.ScrollDownButton
         | 
| 57 | 
            +
                ref={ref}
         | 
| 58 | 
            +
                className={cn(
         | 
| 59 | 
            +
                  "flex cursor-default items-center justify-center py-1",
         | 
| 60 | 
            +
                  className
         | 
| 61 | 
            +
                )}
         | 
| 62 | 
            +
                {...props}
         | 
| 63 | 
            +
              >
         | 
| 64 | 
            +
                <ChevronDown className="h-4 w-4" />
         | 
| 65 | 
            +
              </SelectPrimitive.ScrollDownButton>
         | 
| 66 | 
            +
            ))
         | 
| 67 | 
            +
            SelectScrollDownButton.displayName =
         | 
| 68 | 
            +
              SelectPrimitive.ScrollDownButton.displayName
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            const SelectContent = React.forwardRef<
         | 
| 71 | 
            +
              React.ElementRef<typeof SelectPrimitive.Content>,
         | 
| 72 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
         | 
| 73 | 
            +
            >(({ className, children, position = "popper", ...props }, ref) => (
         | 
| 74 | 
            +
              <SelectPrimitive.Portal>
         | 
| 75 | 
            +
                <SelectPrimitive.Content
         | 
| 76 | 
            +
                  ref={ref}
         | 
| 77 | 
            +
                  className={cn(
         | 
| 78 | 
            +
                    "relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-select-content-transform-origin]",
         | 
| 79 | 
            +
                    position === "popper" &&
         | 
| 80 | 
            +
                      "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
         | 
| 81 | 
            +
                    className
         | 
| 82 | 
            +
                  )}
         | 
| 83 | 
            +
                  position={position}
         | 
| 84 | 
            +
                  {...props}
         | 
| 85 | 
            +
                >
         | 
| 86 | 
            +
                  <SelectScrollUpButton />
         | 
| 87 | 
            +
                  <SelectPrimitive.Viewport
         | 
| 88 | 
            +
                    className={cn(
         | 
| 89 | 
            +
                      "p-1",
         | 
| 90 | 
            +
                      position === "popper" &&
         | 
| 91 | 
            +
                        "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
         | 
| 92 | 
            +
                    )}
         | 
| 93 | 
            +
                  >
         | 
| 94 | 
            +
                    {children}
         | 
| 95 | 
            +
                  </SelectPrimitive.Viewport>
         | 
| 96 | 
            +
                  <SelectScrollDownButton />
         | 
| 97 | 
            +
                </SelectPrimitive.Content>
         | 
| 98 | 
            +
              </SelectPrimitive.Portal>
         | 
| 99 | 
            +
            ))
         | 
| 100 | 
            +
            SelectContent.displayName = SelectPrimitive.Content.displayName
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            const SelectLabel = React.forwardRef<
         | 
| 103 | 
            +
              React.ElementRef<typeof SelectPrimitive.Label>,
         | 
| 104 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
         | 
| 105 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 106 | 
            +
              <SelectPrimitive.Label
         | 
| 107 | 
            +
                ref={ref}
         | 
| 108 | 
            +
                className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
         | 
| 109 | 
            +
                {...props}
         | 
| 110 | 
            +
              />
         | 
| 111 | 
            +
            ))
         | 
| 112 | 
            +
            SelectLabel.displayName = SelectPrimitive.Label.displayName
         | 
| 113 | 
            +
             | 
| 114 | 
            +
            const SelectItem = React.forwardRef<
         | 
| 115 | 
            +
              React.ElementRef<typeof SelectPrimitive.Item>,
         | 
| 116 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
         | 
| 117 | 
            +
            >(({ className, children, ...props }, ref) => (
         | 
| 118 | 
            +
              <SelectPrimitive.Item
         | 
| 119 | 
            +
                ref={ref}
         | 
| 120 | 
            +
                className={cn(
         | 
| 121 | 
            +
                  "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
         | 
| 122 | 
            +
                  className
         | 
| 123 | 
            +
                )}
         | 
| 124 | 
            +
                {...props}
         | 
| 125 | 
            +
              >
         | 
| 126 | 
            +
                <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
         | 
| 127 | 
            +
                  <SelectPrimitive.ItemIndicator>
         | 
| 128 | 
            +
                    <Check className="h-4 w-4" />
         | 
| 129 | 
            +
                  </SelectPrimitive.ItemIndicator>
         | 
| 130 | 
            +
                </span>
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
         | 
| 133 | 
            +
              </SelectPrimitive.Item>
         | 
| 134 | 
            +
            ))
         | 
| 135 | 
            +
            SelectItem.displayName = SelectPrimitive.Item.displayName
         | 
| 136 | 
            +
             | 
| 137 | 
            +
            const SelectSeparator = React.forwardRef<
         | 
| 138 | 
            +
              React.ElementRef<typeof SelectPrimitive.Separator>,
         | 
| 139 | 
            +
              React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
         | 
| 140 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 141 | 
            +
              <SelectPrimitive.Separator
         | 
| 142 | 
            +
                ref={ref}
         | 
| 143 | 
            +
                className={cn("-mx-1 my-1 h-px bg-muted", className)}
         | 
| 144 | 
            +
                {...props}
         | 
| 145 | 
            +
              />
         | 
| 146 | 
            +
            ))
         | 
| 147 | 
            +
            SelectSeparator.displayName = SelectPrimitive.Separator.displayName
         | 
| 148 | 
            +
             | 
| 149 | 
            +
            export {
         | 
| 150 | 
            +
              Select,
         | 
| 151 | 
            +
              SelectGroup,
         | 
| 152 | 
            +
              SelectValue,
         | 
| 153 | 
            +
              SelectTrigger,
         | 
| 154 | 
            +
              SelectContent,
         | 
| 155 | 
            +
              SelectLabel,
         | 
| 156 | 
            +
              SelectItem,
         | 
| 157 | 
            +
              SelectSeparator,
         | 
| 158 | 
            +
              SelectScrollUpButton,
         | 
| 159 | 
            +
              SelectScrollDownButton,
         | 
| 160 | 
            +
            }
         | 
    	
        client/src/components/ui/separator.tsx
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import * as SeparatorPrimitive from "@radix-ui/react-separator"
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            const Separator = React.forwardRef<
         | 
| 7 | 
            +
              React.ElementRef<typeof SeparatorPrimitive.Root>,
         | 
| 8 | 
            +
              React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
         | 
| 9 | 
            +
            >(
         | 
| 10 | 
            +
              (
         | 
| 11 | 
            +
                { className, orientation = "horizontal", decorative = true, ...props },
         | 
| 12 | 
            +
                ref
         | 
| 13 | 
            +
              ) => (
         | 
| 14 | 
            +
                <SeparatorPrimitive.Root
         | 
| 15 | 
            +
                  ref={ref}
         | 
| 16 | 
            +
                  decorative={decorative}
         | 
| 17 | 
            +
                  orientation={orientation}
         | 
| 18 | 
            +
                  className={cn(
         | 
| 19 | 
            +
                    "shrink-0 bg-border",
         | 
| 20 | 
            +
                    orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
         | 
| 21 | 
            +
                    className
         | 
| 22 | 
            +
                  )}
         | 
| 23 | 
            +
                  {...props}
         | 
| 24 | 
            +
                />
         | 
| 25 | 
            +
              )
         | 
| 26 | 
            +
            )
         | 
| 27 | 
            +
            Separator.displayName = SeparatorPrimitive.Root.displayName
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            export { Separator }
         | 
    	
        client/src/components/ui/sheet.tsx
    ADDED
    
    | @@ -0,0 +1,140 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            "use client"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            import * as React from "react"
         | 
| 4 | 
            +
            import * as SheetPrimitive from "@radix-ui/react-dialog"
         | 
| 5 | 
            +
            import { cva, type VariantProps } from "class-variance-authority"
         | 
| 6 | 
            +
            import { X } from "lucide-react"
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            const Sheet = SheetPrimitive.Root
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            const SheetTrigger = SheetPrimitive.Trigger
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            const SheetClose = SheetPrimitive.Close
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            const SheetPortal = SheetPrimitive.Portal
         | 
| 17 | 
            +
             | 
| 18 | 
            +
            const SheetOverlay = React.forwardRef<
         | 
| 19 | 
            +
              React.ElementRef<typeof SheetPrimitive.Overlay>,
         | 
| 20 | 
            +
              React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
         | 
| 21 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 22 | 
            +
              <SheetPrimitive.Overlay
         | 
| 23 | 
            +
                className={cn(
         | 
| 24 | 
            +
                  "fixed inset-0 z-50 bg-black/80  data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
         | 
| 25 | 
            +
                  className
         | 
| 26 | 
            +
                )}
         | 
| 27 | 
            +
                {...props}
         | 
| 28 | 
            +
                ref={ref}
         | 
| 29 | 
            +
              />
         | 
| 30 | 
            +
            ))
         | 
| 31 | 
            +
            SheetOverlay.displayName = SheetPrimitive.Overlay.displayName
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            const sheetVariants = cva(
         | 
| 34 | 
            +
              "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
         | 
| 35 | 
            +
              {
         | 
| 36 | 
            +
                variants: {
         | 
| 37 | 
            +
                  side: {
         | 
| 38 | 
            +
                    top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
         | 
| 39 | 
            +
                    bottom:
         | 
| 40 | 
            +
                      "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
         | 
| 41 | 
            +
                    left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
         | 
| 42 | 
            +
                    right:
         | 
| 43 | 
            +
                      "inset-y-0 right-0 h-full w-3/4  border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
         | 
| 44 | 
            +
                  },
         | 
| 45 | 
            +
                },
         | 
| 46 | 
            +
                defaultVariants: {
         | 
| 47 | 
            +
                  side: "right",
         | 
| 48 | 
            +
                },
         | 
| 49 | 
            +
              }
         | 
| 50 | 
            +
            )
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            interface SheetContentProps
         | 
| 53 | 
            +
              extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
         | 
| 54 | 
            +
                VariantProps<typeof sheetVariants> {}
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            const SheetContent = React.forwardRef<
         | 
| 57 | 
            +
              React.ElementRef<typeof SheetPrimitive.Content>,
         | 
| 58 | 
            +
              SheetContentProps
         | 
| 59 | 
            +
            >(({ side = "right", className, children, ...props }, ref) => (
         | 
| 60 | 
            +
              <SheetPortal>
         | 
| 61 | 
            +
                <SheetOverlay />
         | 
| 62 | 
            +
                <SheetPrimitive.Content
         | 
| 63 | 
            +
                  ref={ref}
         | 
| 64 | 
            +
                  className={cn(sheetVariants({ side }), className)}
         | 
| 65 | 
            +
                  {...props}
         | 
| 66 | 
            +
                >
         | 
| 67 | 
            +
                  {children}
         | 
| 68 | 
            +
                  <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
         | 
| 69 | 
            +
                    <X className="h-4 w-4" />
         | 
| 70 | 
            +
                    <span className="sr-only">Close</span>
         | 
| 71 | 
            +
                  </SheetPrimitive.Close>
         | 
| 72 | 
            +
                </SheetPrimitive.Content>
         | 
| 73 | 
            +
              </SheetPortal>
         | 
| 74 | 
            +
            ))
         | 
| 75 | 
            +
            SheetContent.displayName = SheetPrimitive.Content.displayName
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            const SheetHeader = ({
         | 
| 78 | 
            +
              className,
         | 
| 79 | 
            +
              ...props
         | 
| 80 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 81 | 
            +
              <div
         | 
| 82 | 
            +
                className={cn(
         | 
| 83 | 
            +
                  "flex flex-col space-y-2 text-center sm:text-left",
         | 
| 84 | 
            +
                  className
         | 
| 85 | 
            +
                )}
         | 
| 86 | 
            +
                {...props}
         | 
| 87 | 
            +
              />
         | 
| 88 | 
            +
            )
         | 
| 89 | 
            +
            SheetHeader.displayName = "SheetHeader"
         | 
| 90 | 
            +
             | 
| 91 | 
            +
            const SheetFooter = ({
         | 
| 92 | 
            +
              className,
         | 
| 93 | 
            +
              ...props
         | 
| 94 | 
            +
            }: React.HTMLAttributes<HTMLDivElement>) => (
         | 
| 95 | 
            +
              <div
         | 
| 96 | 
            +
                className={cn(
         | 
| 97 | 
            +
                  "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
         | 
| 98 | 
            +
                  className
         | 
| 99 | 
            +
                )}
         | 
| 100 | 
            +
                {...props}
         | 
| 101 | 
            +
              />
         | 
| 102 | 
            +
            )
         | 
| 103 | 
            +
            SheetFooter.displayName = "SheetFooter"
         | 
| 104 | 
            +
             | 
| 105 | 
            +
            const SheetTitle = React.forwardRef<
         | 
| 106 | 
            +
              React.ElementRef<typeof SheetPrimitive.Title>,
         | 
| 107 | 
            +
              React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
         | 
| 108 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 109 | 
            +
              <SheetPrimitive.Title
         | 
| 110 | 
            +
                ref={ref}
         | 
| 111 | 
            +
                className={cn("text-lg font-semibold text-foreground", className)}
         | 
| 112 | 
            +
                {...props}
         | 
| 113 | 
            +
              />
         | 
| 114 | 
            +
            ))
         | 
| 115 | 
            +
            SheetTitle.displayName = SheetPrimitive.Title.displayName
         | 
| 116 | 
            +
             | 
| 117 | 
            +
            const SheetDescription = React.forwardRef<
         | 
| 118 | 
            +
              React.ElementRef<typeof SheetPrimitive.Description>,
         | 
| 119 | 
            +
              React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
         | 
| 120 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 121 | 
            +
              <SheetPrimitive.Description
         | 
| 122 | 
            +
                ref={ref}
         | 
| 123 | 
            +
                className={cn("text-sm text-muted-foreground", className)}
         | 
| 124 | 
            +
                {...props}
         | 
| 125 | 
            +
              />
         | 
| 126 | 
            +
            ))
         | 
| 127 | 
            +
            SheetDescription.displayName = SheetPrimitive.Description.displayName
         | 
| 128 | 
            +
             | 
| 129 | 
            +
            export {
         | 
| 130 | 
            +
              Sheet,
         | 
| 131 | 
            +
              SheetPortal,
         | 
| 132 | 
            +
              SheetOverlay,
         | 
| 133 | 
            +
              SheetTrigger,
         | 
| 134 | 
            +
              SheetClose,
         | 
| 135 | 
            +
              SheetContent,
         | 
| 136 | 
            +
              SheetHeader,
         | 
| 137 | 
            +
              SheetFooter,
         | 
| 138 | 
            +
              SheetTitle,
         | 
| 139 | 
            +
              SheetDescription,
         | 
| 140 | 
            +
            }
         | 
    	
        client/src/components/ui/sidebar.tsx
    ADDED
    
    | @@ -0,0 +1,771 @@ | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | |
|  | 
|  | |
| 1 | 
            +
            import * as React from "react"
         | 
| 2 | 
            +
            import { Slot } from "@radix-ui/react-slot"
         | 
| 3 | 
            +
            import { VariantProps, cva } from "class-variance-authority"
         | 
| 4 | 
            +
            import { PanelLeft } from "lucide-react"
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            import { useIsMobile } from "@/hooks/use-mobile"
         | 
| 7 | 
            +
            import { cn } from "@/lib/utils"
         | 
| 8 | 
            +
            import { Button } from "@/components/ui/button"
         | 
| 9 | 
            +
            import { Input } from "@/components/ui/input"
         | 
| 10 | 
            +
            import { Separator } from "@/components/ui/separator"
         | 
| 11 | 
            +
            import {
         | 
| 12 | 
            +
              Sheet,
         | 
| 13 | 
            +
              SheetContent,
         | 
| 14 | 
            +
              SheetDescription,
         | 
| 15 | 
            +
              SheetHeader,
         | 
| 16 | 
            +
              SheetTitle,
         | 
| 17 | 
            +
            } from "@/components/ui/sheet"
         | 
| 18 | 
            +
            import { Skeleton } from "@/components/ui/skeleton"
         | 
| 19 | 
            +
            import {
         | 
| 20 | 
            +
              Tooltip,
         | 
| 21 | 
            +
              TooltipContent,
         | 
| 22 | 
            +
              TooltipProvider,
         | 
| 23 | 
            +
              TooltipTrigger,
         | 
| 24 | 
            +
            } from "@/components/ui/tooltip"
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            const SIDEBAR_COOKIE_NAME = "sidebar_state"
         | 
| 27 | 
            +
            const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
         | 
| 28 | 
            +
            const SIDEBAR_WIDTH = "16rem"
         | 
| 29 | 
            +
            const SIDEBAR_WIDTH_MOBILE = "18rem"
         | 
| 30 | 
            +
            const SIDEBAR_WIDTH_ICON = "3rem"
         | 
| 31 | 
            +
            const SIDEBAR_KEYBOARD_SHORTCUT = "b"
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            type SidebarContextProps = {
         | 
| 34 | 
            +
              state: "expanded" | "collapsed"
         | 
| 35 | 
            +
              open: boolean
         | 
| 36 | 
            +
              setOpen: (open: boolean) => void
         | 
| 37 | 
            +
              openMobile: boolean
         | 
| 38 | 
            +
              setOpenMobile: (open: boolean) => void
         | 
| 39 | 
            +
              isMobile: boolean
         | 
| 40 | 
            +
              toggleSidebar: () => void
         | 
| 41 | 
            +
            }
         | 
| 42 | 
            +
             | 
| 43 | 
            +
            const SidebarContext = React.createContext<SidebarContextProps | null>(null)
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            function useSidebar() {
         | 
| 46 | 
            +
              const context = React.useContext(SidebarContext)
         | 
| 47 | 
            +
              if (!context) {
         | 
| 48 | 
            +
                throw new Error("useSidebar must be used within a SidebarProvider.")
         | 
| 49 | 
            +
              }
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              return context
         | 
| 52 | 
            +
            }
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            const SidebarProvider = React.forwardRef<
         | 
| 55 | 
            +
              HTMLDivElement,
         | 
| 56 | 
            +
              React.ComponentProps<"div"> & {
         | 
| 57 | 
            +
                defaultOpen?: boolean
         | 
| 58 | 
            +
                open?: boolean
         | 
| 59 | 
            +
                onOpenChange?: (open: boolean) => void
         | 
| 60 | 
            +
              }
         | 
| 61 | 
            +
            >(
         | 
| 62 | 
            +
              (
         | 
| 63 | 
            +
                {
         | 
| 64 | 
            +
                  defaultOpen = true,
         | 
| 65 | 
            +
                  open: openProp,
         | 
| 66 | 
            +
                  onOpenChange: setOpenProp,
         | 
| 67 | 
            +
                  className,
         | 
| 68 | 
            +
                  style,
         | 
| 69 | 
            +
                  children,
         | 
| 70 | 
            +
                  ...props
         | 
| 71 | 
            +
                },
         | 
| 72 | 
            +
                ref
         | 
| 73 | 
            +
              ) => {
         | 
| 74 | 
            +
                const isMobile = useIsMobile()
         | 
| 75 | 
            +
                const [openMobile, setOpenMobile] = React.useState(false)
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                // This is the internal state of the sidebar.
         | 
| 78 | 
            +
                // We use openProp and setOpenProp for control from outside the component.
         | 
| 79 | 
            +
                const [_open, _setOpen] = React.useState(defaultOpen)
         | 
| 80 | 
            +
                const open = openProp ?? _open
         | 
| 81 | 
            +
                const setOpen = React.useCallback(
         | 
| 82 | 
            +
                  (value: boolean | ((value: boolean) => boolean)) => {
         | 
| 83 | 
            +
                    const openState = typeof value === "function" ? value(open) : value
         | 
| 84 | 
            +
                    if (setOpenProp) {
         | 
| 85 | 
            +
                      setOpenProp(openState)
         | 
| 86 | 
            +
                    } else {
         | 
| 87 | 
            +
                      _setOpen(openState)
         | 
| 88 | 
            +
                    }
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                    // This sets the cookie to keep the sidebar state.
         | 
| 91 | 
            +
                    document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`
         | 
| 92 | 
            +
                  },
         | 
| 93 | 
            +
                  [setOpenProp, open]
         | 
| 94 | 
            +
                )
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                // Helper to toggle the sidebar.
         | 
| 97 | 
            +
                const toggleSidebar = React.useCallback(() => {
         | 
| 98 | 
            +
                  return isMobile
         | 
| 99 | 
            +
                    ? setOpenMobile((open) => !open)
         | 
| 100 | 
            +
                    : setOpen((open) => !open)
         | 
| 101 | 
            +
                }, [isMobile, setOpen, setOpenMobile])
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                // Adds a keyboard shortcut to toggle the sidebar.
         | 
| 104 | 
            +
                React.useEffect(() => {
         | 
| 105 | 
            +
                  const handleKeyDown = (event: KeyboardEvent) => {
         | 
| 106 | 
            +
                    if (
         | 
| 107 | 
            +
                      event.key === SIDEBAR_KEYBOARD_SHORTCUT &&
         | 
| 108 | 
            +
                      (event.metaKey || event.ctrlKey)
         | 
| 109 | 
            +
                    ) {
         | 
| 110 | 
            +
                      event.preventDefault()
         | 
| 111 | 
            +
                      toggleSidebar()
         | 
| 112 | 
            +
                    }
         | 
| 113 | 
            +
                  }
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  window.addEventListener("keydown", handleKeyDown)
         | 
| 116 | 
            +
                  return () => window.removeEventListener("keydown", handleKeyDown)
         | 
| 117 | 
            +
                }, [toggleSidebar])
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                // We add a state so that we can do data-state="expanded" or "collapsed".
         | 
| 120 | 
            +
                // This makes it easier to style the sidebar with Tailwind classes.
         | 
| 121 | 
            +
                const state = open ? "expanded" : "collapsed"
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                const contextValue = React.useMemo<SidebarContextProps>(
         | 
| 124 | 
            +
                  () => ({
         | 
| 125 | 
            +
                    state,
         | 
| 126 | 
            +
                    open,
         | 
| 127 | 
            +
                    setOpen,
         | 
| 128 | 
            +
                    isMobile,
         | 
| 129 | 
            +
                    openMobile,
         | 
| 130 | 
            +
                    setOpenMobile,
         | 
| 131 | 
            +
                    toggleSidebar,
         | 
| 132 | 
            +
                  }),
         | 
| 133 | 
            +
                  [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]
         | 
| 134 | 
            +
                )
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                return (
         | 
| 137 | 
            +
                  <SidebarContext.Provider value={contextValue}>
         | 
| 138 | 
            +
                    <TooltipProvider delayDuration={0}>
         | 
| 139 | 
            +
                      <div
         | 
| 140 | 
            +
                        style={
         | 
| 141 | 
            +
                          {
         | 
| 142 | 
            +
                            "--sidebar-width": SIDEBAR_WIDTH,
         | 
| 143 | 
            +
                            "--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
         | 
| 144 | 
            +
                            ...style,
         | 
| 145 | 
            +
                          } as React.CSSProperties
         | 
| 146 | 
            +
                        }
         | 
| 147 | 
            +
                        className={cn(
         | 
| 148 | 
            +
                          "group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar",
         | 
| 149 | 
            +
                          className
         | 
| 150 | 
            +
                        )}
         | 
| 151 | 
            +
                        ref={ref}
         | 
| 152 | 
            +
                        {...props}
         | 
| 153 | 
            +
                      >
         | 
| 154 | 
            +
                        {children}
         | 
| 155 | 
            +
                      </div>
         | 
| 156 | 
            +
                    </TooltipProvider>
         | 
| 157 | 
            +
                  </SidebarContext.Provider>
         | 
| 158 | 
            +
                )
         | 
| 159 | 
            +
              }
         | 
| 160 | 
            +
            )
         | 
| 161 | 
            +
            SidebarProvider.displayName = "SidebarProvider"
         | 
| 162 | 
            +
             | 
| 163 | 
            +
            const Sidebar = React.forwardRef<
         | 
| 164 | 
            +
              HTMLDivElement,
         | 
| 165 | 
            +
              React.ComponentProps<"div"> & {
         | 
| 166 | 
            +
                side?: "left" | "right"
         | 
| 167 | 
            +
                variant?: "sidebar" | "floating" | "inset"
         | 
| 168 | 
            +
                collapsible?: "offcanvas" | "icon" | "none"
         | 
| 169 | 
            +
              }
         | 
| 170 | 
            +
            >(
         | 
| 171 | 
            +
              (
         | 
| 172 | 
            +
                {
         | 
| 173 | 
            +
                  side = "left",
         | 
| 174 | 
            +
                  variant = "sidebar",
         | 
| 175 | 
            +
                  collapsible = "offcanvas",
         | 
| 176 | 
            +
                  className,
         | 
| 177 | 
            +
                  children,
         | 
| 178 | 
            +
                  ...props
         | 
| 179 | 
            +
                },
         | 
| 180 | 
            +
                ref
         | 
| 181 | 
            +
              ) => {
         | 
| 182 | 
            +
                const { isMobile, state, openMobile, setOpenMobile } = useSidebar()
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                if (collapsible === "none") {
         | 
| 185 | 
            +
                  return (
         | 
| 186 | 
            +
                    <div
         | 
| 187 | 
            +
                      className={cn(
         | 
| 188 | 
            +
                        "flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground",
         | 
| 189 | 
            +
                        className
         | 
| 190 | 
            +
                      )}
         | 
| 191 | 
            +
                      ref={ref}
         | 
| 192 | 
            +
                      {...props}
         | 
| 193 | 
            +
                    >
         | 
| 194 | 
            +
                      {children}
         | 
| 195 | 
            +
                    </div>
         | 
| 196 | 
            +
                  )
         | 
| 197 | 
            +
                }
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                if (isMobile) {
         | 
| 200 | 
            +
                  return (
         | 
| 201 | 
            +
                    <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
         | 
| 202 | 
            +
                      <SheetContent
         | 
| 203 | 
            +
                        data-sidebar="sidebar"
         | 
| 204 | 
            +
                        data-mobile="true"
         | 
| 205 | 
            +
                        className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
         | 
| 206 | 
            +
                        style={
         | 
| 207 | 
            +
                          {
         | 
| 208 | 
            +
                            "--sidebar-width": SIDEBAR_WIDTH_MOBILE,
         | 
| 209 | 
            +
                          } as React.CSSProperties
         | 
| 210 | 
            +
                        }
         | 
| 211 | 
            +
                        side={side}
         | 
| 212 | 
            +
                      >
         | 
| 213 | 
            +
                        <SheetHeader className="sr-only">
         | 
| 214 | 
            +
                          <SheetTitle>Sidebar</SheetTitle>
         | 
| 215 | 
            +
                          <SheetDescription>Displays the mobile sidebar.</SheetDescription>
         | 
| 216 | 
            +
                        </SheetHeader>
         | 
| 217 | 
            +
                        <div className="flex h-full w-full flex-col">{children}</div>
         | 
| 218 | 
            +
                      </SheetContent>
         | 
| 219 | 
            +
                    </Sheet>
         | 
| 220 | 
            +
                  )
         | 
| 221 | 
            +
                }
         | 
| 222 | 
            +
             | 
| 223 | 
            +
                return (
         | 
| 224 | 
            +
                  <div
         | 
| 225 | 
            +
                    ref={ref}
         | 
| 226 | 
            +
                    className="group peer hidden text-sidebar-foreground md:block"
         | 
| 227 | 
            +
                    data-state={state}
         | 
| 228 | 
            +
                    data-collapsible={state === "collapsed" ? collapsible : ""}
         | 
| 229 | 
            +
                    data-variant={variant}
         | 
| 230 | 
            +
                    data-side={side}
         | 
| 231 | 
            +
                  >
         | 
| 232 | 
            +
                    {/* This is what handles the sidebar gap on desktop */}
         | 
| 233 | 
            +
                    <div
         | 
| 234 | 
            +
                      className={cn(
         | 
| 235 | 
            +
                        "relative w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear",
         | 
| 236 | 
            +
                        "group-data-[collapsible=offcanvas]:w-0",
         | 
| 237 | 
            +
                        "group-data-[side=right]:rotate-180",
         | 
| 238 | 
            +
                        variant === "floating" || variant === "inset"
         | 
| 239 | 
            +
                          ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
         | 
| 240 | 
            +
                          : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]"
         | 
| 241 | 
            +
                      )}
         | 
| 242 | 
            +
                    />
         | 
| 243 | 
            +
                    <div
         | 
| 244 | 
            +
                      className={cn(
         | 
| 245 | 
            +
                        "fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex",
         | 
| 246 | 
            +
                        side === "left"
         | 
| 247 | 
            +
                          ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
         | 
| 248 | 
            +
                          : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
         | 
| 249 | 
            +
                        // Adjust the padding for floating and inset variants.
         | 
| 250 | 
            +
                        variant === "floating" || variant === "inset"
         | 
| 251 | 
            +
                          ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
         | 
| 252 | 
            +
                          : "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l",
         | 
| 253 | 
            +
                        className
         | 
| 254 | 
            +
                      )}
         | 
| 255 | 
            +
                      {...props}
         | 
| 256 | 
            +
                    >
         | 
| 257 | 
            +
                      <div
         | 
| 258 | 
            +
                        data-sidebar="sidebar"
         | 
| 259 | 
            +
                        className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
         | 
| 260 | 
            +
                      >
         | 
| 261 | 
            +
                        {children}
         | 
| 262 | 
            +
                      </div>
         | 
| 263 | 
            +
                    </div>
         | 
| 264 | 
            +
                  </div>
         | 
| 265 | 
            +
                )
         | 
| 266 | 
            +
              }
         | 
| 267 | 
            +
            )
         | 
| 268 | 
            +
            Sidebar.displayName = "Sidebar"
         | 
| 269 | 
            +
             | 
| 270 | 
            +
            const SidebarTrigger = React.forwardRef<
         | 
| 271 | 
            +
              React.ElementRef<typeof Button>,
         | 
| 272 | 
            +
              React.ComponentProps<typeof Button>
         | 
| 273 | 
            +
            >(({ className, onClick, ...props }, ref) => {
         | 
| 274 | 
            +
              const { toggleSidebar } = useSidebar()
         | 
| 275 | 
            +
             | 
| 276 | 
            +
              return (
         | 
| 277 | 
            +
                <Button
         | 
| 278 | 
            +
                  ref={ref}
         | 
| 279 | 
            +
                  data-sidebar="trigger"
         | 
| 280 | 
            +
                  variant="ghost"
         | 
| 281 | 
            +
                  size="icon"
         | 
| 282 | 
            +
                  className={cn("h-7 w-7", className)}
         | 
| 283 | 
            +
                  onClick={(event) => {
         | 
| 284 | 
            +
                    onClick?.(event)
         | 
| 285 | 
            +
                    toggleSidebar()
         | 
| 286 | 
            +
                  }}
         | 
| 287 | 
            +
                  {...props}
         | 
| 288 | 
            +
                >
         | 
| 289 | 
            +
                  <PanelLeft />
         | 
| 290 | 
            +
                  <span className="sr-only">Toggle Sidebar</span>
         | 
| 291 | 
            +
                </Button>
         | 
| 292 | 
            +
              )
         | 
| 293 | 
            +
            })
         | 
| 294 | 
            +
            SidebarTrigger.displayName = "SidebarTrigger"
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            const SidebarRail = React.forwardRef<
         | 
| 297 | 
            +
              HTMLButtonElement,
         | 
| 298 | 
            +
              React.ComponentProps<"button">
         | 
| 299 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 300 | 
            +
              const { toggleSidebar } = useSidebar()
         | 
| 301 | 
            +
             | 
| 302 | 
            +
              return (
         | 
| 303 | 
            +
                <button
         | 
| 304 | 
            +
                  ref={ref}
         | 
| 305 | 
            +
                  data-sidebar="rail"
         | 
| 306 | 
            +
                  aria-label="Toggle Sidebar"
         | 
| 307 | 
            +
                  tabIndex={-1}
         | 
| 308 | 
            +
                  onClick={toggleSidebar}
         | 
| 309 | 
            +
                  title="Toggle Sidebar"
         | 
| 310 | 
            +
                  className={cn(
         | 
| 311 | 
            +
                    "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
         | 
| 312 | 
            +
                    "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
         | 
| 313 | 
            +
                    "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
         | 
| 314 | 
            +
                    "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
         | 
| 315 | 
            +
                    "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
         | 
| 316 | 
            +
                    "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
         | 
| 317 | 
            +
                    className
         | 
| 318 | 
            +
                  )}
         | 
| 319 | 
            +
                  {...props}
         | 
| 320 | 
            +
                />
         | 
| 321 | 
            +
              )
         | 
| 322 | 
            +
            })
         | 
| 323 | 
            +
            SidebarRail.displayName = "SidebarRail"
         | 
| 324 | 
            +
             | 
| 325 | 
            +
            const SidebarInset = React.forwardRef<
         | 
| 326 | 
            +
              HTMLDivElement,
         | 
| 327 | 
            +
              React.ComponentProps<"main">
         | 
| 328 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 329 | 
            +
              return (
         | 
| 330 | 
            +
                <main
         | 
| 331 | 
            +
                  ref={ref}
         | 
| 332 | 
            +
                  className={cn(
         | 
| 333 | 
            +
                    "relative flex w-full flex-1 flex-col bg-background",
         | 
| 334 | 
            +
                    "md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
         | 
| 335 | 
            +
                    className
         | 
| 336 | 
            +
                  )}
         | 
| 337 | 
            +
                  {...props}
         | 
| 338 | 
            +
                />
         | 
| 339 | 
            +
              )
         | 
| 340 | 
            +
            })
         | 
| 341 | 
            +
            SidebarInset.displayName = "SidebarInset"
         | 
| 342 | 
            +
             | 
| 343 | 
            +
            const SidebarInput = React.forwardRef<
         | 
| 344 | 
            +
              React.ElementRef<typeof Input>,
         | 
| 345 | 
            +
              React.ComponentProps<typeof Input>
         | 
| 346 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 347 | 
            +
              return (
         | 
| 348 | 
            +
                <Input
         | 
| 349 | 
            +
                  ref={ref}
         | 
| 350 | 
            +
                  data-sidebar="input"
         | 
| 351 | 
            +
                  className={cn(
         | 
| 352 | 
            +
                    "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
         | 
| 353 | 
            +
                    className
         | 
| 354 | 
            +
                  )}
         | 
| 355 | 
            +
                  {...props}
         | 
| 356 | 
            +
                />
         | 
| 357 | 
            +
              )
         | 
| 358 | 
            +
            })
         | 
| 359 | 
            +
            SidebarInput.displayName = "SidebarInput"
         | 
| 360 | 
            +
             | 
| 361 | 
            +
            const SidebarHeader = React.forwardRef<
         | 
| 362 | 
            +
              HTMLDivElement,
         | 
| 363 | 
            +
              React.ComponentProps<"div">
         | 
| 364 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 365 | 
            +
              return (
         | 
| 366 | 
            +
                <div
         | 
| 367 | 
            +
                  ref={ref}
         | 
| 368 | 
            +
                  data-sidebar="header"
         | 
| 369 | 
            +
                  className={cn("flex flex-col gap-2 p-2", className)}
         | 
| 370 | 
            +
                  {...props}
         | 
| 371 | 
            +
                />
         | 
| 372 | 
            +
              )
         | 
| 373 | 
            +
            })
         | 
| 374 | 
            +
            SidebarHeader.displayName = "SidebarHeader"
         | 
| 375 | 
            +
             | 
| 376 | 
            +
            const SidebarFooter = React.forwardRef<
         | 
| 377 | 
            +
              HTMLDivElement,
         | 
| 378 | 
            +
              React.ComponentProps<"div">
         | 
| 379 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 380 | 
            +
              return (
         | 
| 381 | 
            +
                <div
         | 
| 382 | 
            +
                  ref={ref}
         | 
| 383 | 
            +
                  data-sidebar="footer"
         | 
| 384 | 
            +
                  className={cn("flex flex-col gap-2 p-2", className)}
         | 
| 385 | 
            +
                  {...props}
         | 
| 386 | 
            +
                />
         | 
| 387 | 
            +
              )
         | 
| 388 | 
            +
            })
         | 
| 389 | 
            +
            SidebarFooter.displayName = "SidebarFooter"
         | 
| 390 | 
            +
             | 
| 391 | 
            +
            const SidebarSeparator = React.forwardRef<
         | 
| 392 | 
            +
              React.ElementRef<typeof Separator>,
         | 
| 393 | 
            +
              React.ComponentProps<typeof Separator>
         | 
| 394 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 395 | 
            +
              return (
         | 
| 396 | 
            +
                <Separator
         | 
| 397 | 
            +
                  ref={ref}
         | 
| 398 | 
            +
                  data-sidebar="separator"
         | 
| 399 | 
            +
                  className={cn("mx-2 w-auto bg-sidebar-border", className)}
         | 
| 400 | 
            +
                  {...props}
         | 
| 401 | 
            +
                />
         | 
| 402 | 
            +
              )
         | 
| 403 | 
            +
            })
         | 
| 404 | 
            +
            SidebarSeparator.displayName = "SidebarSeparator"
         | 
| 405 | 
            +
             | 
| 406 | 
            +
            const SidebarContent = React.forwardRef<
         | 
| 407 | 
            +
              HTMLDivElement,
         | 
| 408 | 
            +
              React.ComponentProps<"div">
         | 
| 409 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 410 | 
            +
              return (
         | 
| 411 | 
            +
                <div
         | 
| 412 | 
            +
                  ref={ref}
         | 
| 413 | 
            +
                  data-sidebar="content"
         | 
| 414 | 
            +
                  className={cn(
         | 
| 415 | 
            +
                    "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
         | 
| 416 | 
            +
                    className
         | 
| 417 | 
            +
                  )}
         | 
| 418 | 
            +
                  {...props}
         | 
| 419 | 
            +
                />
         | 
| 420 | 
            +
              )
         | 
| 421 | 
            +
            })
         | 
| 422 | 
            +
            SidebarContent.displayName = "SidebarContent"
         | 
| 423 | 
            +
             | 
| 424 | 
            +
            const SidebarGroup = React.forwardRef<
         | 
| 425 | 
            +
              HTMLDivElement,
         | 
| 426 | 
            +
              React.ComponentProps<"div">
         | 
| 427 | 
            +
            >(({ className, ...props }, ref) => {
         | 
| 428 | 
            +
              return (
         | 
| 429 | 
            +
                <div
         | 
| 430 | 
            +
                  ref={ref}
         | 
| 431 | 
            +
                  data-sidebar="group"
         | 
| 432 | 
            +
                  className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
         | 
| 433 | 
            +
                  {...props}
         | 
| 434 | 
            +
                />
         | 
| 435 | 
            +
              )
         | 
| 436 | 
            +
            })
         | 
| 437 | 
            +
            SidebarGroup.displayName = "SidebarGroup"
         | 
| 438 | 
            +
             | 
| 439 | 
            +
            const SidebarGroupLabel = React.forwardRef<
         | 
| 440 | 
            +
              HTMLDivElement,
         | 
| 441 | 
            +
              React.ComponentProps<"div"> & { asChild?: boolean }
         | 
| 442 | 
            +
            >(({ className, asChild = false, ...props }, ref) => {
         | 
| 443 | 
            +
              const Comp = asChild ? Slot : "div"
         | 
| 444 | 
            +
             | 
| 445 | 
            +
              return (
         | 
| 446 | 
            +
                <Comp
         | 
| 447 | 
            +
                  ref={ref}
         | 
| 448 | 
            +
                  data-sidebar="group-label"
         | 
| 449 | 
            +
                  className={cn(
         | 
| 450 | 
            +
                    "flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
         | 
| 451 | 
            +
                    "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
         | 
| 452 | 
            +
                    className
         | 
| 453 | 
            +
                  )}
         | 
| 454 | 
            +
                  {...props}
         | 
| 455 | 
            +
                />
         | 
| 456 | 
            +
              )
         | 
| 457 | 
            +
            })
         | 
| 458 | 
            +
            SidebarGroupLabel.displayName = "SidebarGroupLabel"
         | 
| 459 | 
            +
             | 
| 460 | 
            +
            const SidebarGroupAction = React.forwardRef<
         | 
| 461 | 
            +
              HTMLButtonElement,
         | 
| 462 | 
            +
              React.ComponentProps<"button"> & { asChild?: boolean }
         | 
| 463 | 
            +
            >(({ className, asChild = false, ...props }, ref) => {
         | 
| 464 | 
            +
              const Comp = asChild ? Slot : "button"
         | 
| 465 | 
            +
             | 
| 466 | 
            +
              return (
         | 
| 467 | 
            +
                <Comp
         | 
| 468 | 
            +
                  ref={ref}
         | 
| 469 | 
            +
                  data-sidebar="group-action"
         | 
| 470 | 
            +
                  className={cn(
         | 
| 471 | 
            +
                    "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
         | 
| 472 | 
            +
                    // Increases the hit area of the button on mobile.
         | 
| 473 | 
            +
                    "after:absolute after:-inset-2 after:md:hidden",
         | 
| 474 | 
            +
                    "group-data-[collapsible=icon]:hidden",
         | 
| 475 | 
            +
                    className
         | 
| 476 | 
            +
                  )}
         | 
| 477 | 
            +
                  {...props}
         | 
| 478 | 
            +
                />
         | 
| 479 | 
            +
              )
         | 
| 480 | 
            +
            })
         | 
| 481 | 
            +
            SidebarGroupAction.displayName = "SidebarGroupAction"
         | 
| 482 | 
            +
             | 
| 483 | 
            +
            const SidebarGroupContent = React.forwardRef<
         | 
| 484 | 
            +
              HTMLDivElement,
         | 
| 485 | 
            +
              React.ComponentProps<"div">
         | 
| 486 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 487 | 
            +
              <div
         | 
| 488 | 
            +
                ref={ref}
         | 
| 489 | 
            +
                data-sidebar="group-content"
         | 
| 490 | 
            +
                className={cn("w-full text-sm", className)}
         | 
| 491 | 
            +
                {...props}
         | 
| 492 | 
            +
              />
         | 
| 493 | 
            +
            ))
         | 
| 494 | 
            +
            SidebarGroupContent.displayName = "SidebarGroupContent"
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            const SidebarMenu = React.forwardRef<
         | 
| 497 | 
            +
              HTMLUListElement,
         | 
| 498 | 
            +
              React.ComponentProps<"ul">
         | 
| 499 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 500 | 
            +
              <ul
         | 
| 501 | 
            +
                ref={ref}
         | 
| 502 | 
            +
                data-sidebar="menu"
         | 
| 503 | 
            +
                className={cn("flex w-full min-w-0 flex-col gap-1", className)}
         | 
| 504 | 
            +
                {...props}
         | 
| 505 | 
            +
              />
         | 
| 506 | 
            +
            ))
         | 
| 507 | 
            +
            SidebarMenu.displayName = "SidebarMenu"
         | 
| 508 | 
            +
             | 
| 509 | 
            +
            const SidebarMenuItem = React.forwardRef<
         | 
| 510 | 
            +
              HTMLLIElement,
         | 
| 511 | 
            +
              React.ComponentProps<"li">
         | 
| 512 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 513 | 
            +
              <li
         | 
| 514 | 
            +
                ref={ref}
         | 
| 515 | 
            +
                data-sidebar="menu-item"
         | 
| 516 | 
            +
                className={cn("group/menu-item relative", className)}
         | 
| 517 | 
            +
                {...props}
         | 
| 518 | 
            +
              />
         | 
| 519 | 
            +
            ))
         | 
| 520 | 
            +
            SidebarMenuItem.displayName = "SidebarMenuItem"
         | 
| 521 | 
            +
             | 
| 522 | 
            +
            const sidebarMenuButtonVariants = cva(
         | 
| 523 | 
            +
              "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
         | 
| 524 | 
            +
              {
         | 
| 525 | 
            +
                variants: {
         | 
| 526 | 
            +
                  variant: {
         | 
| 527 | 
            +
                    default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
         | 
| 528 | 
            +
                    outline:
         | 
| 529 | 
            +
                      "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
         | 
| 530 | 
            +
                  },
         | 
| 531 | 
            +
                  size: {
         | 
| 532 | 
            +
                    default: "h-8 text-sm",
         | 
| 533 | 
            +
                    sm: "h-7 text-xs",
         | 
| 534 | 
            +
                    lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",
         | 
| 535 | 
            +
                  },
         | 
| 536 | 
            +
                },
         | 
| 537 | 
            +
                defaultVariants: {
         | 
| 538 | 
            +
                  variant: "default",
         | 
| 539 | 
            +
                  size: "default",
         | 
| 540 | 
            +
                },
         | 
| 541 | 
            +
              }
         | 
| 542 | 
            +
            )
         | 
| 543 | 
            +
             | 
| 544 | 
            +
            const SidebarMenuButton = React.forwardRef<
         | 
| 545 | 
            +
              HTMLButtonElement,
         | 
| 546 | 
            +
              React.ComponentProps<"button"> & {
         | 
| 547 | 
            +
                asChild?: boolean
         | 
| 548 | 
            +
                isActive?: boolean
         | 
| 549 | 
            +
                tooltip?: string | React.ComponentProps<typeof TooltipContent>
         | 
| 550 | 
            +
              } & VariantProps<typeof sidebarMenuButtonVariants>
         | 
| 551 | 
            +
            >(
         | 
| 552 | 
            +
              (
         | 
| 553 | 
            +
                {
         | 
| 554 | 
            +
                  asChild = false,
         | 
| 555 | 
            +
                  isActive = false,
         | 
| 556 | 
            +
                  variant = "default",
         | 
| 557 | 
            +
                  size = "default",
         | 
| 558 | 
            +
                  tooltip,
         | 
| 559 | 
            +
                  className,
         | 
| 560 | 
            +
                  ...props
         | 
| 561 | 
            +
                },
         | 
| 562 | 
            +
                ref
         | 
| 563 | 
            +
              ) => {
         | 
| 564 | 
            +
                const Comp = asChild ? Slot : "button"
         | 
| 565 | 
            +
                const { isMobile, state } = useSidebar()
         | 
| 566 | 
            +
             | 
| 567 | 
            +
                const button = (
         | 
| 568 | 
            +
                  <Comp
         | 
| 569 | 
            +
                    ref={ref}
         | 
| 570 | 
            +
                    data-sidebar="menu-button"
         | 
| 571 | 
            +
                    data-size={size}
         | 
| 572 | 
            +
                    data-active={isActive}
         | 
| 573 | 
            +
                    className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
         | 
| 574 | 
            +
                    {...props}
         | 
| 575 | 
            +
                  />
         | 
| 576 | 
            +
                )
         | 
| 577 | 
            +
             | 
| 578 | 
            +
                if (!tooltip) {
         | 
| 579 | 
            +
                  return button
         | 
| 580 | 
            +
                }
         | 
| 581 | 
            +
             | 
| 582 | 
            +
                if (typeof tooltip === "string") {
         | 
| 583 | 
            +
                  tooltip = {
         | 
| 584 | 
            +
                    children: tooltip,
         | 
| 585 | 
            +
                  }
         | 
| 586 | 
            +
                }
         | 
| 587 | 
            +
             | 
| 588 | 
            +
                return (
         | 
| 589 | 
            +
                  <Tooltip>
         | 
| 590 | 
            +
                    <TooltipTrigger asChild>{button}</TooltipTrigger>
         | 
| 591 | 
            +
                    <TooltipContent
         | 
| 592 | 
            +
                      side="right"
         | 
| 593 | 
            +
                      align="center"
         | 
| 594 | 
            +
                      hidden={state !== "collapsed" || isMobile}
         | 
| 595 | 
            +
                      {...tooltip}
         | 
| 596 | 
            +
                    />
         | 
| 597 | 
            +
                  </Tooltip>
         | 
| 598 | 
            +
                )
         | 
| 599 | 
            +
              }
         | 
| 600 | 
            +
            )
         | 
| 601 | 
            +
            SidebarMenuButton.displayName = "SidebarMenuButton"
         | 
| 602 | 
            +
             | 
| 603 | 
            +
            const SidebarMenuAction = React.forwardRef<
         | 
| 604 | 
            +
              HTMLButtonElement,
         | 
| 605 | 
            +
              React.ComponentProps<"button"> & {
         | 
| 606 | 
            +
                asChild?: boolean
         | 
| 607 | 
            +
                showOnHover?: boolean
         | 
| 608 | 
            +
              }
         | 
| 609 | 
            +
            >(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
         | 
| 610 | 
            +
              const Comp = asChild ? Slot : "button"
         | 
| 611 | 
            +
             | 
| 612 | 
            +
              return (
         | 
| 613 | 
            +
                <Comp
         | 
| 614 | 
            +
                  ref={ref}
         | 
| 615 | 
            +
                  data-sidebar="menu-action"
         | 
| 616 | 
            +
                  className={cn(
         | 
| 617 | 
            +
                    "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0",
         | 
| 618 | 
            +
                    // Increases the hit area of the button on mobile.
         | 
| 619 | 
            +
                    "after:absolute after:-inset-2 after:md:hidden",
         | 
| 620 | 
            +
                    "peer-data-[size=sm]/menu-button:top-1",
         | 
| 621 | 
            +
                    "peer-data-[size=default]/menu-button:top-1.5",
         | 
| 622 | 
            +
                    "peer-data-[size=lg]/menu-button:top-2.5",
         | 
| 623 | 
            +
                    "group-data-[collapsible=icon]:hidden",
         | 
| 624 | 
            +
                    showOnHover &&
         | 
| 625 | 
            +
                      "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
         | 
| 626 | 
            +
                    className
         | 
| 627 | 
            +
                  )}
         | 
| 628 | 
            +
                  {...props}
         | 
| 629 | 
            +
                />
         | 
| 630 | 
            +
              )
         | 
| 631 | 
            +
            })
         | 
| 632 | 
            +
            SidebarMenuAction.displayName = "SidebarMenuAction"
         | 
| 633 | 
            +
             | 
| 634 | 
            +
            const SidebarMenuBadge = React.forwardRef<
         | 
| 635 | 
            +
              HTMLDivElement,
         | 
| 636 | 
            +
              React.ComponentProps<"div">
         | 
| 637 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 638 | 
            +
              <div
         | 
| 639 | 
            +
                ref={ref}
         | 
| 640 | 
            +
                data-sidebar="menu-badge"
         | 
| 641 | 
            +
                className={cn(
         | 
| 642 | 
            +
                  "pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground",
         | 
| 643 | 
            +
                  "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
         | 
| 644 | 
            +
                  "peer-data-[size=sm]/menu-button:top-1",
         | 
| 645 | 
            +
                  "peer-data-[size=default]/menu-button:top-1.5",
         | 
| 646 | 
            +
                  "peer-data-[size=lg]/menu-button:top-2.5",
         | 
| 647 | 
            +
                  "group-data-[collapsible=icon]:hidden",
         | 
| 648 | 
            +
                  className
         | 
| 649 | 
            +
                )}
         | 
| 650 | 
            +
                {...props}
         | 
| 651 | 
            +
              />
         | 
| 652 | 
            +
            ))
         | 
| 653 | 
            +
            SidebarMenuBadge.displayName = "SidebarMenuBadge"
         | 
| 654 | 
            +
             | 
| 655 | 
            +
            const SidebarMenuSkeleton = React.forwardRef<
         | 
| 656 | 
            +
              HTMLDivElement,
         | 
| 657 | 
            +
              React.ComponentProps<"div"> & {
         | 
| 658 | 
            +
                showIcon?: boolean
         | 
| 659 | 
            +
              }
         | 
| 660 | 
            +
            >(({ className, showIcon = false, ...props }, ref) => {
         | 
| 661 | 
            +
              // Random width between 50 to 90%.
         | 
| 662 | 
            +
              const width = React.useMemo(() => {
         | 
| 663 | 
            +
                return `${Math.floor(Math.random() * 40) + 50}%`
         | 
| 664 | 
            +
              }, [])
         | 
| 665 | 
            +
             | 
| 666 | 
            +
              return (
         | 
| 667 | 
            +
                <div
         | 
| 668 | 
            +
                  ref={ref}
         | 
| 669 | 
            +
                  data-sidebar="menu-skeleton"
         | 
| 670 | 
            +
                  className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
         | 
| 671 | 
            +
                  {...props}
         | 
| 672 | 
            +
                >
         | 
| 673 | 
            +
                  {showIcon && (
         | 
| 674 | 
            +
                    <Skeleton
         | 
| 675 | 
            +
                      className="size-4 rounded-md"
         | 
| 676 | 
            +
                      data-sidebar="menu-skeleton-icon"
         | 
| 677 | 
            +
                    />
         | 
| 678 | 
            +
                  )}
         | 
| 679 | 
            +
                  <Skeleton
         | 
| 680 | 
            +
                    className="h-4 max-w-[--skeleton-width] flex-1"
         | 
| 681 | 
            +
                    data-sidebar="menu-skeleton-text"
         | 
| 682 | 
            +
                    style={
         | 
| 683 | 
            +
                      {
         | 
| 684 | 
            +
                        "--skeleton-width": width,
         | 
| 685 | 
            +
                      } as React.CSSProperties
         | 
| 686 | 
            +
                    }
         | 
| 687 | 
            +
                  />
         | 
| 688 | 
            +
                </div>
         | 
| 689 | 
            +
              )
         | 
| 690 | 
            +
            })
         | 
| 691 | 
            +
            SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton"
         | 
| 692 | 
            +
             | 
| 693 | 
            +
            const SidebarMenuSub = React.forwardRef<
         | 
| 694 | 
            +
              HTMLUListElement,
         | 
| 695 | 
            +
              React.ComponentProps<"ul">
         | 
| 696 | 
            +
            >(({ className, ...props }, ref) => (
         | 
| 697 | 
            +
              <ul
         | 
| 698 | 
            +
                ref={ref}
         | 
| 699 | 
            +
                data-sidebar="menu-sub"
         | 
| 700 | 
            +
                className={cn(
         | 
| 701 | 
            +
                  "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
         | 
| 702 | 
            +
                  "group-data-[collapsible=icon]:hidden",
         | 
| 703 | 
            +
                  className
         | 
| 704 | 
            +
                )}
         | 
| 705 | 
            +
                {...props}
         | 
| 706 | 
            +
              />
         | 
| 707 | 
            +
            ))
         | 
| 708 | 
            +
            SidebarMenuSub.displayName = "SidebarMenuSub"
         | 
| 709 | 
            +
             | 
| 710 | 
            +
            const SidebarMenuSubItem = React.forwardRef<
         | 
| 711 | 
            +
              HTMLLIElement,
         | 
| 712 | 
            +
              React.ComponentProps<"li">
         | 
| 713 | 
            +
            >(({ ...props }, ref) => <li ref={ref} {...props} />)
         | 
| 714 | 
            +
            SidebarMenuSubItem.displayName = "SidebarMenuSubItem"
         | 
| 715 | 
            +
             | 
| 716 | 
            +
            const SidebarMenuSubButton = React.forwardRef<
         | 
| 717 | 
            +
              HTMLAnchorElement,
         | 
| 718 | 
            +
              React.ComponentProps<"a"> & {
         | 
| 719 | 
            +
                asChild?: boolean
         | 
| 720 | 
            +
                size?: "sm" | "md"
         | 
| 721 | 
            +
                isActive?: boolean
         | 
| 722 | 
            +
              }
         | 
| 723 | 
            +
            >(({ asChild = false, size = "md", isActive, className, ...props }, ref) => {
         | 
| 724 | 
            +
              const Comp = asChild ? Slot : "a"
         | 
| 725 | 
            +
             | 
| 726 | 
            +
              return (
         | 
| 727 | 
            +
                <Comp
         | 
| 728 | 
            +
                  ref={ref}
         | 
| 729 | 
            +
                  data-sidebar="menu-sub-button"
         | 
| 730 | 
            +
                  data-size={size}
         | 
| 731 | 
            +
                  data-active={isActive}
         | 
| 732 | 
            +
                  className={cn(
         | 
| 733 | 
            +
                    "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
         | 
| 734 | 
            +
                    "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
         | 
| 735 | 
            +
                    size === "sm" && "text-xs",
         | 
| 736 | 
            +
                    size === "md" && "text-sm",
         | 
| 737 | 
            +
                    "group-data-[collapsible=icon]:hidden",
         | 
| 738 | 
            +
                    className
         | 
| 739 | 
            +
                  )}
         | 
| 740 | 
            +
                  {...props}
         | 
| 741 | 
            +
                />
         | 
| 742 | 
            +
              )
         | 
| 743 | 
            +
            })
         | 
| 744 | 
            +
            SidebarMenuSubButton.displayName = "SidebarMenuSubButton"
         | 
| 745 | 
            +
             | 
| 746 | 
            +
            export {
         | 
| 747 | 
            +
              Sidebar,
         | 
| 748 | 
            +
              SidebarContent,
         | 
| 749 | 
            +
              SidebarFooter,
         | 
| 750 | 
            +
              SidebarGroup,
         | 
| 751 | 
            +
              SidebarGroupAction,
         | 
| 752 | 
            +
              SidebarGroupContent,
         | 
| 753 | 
            +
              SidebarGroupLabel,
         | 
| 754 | 
            +
              SidebarHeader,
         | 
| 755 | 
            +
              SidebarInput,
         | 
| 756 | 
            +
              SidebarInset,
         | 
| 757 | 
            +
              SidebarMenu,
         | 
| 758 | 
            +
              SidebarMenuAction,
         | 
| 759 | 
            +
              SidebarMenuBadge,
         | 
| 760 | 
            +
              SidebarMenuButton,
         | 
| 761 | 
            +
              SidebarMenuItem,
         | 
| 762 | 
            +
              SidebarMenuSkeleton,
         | 
| 763 | 
            +
              SidebarMenuSub,
         | 
| 764 | 
            +
              SidebarMenuSubButton,
         | 
| 765 | 
            +
              SidebarMenuSubItem,
         | 
| 766 | 
            +
              SidebarProvider,
         | 
| 767 | 
            +
              SidebarRail,
         | 
| 768 | 
            +
              SidebarSeparator,
         | 
| 769 | 
            +
              SidebarTrigger,
         | 
| 770 | 
            +
              useSidebar,
         | 
| 771 | 
            +
            }
         | 
