Repository: cosscom/coss Branch: main Commit: da381b51d9b5 Files: 2789 Total size: 8.3 MB Directory structure: gitextract_1xyzqltd/ ├── .biome-packages-sync/ │ └── packages-sync.json ├── .github/ │ ├── labeler.yml │ └── workflows/ │ ├── build.yml │ ├── ci.yml │ ├── format.yml │ ├── labeler.yml │ ├── lint.yml │ ├── publish.yml │ ├── semantic-pull-requests.yml │ ├── test.yml │ └── typecheck.yml ├── .gitignore ├── .husky/ │ ├── pre-commit │ └── pre-push ├── .vscode/ │ └── settings.json ├── .zed/ │ └── settings.json ├── AGENTS.md ├── LICENSE ├── LICENSING.md ├── README.md ├── apps/ │ ├── examples/ │ │ ├── calcom/ │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── app/ │ │ │ │ ├── (dashboard)/ │ │ │ │ │ ├── booking/ │ │ │ │ │ │ ├── booking-skeleton.tsx │ │ │ │ │ │ ├── canceled/ │ │ │ │ │ │ │ ├── bookings-empty.tsx │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ ├── past/ │ │ │ │ │ │ │ ├── booking-actions.tsx │ │ │ │ │ │ │ ├── bookings-list.tsx │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── recurring/ │ │ │ │ │ │ │ ├── bookings-empty.tsx │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── unconfirmed/ │ │ │ │ │ │ │ ├── bookings-empty.tsx │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ └── upcoming/ │ │ │ │ │ │ ├── bookings-empty.tsx │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── event-types/ │ │ │ │ │ │ ├── add-event-type-dialog.tsx │ │ │ │ │ │ ├── event-type-actions.tsx │ │ │ │ │ │ ├── event-types-list.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── (settings)/ │ │ │ │ │ └── settings/ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── my-account/ │ │ │ │ │ │ ├── general/ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── profile/ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ │ ├── globals.css │ │ │ │ └── layout.tsx │ │ │ ├── components/ │ │ │ │ ├── app/ │ │ │ │ │ ├── app-command.tsx │ │ │ │ │ ├── app-header.tsx │ │ │ │ │ ├── app-mobile-footer.tsx │ │ │ │ │ ├── app-mobile-header.tsx │ │ │ │ │ ├── app-sidebar.tsx │ │ │ │ │ ├── bookings-filters.tsx │ │ │ │ │ ├── bookings-nav.tsx │ │ │ │ │ ├── bookings-view.tsx │ │ │ │ │ ├── nav-main.tsx │ │ │ │ │ ├── nav-secondary.tsx │ │ │ │ │ └── tabbed-nav.tsx │ │ │ │ ├── copyable-field.tsx │ │ │ │ ├── debug-context.tsx │ │ │ │ ├── debug-popover.tsx │ │ │ │ ├── header-actions.tsx │ │ │ │ ├── item-label.tsx │ │ │ │ ├── list-item.tsx │ │ │ │ ├── logo.tsx │ │ │ │ ├── mobile-header.tsx │ │ │ │ ├── settings/ │ │ │ │ │ ├── settings-mobile-header.tsx │ │ │ │ │ ├── settings-nav-section.tsx │ │ │ │ │ ├── settings-sheet.tsx │ │ │ │ │ ├── settings-sidebar.tsx │ │ │ │ │ └── settings-toggle.tsx │ │ │ │ ├── settings-toggle.tsx │ │ │ │ ├── sortable.tsx │ │ │ │ ├── ui/ │ │ │ │ │ └── sidebar.tsx │ │ │ │ ├── user-menu.tsx │ │ │ │ └── workflows-badge.tsx │ │ │ ├── hooks/ │ │ │ │ ├── use-loading-state.ts │ │ │ │ └── use-scroll-hide.ts │ │ │ ├── lib/ │ │ │ │ ├── event-types-types.ts │ │ │ │ ├── markdown-to-safe-html.ts │ │ │ │ ├── mock-ai-data.ts │ │ │ │ ├── mock-bookings-data.ts │ │ │ │ ├── mock-event-types-data.ts │ │ │ │ ├── navigation-data.ts │ │ │ │ └── settings-navigation-data.ts │ │ │ ├── next.config.ts │ │ │ ├── package.json │ │ │ ├── postcss.config.mjs │ │ │ └── tsconfig.json │ │ └── next-env.d.ts │ ├── origin/ │ │ ├── .gitignore │ │ ├── LICENSE.md │ │ ├── README.md │ │ ├── app/ │ │ │ ├── [category]/ │ │ │ │ └── page.tsx │ │ │ ├── easings/ │ │ │ │ ├── copy-class.tsx │ │ │ │ ├── easings.tsx │ │ │ │ └── page.tsx │ │ │ ├── globals.css │ │ │ ├── layout.tsx │ │ │ ├── not-found.tsx │ │ │ ├── page.tsx │ │ │ ├── search/ │ │ │ │ ├── components-container.tsx │ │ │ │ ├── multiselect.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── search-field.tsx │ │ │ └── sitemap.ts │ │ ├── components/ │ │ │ ├── cli-commands.tsx │ │ │ ├── code-block.tsx │ │ │ ├── component-card.tsx │ │ │ ├── component-details.tsx │ │ │ ├── component-loader-client.tsx │ │ │ ├── component-loader-server.tsx │ │ │ ├── copy-button.tsx │ │ │ ├── copy-layout.tsx │ │ │ ├── copy-registry.tsx │ │ │ ├── cta.tsx │ │ │ ├── footer.tsx │ │ │ ├── header-link.tsx │ │ │ ├── header.tsx │ │ │ ├── open-in-v0.tsx │ │ │ ├── page-grid.tsx │ │ │ ├── page-header.tsx │ │ │ ├── search-button.tsx │ │ │ ├── subscribe-action.ts │ │ │ ├── subscribe-form.tsx │ │ │ ├── theme-provider.tsx │ │ │ ├── theme-toggle.tsx │ │ │ └── top-banner.tsx │ │ ├── components.json │ │ ├── config/ │ │ │ └── components.ts │ │ ├── docs/ │ │ │ └── use-file-upload.md │ │ ├── hooks/ │ │ │ ├── use-config.ts │ │ │ ├── use-copy.ts │ │ │ └── use-mobile.tsx │ │ ├── lib/ │ │ │ └── utils.ts │ │ ├── next.config.ts │ │ ├── package.json │ │ ├── postcss.config.mjs │ │ ├── public/ │ │ │ └── r/ │ │ │ ├── accordion.json │ │ │ ├── alert-dialog.json │ │ │ ├── avatar.json │ │ │ ├── badge.json │ │ │ ├── breadcrumb.json │ │ │ ├── button.json │ │ │ ├── calendar-rac.json │ │ │ ├── calendar.json │ │ │ ├── checkbox-tree.json │ │ │ ├── checkbox.json │ │ │ ├── collapsible.json │ │ │ ├── command.json │ │ │ ├── comp-01.json │ │ │ ├── comp-02.json │ │ │ ├── comp-03.json │ │ │ ├── comp-04.json │ │ │ ├── comp-05.json │ │ │ ├── comp-06.json │ │ │ ├── comp-07.json │ │ │ ├── comp-08.json │ │ │ ├── comp-09.json │ │ │ ├── comp-10.json │ │ │ ├── comp-100.json │ │ │ ├── comp-101.json │ │ │ ├── comp-102.json │ │ │ ├── comp-103.json │ │ │ ├── comp-104.json │ │ │ ├── comp-105.json │ │ │ ├── comp-106.json │ │ │ ├── comp-107.json │ │ │ ├── comp-108.json │ │ │ ├── comp-109.json │ │ │ ├── comp-11.json │ │ │ ├── comp-110.json │ │ │ ├── comp-111.json │ │ │ ├── comp-112.json │ │ │ ├── comp-113.json │ │ │ ├── comp-114.json │ │ │ ├── comp-115.json │ │ │ ├── comp-116.json │ │ │ ├── comp-117.json │ │ │ ├── comp-118.json │ │ │ ├── comp-119.json │ │ │ ├── comp-12.json │ │ │ ├── comp-120.json │ │ │ ├── comp-121.json │ │ │ ├── comp-122.json │ │ │ ├── comp-123.json │ │ │ ├── comp-124.json │ │ │ ├── comp-125.json │ │ │ ├── comp-126.json │ │ │ ├── comp-127.json │ │ │ ├── comp-128.json │ │ │ ├── comp-129.json │ │ │ ├── comp-13.json │ │ │ ├── comp-130.json │ │ │ ├── comp-131.json │ │ │ ├── comp-132.json │ │ │ ├── comp-133.json │ │ │ ├── comp-134.json │ │ │ ├── comp-135.json │ │ │ ├── comp-136.json │ │ │ ├── comp-137.json │ │ │ ├── comp-138.json │ │ │ ├── comp-139.json │ │ │ ├── comp-14.json │ │ │ ├── comp-140.json │ │ │ ├── comp-141.json │ │ │ ├── comp-142.json │ │ │ ├── comp-143.json │ │ │ ├── comp-144.json │ │ │ ├── comp-145.json │ │ │ ├── comp-146.json │ │ │ ├── comp-147.json │ │ │ ├── comp-148.json │ │ │ ├── comp-149.json │ │ │ ├── comp-15.json │ │ │ ├── comp-150.json │ │ │ ├── comp-151.json │ │ │ ├── comp-152.json │ │ │ ├── comp-153.json │ │ │ ├── comp-154.json │ │ │ ├── comp-155.json │ │ │ ├── comp-156.json │ │ │ ├── comp-157.json │ │ │ ├── comp-158.json │ │ │ ├── comp-159.json │ │ │ ├── comp-16.json │ │ │ ├── comp-160.json │ │ │ ├── comp-161.json │ │ │ ├── comp-162.json │ │ │ ├── comp-163.json │ │ │ ├── comp-164.json │ │ │ ├── comp-165.json │ │ │ ├── comp-166.json │ │ │ ├── comp-167.json │ │ │ ├── comp-168.json │ │ │ ├── comp-169.json │ │ │ ├── comp-17.json │ │ │ ├── comp-170.json │ │ │ ├── comp-171.json │ │ │ ├── comp-172.json │ │ │ ├── comp-173.json │ │ │ ├── comp-174.json │ │ │ ├── comp-175.json │ │ │ ├── comp-176.json │ │ │ ├── comp-177.json │ │ │ ├── comp-178.json │ │ │ ├── comp-179.json │ │ │ ├── comp-18.json │ │ │ ├── comp-180.json │ │ │ ├── comp-181.json │ │ │ ├── comp-182.json │ │ │ ├── comp-183.json │ │ │ ├── comp-184.json │ │ │ ├── comp-185.json │ │ │ ├── comp-186.json │ │ │ ├── comp-187.json │ │ │ ├── comp-188.json │ │ │ ├── comp-189.json │ │ │ ├── comp-19.json │ │ │ ├── comp-190.json │ │ │ ├── comp-191.json │ │ │ ├── comp-192.json │ │ │ ├── comp-193.json │ │ │ ├── comp-194.json │ │ │ ├── comp-195.json │ │ │ ├── comp-196.json │ │ │ ├── comp-197.json │ │ │ ├── comp-198.json │ │ │ ├── comp-199.json │ │ │ ├── comp-20.json │ │ │ ├── comp-200.json │ │ │ ├── comp-201.json │ │ │ ├── comp-202.json │ │ │ ├── comp-203.json │ │ │ ├── comp-204.json │ │ │ ├── comp-205.json │ │ │ ├── comp-206.json │ │ │ ├── comp-207.json │ │ │ ├── comp-208.json │ │ │ ├── comp-209.json │ │ │ ├── comp-21.json │ │ │ ├── comp-210.json │ │ │ ├── comp-211.json │ │ │ ├── comp-212.json │ │ │ ├── comp-213.json │ │ │ ├── comp-214.json │ │ │ ├── comp-215.json │ │ │ ├── comp-216.json │ │ │ ├── comp-217.json │ │ │ ├── comp-218.json │ │ │ ├── comp-219.json │ │ │ ├── comp-22.json │ │ │ ├── comp-220.json │ │ │ ├── comp-221.json │ │ │ ├── comp-222.json │ │ │ ├── comp-223.json │ │ │ ├── comp-224.json │ │ │ ├── comp-225.json │ │ │ ├── comp-226.json │ │ │ ├── comp-227.json │ │ │ ├── comp-228.json │ │ │ ├── comp-229.json │ │ │ ├── comp-23.json │ │ │ ├── comp-230.json │ │ │ ├── comp-231.json │ │ │ ├── comp-232.json │ │ │ ├── comp-233.json │ │ │ ├── comp-234.json │ │ │ ├── comp-235.json │ │ │ ├── comp-236.json │ │ │ ├── comp-237.json │ │ │ ├── comp-238.json │ │ │ ├── comp-239.json │ │ │ ├── comp-24.json │ │ │ ├── comp-240.json │ │ │ ├── comp-241.json │ │ │ ├── comp-242.json │ │ │ ├── comp-243.json │ │ │ ├── comp-244.json │ │ │ ├── comp-245.json │ │ │ ├── comp-246.json │ │ │ ├── comp-247.json │ │ │ ├── comp-248.json │ │ │ ├── comp-249.json │ │ │ ├── comp-25.json │ │ │ ├── comp-250.json │ │ │ ├── comp-251.json │ │ │ ├── comp-252.json │ │ │ ├── comp-253.json │ │ │ ├── comp-254.json │ │ │ ├── comp-255.json │ │ │ ├── comp-256.json │ │ │ ├── comp-257.json │ │ │ ├── comp-258.json │ │ │ ├── comp-259.json │ │ │ ├── comp-26.json │ │ │ ├── comp-260.json │ │ │ ├── comp-261.json │ │ │ ├── comp-262.json │ │ │ ├── comp-263.json │ │ │ ├── comp-264.json │ │ │ ├── comp-265.json │ │ │ ├── comp-266.json │ │ │ ├── comp-267.json │ │ │ ├── comp-268.json │ │ │ ├── comp-269.json │ │ │ ├── comp-27.json │ │ │ ├── comp-270.json │ │ │ ├── comp-271.json │ │ │ ├── comp-272.json │ │ │ ├── comp-273.json │ │ │ ├── comp-274.json │ │ │ ├── comp-275.json │ │ │ ├── comp-276.json │ │ │ ├── comp-277.json │ │ │ ├── comp-278.json │ │ │ ├── comp-279.json │ │ │ ├── comp-28.json │ │ │ ├── comp-280.json │ │ │ ├── comp-281.json │ │ │ ├── comp-282.json │ │ │ ├── comp-283.json │ │ │ ├── comp-284.json │ │ │ ├── comp-285.json │ │ │ ├── comp-286.json │ │ │ ├── comp-287.json │ │ │ ├── comp-288.json │ │ │ ├── comp-289.json │ │ │ ├── comp-29.json │ │ │ ├── comp-290.json │ │ │ ├── comp-291.json │ │ │ ├── comp-292.json │ │ │ ├── comp-293.json │ │ │ ├── comp-294.json │ │ │ ├── comp-295.json │ │ │ ├── comp-296.json │ │ │ ├── comp-297.json │ │ │ ├── comp-298.json │ │ │ ├── comp-299.json │ │ │ ├── comp-30.json │ │ │ ├── comp-300.json │ │ │ ├── comp-301.json │ │ │ ├── comp-302.json │ │ │ ├── comp-303.json │ │ │ ├── comp-304.json │ │ │ ├── comp-305.json │ │ │ ├── comp-306.json │ │ │ ├── comp-307.json │ │ │ ├── comp-308.json │ │ │ ├── comp-309.json │ │ │ ├── comp-31.json │ │ │ ├── comp-310.json │ │ │ ├── comp-311.json │ │ │ ├── comp-312.json │ │ │ ├── comp-313.json │ │ │ ├── comp-314.json │ │ │ ├── comp-315.json │ │ │ ├── comp-316.json │ │ │ ├── comp-317.json │ │ │ ├── comp-318.json │ │ │ ├── comp-319.json │ │ │ ├── comp-32.json │ │ │ ├── comp-320.json │ │ │ ├── comp-321.json │ │ │ ├── comp-322.json │ │ │ ├── comp-323.json │ │ │ ├── comp-324.json │ │ │ ├── comp-325.json │ │ │ ├── comp-326.json │ │ │ ├── comp-327.json │ │ │ ├── comp-328.json │ │ │ ├── comp-329.json │ │ │ ├── comp-33.json │ │ │ ├── comp-330.json │ │ │ ├── comp-331.json │ │ │ ├── comp-332.json │ │ │ ├── comp-333.json │ │ │ ├── comp-334.json │ │ │ ├── comp-335.json │ │ │ ├── comp-336.json │ │ │ ├── comp-337.json │ │ │ ├── comp-338.json │ │ │ ├── comp-339.json │ │ │ ├── comp-34.json │ │ │ ├── comp-340.json │ │ │ ├── comp-341.json │ │ │ ├── comp-342.json │ │ │ ├── comp-343.json │ │ │ ├── comp-344.json │ │ │ ├── comp-345.json │ │ │ ├── comp-346.json │ │ │ ├── comp-347.json │ │ │ ├── comp-348.json │ │ │ ├── comp-349.json │ │ │ ├── comp-35.json │ │ │ ├── comp-350.json │ │ │ ├── comp-351.json │ │ │ ├── comp-352.json │ │ │ ├── comp-353.json │ │ │ ├── comp-354.json │ │ │ ├── comp-355.json │ │ │ ├── comp-356.json │ │ │ ├── comp-357.json │ │ │ ├── comp-358.json │ │ │ ├── comp-359.json │ │ │ ├── comp-36.json │ │ │ ├── comp-360.json │ │ │ ├── comp-361.json │ │ │ ├── comp-362.json │ │ │ ├── comp-363.json │ │ │ ├── comp-364.json │ │ │ ├── comp-365.json │ │ │ ├── comp-366.json │ │ │ ├── comp-367.json │ │ │ ├── comp-368.json │ │ │ ├── comp-369.json │ │ │ ├── comp-37.json │ │ │ ├── comp-370.json │ │ │ ├── comp-371.json │ │ │ ├── comp-372.json │ │ │ ├── comp-373.json │ │ │ ├── comp-374.json │ │ │ ├── comp-375.json │ │ │ ├── comp-376.json │ │ │ ├── comp-377.json │ │ │ ├── comp-378.json │ │ │ ├── comp-379.json │ │ │ ├── comp-38.json │ │ │ ├── comp-380.json │ │ │ ├── comp-381.json │ │ │ ├── comp-382.json │ │ │ ├── comp-383.json │ │ │ ├── comp-384.json │ │ │ ├── comp-385.json │ │ │ ├── comp-386.json │ │ │ ├── comp-387.json │ │ │ ├── comp-388.json │ │ │ ├── comp-389.json │ │ │ ├── comp-39.json │ │ │ ├── comp-390.json │ │ │ ├── comp-391.json │ │ │ ├── comp-392.json │ │ │ ├── comp-393.json │ │ │ ├── comp-394.json │ │ │ ├── comp-395.json │ │ │ ├── comp-396.json │ │ │ ├── comp-397.json │ │ │ ├── comp-398.json │ │ │ ├── comp-399.json │ │ │ ├── comp-40.json │ │ │ ├── comp-400.json │ │ │ ├── comp-401.json │ │ │ ├── comp-402.json │ │ │ ├── comp-403.json │ │ │ ├── comp-404.json │ │ │ ├── comp-405.json │ │ │ ├── comp-406.json │ │ │ ├── comp-407.json │ │ │ ├── comp-408.json │ │ │ ├── comp-409.json │ │ │ ├── comp-41.json │ │ │ ├── comp-410.json │ │ │ ├── comp-411.json │ │ │ ├── comp-412.json │ │ │ ├── comp-413.json │ │ │ ├── comp-414.json │ │ │ ├── comp-415.json │ │ │ ├── comp-416.json │ │ │ ├── comp-417.json │ │ │ ├── comp-418.json │ │ │ ├── comp-419.json │ │ │ ├── comp-42.json │ │ │ ├── comp-420.json │ │ │ ├── comp-421.json │ │ │ ├── comp-422.json │ │ │ ├── comp-423.json │ │ │ ├── comp-424.json │ │ │ ├── comp-425.json │ │ │ ├── comp-426.json │ │ │ ├── comp-427.json │ │ │ ├── comp-428.json │ │ │ ├── comp-429.json │ │ │ ├── comp-43.json │ │ │ ├── comp-430.json │ │ │ ├── comp-431.json │ │ │ ├── comp-432.json │ │ │ ├── comp-433.json │ │ │ ├── comp-434.json │ │ │ ├── comp-435.json │ │ │ ├── comp-436.json │ │ │ ├── comp-437.json │ │ │ ├── comp-438.json │ │ │ ├── comp-439.json │ │ │ ├── comp-44.json │ │ │ ├── comp-440.json │ │ │ ├── comp-441.json │ │ │ ├── comp-442.json │ │ │ ├── comp-443.json │ │ │ ├── comp-444.json │ │ │ ├── comp-445.json │ │ │ ├── comp-446.json │ │ │ ├── comp-447.json │ │ │ ├── comp-448.json │ │ │ ├── comp-449.json │ │ │ ├── comp-45.json │ │ │ ├── comp-450.json │ │ │ ├── comp-451.json │ │ │ ├── comp-452.json │ │ │ ├── comp-453.json │ │ │ ├── comp-454.json │ │ │ ├── comp-455.json │ │ │ ├── comp-456.json │ │ │ ├── comp-457.json │ │ │ ├── comp-458.json │ │ │ ├── comp-459.json │ │ │ ├── comp-46.json │ │ │ ├── comp-460.json │ │ │ ├── comp-461.json │ │ │ ├── comp-462.json │ │ │ ├── comp-463.json │ │ │ ├── comp-464.json │ │ │ ├── comp-465.json │ │ │ ├── comp-466.json │ │ │ ├── comp-467.json │ │ │ ├── comp-468.json │ │ │ ├── comp-469.json │ │ │ ├── comp-47.json │ │ │ ├── comp-470.json │ │ │ ├── comp-471.json │ │ │ ├── comp-472.json │ │ │ ├── comp-473.json │ │ │ ├── comp-474.json │ │ │ ├── comp-475.json │ │ │ ├── comp-476.json │ │ │ ├── comp-477.json │ │ │ ├── comp-478.json │ │ │ ├── comp-479.json │ │ │ ├── comp-48.json │ │ │ ├── comp-480.json │ │ │ ├── comp-481.json │ │ │ ├── comp-482.json │ │ │ ├── comp-483.json │ │ │ ├── comp-484.json │ │ │ ├── comp-485.json │ │ │ ├── comp-486.json │ │ │ ├── comp-487.json │ │ │ ├── comp-488.json │ │ │ ├── comp-489.json │ │ │ ├── comp-49.json │ │ │ ├── comp-490.json │ │ │ ├── comp-491.json │ │ │ ├── comp-492.json │ │ │ ├── comp-493.json │ │ │ ├── comp-494.json │ │ │ ├── comp-495.json │ │ │ ├── comp-496.json │ │ │ ├── comp-497.json │ │ │ ├── comp-498.json │ │ │ ├── comp-499.json │ │ │ ├── comp-50.json │ │ │ ├── comp-500.json │ │ │ ├── comp-501.json │ │ │ ├── comp-502.json │ │ │ ├── comp-503.json │ │ │ ├── comp-504.json │ │ │ ├── comp-505.json │ │ │ ├── comp-506.json │ │ │ ├── comp-507.json │ │ │ ├── comp-508.json │ │ │ ├── comp-509.json │ │ │ ├── comp-51.json │ │ │ ├── comp-510.json │ │ │ ├── comp-511.json │ │ │ ├── comp-512.json │ │ │ ├── comp-513.json │ │ │ ├── comp-514.json │ │ │ ├── comp-515.json │ │ │ ├── comp-516.json │ │ │ ├── comp-517.json │ │ │ ├── comp-518.json │ │ │ ├── comp-519.json │ │ │ ├── comp-52.json │ │ │ ├── comp-520.json │ │ │ ├── comp-521.json │ │ │ ├── comp-522.json │ │ │ ├── comp-523.json │ │ │ ├── comp-524.json │ │ │ ├── comp-525.json │ │ │ ├── comp-526.json │ │ │ ├── comp-527.json │ │ │ ├── comp-528.json │ │ │ ├── comp-529.json │ │ │ ├── comp-53.json │ │ │ ├── comp-530.json │ │ │ ├── comp-531.json │ │ │ ├── comp-532.json │ │ │ ├── comp-533.json │ │ │ ├── comp-534.json │ │ │ ├── comp-535.json │ │ │ ├── comp-536.json │ │ │ ├── comp-537.json │ │ │ ├── comp-538.json │ │ │ ├── comp-539.json │ │ │ ├── comp-54.json │ │ │ ├── comp-540.json │ │ │ ├── comp-541.json │ │ │ ├── comp-542.json │ │ │ ├── comp-543.json │ │ │ ├── comp-544.json │ │ │ ├── comp-545.json │ │ │ ├── comp-546.json │ │ │ ├── comp-547.json │ │ │ ├── comp-548.json │ │ │ ├── comp-549.json │ │ │ ├── comp-55.json │ │ │ ├── comp-550.json │ │ │ ├── comp-551.json │ │ │ ├── comp-552.json │ │ │ ├── comp-553.json │ │ │ ├── comp-554.json │ │ │ ├── comp-555.json │ │ │ ├── comp-556.json │ │ │ ├── comp-557.json │ │ │ ├── comp-558.json │ │ │ ├── comp-559.json │ │ │ ├── comp-56.json │ │ │ ├── comp-560.json │ │ │ ├── comp-561.json │ │ │ ├── comp-562.json │ │ │ ├── comp-563.json │ │ │ ├── comp-564.json │ │ │ ├── comp-565.json │ │ │ ├── comp-566.json │ │ │ ├── comp-567.json │ │ │ ├── comp-568.json │ │ │ ├── comp-569.json │ │ │ ├── comp-57.json │ │ │ ├── comp-570.json │ │ │ ├── comp-571.json │ │ │ ├── comp-572.json │ │ │ ├── comp-573.json │ │ │ ├── comp-574.json │ │ │ ├── comp-575.json │ │ │ ├── comp-576.json │ │ │ ├── comp-577.json │ │ │ ├── comp-578.json │ │ │ ├── comp-579.json │ │ │ ├── comp-58.json │ │ │ ├── comp-580.json │ │ │ ├── comp-581.json │ │ │ ├── comp-582.json │ │ │ ├── comp-583.json │ │ │ ├── comp-584.json │ │ │ ├── comp-585.json │ │ │ ├── comp-586.json │ │ │ ├── comp-587.json │ │ │ ├── comp-588.json │ │ │ ├── comp-589.json │ │ │ ├── comp-59.json │ │ │ ├── comp-590.json │ │ │ ├── comp-591.json │ │ │ ├── comp-592.json │ │ │ ├── comp-593.json │ │ │ ├── comp-594.json │ │ │ ├── comp-595.json │ │ │ ├── comp-596.json │ │ │ ├── comp-597.json │ │ │ ├── comp-598.json │ │ │ ├── comp-599.json │ │ │ ├── comp-60.json │ │ │ ├── comp-61.json │ │ │ ├── comp-62.json │ │ │ ├── comp-63.json │ │ │ ├── comp-64.json │ │ │ ├── comp-65.json │ │ │ ├── comp-66.json │ │ │ ├── comp-67.json │ │ │ ├── comp-68.json │ │ │ ├── comp-69.json │ │ │ ├── comp-70.json │ │ │ ├── comp-71.json │ │ │ ├── comp-72.json │ │ │ ├── comp-73.json │ │ │ ├── comp-74.json │ │ │ ├── comp-75.json │ │ │ ├── comp-76.json │ │ │ ├── comp-77.json │ │ │ ├── comp-78.json │ │ │ ├── comp-79.json │ │ │ ├── comp-80.json │ │ │ ├── comp-81.json │ │ │ ├── comp-82.json │ │ │ ├── comp-83.json │ │ │ ├── comp-84.json │ │ │ ├── comp-85.json │ │ │ ├── comp-86.json │ │ │ ├── comp-87.json │ │ │ ├── comp-88.json │ │ │ ├── comp-89.json │ │ │ ├── comp-90.json │ │ │ ├── comp-91.json │ │ │ ├── comp-92.json │ │ │ ├── comp-93.json │ │ │ ├── comp-94.json │ │ │ ├── comp-95.json │ │ │ ├── comp-96.json │ │ │ ├── comp-97.json │ │ │ ├── comp-98.json │ │ │ ├── comp-99.json │ │ │ ├── cropper.json │ │ │ ├── datefield-rac.json │ │ │ ├── dialog.json │ │ │ ├── dropdown-menu.json │ │ │ ├── hover-card.json │ │ │ ├── input.json │ │ │ ├── label.json │ │ │ ├── multiselect.json │ │ │ ├── navigation-menu.json │ │ │ ├── pagination.json │ │ │ ├── popover.json │ │ │ ├── progress.json │ │ │ ├── radio-group.json │ │ │ ├── scroll-area.json │ │ │ ├── select-native.json │ │ │ ├── select.json │ │ │ ├── slider.json │ │ │ ├── sonner.json │ │ │ ├── stepper.json │ │ │ ├── switch.json │ │ │ ├── table.json │ │ │ ├── tabs.json │ │ │ ├── textarea.json │ │ │ ├── timeline.json │ │ │ ├── toast.json │ │ │ ├── toggle-group.json │ │ │ ├── toggle.json │ │ │ ├── tooltip.json │ │ │ ├── tree.json │ │ │ ├── use-character-limit.json │ │ │ ├── use-file-upload.json │ │ │ ├── use-pagination.json │ │ │ ├── use-slider-with-input.json │ │ │ ├── use-toast.json │ │ │ └── utils.json │ │ ├── registry/ │ │ │ ├── default/ │ │ │ │ ├── components/ │ │ │ │ │ ├── comp-01.tsx │ │ │ │ │ ├── comp-02.tsx │ │ │ │ │ ├── comp-03.tsx │ │ │ │ │ ├── comp-04.tsx │ │ │ │ │ ├── comp-05.tsx │ │ │ │ │ ├── comp-06.tsx │ │ │ │ │ ├── comp-07.tsx │ │ │ │ │ ├── comp-08.tsx │ │ │ │ │ ├── comp-09.tsx │ │ │ │ │ ├── comp-10.tsx │ │ │ │ │ ├── comp-100.tsx │ │ │ │ │ ├── comp-101.tsx │ │ │ │ │ ├── comp-102.tsx │ │ │ │ │ ├── comp-103.tsx │ │ │ │ │ ├── comp-104.tsx │ │ │ │ │ ├── comp-105.tsx │ │ │ │ │ ├── comp-106.tsx │ │ │ │ │ ├── comp-107.tsx │ │ │ │ │ ├── comp-108.tsx │ │ │ │ │ ├── comp-109.tsx │ │ │ │ │ ├── comp-11.tsx │ │ │ │ │ ├── comp-110.tsx │ │ │ │ │ ├── comp-111.tsx │ │ │ │ │ ├── comp-112.tsx │ │ │ │ │ ├── comp-113.tsx │ │ │ │ │ ├── comp-114.tsx │ │ │ │ │ ├── comp-115.tsx │ │ │ │ │ ├── comp-116.tsx │ │ │ │ │ ├── comp-117.tsx │ │ │ │ │ ├── comp-118.tsx │ │ │ │ │ ├── comp-119.tsx │ │ │ │ │ ├── comp-12.tsx │ │ │ │ │ ├── comp-120.tsx │ │ │ │ │ ├── comp-121.tsx │ │ │ │ │ ├── comp-122.tsx │ │ │ │ │ ├── comp-123.tsx │ │ │ │ │ ├── comp-124.tsx │ │ │ │ │ ├── comp-125.tsx │ │ │ │ │ ├── comp-126.tsx │ │ │ │ │ ├── comp-127.tsx │ │ │ │ │ ├── comp-128.tsx │ │ │ │ │ ├── comp-129.tsx │ │ │ │ │ ├── comp-13.tsx │ │ │ │ │ ├── comp-130.tsx │ │ │ │ │ ├── comp-131.tsx │ │ │ │ │ ├── comp-132.tsx │ │ │ │ │ ├── comp-133.tsx │ │ │ │ │ ├── comp-134.tsx │ │ │ │ │ ├── comp-135.tsx │ │ │ │ │ ├── comp-136.tsx │ │ │ │ │ ├── comp-137.tsx │ │ │ │ │ ├── comp-138.tsx │ │ │ │ │ ├── comp-139.tsx │ │ │ │ │ ├── comp-14.tsx │ │ │ │ │ ├── comp-140.tsx │ │ │ │ │ ├── comp-141.tsx │ │ │ │ │ ├── comp-142.tsx │ │ │ │ │ ├── comp-143.tsx │ │ │ │ │ ├── comp-144.tsx │ │ │ │ │ ├── comp-145.tsx │ │ │ │ │ ├── comp-146.tsx │ │ │ │ │ ├── comp-147.tsx │ │ │ │ │ ├── comp-148.tsx │ │ │ │ │ ├── comp-149.tsx │ │ │ │ │ ├── comp-15.tsx │ │ │ │ │ ├── comp-150.tsx │ │ │ │ │ ├── comp-151.tsx │ │ │ │ │ ├── comp-152.tsx │ │ │ │ │ ├── comp-153.tsx │ │ │ │ │ ├── comp-154.tsx │ │ │ │ │ ├── comp-155.tsx │ │ │ │ │ ├── comp-156.tsx │ │ │ │ │ ├── comp-157.tsx │ │ │ │ │ ├── comp-158.tsx │ │ │ │ │ ├── comp-159.tsx │ │ │ │ │ ├── comp-16.tsx │ │ │ │ │ ├── comp-160.tsx │ │ │ │ │ ├── comp-161.tsx │ │ │ │ │ ├── comp-162.tsx │ │ │ │ │ ├── comp-163.tsx │ │ │ │ │ ├── comp-164.tsx │ │ │ │ │ ├── comp-165.tsx │ │ │ │ │ ├── comp-166.tsx │ │ │ │ │ ├── comp-167.tsx │ │ │ │ │ ├── comp-168.tsx │ │ │ │ │ ├── comp-169.tsx │ │ │ │ │ ├── comp-17.tsx │ │ │ │ │ ├── comp-170.tsx │ │ │ │ │ ├── comp-171.tsx │ │ │ │ │ ├── comp-172.tsx │ │ │ │ │ ├── comp-173.tsx │ │ │ │ │ ├── comp-174.tsx │ │ │ │ │ ├── comp-175.tsx │ │ │ │ │ ├── comp-176.tsx │ │ │ │ │ ├── comp-177.tsx │ │ │ │ │ ├── comp-178.tsx │ │ │ │ │ ├── comp-179.tsx │ │ │ │ │ ├── comp-18.tsx │ │ │ │ │ ├── comp-180.tsx │ │ │ │ │ ├── comp-181.tsx │ │ │ │ │ ├── comp-182.tsx │ │ │ │ │ ├── comp-183.tsx │ │ │ │ │ ├── comp-184.tsx │ │ │ │ │ ├── comp-185.tsx │ │ │ │ │ ├── comp-186.tsx │ │ │ │ │ ├── comp-187.tsx │ │ │ │ │ ├── comp-188.tsx │ │ │ │ │ ├── comp-189.tsx │ │ │ │ │ ├── comp-19.tsx │ │ │ │ │ ├── comp-190.tsx │ │ │ │ │ ├── comp-191.tsx │ │ │ │ │ ├── comp-192.tsx │ │ │ │ │ ├── comp-193.tsx │ │ │ │ │ ├── comp-194.tsx │ │ │ │ │ ├── comp-195.tsx │ │ │ │ │ ├── comp-196.tsx │ │ │ │ │ ├── comp-197.tsx │ │ │ │ │ ├── comp-198.tsx │ │ │ │ │ ├── comp-199.tsx │ │ │ │ │ ├── comp-20.tsx │ │ │ │ │ ├── comp-200.tsx │ │ │ │ │ ├── comp-201.tsx │ │ │ │ │ ├── comp-202.tsx │ │ │ │ │ ├── comp-203.tsx │ │ │ │ │ ├── comp-204.tsx │ │ │ │ │ ├── comp-205.tsx │ │ │ │ │ ├── comp-206.tsx │ │ │ │ │ ├── comp-207.tsx │ │ │ │ │ ├── comp-208.tsx │ │ │ │ │ ├── comp-209.tsx │ │ │ │ │ ├── comp-21.tsx │ │ │ │ │ ├── comp-210.tsx │ │ │ │ │ ├── comp-211.tsx │ │ │ │ │ ├── comp-212.tsx │ │ │ │ │ ├── comp-213.tsx │ │ │ │ │ ├── comp-214.tsx │ │ │ │ │ ├── comp-215.tsx │ │ │ │ │ ├── comp-216.tsx │ │ │ │ │ ├── comp-217.tsx │ │ │ │ │ ├── comp-218.tsx │ │ │ │ │ ├── comp-219.tsx │ │ │ │ │ ├── comp-22.tsx │ │ │ │ │ ├── comp-220.tsx │ │ │ │ │ ├── comp-221.tsx │ │ │ │ │ ├── comp-222.tsx │ │ │ │ │ ├── comp-223.tsx │ │ │ │ │ ├── comp-224.tsx │ │ │ │ │ ├── comp-225.tsx │ │ │ │ │ ├── comp-226.tsx │ │ │ │ │ ├── comp-227.tsx │ │ │ │ │ ├── comp-228.tsx │ │ │ │ │ ├── comp-229.tsx │ │ │ │ │ ├── comp-23.tsx │ │ │ │ │ ├── comp-230.tsx │ │ │ │ │ ├── comp-231.tsx │ │ │ │ │ ├── comp-232.tsx │ │ │ │ │ ├── comp-233.tsx │ │ │ │ │ ├── comp-234.tsx │ │ │ │ │ ├── comp-235.tsx │ │ │ │ │ ├── comp-236.tsx │ │ │ │ │ ├── comp-237.tsx │ │ │ │ │ ├── comp-238.tsx │ │ │ │ │ ├── comp-239.tsx │ │ │ │ │ ├── comp-24.tsx │ │ │ │ │ ├── comp-240.tsx │ │ │ │ │ ├── comp-241.tsx │ │ │ │ │ ├── comp-242.tsx │ │ │ │ │ ├── comp-243.tsx │ │ │ │ │ ├── comp-244.tsx │ │ │ │ │ ├── comp-245.tsx │ │ │ │ │ ├── comp-246.tsx │ │ │ │ │ ├── comp-247.tsx │ │ │ │ │ ├── comp-248.tsx │ │ │ │ │ ├── comp-249.tsx │ │ │ │ │ ├── comp-25.tsx │ │ │ │ │ ├── comp-250.tsx │ │ │ │ │ ├── comp-251.tsx │ │ │ │ │ ├── comp-252.tsx │ │ │ │ │ ├── comp-253.tsx │ │ │ │ │ ├── comp-254.tsx │ │ │ │ │ ├── comp-255.tsx │ │ │ │ │ ├── comp-256.tsx │ │ │ │ │ ├── comp-257.tsx │ │ │ │ │ ├── comp-258.tsx │ │ │ │ │ ├── comp-259.tsx │ │ │ │ │ ├── comp-26.tsx │ │ │ │ │ ├── comp-260.tsx │ │ │ │ │ ├── comp-261.tsx │ │ │ │ │ ├── comp-262.tsx │ │ │ │ │ ├── comp-263.tsx │ │ │ │ │ ├── comp-264.tsx │ │ │ │ │ ├── comp-265.tsx │ │ │ │ │ ├── comp-266.tsx │ │ │ │ │ ├── comp-267.tsx │ │ │ │ │ ├── comp-268.tsx │ │ │ │ │ ├── comp-269.tsx │ │ │ │ │ ├── comp-27.tsx │ │ │ │ │ ├── comp-270.tsx │ │ │ │ │ ├── comp-271.tsx │ │ │ │ │ ├── comp-272.tsx │ │ │ │ │ ├── comp-273.tsx │ │ │ │ │ ├── comp-274.tsx │ │ │ │ │ ├── comp-275.tsx │ │ │ │ │ ├── comp-276.tsx │ │ │ │ │ ├── comp-277.tsx │ │ │ │ │ ├── comp-278.tsx │ │ │ │ │ ├── comp-279.tsx │ │ │ │ │ ├── comp-28.tsx │ │ │ │ │ ├── comp-280.tsx │ │ │ │ │ ├── comp-281.tsx │ │ │ │ │ ├── comp-282.tsx │ │ │ │ │ ├── comp-283.tsx │ │ │ │ │ ├── comp-284.tsx │ │ │ │ │ ├── comp-285.tsx │ │ │ │ │ ├── comp-286.tsx │ │ │ │ │ ├── comp-287.tsx │ │ │ │ │ ├── comp-288.tsx │ │ │ │ │ ├── comp-289.tsx │ │ │ │ │ ├── comp-29.tsx │ │ │ │ │ ├── comp-290.tsx │ │ │ │ │ ├── comp-291.tsx │ │ │ │ │ ├── comp-292.tsx │ │ │ │ │ ├── comp-293.tsx │ │ │ │ │ ├── comp-294.tsx │ │ │ │ │ ├── comp-295.tsx │ │ │ │ │ ├── comp-296.tsx │ │ │ │ │ ├── comp-297.tsx │ │ │ │ │ ├── comp-298.tsx │ │ │ │ │ ├── comp-299.tsx │ │ │ │ │ ├── comp-30.tsx │ │ │ │ │ ├── comp-300.tsx │ │ │ │ │ ├── comp-301.tsx │ │ │ │ │ ├── comp-302.tsx │ │ │ │ │ ├── comp-303.tsx │ │ │ │ │ ├── comp-304.tsx │ │ │ │ │ ├── comp-305.tsx │ │ │ │ │ ├── comp-306.tsx │ │ │ │ │ ├── comp-307.tsx │ │ │ │ │ ├── comp-308.tsx │ │ │ │ │ ├── comp-309.tsx │ │ │ │ │ ├── comp-31.tsx │ │ │ │ │ ├── comp-310.tsx │ │ │ │ │ ├── comp-311.tsx │ │ │ │ │ ├── comp-312.tsx │ │ │ │ │ ├── comp-313.tsx │ │ │ │ │ ├── comp-314.tsx │ │ │ │ │ ├── comp-315.tsx │ │ │ │ │ ├── comp-316.tsx │ │ │ │ │ ├── comp-317.tsx │ │ │ │ │ ├── comp-318.tsx │ │ │ │ │ ├── comp-319.tsx │ │ │ │ │ ├── comp-32.tsx │ │ │ │ │ ├── comp-320.tsx │ │ │ │ │ ├── comp-321.tsx │ │ │ │ │ ├── comp-322.tsx │ │ │ │ │ ├── comp-323.tsx │ │ │ │ │ ├── comp-324.tsx │ │ │ │ │ ├── comp-325.tsx │ │ │ │ │ ├── comp-326.tsx │ │ │ │ │ ├── comp-327.tsx │ │ │ │ │ ├── comp-328.tsx │ │ │ │ │ ├── comp-329.tsx │ │ │ │ │ ├── comp-33.tsx │ │ │ │ │ ├── comp-330.tsx │ │ │ │ │ ├── comp-331.tsx │ │ │ │ │ ├── comp-332.tsx │ │ │ │ │ ├── comp-333.tsx │ │ │ │ │ ├── comp-334.tsx │ │ │ │ │ ├── comp-335.tsx │ │ │ │ │ ├── comp-336.tsx │ │ │ │ │ ├── comp-337.tsx │ │ │ │ │ ├── comp-338.tsx │ │ │ │ │ ├── comp-339.tsx │ │ │ │ │ ├── comp-34.tsx │ │ │ │ │ ├── comp-340.tsx │ │ │ │ │ ├── comp-341.tsx │ │ │ │ │ ├── comp-342.tsx │ │ │ │ │ ├── comp-343.tsx │ │ │ │ │ ├── comp-344.tsx │ │ │ │ │ ├── comp-345.tsx │ │ │ │ │ ├── comp-346.tsx │ │ │ │ │ ├── comp-347.tsx │ │ │ │ │ ├── comp-348.tsx │ │ │ │ │ ├── comp-349.tsx │ │ │ │ │ ├── comp-35.tsx │ │ │ │ │ ├── comp-350.tsx │ │ │ │ │ ├── comp-351.tsx │ │ │ │ │ ├── comp-352.tsx │ │ │ │ │ ├── comp-353.tsx │ │ │ │ │ ├── comp-354.tsx │ │ │ │ │ ├── comp-355.tsx │ │ │ │ │ ├── comp-356.tsx │ │ │ │ │ ├── comp-357.tsx │ │ │ │ │ ├── comp-358.tsx │ │ │ │ │ ├── comp-359.tsx │ │ │ │ │ ├── comp-36.tsx │ │ │ │ │ ├── comp-360.tsx │ │ │ │ │ ├── comp-361.tsx │ │ │ │ │ ├── comp-362.tsx │ │ │ │ │ ├── comp-363.tsx │ │ │ │ │ ├── comp-364.tsx │ │ │ │ │ ├── comp-365.tsx │ │ │ │ │ ├── comp-366.tsx │ │ │ │ │ ├── comp-367.tsx │ │ │ │ │ ├── comp-368.tsx │ │ │ │ │ ├── comp-369.tsx │ │ │ │ │ ├── comp-37.tsx │ │ │ │ │ ├── comp-370.tsx │ │ │ │ │ ├── comp-371.tsx │ │ │ │ │ ├── comp-372.tsx │ │ │ │ │ ├── comp-373.tsx │ │ │ │ │ ├── comp-374.tsx │ │ │ │ │ ├── comp-375.tsx │ │ │ │ │ ├── comp-376.tsx │ │ │ │ │ ├── comp-377.tsx │ │ │ │ │ ├── comp-378.tsx │ │ │ │ │ ├── comp-379.tsx │ │ │ │ │ ├── comp-38.tsx │ │ │ │ │ ├── comp-380.tsx │ │ │ │ │ ├── comp-381.tsx │ │ │ │ │ ├── comp-382.tsx │ │ │ │ │ ├── comp-383.tsx │ │ │ │ │ ├── comp-384.tsx │ │ │ │ │ ├── comp-385.tsx │ │ │ │ │ ├── comp-386.tsx │ │ │ │ │ ├── comp-387.tsx │ │ │ │ │ ├── comp-388.tsx │ │ │ │ │ ├── comp-389.tsx │ │ │ │ │ ├── comp-39.tsx │ │ │ │ │ ├── comp-390.tsx │ │ │ │ │ ├── comp-391.tsx │ │ │ │ │ ├── comp-392.tsx │ │ │ │ │ ├── comp-393.tsx │ │ │ │ │ ├── comp-394.tsx │ │ │ │ │ ├── comp-395.tsx │ │ │ │ │ ├── comp-396.tsx │ │ │ │ │ ├── comp-397.tsx │ │ │ │ │ ├── comp-398.tsx │ │ │ │ │ ├── comp-399.tsx │ │ │ │ │ ├── comp-40.tsx │ │ │ │ │ ├── comp-400.tsx │ │ │ │ │ ├── comp-401.tsx │ │ │ │ │ ├── comp-402.tsx │ │ │ │ │ ├── comp-403.tsx │ │ │ │ │ ├── comp-404.tsx │ │ │ │ │ ├── comp-405.tsx │ │ │ │ │ ├── comp-406.tsx │ │ │ │ │ ├── comp-407.tsx │ │ │ │ │ ├── comp-408.tsx │ │ │ │ │ ├── comp-409.tsx │ │ │ │ │ ├── comp-41.tsx │ │ │ │ │ ├── comp-410.tsx │ │ │ │ │ ├── comp-411.tsx │ │ │ │ │ ├── comp-412.tsx │ │ │ │ │ ├── comp-413.tsx │ │ │ │ │ ├── comp-414.tsx │ │ │ │ │ ├── comp-415.tsx │ │ │ │ │ ├── comp-416.tsx │ │ │ │ │ ├── comp-417.tsx │ │ │ │ │ ├── comp-418.tsx │ │ │ │ │ ├── comp-419.tsx │ │ │ │ │ ├── comp-42.tsx │ │ │ │ │ ├── comp-420.tsx │ │ │ │ │ ├── comp-421.tsx │ │ │ │ │ ├── comp-422.tsx │ │ │ │ │ ├── comp-423.tsx │ │ │ │ │ ├── comp-424.tsx │ │ │ │ │ ├── comp-425.tsx │ │ │ │ │ ├── comp-426.tsx │ │ │ │ │ ├── comp-427.tsx │ │ │ │ │ ├── comp-428.tsx │ │ │ │ │ ├── comp-429.tsx │ │ │ │ │ ├── comp-43.tsx │ │ │ │ │ ├── comp-430.tsx │ │ │ │ │ ├── comp-431.tsx │ │ │ │ │ ├── comp-432.tsx │ │ │ │ │ ├── comp-433.tsx │ │ │ │ │ ├── comp-434.tsx │ │ │ │ │ ├── comp-435.tsx │ │ │ │ │ ├── comp-436.tsx │ │ │ │ │ ├── comp-437.tsx │ │ │ │ │ ├── comp-438.tsx │ │ │ │ │ ├── comp-439.tsx │ │ │ │ │ ├── comp-44.tsx │ │ │ │ │ ├── comp-440.tsx │ │ │ │ │ ├── comp-441.tsx │ │ │ │ │ ├── comp-442.tsx │ │ │ │ │ ├── comp-443.tsx │ │ │ │ │ ├── comp-444.tsx │ │ │ │ │ ├── comp-445.tsx │ │ │ │ │ ├── comp-446.tsx │ │ │ │ │ ├── comp-447.tsx │ │ │ │ │ ├── comp-448.tsx │ │ │ │ │ ├── comp-449.tsx │ │ │ │ │ ├── comp-45.tsx │ │ │ │ │ ├── comp-450.tsx │ │ │ │ │ ├── comp-451.tsx │ │ │ │ │ ├── comp-452.tsx │ │ │ │ │ ├── comp-453.tsx │ │ │ │ │ ├── comp-454.tsx │ │ │ │ │ ├── comp-455.tsx │ │ │ │ │ ├── comp-456.tsx │ │ │ │ │ ├── comp-457.tsx │ │ │ │ │ ├── comp-458.tsx │ │ │ │ │ ├── comp-459.tsx │ │ │ │ │ ├── comp-46.tsx │ │ │ │ │ ├── comp-460.tsx │ │ │ │ │ ├── comp-461.tsx │ │ │ │ │ ├── comp-462.tsx │ │ │ │ │ ├── comp-463.tsx │ │ │ │ │ ├── comp-464.tsx │ │ │ │ │ ├── comp-465.tsx │ │ │ │ │ ├── comp-466.tsx │ │ │ │ │ ├── comp-467.tsx │ │ │ │ │ ├── comp-468.tsx │ │ │ │ │ ├── comp-469.tsx │ │ │ │ │ ├── comp-47.tsx │ │ │ │ │ ├── comp-470.tsx │ │ │ │ │ ├── comp-471.tsx │ │ │ │ │ ├── comp-472.tsx │ │ │ │ │ ├── comp-473.tsx │ │ │ │ │ ├── comp-474.tsx │ │ │ │ │ ├── comp-475.tsx │ │ │ │ │ ├── comp-476.tsx │ │ │ │ │ ├── comp-477.tsx │ │ │ │ │ ├── comp-478.tsx │ │ │ │ │ ├── comp-479.tsx │ │ │ │ │ ├── comp-48.tsx │ │ │ │ │ ├── comp-480.tsx │ │ │ │ │ ├── comp-481.tsx │ │ │ │ │ ├── comp-482.tsx │ │ │ │ │ ├── comp-483.tsx │ │ │ │ │ ├── comp-484.tsx │ │ │ │ │ ├── comp-485.tsx │ │ │ │ │ ├── comp-486.tsx │ │ │ │ │ ├── comp-487.tsx │ │ │ │ │ ├── comp-488.tsx │ │ │ │ │ ├── comp-489.tsx │ │ │ │ │ ├── comp-49.tsx │ │ │ │ │ ├── comp-490.tsx │ │ │ │ │ ├── comp-491.tsx │ │ │ │ │ ├── comp-492.tsx │ │ │ │ │ ├── comp-493.tsx │ │ │ │ │ ├── comp-494.tsx │ │ │ │ │ ├── comp-495.tsx │ │ │ │ │ ├── comp-496.tsx │ │ │ │ │ ├── comp-497.tsx │ │ │ │ │ ├── comp-498.tsx │ │ │ │ │ ├── comp-499.tsx │ │ │ │ │ ├── comp-50.tsx │ │ │ │ │ ├── comp-500.tsx │ │ │ │ │ ├── comp-501.tsx │ │ │ │ │ ├── comp-502.tsx │ │ │ │ │ ├── comp-503.tsx │ │ │ │ │ ├── comp-504.tsx │ │ │ │ │ ├── comp-505.tsx │ │ │ │ │ ├── comp-506.tsx │ │ │ │ │ ├── comp-507.tsx │ │ │ │ │ ├── comp-508.tsx │ │ │ │ │ ├── comp-509.tsx │ │ │ │ │ ├── comp-51.tsx │ │ │ │ │ ├── comp-510.tsx │ │ │ │ │ ├── comp-511.tsx │ │ │ │ │ ├── comp-512.tsx │ │ │ │ │ ├── comp-513.tsx │ │ │ │ │ ├── comp-514.tsx │ │ │ │ │ ├── comp-515.tsx │ │ │ │ │ ├── comp-516.tsx │ │ │ │ │ ├── comp-517.tsx │ │ │ │ │ ├── comp-518.tsx │ │ │ │ │ ├── comp-519.tsx │ │ │ │ │ ├── comp-52.tsx │ │ │ │ │ ├── comp-520.tsx │ │ │ │ │ ├── comp-521.tsx │ │ │ │ │ ├── comp-522.tsx │ │ │ │ │ ├── comp-523.tsx │ │ │ │ │ ├── comp-524.tsx │ │ │ │ │ ├── comp-525.tsx │ │ │ │ │ ├── comp-526.tsx │ │ │ │ │ ├── comp-527.tsx │ │ │ │ │ ├── comp-528.tsx │ │ │ │ │ ├── comp-529.tsx │ │ │ │ │ ├── comp-53.tsx │ │ │ │ │ ├── comp-530.tsx │ │ │ │ │ ├── comp-531.tsx │ │ │ │ │ ├── comp-532.tsx │ │ │ │ │ ├── comp-533.tsx │ │ │ │ │ ├── comp-534.tsx │ │ │ │ │ ├── comp-535.tsx │ │ │ │ │ ├── comp-536.tsx │ │ │ │ │ ├── comp-537.tsx │ │ │ │ │ ├── comp-538.tsx │ │ │ │ │ ├── comp-539.tsx │ │ │ │ │ ├── comp-54.tsx │ │ │ │ │ ├── comp-540.tsx │ │ │ │ │ ├── comp-541.tsx │ │ │ │ │ ├── comp-542.tsx │ │ │ │ │ ├── comp-543.tsx │ │ │ │ │ ├── comp-544.tsx │ │ │ │ │ ├── comp-545.tsx │ │ │ │ │ ├── comp-546.tsx │ │ │ │ │ ├── comp-547.tsx │ │ │ │ │ ├── comp-548.tsx │ │ │ │ │ ├── comp-549.tsx │ │ │ │ │ ├── comp-55.tsx │ │ │ │ │ ├── comp-550.tsx │ │ │ │ │ ├── comp-551.tsx │ │ │ │ │ ├── comp-552.tsx │ │ │ │ │ ├── comp-553.tsx │ │ │ │ │ ├── comp-554.tsx │ │ │ │ │ ├── comp-555.tsx │ │ │ │ │ ├── comp-556.tsx │ │ │ │ │ ├── comp-557.tsx │ │ │ │ │ ├── comp-558.tsx │ │ │ │ │ ├── comp-559.tsx │ │ │ │ │ ├── comp-56.tsx │ │ │ │ │ ├── comp-560.tsx │ │ │ │ │ ├── comp-561.tsx │ │ │ │ │ ├── comp-562.tsx │ │ │ │ │ ├── comp-563.tsx │ │ │ │ │ ├── comp-564.tsx │ │ │ │ │ ├── comp-565.tsx │ │ │ │ │ ├── comp-566.tsx │ │ │ │ │ ├── comp-567.tsx │ │ │ │ │ ├── comp-568.tsx │ │ │ │ │ ├── comp-569.tsx │ │ │ │ │ ├── comp-57.tsx │ │ │ │ │ ├── comp-570.tsx │ │ │ │ │ ├── comp-571.tsx │ │ │ │ │ ├── comp-572.tsx │ │ │ │ │ ├── comp-573.tsx │ │ │ │ │ ├── comp-574.tsx │ │ │ │ │ ├── comp-575.tsx │ │ │ │ │ ├── comp-576.tsx │ │ │ │ │ ├── comp-577.tsx │ │ │ │ │ ├── comp-578.tsx │ │ │ │ │ ├── comp-579.tsx │ │ │ │ │ ├── comp-58.tsx │ │ │ │ │ ├── comp-580.tsx │ │ │ │ │ ├── comp-581.tsx │ │ │ │ │ ├── comp-582.tsx │ │ │ │ │ ├── comp-583.tsx │ │ │ │ │ ├── comp-584.tsx │ │ │ │ │ ├── comp-585.tsx │ │ │ │ │ ├── comp-586.tsx │ │ │ │ │ ├── comp-587.tsx │ │ │ │ │ ├── comp-588.tsx │ │ │ │ │ ├── comp-589.tsx │ │ │ │ │ ├── comp-59.tsx │ │ │ │ │ ├── comp-590.tsx │ │ │ │ │ ├── comp-591.tsx │ │ │ │ │ ├── comp-592.tsx │ │ │ │ │ ├── comp-593.tsx │ │ │ │ │ ├── comp-594.tsx │ │ │ │ │ ├── comp-595.tsx │ │ │ │ │ ├── comp-596.tsx │ │ │ │ │ ├── comp-597.tsx │ │ │ │ │ ├── comp-598.tsx │ │ │ │ │ ├── comp-599.tsx │ │ │ │ │ ├── comp-60.tsx │ │ │ │ │ ├── comp-61.tsx │ │ │ │ │ ├── comp-62.tsx │ │ │ │ │ ├── comp-63.tsx │ │ │ │ │ ├── comp-64.tsx │ │ │ │ │ ├── comp-65.tsx │ │ │ │ │ ├── comp-66.tsx │ │ │ │ │ ├── comp-67.tsx │ │ │ │ │ ├── comp-68.tsx │ │ │ │ │ ├── comp-69.tsx │ │ │ │ │ ├── comp-70.tsx │ │ │ │ │ ├── comp-71.tsx │ │ │ │ │ ├── comp-72.tsx │ │ │ │ │ ├── comp-73.tsx │ │ │ │ │ ├── comp-74.tsx │ │ │ │ │ ├── comp-75.tsx │ │ │ │ │ ├── comp-76.tsx │ │ │ │ │ ├── comp-77.tsx │ │ │ │ │ ├── comp-78.tsx │ │ │ │ │ ├── comp-79.tsx │ │ │ │ │ ├── comp-80.tsx │ │ │ │ │ ├── comp-81.tsx │ │ │ │ │ ├── comp-82.tsx │ │ │ │ │ ├── comp-83.tsx │ │ │ │ │ ├── comp-84.tsx │ │ │ │ │ ├── comp-85.tsx │ │ │ │ │ ├── comp-86.tsx │ │ │ │ │ ├── comp-87.tsx │ │ │ │ │ ├── comp-88.tsx │ │ │ │ │ ├── comp-89.tsx │ │ │ │ │ ├── comp-90.tsx │ │ │ │ │ ├── comp-91.tsx │ │ │ │ │ ├── comp-92.tsx │ │ │ │ │ ├── comp-93.tsx │ │ │ │ │ ├── comp-94.tsx │ │ │ │ │ ├── comp-95.tsx │ │ │ │ │ ├── comp-96.tsx │ │ │ │ │ ├── comp-97.tsx │ │ │ │ │ ├── comp-98.tsx │ │ │ │ │ ├── comp-99.tsx │ │ │ │ │ ├── event-calendar/ │ │ │ │ │ │ ├── agenda-view.tsx │ │ │ │ │ │ ├── calendar-dnd-context.tsx │ │ │ │ │ │ ├── constants.ts │ │ │ │ │ │ ├── day-view.tsx │ │ │ │ │ │ ├── draggable-event.tsx │ │ │ │ │ │ ├── droppable-cell.tsx │ │ │ │ │ │ ├── event-calendar.tsx │ │ │ │ │ │ ├── event-dialog.tsx │ │ │ │ │ │ ├── event-item.tsx │ │ │ │ │ │ ├── events-popup.tsx │ │ │ │ │ │ ├── hooks/ │ │ │ │ │ │ │ ├── use-current-time-indicator.ts │ │ │ │ │ │ │ └── use-event-visibility.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── month-view.tsx │ │ │ │ │ │ ├── types.ts │ │ │ │ │ │ ├── utils.ts │ │ │ │ │ │ └── week-view.tsx │ │ │ │ │ └── navbar-components/ │ │ │ │ │ ├── app-toggle.tsx │ │ │ │ │ ├── date-picker.tsx │ │ │ │ │ ├── filters.tsx │ │ │ │ │ ├── info-menu.tsx │ │ │ │ │ ├── logo.tsx │ │ │ │ │ ├── notification-menu.tsx │ │ │ │ │ ├── settings-menu.tsx │ │ │ │ │ ├── team-switcher.tsx │ │ │ │ │ ├── theme-toggle.tsx │ │ │ │ │ └── user-menu.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-character-limit.ts │ │ │ │ │ ├── use-file-upload.ts │ │ │ │ │ ├── use-pagination.ts │ │ │ │ │ ├── use-slider-with-input.ts │ │ │ │ │ └── use-toast.ts │ │ │ │ ├── lib/ │ │ │ │ │ └── utils.ts │ │ │ │ └── ui/ │ │ │ │ ├── accordion.tsx │ │ │ │ ├── alert-dialog.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── badge.tsx │ │ │ │ ├── breadcrumb.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── calendar-rac.tsx │ │ │ │ ├── calendar.tsx │ │ │ │ ├── checkbox-tree.tsx │ │ │ │ ├── checkbox.tsx │ │ │ │ ├── collapsible.tsx │ │ │ │ ├── command.tsx │ │ │ │ ├── cropper.tsx │ │ │ │ ├── datefield-rac.tsx │ │ │ │ ├── dialog.tsx │ │ │ │ ├── dropdown-menu.tsx │ │ │ │ ├── hover-card.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── multiselect.tsx │ │ │ │ ├── navigation-menu.tsx │ │ │ │ ├── pagination.tsx │ │ │ │ ├── popover.tsx │ │ │ │ ├── progress.tsx │ │ │ │ ├── radio-group.tsx │ │ │ │ ├── resizable.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ ├── select-native.tsx │ │ │ │ ├── select.tsx │ │ │ │ ├── slider.tsx │ │ │ │ ├── sonner.tsx │ │ │ │ ├── stepper.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── table.tsx │ │ │ │ ├── tabs.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ ├── timeline.tsx │ │ │ │ ├── toast.tsx │ │ │ │ ├── toaster.tsx │ │ │ │ ├── toggle-group.tsx │ │ │ │ ├── toggle.tsx │ │ │ │ ├── tooltip.tsx │ │ │ │ └── tree.tsx │ │ │ └── registry-tags.ts │ │ ├── registry.json │ │ ├── tsconfig.json │ │ ├── tsconfig.scripts.json │ │ └── types/ │ │ └── styled-jsx.d.ts │ ├── ui/ │ │ ├── .gitignore │ │ ├── AGENTS.md │ │ ├── CONTRIBUTING.md │ │ ├── README.md │ │ ├── app/ │ │ │ ├── api/ │ │ │ │ └── raw/ │ │ │ │ └── [...slug]/ │ │ │ │ └── route.ts │ │ │ ├── docs/ │ │ │ │ ├── [[...slug]]/ │ │ │ │ │ └── page.tsx │ │ │ │ └── layout.tsx │ │ │ ├── globals.css │ │ │ ├── layout.tsx │ │ │ ├── not-found.tsx │ │ │ ├── page.tsx │ │ │ ├── particles/ │ │ │ │ ├── page.tsx │ │ │ │ ├── particle-card-container.tsx │ │ │ │ ├── particle-card.tsx │ │ │ │ ├── particles-display.tsx │ │ │ │ ├── search-container.tsx │ │ │ │ └── search-field.tsx │ │ │ └── sitemap.ts │ │ ├── components/ │ │ │ ├── category-thumbnails.tsx │ │ │ ├── code-block-command.tsx │ │ │ ├── code-collapsible-wrapper.tsx │ │ │ ├── code-tabs.tsx │ │ │ ├── command-menu.tsx │ │ │ ├── component-preview-tabs.tsx │ │ │ ├── component-preview.tsx │ │ │ ├── component-source.tsx │ │ │ ├── copy-registry.tsx │ │ │ ├── docs-copy-page.tsx │ │ │ ├── docs-sidebar.tsx │ │ │ ├── docs-toc.tsx │ │ │ ├── main-nav.tsx │ │ │ ├── media-query-demo.tsx │ │ │ ├── mobile-nav.tsx │ │ │ ├── site-footer.tsx │ │ │ └── site-header.tsx │ │ ├── config/ │ │ │ └── categories.ts │ │ ├── content/ │ │ │ └── docs/ │ │ │ ├── (root)/ │ │ │ │ ├── get-started.mdx │ │ │ │ ├── index.mdx │ │ │ │ ├── meta.json │ │ │ │ ├── radix-migration.mdx │ │ │ │ ├── roadmap.mdx │ │ │ │ └── styling.mdx │ │ │ ├── components/ │ │ │ │ ├── accordion.mdx │ │ │ │ ├── alert-dialog.mdx │ │ │ │ ├── alert.mdx │ │ │ │ ├── autocomplete.mdx │ │ │ │ ├── avatar.mdx │ │ │ │ ├── badge.mdx │ │ │ │ ├── breadcrumb.mdx │ │ │ │ ├── button.mdx │ │ │ │ ├── calendar.mdx │ │ │ │ ├── card.mdx │ │ │ │ ├── checkbox-group.mdx │ │ │ │ ├── checkbox.mdx │ │ │ │ ├── collapsible.mdx │ │ │ │ ├── combobox.mdx │ │ │ │ ├── command.mdx │ │ │ │ ├── date-picker.mdx │ │ │ │ ├── dialog.mdx │ │ │ │ ├── drawer.mdx │ │ │ │ ├── empty.mdx │ │ │ │ ├── field.mdx │ │ │ │ ├── fieldset.mdx │ │ │ │ ├── form.mdx │ │ │ │ ├── frame.mdx │ │ │ │ ├── group.mdx │ │ │ │ ├── input-group.mdx │ │ │ │ ├── input-otp.mdx │ │ │ │ ├── input.mdx │ │ │ │ ├── kbd.mdx │ │ │ │ ├── label.mdx │ │ │ │ ├── menu.mdx │ │ │ │ ├── meta.json │ │ │ │ ├── meter.mdx │ │ │ │ ├── number-field.mdx │ │ │ │ ├── pagination.mdx │ │ │ │ ├── popover.mdx │ │ │ │ ├── preview-card.mdx │ │ │ │ ├── progress.mdx │ │ │ │ ├── radio-group.mdx │ │ │ │ ├── scroll-area.mdx │ │ │ │ ├── select.mdx │ │ │ │ ├── separator.mdx │ │ │ │ ├── sheet.mdx │ │ │ │ ├── skeleton.mdx │ │ │ │ ├── slider.mdx │ │ │ │ ├── spinner.mdx │ │ │ │ ├── switch.mdx │ │ │ │ ├── table.mdx │ │ │ │ ├── tabs.mdx │ │ │ │ ├── textarea.mdx │ │ │ │ ├── toast.mdx │ │ │ │ ├── toggle-group.mdx │ │ │ │ ├── toggle.mdx │ │ │ │ ├── toolbar.mdx │ │ │ │ └── tooltip.mdx │ │ │ ├── hooks/ │ │ │ │ ├── meta.json │ │ │ │ ├── use-copy-to-clipboard.mdx │ │ │ │ └── use-media-query.mdx │ │ │ ├── meta.json │ │ │ └── resources/ │ │ │ └── meta.json │ │ ├── hooks/ │ │ │ ├── use-config.ts │ │ │ ├── use-is-mac.ts │ │ │ └── use-mutation-observer.ts │ │ ├── lib/ │ │ │ ├── config.ts │ │ │ ├── docs.ts │ │ │ ├── registry.ts │ │ │ ├── source.ts │ │ │ └── utils.ts │ │ ├── mdx-components.tsx │ │ ├── next.config.ts │ │ ├── package.json │ │ ├── postcss.config.mjs │ │ ├── public/ │ │ │ ├── llms.txt │ │ │ └── r/ │ │ │ ├── accordion.json │ │ │ ├── alert-dialog.json │ │ │ ├── alert.json │ │ │ ├── autocomplete.json │ │ │ ├── avatar.json │ │ │ ├── badge.json │ │ │ ├── breadcrumb.json │ │ │ ├── button.json │ │ │ ├── calendar.json │ │ │ ├── card.json │ │ │ ├── checkbox-group.json │ │ │ ├── checkbox.json │ │ │ ├── collapsible.json │ │ │ ├── colors-neutral.json │ │ │ ├── combobox.json │ │ │ ├── command.json │ │ │ ├── csp-provider.json │ │ │ ├── dialog.json │ │ │ ├── direction-provider.json │ │ │ ├── drawer.json │ │ │ ├── empty.json │ │ │ ├── field.json │ │ │ ├── fieldset.json │ │ │ ├── form.json │ │ │ ├── frame.json │ │ │ ├── group.json │ │ │ ├── input-group.json │ │ │ ├── input-otp.json │ │ │ ├── input.json │ │ │ ├── kbd.json │ │ │ ├── label.json │ │ │ ├── menu.json │ │ │ ├── merge-props.json │ │ │ ├── meter.json │ │ │ ├── number-field.json │ │ │ ├── p-accordion-1.json │ │ │ ├── p-accordion-2.json │ │ │ ├── p-accordion-3.json │ │ │ ├── p-accordion-4.json │ │ │ ├── p-alert-1.json │ │ │ ├── p-alert-2.json │ │ │ ├── p-alert-3.json │ │ │ ├── p-alert-4.json │ │ │ ├── p-alert-5.json │ │ │ ├── p-alert-6.json │ │ │ ├── p-alert-7.json │ │ │ ├── p-alert-dialog-1.json │ │ │ ├── p-alert-dialog-2.json │ │ │ ├── p-autocomplete-1.json │ │ │ ├── p-autocomplete-10.json │ │ │ ├── p-autocomplete-11.json │ │ │ ├── p-autocomplete-12.json │ │ │ ├── p-autocomplete-13.json │ │ │ ├── p-autocomplete-14.json │ │ │ ├── p-autocomplete-15.json │ │ │ ├── p-autocomplete-2.json │ │ │ ├── p-autocomplete-3.json │ │ │ ├── p-autocomplete-4.json │ │ │ ├── p-autocomplete-5.json │ │ │ ├── p-autocomplete-6.json │ │ │ ├── p-autocomplete-7.json │ │ │ ├── p-autocomplete-8.json │ │ │ ├── p-autocomplete-9.json │ │ │ ├── p-avatar-1.json │ │ │ ├── p-avatar-10.json │ │ │ ├── p-avatar-11.json │ │ │ ├── p-avatar-12.json │ │ │ ├── p-avatar-13.json │ │ │ ├── p-avatar-14.json │ │ │ ├── p-avatar-2.json │ │ │ ├── p-avatar-3.json │ │ │ ├── p-avatar-4.json │ │ │ ├── p-avatar-5.json │ │ │ ├── p-avatar-6.json │ │ │ ├── p-avatar-7.json │ │ │ ├── p-avatar-8.json │ │ │ ├── p-avatar-9.json │ │ │ ├── p-badge-1.json │ │ │ ├── p-badge-10.json │ │ │ ├── p-badge-11.json │ │ │ ├── p-badge-12.json │ │ │ ├── p-badge-13.json │ │ │ ├── p-badge-14.json │ │ │ ├── p-badge-15.json │ │ │ ├── p-badge-16.json │ │ │ ├── p-badge-17.json │ │ │ ├── p-badge-18.json │ │ │ ├── p-badge-19.json │ │ │ ├── p-badge-2.json │ │ │ ├── p-badge-20.json │ │ │ ├── p-badge-3.json │ │ │ ├── p-badge-4.json │ │ │ ├── p-badge-5.json │ │ │ ├── p-badge-6.json │ │ │ ├── p-badge-7.json │ │ │ ├── p-badge-8.json │ │ │ ├── p-badge-9.json │ │ │ ├── p-breadcrumb-1.json │ │ │ ├── p-breadcrumb-2.json │ │ │ ├── p-breadcrumb-3.json │ │ │ ├── p-breadcrumb-4.json │ │ │ ├── p-breadcrumb-5.json │ │ │ ├── p-breadcrumb-6.json │ │ │ ├── p-breadcrumb-7.json │ │ │ ├── p-button-1.json │ │ │ ├── p-button-10.json │ │ │ ├── p-button-11.json │ │ │ ├── p-button-12.json │ │ │ ├── p-button-13.json │ │ │ ├── p-button-14.json │ │ │ ├── p-button-15.json │ │ │ ├── p-button-16.json │ │ │ ├── p-button-17.json │ │ │ ├── p-button-18.json │ │ │ ├── p-button-19.json │ │ │ ├── p-button-2.json │ │ │ ├── p-button-20.json │ │ │ ├── p-button-21.json │ │ │ ├── p-button-22.json │ │ │ ├── p-button-23.json │ │ │ ├── p-button-24.json │ │ │ ├── p-button-26.json │ │ │ ├── p-button-27.json │ │ │ ├── p-button-28.json │ │ │ ├── p-button-29.json │ │ │ ├── p-button-3.json │ │ │ ├── p-button-30.json │ │ │ ├── p-button-31.json │ │ │ ├── p-button-32.json │ │ │ ├── p-button-33.json │ │ │ ├── p-button-34.json │ │ │ ├── p-button-35.json │ │ │ ├── p-button-36.json │ │ │ ├── p-button-37.json │ │ │ ├── p-button-38.json │ │ │ ├── p-button-39.json │ │ │ ├── p-button-4.json │ │ │ ├── p-button-40.json │ │ │ ├── p-button-41.json │ │ │ ├── p-button-5.json │ │ │ ├── p-button-6.json │ │ │ ├── p-button-7.json │ │ │ ├── p-button-8.json │ │ │ ├── p-button-9.json │ │ │ ├── p-calendar-1.json │ │ │ ├── p-calendar-10.json │ │ │ ├── p-calendar-11.json │ │ │ ├── p-calendar-12.json │ │ │ ├── p-calendar-13.json │ │ │ ├── p-calendar-14.json │ │ │ ├── p-calendar-15.json │ │ │ ├── p-calendar-16.json │ │ │ ├── p-calendar-17.json │ │ │ ├── p-calendar-18.json │ │ │ ├── p-calendar-19.json │ │ │ ├── p-calendar-2.json │ │ │ ├── p-calendar-20.json │ │ │ ├── p-calendar-21.json │ │ │ ├── p-calendar-22.json │ │ │ ├── p-calendar-23.json │ │ │ ├── p-calendar-24.json │ │ │ ├── p-calendar-3.json │ │ │ ├── p-calendar-4.json │ │ │ ├── p-calendar-5.json │ │ │ ├── p-calendar-6.json │ │ │ ├── p-calendar-7.json │ │ │ ├── p-calendar-8.json │ │ │ ├── p-calendar-9.json │ │ │ ├── p-card-1.json │ │ │ ├── p-card-10.json │ │ │ ├── p-card-11.json │ │ │ ├── p-card-2.json │ │ │ ├── p-card-3.json │ │ │ ├── p-card-4.json │ │ │ ├── p-card-5.json │ │ │ ├── p-card-6.json │ │ │ ├── p-card-7.json │ │ │ ├── p-card-8.json │ │ │ ├── p-card-9.json │ │ │ ├── p-checkbox-1.json │ │ │ ├── p-checkbox-2.json │ │ │ ├── p-checkbox-3.json │ │ │ ├── p-checkbox-4.json │ │ │ ├── p-checkbox-5.json │ │ │ ├── p-checkbox-group-1.json │ │ │ ├── p-checkbox-group-2.json │ │ │ ├── p-checkbox-group-3.json │ │ │ ├── p-checkbox-group-4.json │ │ │ ├── p-checkbox-group-5.json │ │ │ ├── p-collapsible-1.json │ │ │ ├── p-combobox-1.json │ │ │ ├── p-combobox-10.json │ │ │ ├── p-combobox-11.json │ │ │ ├── p-combobox-12.json │ │ │ ├── p-combobox-13.json │ │ │ ├── p-combobox-14.json │ │ │ ├── p-combobox-15.json │ │ │ ├── p-combobox-16.json │ │ │ ├── p-combobox-17.json │ │ │ ├── p-combobox-18.json │ │ │ ├── p-combobox-2.json │ │ │ ├── p-combobox-3.json │ │ │ ├── p-combobox-4.json │ │ │ ├── p-combobox-5.json │ │ │ ├── p-combobox-6.json │ │ │ ├── p-combobox-7.json │ │ │ ├── p-combobox-8.json │ │ │ ├── p-combobox-9.json │ │ │ ├── p-command-1.json │ │ │ ├── p-command-2.json │ │ │ ├── p-date-picker-1.json │ │ │ ├── p-date-picker-2.json │ │ │ ├── p-date-picker-3.json │ │ │ ├── p-date-picker-4.json │ │ │ ├── p-date-picker-5.json │ │ │ ├── p-date-picker-6.json │ │ │ ├── p-date-picker-7.json │ │ │ ├── p-date-picker-8.json │ │ │ ├── p-date-picker-9.json │ │ │ ├── p-dialog-1.json │ │ │ ├── p-dialog-2.json │ │ │ ├── p-dialog-3.json │ │ │ ├── p-dialog-4.json │ │ │ ├── p-dialog-5.json │ │ │ ├── p-dialog-6.json │ │ │ ├── p-drawer-1.json │ │ │ ├── p-drawer-10.json │ │ │ ├── p-drawer-11.json │ │ │ ├── p-drawer-12.json │ │ │ ├── p-drawer-13.json │ │ │ ├── p-drawer-14.json │ │ │ ├── p-drawer-2.json │ │ │ ├── p-drawer-3.json │ │ │ ├── p-drawer-4.json │ │ │ ├── p-drawer-5.json │ │ │ ├── p-drawer-6.json │ │ │ ├── p-drawer-7.json │ │ │ ├── p-drawer-8.json │ │ │ ├── p-drawer-9.json │ │ │ ├── p-empty-1.json │ │ │ ├── p-field-1.json │ │ │ ├── p-field-10.json │ │ │ ├── p-field-11.json │ │ │ ├── p-field-12.json │ │ │ ├── p-field-13.json │ │ │ ├── p-field-14.json │ │ │ ├── p-field-15.json │ │ │ ├── p-field-16.json │ │ │ ├── p-field-17.json │ │ │ ├── p-field-18.json │ │ │ ├── p-field-2.json │ │ │ ├── p-field-3.json │ │ │ ├── p-field-4.json │ │ │ ├── p-field-5.json │ │ │ ├── p-field-6.json │ │ │ ├── p-field-7.json │ │ │ ├── p-field-8.json │ │ │ ├── p-field-9.json │ │ │ ├── p-fieldset-1.json │ │ │ ├── p-form-1.json │ │ │ ├── p-form-2.json │ │ │ ├── p-frame-1.json │ │ │ ├── p-frame-2.json │ │ │ ├── p-frame-3.json │ │ │ ├── p-frame-4.json │ │ │ ├── p-group-1.json │ │ │ ├── p-group-10.json │ │ │ ├── p-group-11.json │ │ │ ├── p-group-12.json │ │ │ ├── p-group-13.json │ │ │ ├── p-group-14.json │ │ │ ├── p-group-15.json │ │ │ ├── p-group-16.json │ │ │ ├── p-group-17.json │ │ │ ├── p-group-18.json │ │ │ ├── p-group-19.json │ │ │ ├── p-group-2.json │ │ │ ├── p-group-20.json │ │ │ ├── p-group-22.json │ │ │ ├── p-group-23.json │ │ │ ├── p-group-3.json │ │ │ ├── p-group-4.json │ │ │ ├── p-group-5.json │ │ │ ├── p-group-6.json │ │ │ ├── p-group-7.json │ │ │ ├── p-group-8.json │ │ │ ├── p-group-9.json │ │ │ ├── p-input-1.json │ │ │ ├── p-input-10.json │ │ │ ├── p-input-11.json │ │ │ ├── p-input-12.json │ │ │ ├── p-input-13.json │ │ │ ├── p-input-14.json │ │ │ ├── p-input-15.json │ │ │ ├── p-input-16.json │ │ │ ├── p-input-17.json │ │ │ ├── p-input-18.json │ │ │ ├── p-input-19.json │ │ │ ├── p-input-2.json │ │ │ ├── p-input-3.json │ │ │ ├── p-input-4.json │ │ │ ├── p-input-5.json │ │ │ ├── p-input-6.json │ │ │ ├── p-input-7.json │ │ │ ├── p-input-8.json │ │ │ ├── p-input-9.json │ │ │ ├── p-input-group-1.json │ │ │ ├── p-input-group-10.json │ │ │ ├── p-input-group-11.json │ │ │ ├── p-input-group-12.json │ │ │ ├── p-input-group-13.json │ │ │ ├── p-input-group-14.json │ │ │ ├── p-input-group-15.json │ │ │ ├── p-input-group-16.json │ │ │ ├── p-input-group-17.json │ │ │ ├── p-input-group-18.json │ │ │ ├── p-input-group-19.json │ │ │ ├── p-input-group-2.json │ │ │ ├── p-input-group-20.json │ │ │ ├── p-input-group-21.json │ │ │ ├── p-input-group-22.json │ │ │ ├── p-input-group-23.json │ │ │ ├── p-input-group-24.json │ │ │ ├── p-input-group-25.json │ │ │ ├── p-input-group-26.json │ │ │ ├── p-input-group-27.json │ │ │ ├── p-input-group-28.json │ │ │ ├── p-input-group-29.json │ │ │ ├── p-input-group-3.json │ │ │ ├── p-input-group-4.json │ │ │ ├── p-input-group-5.json │ │ │ ├── p-input-group-6.json │ │ │ ├── p-input-group-7.json │ │ │ ├── p-input-group-8.json │ │ │ ├── p-input-group-9.json │ │ │ ├── p-input-otp-1.json │ │ │ ├── p-input-otp-2.json │ │ │ ├── p-input-otp-3.json │ │ │ ├── p-input-otp-4.json │ │ │ ├── p-input-otp-5.json │ │ │ ├── p-input-otp-6.json │ │ │ ├── p-input-otp-7.json │ │ │ ├── p-kbd-1.json │ │ │ ├── p-menu-1.json │ │ │ ├── p-menu-2.json │ │ │ ├── p-menu-3.json │ │ │ ├── p-menu-4.json │ │ │ ├── p-menu-5.json │ │ │ ├── p-menu-6.json │ │ │ ├── p-menu-7.json │ │ │ ├── p-menu-8.json │ │ │ ├── p-menu-9.json │ │ │ ├── p-meter-1.json │ │ │ ├── p-meter-2.json │ │ │ ├── p-meter-3.json │ │ │ ├── p-meter-4.json │ │ │ ├── p-number-field-1.json │ │ │ ├── p-number-field-10.json │ │ │ ├── p-number-field-11.json │ │ │ ├── p-number-field-2.json │ │ │ ├── p-number-field-3.json │ │ │ ├── p-number-field-4.json │ │ │ ├── p-number-field-5.json │ │ │ ├── p-number-field-6.json │ │ │ ├── p-number-field-7.json │ │ │ ├── p-number-field-8.json │ │ │ ├── p-number-field-9.json │ │ │ ├── p-pagination-1.json │ │ │ ├── p-pagination-2.json │ │ │ ├── p-pagination-3.json │ │ │ ├── p-popover-1.json │ │ │ ├── p-popover-2.json │ │ │ ├── p-popover-3.json │ │ │ ├── p-preview-card-1.json │ │ │ ├── p-progress-1.json │ │ │ ├── p-progress-2.json │ │ │ ├── p-progress-3.json │ │ │ ├── p-radio-group-1.json │ │ │ ├── p-radio-group-2.json │ │ │ ├── p-radio-group-3.json │ │ │ ├── p-radio-group-4.json │ │ │ ├── p-radio-group-5.json │ │ │ ├── p-scroll-area-1.json │ │ │ ├── p-scroll-area-2.json │ │ │ ├── p-scroll-area-3.json │ │ │ ├── p-scroll-area-4.json │ │ │ ├── p-scroll-area-5.json │ │ │ ├── p-select-1.json │ │ │ ├── p-select-10.json │ │ │ ├── p-select-11.json │ │ │ ├── p-select-12.json │ │ │ ├── p-select-13.json │ │ │ ├── p-select-14.json │ │ │ ├── p-select-15.json │ │ │ ├── p-select-16.json │ │ │ ├── p-select-17.json │ │ │ ├── p-select-18.json │ │ │ ├── p-select-19.json │ │ │ ├── p-select-2.json │ │ │ ├── p-select-20.json │ │ │ ├── p-select-21.json │ │ │ ├── p-select-22.json │ │ │ ├── p-select-23.json │ │ │ ├── p-select-3.json │ │ │ ├── p-select-4.json │ │ │ ├── p-select-5.json │ │ │ ├── p-select-6.json │ │ │ ├── p-select-7.json │ │ │ ├── p-select-8.json │ │ │ ├── p-select-9.json │ │ │ ├── p-separator-1.json │ │ │ ├── p-sheet-1.json │ │ │ ├── p-sheet-2.json │ │ │ ├── p-sheet-3.json │ │ │ ├── p-skeleton-1.json │ │ │ ├── p-skeleton-2.json │ │ │ ├── p-slider-1.json │ │ │ ├── p-slider-10.json │ │ │ ├── p-slider-11.json │ │ │ ├── p-slider-12.json │ │ │ ├── p-slider-13.json │ │ │ ├── p-slider-14.json │ │ │ ├── p-slider-15.json │ │ │ ├── p-slider-16.json │ │ │ ├── p-slider-17.json │ │ │ ├── p-slider-18.json │ │ │ ├── p-slider-19.json │ │ │ ├── p-slider-2.json │ │ │ ├── p-slider-20.json │ │ │ ├── p-slider-21.json │ │ │ ├── p-slider-22.json │ │ │ ├── p-slider-23.json │ │ │ ├── p-slider-3.json │ │ │ ├── p-slider-4.json │ │ │ ├── p-slider-5.json │ │ │ ├── p-slider-6.json │ │ │ ├── p-slider-7.json │ │ │ ├── p-slider-8.json │ │ │ ├── p-slider-9.json │ │ │ ├── p-spinner-1.json │ │ │ ├── p-switch-1.json │ │ │ ├── p-switch-2.json │ │ │ ├── p-switch-3.json │ │ │ ├── p-switch-4.json │ │ │ ├── p-switch-5.json │ │ │ ├── p-switch-6.json │ │ │ ├── p-switch-7.json │ │ │ ├── p-table-1.json │ │ │ ├── p-table-2.json │ │ │ ├── p-table-3.json │ │ │ ├── p-table-4.json │ │ │ ├── p-tabs-1.json │ │ │ ├── p-tabs-10.json │ │ │ ├── p-tabs-11.json │ │ │ ├── p-tabs-12.json │ │ │ ├── p-tabs-13.json │ │ │ ├── p-tabs-2.json │ │ │ ├── p-tabs-3.json │ │ │ ├── p-tabs-4.json │ │ │ ├── p-tabs-5.json │ │ │ ├── p-tabs-6.json │ │ │ ├── p-tabs-7.json │ │ │ ├── p-tabs-8.json │ │ │ ├── p-tabs-9.json │ │ │ ├── p-textarea-1.json │ │ │ ├── p-textarea-10.json │ │ │ ├── p-textarea-11.json │ │ │ ├── p-textarea-12.json │ │ │ ├── p-textarea-13.json │ │ │ ├── p-textarea-14.json │ │ │ ├── p-textarea-15.json │ │ │ ├── p-textarea-2.json │ │ │ ├── p-textarea-3.json │ │ │ ├── p-textarea-4.json │ │ │ ├── p-textarea-5.json │ │ │ ├── p-textarea-6.json │ │ │ ├── p-textarea-7.json │ │ │ ├── p-textarea-8.json │ │ │ ├── p-textarea-9.json │ │ │ ├── p-toast-1.json │ │ │ ├── p-toast-2.json │ │ │ ├── p-toast-3.json │ │ │ ├── p-toast-4.json │ │ │ ├── p-toast-5.json │ │ │ ├── p-toast-6.json │ │ │ ├── p-toast-7.json │ │ │ ├── p-toast-8.json │ │ │ ├── p-toast-9.json │ │ │ ├── p-toggle-1.json │ │ │ ├── p-toggle-2.json │ │ │ ├── p-toggle-3.json │ │ │ ├── p-toggle-4.json │ │ │ ├── p-toggle-5.json │ │ │ ├── p-toggle-6.json │ │ │ ├── p-toggle-7.json │ │ │ ├── p-toggle-8.json │ │ │ ├── p-toggle-group-1.json │ │ │ ├── p-toggle-group-2.json │ │ │ ├── p-toggle-group-3.json │ │ │ ├── p-toggle-group-4.json │ │ │ ├── p-toggle-group-5.json │ │ │ ├── p-toggle-group-6.json │ │ │ ├── p-toggle-group-7.json │ │ │ ├── p-toggle-group-8.json │ │ │ ├── p-toggle-group-9.json │ │ │ ├── p-toolbar-1.json │ │ │ ├── p-tooltip-1.json │ │ │ ├── p-tooltip-2.json │ │ │ ├── p-tooltip-3.json │ │ │ ├── p-tooltip-4.json │ │ │ ├── pagination.json │ │ │ ├── popover.json │ │ │ ├── preview-card.json │ │ │ ├── progress.json │ │ │ ├── radio-group.json │ │ │ ├── registry.json │ │ │ ├── scroll-area.json │ │ │ ├── select.json │ │ │ ├── separator.json │ │ │ ├── sheet.json │ │ │ ├── sidebar.json │ │ │ ├── skeleton.json │ │ │ ├── slider.json │ │ │ ├── spinner.json │ │ │ ├── style.json │ │ │ ├── switch.json │ │ │ ├── table.json │ │ │ ├── tabs.json │ │ │ ├── textarea.json │ │ │ ├── toast.json │ │ │ ├── toggle-group.json │ │ │ ├── toggle.json │ │ │ ├── toolbar.json │ │ │ ├── tooltip.json │ │ │ ├── ui.json │ │ │ ├── use-copy-to-clipboard.json │ │ │ ├── use-media-query.json │ │ │ ├── use-render.json │ │ │ └── utils.json │ │ ├── registry/ │ │ │ ├── __index__.tsx │ │ │ ├── default/ │ │ │ │ ├── base-ui/ │ │ │ │ │ ├── csp-provider.ts │ │ │ │ │ ├── direction-provider.ts │ │ │ │ │ ├── merge-props.ts │ │ │ │ │ └── use-render.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-copy-to-clipboard.ts │ │ │ │ │ └── use-media-query.ts │ │ │ │ ├── lib/ │ │ │ │ │ └── utils.ts │ │ │ │ ├── particles/ │ │ │ │ │ ├── p-accordion-1.tsx │ │ │ │ │ ├── p-accordion-2.tsx │ │ │ │ │ ├── p-accordion-3.tsx │ │ │ │ │ ├── p-accordion-4.tsx │ │ │ │ │ ├── p-alert-1.tsx │ │ │ │ │ ├── p-alert-2.tsx │ │ │ │ │ ├── p-alert-3.tsx │ │ │ │ │ ├── p-alert-4.tsx │ │ │ │ │ ├── p-alert-5.tsx │ │ │ │ │ ├── p-alert-6.tsx │ │ │ │ │ ├── p-alert-7.tsx │ │ │ │ │ ├── p-alert-dialog-1.tsx │ │ │ │ │ ├── p-alert-dialog-2.tsx │ │ │ │ │ ├── p-autocomplete-1.tsx │ │ │ │ │ ├── p-autocomplete-10.tsx │ │ │ │ │ ├── p-autocomplete-11.tsx │ │ │ │ │ ├── p-autocomplete-12.tsx │ │ │ │ │ ├── p-autocomplete-13.tsx │ │ │ │ │ ├── p-autocomplete-14.tsx │ │ │ │ │ ├── p-autocomplete-15.tsx │ │ │ │ │ ├── p-autocomplete-2.tsx │ │ │ │ │ ├── p-autocomplete-3.tsx │ │ │ │ │ ├── p-autocomplete-4.tsx │ │ │ │ │ ├── p-autocomplete-5.tsx │ │ │ │ │ ├── p-autocomplete-6.tsx │ │ │ │ │ ├── p-autocomplete-7.tsx │ │ │ │ │ ├── p-autocomplete-8.tsx │ │ │ │ │ ├── p-autocomplete-9.tsx │ │ │ │ │ ├── p-avatar-1.tsx │ │ │ │ │ ├── p-avatar-10.tsx │ │ │ │ │ ├── p-avatar-11.tsx │ │ │ │ │ ├── p-avatar-12.tsx │ │ │ │ │ ├── p-avatar-13.tsx │ │ │ │ │ ├── p-avatar-14.tsx │ │ │ │ │ ├── p-avatar-2.tsx │ │ │ │ │ ├── p-avatar-3.tsx │ │ │ │ │ ├── p-avatar-4.tsx │ │ │ │ │ ├── p-avatar-5.tsx │ │ │ │ │ ├── p-avatar-6.tsx │ │ │ │ │ ├── p-avatar-7.tsx │ │ │ │ │ ├── p-avatar-8.tsx │ │ │ │ │ ├── p-avatar-9.tsx │ │ │ │ │ ├── p-badge-1.tsx │ │ │ │ │ ├── p-badge-10.tsx │ │ │ │ │ ├── p-badge-11.tsx │ │ │ │ │ ├── p-badge-12.tsx │ │ │ │ │ ├── p-badge-13.tsx │ │ │ │ │ ├── p-badge-14.tsx │ │ │ │ │ ├── p-badge-15.tsx │ │ │ │ │ ├── p-badge-16.tsx │ │ │ │ │ ├── p-badge-17.tsx │ │ │ │ │ ├── p-badge-18.tsx │ │ │ │ │ ├── p-badge-19.tsx │ │ │ │ │ ├── p-badge-2.tsx │ │ │ │ │ ├── p-badge-20.tsx │ │ │ │ │ ├── p-badge-3.tsx │ │ │ │ │ ├── p-badge-4.tsx │ │ │ │ │ ├── p-badge-5.tsx │ │ │ │ │ ├── p-badge-6.tsx │ │ │ │ │ ├── p-badge-7.tsx │ │ │ │ │ ├── p-badge-8.tsx │ │ │ │ │ ├── p-badge-9.tsx │ │ │ │ │ ├── p-breadcrumb-1.tsx │ │ │ │ │ ├── p-breadcrumb-2.tsx │ │ │ │ │ ├── p-breadcrumb-3.tsx │ │ │ │ │ ├── p-breadcrumb-4.tsx │ │ │ │ │ ├── p-breadcrumb-5.tsx │ │ │ │ │ ├── p-breadcrumb-6.tsx │ │ │ │ │ ├── p-breadcrumb-7.tsx │ │ │ │ │ ├── p-button-1.tsx │ │ │ │ │ ├── p-button-10.tsx │ │ │ │ │ ├── p-button-11.tsx │ │ │ │ │ ├── p-button-12.tsx │ │ │ │ │ ├── p-button-13.tsx │ │ │ │ │ ├── p-button-14.tsx │ │ │ │ │ ├── p-button-15.tsx │ │ │ │ │ ├── p-button-16.tsx │ │ │ │ │ ├── p-button-17.tsx │ │ │ │ │ ├── p-button-18.tsx │ │ │ │ │ ├── p-button-19.tsx │ │ │ │ │ ├── p-button-2.tsx │ │ │ │ │ ├── p-button-20.tsx │ │ │ │ │ ├── p-button-21.tsx │ │ │ │ │ ├── p-button-22.tsx │ │ │ │ │ ├── p-button-23.tsx │ │ │ │ │ ├── p-button-24.tsx │ │ │ │ │ ├── p-button-26.tsx │ │ │ │ │ ├── p-button-27.tsx │ │ │ │ │ ├── p-button-28.tsx │ │ │ │ │ ├── p-button-29.tsx │ │ │ │ │ ├── p-button-3.tsx │ │ │ │ │ ├── p-button-30.tsx │ │ │ │ │ ├── p-button-31.tsx │ │ │ │ │ ├── p-button-32.tsx │ │ │ │ │ ├── p-button-33.tsx │ │ │ │ │ ├── p-button-34.tsx │ │ │ │ │ ├── p-button-35.tsx │ │ │ │ │ ├── p-button-36.tsx │ │ │ │ │ ├── p-button-37.tsx │ │ │ │ │ ├── p-button-38.tsx │ │ │ │ │ ├── p-button-39.tsx │ │ │ │ │ ├── p-button-4.tsx │ │ │ │ │ ├── p-button-40.tsx │ │ │ │ │ ├── p-button-41.tsx │ │ │ │ │ ├── p-button-5.tsx │ │ │ │ │ ├── p-button-6.tsx │ │ │ │ │ ├── p-button-7.tsx │ │ │ │ │ ├── p-button-8.tsx │ │ │ │ │ ├── p-button-9.tsx │ │ │ │ │ ├── p-calendar-1.tsx │ │ │ │ │ ├── p-calendar-10.tsx │ │ │ │ │ ├── p-calendar-11.tsx │ │ │ │ │ ├── p-calendar-12.tsx │ │ │ │ │ ├── p-calendar-13.tsx │ │ │ │ │ ├── p-calendar-14.tsx │ │ │ │ │ ├── p-calendar-15.tsx │ │ │ │ │ ├── p-calendar-16.tsx │ │ │ │ │ ├── p-calendar-17.tsx │ │ │ │ │ ├── p-calendar-18.tsx │ │ │ │ │ ├── p-calendar-19.tsx │ │ │ │ │ ├── p-calendar-2.tsx │ │ │ │ │ ├── p-calendar-20.tsx │ │ │ │ │ ├── p-calendar-21.tsx │ │ │ │ │ ├── p-calendar-22.tsx │ │ │ │ │ ├── p-calendar-23.tsx │ │ │ │ │ ├── p-calendar-24.tsx │ │ │ │ │ ├── p-calendar-3.tsx │ │ │ │ │ ├── p-calendar-4.tsx │ │ │ │ │ ├── p-calendar-5.tsx │ │ │ │ │ ├── p-calendar-6.tsx │ │ │ │ │ ├── p-calendar-7.tsx │ │ │ │ │ ├── p-calendar-8.tsx │ │ │ │ │ ├── p-calendar-9.tsx │ │ │ │ │ ├── p-card-1.tsx │ │ │ │ │ ├── p-card-10.tsx │ │ │ │ │ ├── p-card-11.tsx │ │ │ │ │ ├── p-card-2.tsx │ │ │ │ │ ├── p-card-3.tsx │ │ │ │ │ ├── p-card-4.tsx │ │ │ │ │ ├── p-card-5.tsx │ │ │ │ │ ├── p-card-6.tsx │ │ │ │ │ ├── p-card-7.tsx │ │ │ │ │ ├── p-card-8.tsx │ │ │ │ │ ├── p-card-9.tsx │ │ │ │ │ ├── p-checkbox-1.tsx │ │ │ │ │ ├── p-checkbox-2.tsx │ │ │ │ │ ├── p-checkbox-3.tsx │ │ │ │ │ ├── p-checkbox-4.tsx │ │ │ │ │ ├── p-checkbox-5.tsx │ │ │ │ │ ├── p-checkbox-group-1.tsx │ │ │ │ │ ├── p-checkbox-group-2.tsx │ │ │ │ │ ├── p-checkbox-group-3.tsx │ │ │ │ │ ├── p-checkbox-group-4.tsx │ │ │ │ │ ├── p-checkbox-group-5.tsx │ │ │ │ │ ├── p-collapsible-1.tsx │ │ │ │ │ ├── p-combobox-1.tsx │ │ │ │ │ ├── p-combobox-10.tsx │ │ │ │ │ ├── p-combobox-11.tsx │ │ │ │ │ ├── p-combobox-12.tsx │ │ │ │ │ ├── p-combobox-13.tsx │ │ │ │ │ ├── p-combobox-14.tsx │ │ │ │ │ ├── p-combobox-15.tsx │ │ │ │ │ ├── p-combobox-16.tsx │ │ │ │ │ ├── p-combobox-17.tsx │ │ │ │ │ ├── p-combobox-18.tsx │ │ │ │ │ ├── p-combobox-2.tsx │ │ │ │ │ ├── p-combobox-3.tsx │ │ │ │ │ ├── p-combobox-4.tsx │ │ │ │ │ ├── p-combobox-5.tsx │ │ │ │ │ ├── p-combobox-6.tsx │ │ │ │ │ ├── p-combobox-7.tsx │ │ │ │ │ ├── p-combobox-8.tsx │ │ │ │ │ ├── p-combobox-9.tsx │ │ │ │ │ ├── p-command-1.tsx │ │ │ │ │ ├── p-command-2.tsx │ │ │ │ │ ├── p-date-picker-1.tsx │ │ │ │ │ ├── p-date-picker-2.tsx │ │ │ │ │ ├── p-date-picker-3.tsx │ │ │ │ │ ├── p-date-picker-4.tsx │ │ │ │ │ ├── p-date-picker-5.tsx │ │ │ │ │ ├── p-date-picker-6.tsx │ │ │ │ │ ├── p-date-picker-7.tsx │ │ │ │ │ ├── p-date-picker-8.tsx │ │ │ │ │ ├── p-date-picker-9.tsx │ │ │ │ │ ├── p-dialog-1.tsx │ │ │ │ │ ├── p-dialog-2.tsx │ │ │ │ │ ├── p-dialog-3.tsx │ │ │ │ │ ├── p-dialog-4.tsx │ │ │ │ │ ├── p-dialog-5.tsx │ │ │ │ │ ├── p-dialog-6.tsx │ │ │ │ │ ├── p-drawer-1.tsx │ │ │ │ │ ├── p-drawer-10.tsx │ │ │ │ │ ├── p-drawer-11.tsx │ │ │ │ │ ├── p-drawer-12.tsx │ │ │ │ │ ├── p-drawer-13.tsx │ │ │ │ │ ├── p-drawer-14.tsx │ │ │ │ │ ├── p-drawer-2.tsx │ │ │ │ │ ├── p-drawer-3.tsx │ │ │ │ │ ├── p-drawer-4.tsx │ │ │ │ │ ├── p-drawer-5.tsx │ │ │ │ │ ├── p-drawer-6.tsx │ │ │ │ │ ├── p-drawer-7.tsx │ │ │ │ │ ├── p-drawer-8.tsx │ │ │ │ │ ├── p-drawer-9.tsx │ │ │ │ │ ├── p-empty-1.tsx │ │ │ │ │ ├── p-field-1.tsx │ │ │ │ │ ├── p-field-10.tsx │ │ │ │ │ ├── p-field-11.tsx │ │ │ │ │ ├── p-field-12.tsx │ │ │ │ │ ├── p-field-13.tsx │ │ │ │ │ ├── p-field-14.tsx │ │ │ │ │ ├── p-field-15.tsx │ │ │ │ │ ├── p-field-16.tsx │ │ │ │ │ ├── p-field-17.tsx │ │ │ │ │ ├── p-field-18.tsx │ │ │ │ │ ├── p-field-2.tsx │ │ │ │ │ ├── p-field-3.tsx │ │ │ │ │ ├── p-field-4.tsx │ │ │ │ │ ├── p-field-5.tsx │ │ │ │ │ ├── p-field-6.tsx │ │ │ │ │ ├── p-field-7.tsx │ │ │ │ │ ├── p-field-8.tsx │ │ │ │ │ ├── p-field-9.tsx │ │ │ │ │ ├── p-fieldset-1.tsx │ │ │ │ │ ├── p-form-1.tsx │ │ │ │ │ ├── p-form-2.tsx │ │ │ │ │ ├── p-frame-1.tsx │ │ │ │ │ ├── p-frame-2.tsx │ │ │ │ │ ├── p-frame-3.tsx │ │ │ │ │ ├── p-frame-4.tsx │ │ │ │ │ ├── p-group-1.tsx │ │ │ │ │ ├── p-group-10.tsx │ │ │ │ │ ├── p-group-11.tsx │ │ │ │ │ ├── p-group-12.tsx │ │ │ │ │ ├── p-group-13.tsx │ │ │ │ │ ├── p-group-14.tsx │ │ │ │ │ ├── p-group-15.tsx │ │ │ │ │ ├── p-group-16.tsx │ │ │ │ │ ├── p-group-17.tsx │ │ │ │ │ ├── p-group-18.tsx │ │ │ │ │ ├── p-group-19.tsx │ │ │ │ │ ├── p-group-2.tsx │ │ │ │ │ ├── p-group-20.tsx │ │ │ │ │ ├── p-group-22.tsx │ │ │ │ │ ├── p-group-23.tsx │ │ │ │ │ ├── p-group-3.tsx │ │ │ │ │ ├── p-group-4.tsx │ │ │ │ │ ├── p-group-5.tsx │ │ │ │ │ ├── p-group-6.tsx │ │ │ │ │ ├── p-group-7.tsx │ │ │ │ │ ├── p-group-8.tsx │ │ │ │ │ ├── p-group-9.tsx │ │ │ │ │ ├── p-input-1.tsx │ │ │ │ │ ├── p-input-10.tsx │ │ │ │ │ ├── p-input-11.tsx │ │ │ │ │ ├── p-input-12.tsx │ │ │ │ │ ├── p-input-13.tsx │ │ │ │ │ ├── p-input-14.tsx │ │ │ │ │ ├── p-input-15.tsx │ │ │ │ │ ├── p-input-16.tsx │ │ │ │ │ ├── p-input-17.tsx │ │ │ │ │ ├── p-input-18.tsx │ │ │ │ │ ├── p-input-19.tsx │ │ │ │ │ ├── p-input-2.tsx │ │ │ │ │ ├── p-input-3.tsx │ │ │ │ │ ├── p-input-4.tsx │ │ │ │ │ ├── p-input-5.tsx │ │ │ │ │ ├── p-input-6.tsx │ │ │ │ │ ├── p-input-7.tsx │ │ │ │ │ ├── p-input-8.tsx │ │ │ │ │ ├── p-input-9.tsx │ │ │ │ │ ├── p-input-group-1.tsx │ │ │ │ │ ├── p-input-group-10.tsx │ │ │ │ │ ├── p-input-group-11.tsx │ │ │ │ │ ├── p-input-group-12.tsx │ │ │ │ │ ├── p-input-group-13.tsx │ │ │ │ │ ├── p-input-group-14.tsx │ │ │ │ │ ├── p-input-group-15.tsx │ │ │ │ │ ├── p-input-group-16.tsx │ │ │ │ │ ├── p-input-group-17.tsx │ │ │ │ │ ├── p-input-group-18.tsx │ │ │ │ │ ├── p-input-group-19.tsx │ │ │ │ │ ├── p-input-group-2.tsx │ │ │ │ │ ├── p-input-group-20.tsx │ │ │ │ │ ├── p-input-group-21.tsx │ │ │ │ │ ├── p-input-group-22.tsx │ │ │ │ │ ├── p-input-group-23.tsx │ │ │ │ │ ├── p-input-group-24.tsx │ │ │ │ │ ├── p-input-group-26.tsx │ │ │ │ │ ├── p-input-group-27.tsx │ │ │ │ │ ├── p-input-group-28.tsx │ │ │ │ │ ├── p-input-group-29.tsx │ │ │ │ │ ├── p-input-group-3.tsx │ │ │ │ │ ├── p-input-group-4.tsx │ │ │ │ │ ├── p-input-group-5.tsx │ │ │ │ │ ├── p-input-group-6.tsx │ │ │ │ │ ├── p-input-group-7.tsx │ │ │ │ │ ├── p-input-group-8.tsx │ │ │ │ │ ├── p-input-group-9.tsx │ │ │ │ │ ├── p-input-otp-1.tsx │ │ │ │ │ ├── p-input-otp-2.tsx │ │ │ │ │ ├── p-input-otp-3.tsx │ │ │ │ │ ├── p-input-otp-4.tsx │ │ │ │ │ ├── p-input-otp-5.tsx │ │ │ │ │ ├── p-input-otp-6.tsx │ │ │ │ │ ├── p-input-otp-7.tsx │ │ │ │ │ ├── p-kbd-1.tsx │ │ │ │ │ ├── p-menu-1.tsx │ │ │ │ │ ├── p-menu-2.tsx │ │ │ │ │ ├── p-menu-3.tsx │ │ │ │ │ ├── p-menu-4.tsx │ │ │ │ │ ├── p-menu-5.tsx │ │ │ │ │ ├── p-menu-6.tsx │ │ │ │ │ ├── p-menu-7.tsx │ │ │ │ │ ├── p-menu-8.tsx │ │ │ │ │ ├── p-menu-9.tsx │ │ │ │ │ ├── p-meter-1.tsx │ │ │ │ │ ├── p-meter-2.tsx │ │ │ │ │ ├── p-meter-3.tsx │ │ │ │ │ ├── p-meter-4.tsx │ │ │ │ │ ├── p-number-field-1.tsx │ │ │ │ │ ├── p-number-field-10.tsx │ │ │ │ │ ├── p-number-field-11.tsx │ │ │ │ │ ├── p-number-field-2.tsx │ │ │ │ │ ├── p-number-field-3.tsx │ │ │ │ │ ├── p-number-field-4.tsx │ │ │ │ │ ├── p-number-field-5.tsx │ │ │ │ │ ├── p-number-field-6.tsx │ │ │ │ │ ├── p-number-field-7.tsx │ │ │ │ │ ├── p-number-field-8.tsx │ │ │ │ │ ├── p-number-field-9.tsx │ │ │ │ │ ├── p-pagination-1.tsx │ │ │ │ │ ├── p-pagination-2.tsx │ │ │ │ │ ├── p-pagination-3.tsx │ │ │ │ │ ├── p-popover-1.tsx │ │ │ │ │ ├── p-popover-2.tsx │ │ │ │ │ ├── p-popover-3.tsx │ │ │ │ │ ├── p-preview-card-1.tsx │ │ │ │ │ ├── p-progress-1.tsx │ │ │ │ │ ├── p-progress-2.tsx │ │ │ │ │ ├── p-progress-3.tsx │ │ │ │ │ ├── p-radio-group-1.tsx │ │ │ │ │ ├── p-radio-group-2.tsx │ │ │ │ │ ├── p-radio-group-3.tsx │ │ │ │ │ ├── p-radio-group-4.tsx │ │ │ │ │ ├── p-radio-group-5.tsx │ │ │ │ │ ├── p-scroll-area-1.tsx │ │ │ │ │ ├── p-scroll-area-2.tsx │ │ │ │ │ ├── p-scroll-area-3.tsx │ │ │ │ │ ├── p-scroll-area-4.tsx │ │ │ │ │ ├── p-scroll-area-5.tsx │ │ │ │ │ ├── p-select-1.tsx │ │ │ │ │ ├── p-select-10.tsx │ │ │ │ │ ├── p-select-11.tsx │ │ │ │ │ ├── p-select-12.tsx │ │ │ │ │ ├── p-select-13.tsx │ │ │ │ │ ├── p-select-14.tsx │ │ │ │ │ ├── p-select-15.tsx │ │ │ │ │ ├── p-select-16.tsx │ │ │ │ │ ├── p-select-17.tsx │ │ │ │ │ ├── p-select-18.tsx │ │ │ │ │ ├── p-select-19.tsx │ │ │ │ │ ├── p-select-2.tsx │ │ │ │ │ ├── p-select-20.tsx │ │ │ │ │ ├── p-select-21.tsx │ │ │ │ │ ├── p-select-22.tsx │ │ │ │ │ ├── p-select-23.tsx │ │ │ │ │ ├── p-select-3.tsx │ │ │ │ │ ├── p-select-4.tsx │ │ │ │ │ ├── p-select-5.tsx │ │ │ │ │ ├── p-select-6.tsx │ │ │ │ │ ├── p-select-7.tsx │ │ │ │ │ ├── p-select-8.tsx │ │ │ │ │ ├── p-select-9.tsx │ │ │ │ │ ├── p-separator-1.tsx │ │ │ │ │ ├── p-sheet-1.tsx │ │ │ │ │ ├── p-sheet-2.tsx │ │ │ │ │ ├── p-sheet-3.tsx │ │ │ │ │ ├── p-skeleton-1.tsx │ │ │ │ │ ├── p-skeleton-2.tsx │ │ │ │ │ ├── p-slider-1.tsx │ │ │ │ │ ├── p-slider-10.tsx │ │ │ │ │ ├── p-slider-11.tsx │ │ │ │ │ ├── p-slider-12.tsx │ │ │ │ │ ├── p-slider-13.tsx │ │ │ │ │ ├── p-slider-14.tsx │ │ │ │ │ ├── p-slider-15.tsx │ │ │ │ │ ├── p-slider-16.tsx │ │ │ │ │ ├── p-slider-17.tsx │ │ │ │ │ ├── p-slider-18.tsx │ │ │ │ │ ├── p-slider-19.tsx │ │ │ │ │ ├── p-slider-2.tsx │ │ │ │ │ ├── p-slider-20.tsx │ │ │ │ │ ├── p-slider-21.tsx │ │ │ │ │ ├── p-slider-22.tsx │ │ │ │ │ ├── p-slider-23.tsx │ │ │ │ │ ├── p-slider-3.tsx │ │ │ │ │ ├── p-slider-4.tsx │ │ │ │ │ ├── p-slider-5.tsx │ │ │ │ │ ├── p-slider-6.tsx │ │ │ │ │ ├── p-slider-7.tsx │ │ │ │ │ ├── p-slider-8.tsx │ │ │ │ │ ├── p-slider-9.tsx │ │ │ │ │ ├── p-spinner-1.tsx │ │ │ │ │ ├── p-switch-1.tsx │ │ │ │ │ ├── p-switch-2.tsx │ │ │ │ │ ├── p-switch-3.tsx │ │ │ │ │ ├── p-switch-4.tsx │ │ │ │ │ ├── p-switch-5.tsx │ │ │ │ │ ├── p-switch-6.tsx │ │ │ │ │ ├── p-table-1.tsx │ │ │ │ │ ├── p-table-2.tsx │ │ │ │ │ ├── p-table-3.tsx │ │ │ │ │ ├── p-table-4.tsx │ │ │ │ │ ├── p-tabs-1.tsx │ │ │ │ │ ├── p-tabs-10.tsx │ │ │ │ │ ├── p-tabs-11.tsx │ │ │ │ │ ├── p-tabs-12.tsx │ │ │ │ │ ├── p-tabs-13.tsx │ │ │ │ │ ├── p-tabs-2.tsx │ │ │ │ │ ├── p-tabs-3.tsx │ │ │ │ │ ├── p-tabs-4.tsx │ │ │ │ │ ├── p-tabs-5.tsx │ │ │ │ │ ├── p-tabs-6.tsx │ │ │ │ │ ├── p-tabs-7.tsx │ │ │ │ │ ├── p-tabs-8.tsx │ │ │ │ │ ├── p-tabs-9.tsx │ │ │ │ │ ├── p-textarea-1.tsx │ │ │ │ │ ├── p-textarea-10.tsx │ │ │ │ │ ├── p-textarea-11.tsx │ │ │ │ │ ├── p-textarea-12.tsx │ │ │ │ │ ├── p-textarea-13.tsx │ │ │ │ │ ├── p-textarea-14.tsx │ │ │ │ │ ├── p-textarea-15.tsx │ │ │ │ │ ├── p-textarea-2.tsx │ │ │ │ │ ├── p-textarea-3.tsx │ │ │ │ │ ├── p-textarea-4.tsx │ │ │ │ │ ├── p-textarea-5.tsx │ │ │ │ │ ├── p-textarea-6.tsx │ │ │ │ │ ├── p-textarea-7.tsx │ │ │ │ │ ├── p-textarea-8.tsx │ │ │ │ │ ├── p-textarea-9.tsx │ │ │ │ │ ├── p-toast-1.tsx │ │ │ │ │ ├── p-toast-2.tsx │ │ │ │ │ ├── p-toast-3.tsx │ │ │ │ │ ├── p-toast-4.tsx │ │ │ │ │ ├── p-toast-5.tsx │ │ │ │ │ ├── p-toast-6.tsx │ │ │ │ │ ├── p-toast-7.tsx │ │ │ │ │ ├── p-toast-8.tsx │ │ │ │ │ ├── p-toast-9.tsx │ │ │ │ │ ├── p-toggle-1.tsx │ │ │ │ │ ├── p-toggle-2.tsx │ │ │ │ │ ├── p-toggle-3.tsx │ │ │ │ │ ├── p-toggle-4.tsx │ │ │ │ │ ├── p-toggle-5.tsx │ │ │ │ │ ├── p-toggle-6.tsx │ │ │ │ │ ├── p-toggle-7.tsx │ │ │ │ │ ├── p-toggle-8.tsx │ │ │ │ │ ├── p-toggle-group-1.tsx │ │ │ │ │ ├── p-toggle-group-2.tsx │ │ │ │ │ ├── p-toggle-group-3.tsx │ │ │ │ │ ├── p-toggle-group-4.tsx │ │ │ │ │ ├── p-toggle-group-5.tsx │ │ │ │ │ ├── p-toggle-group-6.tsx │ │ │ │ │ ├── p-toggle-group-7.tsx │ │ │ │ │ ├── p-toggle-group-8.tsx │ │ │ │ │ ├── p-toggle-group-9.tsx │ │ │ │ │ ├── p-toolbar-1.tsx │ │ │ │ │ ├── p-tooltip-1.tsx │ │ │ │ │ ├── p-tooltip-2.tsx │ │ │ │ │ ├── p-tooltip-3.tsx │ │ │ │ │ └── p-tooltip-4.tsx │ │ │ │ └── ui/ │ │ │ │ ├── accordion.tsx │ │ │ │ ├── alert-dialog.tsx │ │ │ │ ├── alert.tsx │ │ │ │ ├── autocomplete.tsx │ │ │ │ ├── avatar.tsx │ │ │ │ ├── badge.tsx │ │ │ │ ├── breadcrumb.tsx │ │ │ │ ├── button.tsx │ │ │ │ ├── calendar.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── checkbox-group.tsx │ │ │ │ ├── checkbox.tsx │ │ │ │ ├── collapsible.tsx │ │ │ │ ├── combobox.tsx │ │ │ │ ├── command.tsx │ │ │ │ ├── dialog.tsx │ │ │ │ ├── drawer.tsx │ │ │ │ ├── empty.tsx │ │ │ │ ├── field.tsx │ │ │ │ ├── fieldset.tsx │ │ │ │ ├── form.tsx │ │ │ │ ├── frame.tsx │ │ │ │ ├── group.tsx │ │ │ │ ├── input-group.tsx │ │ │ │ ├── input-otp.tsx │ │ │ │ ├── input.tsx │ │ │ │ ├── kbd.tsx │ │ │ │ ├── label.tsx │ │ │ │ ├── menu.tsx │ │ │ │ ├── meter.tsx │ │ │ │ ├── number-field.tsx │ │ │ │ ├── pagination.tsx │ │ │ │ ├── popover.tsx │ │ │ │ ├── preview-card.tsx │ │ │ │ ├── progress.tsx │ │ │ │ ├── radio-group.tsx │ │ │ │ ├── scroll-area.tsx │ │ │ │ ├── select.tsx │ │ │ │ ├── separator.tsx │ │ │ │ ├── sheet.tsx │ │ │ │ ├── sidebar.tsx │ │ │ │ ├── skeleton.tsx │ │ │ │ ├── slider.tsx │ │ │ │ ├── spinner.tsx │ │ │ │ ├── switch.tsx │ │ │ │ ├── table.tsx │ │ │ │ ├── tabs.tsx │ │ │ │ ├── textarea.tsx │ │ │ │ ├── toast.tsx │ │ │ │ ├── toggle-group.tsx │ │ │ │ ├── toggle.tsx │ │ │ │ ├── toolbar.tsx │ │ │ │ └── tooltip.tsx │ │ │ ├── index.ts │ │ │ ├── registry-base-ui.ts │ │ │ ├── registry-categories.ts │ │ │ ├── registry-hooks.ts │ │ │ ├── registry-lib.ts │ │ │ ├── registry-particles.ts │ │ │ ├── registry-styles.ts │ │ │ └── registry-ui.ts │ │ ├── registry.json │ │ ├── scripts/ │ │ │ ├── build-registry.mts │ │ │ ├── sync-ui.mts │ │ │ └── validate-registry-deps.mts │ │ ├── source.config.ts │ │ ├── tsconfig.json │ │ └── tsconfig.scripts.json │ └── www/ │ ├── .gitignore │ ├── README.md │ ├── app/ │ │ ├── auth/ │ │ │ └── page.tsx │ │ ├── auth copy/ │ │ │ └── page.tsx │ │ ├── calendar/ │ │ │ └── page.tsx │ │ ├── email/ │ │ │ └── page.tsx │ │ ├── globals.css │ │ ├── layout.tsx │ │ ├── not-found.tsx │ │ ├── notifications/ │ │ │ └── page.tsx │ │ ├── page.tsx │ │ ├── payments/ │ │ │ └── page.tsx │ │ ├── robots.ts │ │ ├── scheduling/ │ │ │ └── page.tsx │ │ ├── sitemap.ts │ │ ├── sms/ │ │ │ └── page.tsx │ │ └── video/ │ │ └── page.tsx │ ├── next.config.ts │ ├── package.json │ ├── postcss.config.mjs │ └── tsconfig.json ├── biome.json ├── bunfig.toml ├── lint-staged.config.mjs ├── package.json ├── packages/ │ ├── typescript-config/ │ │ ├── base.json │ │ ├── nextjs.json │ │ ├── package.json │ │ └── react-library.json │ └── ui/ │ ├── components.json │ ├── package.json │ ├── postcss.config.mjs │ ├── src/ │ │ ├── base-ui/ │ │ │ ├── csp-provider.ts │ │ │ ├── direction-provider.ts │ │ │ ├── merge-props.ts │ │ │ └── use-render.ts │ │ ├── components/ │ │ │ ├── accordion.tsx │ │ │ ├── alert-dialog.tsx │ │ │ ├── alert.tsx │ │ │ ├── autocomplete.tsx │ │ │ ├── avatar.tsx │ │ │ ├── badge.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── button.tsx │ │ │ ├── calendar.tsx │ │ │ ├── card.tsx │ │ │ ├── checkbox-group.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── combobox.tsx │ │ │ ├── command.tsx │ │ │ ├── dialog.tsx │ │ │ ├── drawer.tsx │ │ │ ├── empty.tsx │ │ │ ├── field.tsx │ │ │ ├── fieldset.tsx │ │ │ ├── form.tsx │ │ │ ├── frame.tsx │ │ │ ├── group.tsx │ │ │ ├── input-group.tsx │ │ │ ├── input-otp.tsx │ │ │ ├── input.tsx │ │ │ ├── kbd.tsx │ │ │ ├── label.tsx │ │ │ ├── menu.tsx │ │ │ ├── meter.tsx │ │ │ ├── number-field.tsx │ │ │ ├── pagination.tsx │ │ │ ├── popover.tsx │ │ │ ├── preview-card.tsx │ │ │ ├── progress.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── scroll-area.tsx │ │ │ ├── select.tsx │ │ │ ├── separator.tsx │ │ │ ├── sheet.tsx │ │ │ ├── sidebar.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── slider.tsx │ │ │ ├── spinner.tsx │ │ │ ├── switch.tsx │ │ │ ├── table.tsx │ │ │ ├── tabs.tsx │ │ │ ├── textarea.tsx │ │ │ ├── toast.tsx │ │ │ ├── toggle-group.tsx │ │ │ ├── toggle.tsx │ │ │ ├── toolbar.tsx │ │ │ └── tooltip.tsx │ │ ├── fonts/ │ │ │ ├── README.md │ │ │ └── index.ts │ │ ├── hooks/ │ │ │ ├── use-copy-to-clipboard.ts │ │ │ └── use-media-query.ts │ │ ├── lib/ │ │ │ ├── config.ts │ │ │ ├── highlight-code.ts │ │ │ └── utils.ts │ │ ├── shared/ │ │ │ ├── code-block.tsx │ │ │ ├── copy-button.tsx │ │ │ ├── github-link.tsx │ │ │ ├── icons.tsx │ │ │ ├── mobile-nav.tsx │ │ │ ├── mode-switcher.tsx │ │ │ ├── page-header.tsx │ │ │ ├── product-label.tsx │ │ │ ├── products-dropdown.tsx │ │ │ ├── site-cta.tsx │ │ │ ├── site-footer.tsx │ │ │ ├── site-header.tsx │ │ │ └── theme-provider.tsx │ │ └── styles/ │ │ └── globals.css │ ├── test/ │ │ └── components/ │ │ ├── button.test.tsx │ │ └── separator.test.tsx │ ├── tsconfig.json │ ├── tsconfig.lint.json │ └── tsconfig.tsbuildinfo ├── tsconfig.json └── turbo.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .biome-packages-sync/packages-sync.json ================================================ { "$schema": "https://biomejs.dev/schemas/2.3.10/schema.json", "root": false, "assist": { "enabled": true, "actions": { "source": { "organizeImports": "on" } } } } ================================================ FILE: .github/labeler.yml ================================================ "area:apps/origin": - changed-files: - any-glob-to-any-file: "apps/origin/**" "area:apps/ui": - changed-files: - any-glob-to-any-file: "apps/ui/**" "area:apps/www": - changed-files: - any-glob-to-any-file: "apps/www/**" "pkg:ui": - changed-files: - any-glob-to-any-file: "packages/ui/**" "pkg:tsconfig": - changed-files: - any-glob-to-any-file: "packages/typescript-config/**" "area:config": - changed-files: - any-glob-to-any-file: ".github/**" - any-glob-to-any-file: "biome.json" - any-glob-to-any-file: "turbo.json" - any-glob-to-any-file: "tsconfig.json" - any-glob-to-any-file: "bunfig.toml" - any-glob-to-any-file: "lint-staged.config.mjs" "docs": - changed-files: - any-glob-to-any-file: "**/*.md" "deps": - changed-files: - any-glob-to-any-file: "package.json" - any-glob-to-any-file: "bun.lock" - any-glob-to-any-file: "packages/**/package.json" ================================================ FILE: .github/workflows/build.yml ================================================ name: Build on: workflow_call: env: BUN_VERSION: 1.3.1 jobs: build: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} - name: Install dependencies run: bun install --frozen-lockfile - name: Run build run: bun run build ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: branches: - main pull_request: concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: format: name: Format Check uses: ./.github/workflows/format.yml secrets: inherit lint: name: Lint uses: ./.github/workflows/lint.yml secrets: inherit typecheck: name: Typecheck uses: ./.github/workflows/typecheck.yml secrets: inherit test: name: Test uses: ./.github/workflows/test.yml secrets: inherit build: name: Build needs: [lint, test, format, typecheck] uses: ./.github/workflows/build.yml secrets: inherit ================================================ FILE: .github/workflows/format.yml ================================================ name: Format on: workflow_call: env: BUN_VERSION: 1.3.1 jobs: format: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} - name: Install dependencies run: bun install --frozen-lockfile - name: Verify formatting run: bunx biome check --linter-enabled=false . ================================================ FILE: .github/workflows/labeler.yml ================================================ name: PR Labeler on: pull_request: types: - opened - synchronize - reopened pull_request_target: types: - opened - synchronize - reopened jobs: label: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/labeler@v5 with: repo-token: ${{ secrets.GITHUB_TOKEN }} configuration-path: .github/labeler.yml ================================================ FILE: .github/workflows/lint.yml ================================================ name: Lint on: workflow_call: env: BUN_VERSION: 1.3.1 jobs: lint: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} - name: Install dependencies run: bun install --frozen-lockfile - name: Run lint run: bun run lint ================================================ FILE: .github/workflows/publish.yml ================================================ name: Publish Package on: workflow_dispatch: inputs: package: description: Name of the package directory inside packages/ required: true default: ui type: choice options: - ui release_type: description: Semver bump type to apply before publishing required: true default: patch type: choice options: - patch - minor - major concurrency: group: publish-${{ github.ref }} cancel-in-progress: false env: BUN_VERSION: 1.3.1 jobs: format: uses: ./.github/workflows/format.yml secrets: inherit lint: needs: format uses: ./.github/workflows/lint.yml secrets: inherit test: needs: lint uses: ./.github/workflows/test.yml secrets: inherit build: needs: [lint, test] uses: ./.github/workflows/build.yml secrets: inherit publish: needs: build runs-on: ubuntu-latest permissions: contents: write packages: write id-token: write env: PACKAGE_DIR: packages/${{ inputs.package }} NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Install dependencies run: bun install --frozen-lockfile - name: Resolve package metadata id: pkg run: | PACKAGE_JSON="${{ env.PACKAGE_DIR }}/package.json" if [ ! -f "$PACKAGE_JSON" ]; then echo "::error::Package manifest not found at $PACKAGE_JSON" exit 1 fi NAME=$(node -p "require('./${{ env.PACKAGE_DIR }}/package.json').name") VERSION=$(node -p "require('./${{ env.PACKAGE_DIR }}/package.json').version") echo "name=$NAME" >> "$GITHUB_OUTPUT" echo "current_version=$VERSION" >> "$GITHUB_OUTPUT" - name: Build target package run: bunx turbo run build --filter=${{ steps.pkg.outputs.name }} - name: Bump package version id: bump working-directory: ${{ env.PACKAGE_DIR }} run: | npm version ${{ inputs.release_type }} --no-git-tag-version --no-commit > /dev/null NEW_VERSION=$(node -p "require('./package.json').version") echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT" - name: Verify npm token run: | if [ -z "${NODE_AUTH_TOKEN:-}" ]; then echo "::error::NPM_TOKEN secret is not configured" exit 1 fi - name: Publish to npm working-directory: ${{ env.PACKAGE_DIR }} env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} run: npm publish --access public --provenance - name: Commit version bump run: | git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" git add "${{ env.PACKAGE_DIR }}/package.json" git commit -m "chore(release): ${{ steps.pkg.outputs.name }} v${{ steps.bump.outputs.version }}" - name: Push changes run: | git push origin HEAD:${GITHUB_REF_NAME} - name: Tag release run: | TAG="${{ steps.pkg.outputs.name }}@${{ steps.bump.outputs.version }}" git tag "$TAG" git push origin "$TAG" ================================================ FILE: .github/workflows/semantic-pull-requests.yml ================================================ name: "Validate PRs" on: pull_request_target: types: - opened - reopened - edited - synchronize permissions: pull-requests: write jobs: validate-pr: name: Validate PR title runs-on: ubuntu-latest steps: - uses: amannn/action-semantic-pull-request@v5 id: lint_pr_title env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - uses: marocchino/sticky-pull-request-comment@v2 # When the previous steps fails, the workflow would stop. By adding this # condition you can continue the execution with the populated error message. if: always() && (steps.lint_pr_title.outputs.error_message != null) with: header: pr-title-lint-error message: | Hey there and thank you for opening this pull request! 👋🏼 We require pull request titles to follow the [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted. Details: ``` ${{ steps.lint_pr_title.outputs.error_message }} ``` ================================================ FILE: .github/workflows/test.yml ================================================ name: Test on: workflow_call: env: BUN_VERSION: 1.3.1 jobs: test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} - name: Install dependencies run: bun install --frozen-lockfile - name: Run tests run: bun run test ================================================ FILE: .github/workflows/typecheck.yml ================================================ name: Typecheck on: workflow_call: env: BUN_VERSION: 1.3.1 jobs: typecheck: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v1 with: bun-version: ${{ env.BUN_VERSION }} - name: Cache dependencies uses: actions/cache@v4 with: path: | ~/.bun/install/cache node_modules key: ${{ runner.os }}-bun-${{ hashFiles('bun.lock') }} - name: Install dependencies run: bun install --frozen-lockfile - name: Run typecheck run: bun run typecheck ================================================ FILE: .gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # Dependencies node_modules .pnp .pnp.js # Local env files .env .env.local .env.development.local .env.test.local .env.production.local # Testing coverage # Turbo .turbo # Vercel .vercel # Build Outputs .next/ out/ build dist # Debug npm-debug.log* # Misc .DS_Store *.pem ================================================ FILE: .husky/pre-commit ================================================ bunx lint-staged ================================================ FILE: .husky/pre-push ================================================ #!/bin/sh # Format all files first bun format:all || exit $? # Then build registry and sync UI components cd apps/ui bun registry:build && bun ui:sync ================================================ FILE: .vscode/settings.json ================================================ { "eslint.workingDirectories": [ { "mode": "auto" } ] } ================================================ FILE: .zed/settings.json ================================================ { "code_actions_on_format": { "source.fixAll.biome": true, "source.organizeImports.biome": true }, "format_on_save": "on", "formatter": { "language_server": { "name": "biome" } } } ================================================ FILE: AGENTS.md ================================================ # AGENTS.md Guidelines for AI agents working on this codebase. ## Main Documentation The comprehensive agent guidelines for this repository are located in: **[apps/ui/AGENTS.md](apps/ui/AGENTS.md)** ================================================ FILE: LICENSE ================================================ GNU AFFERO GENERAL PUBLIC LICENSE Version 3, 19 November 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed to ensure cooperation with the community in the case of network server software. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. Developers that use our General Public Licenses protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you legal permission to copy, distribute and/or modify the software. A secondary benefit of defending all users' freedom is that improvements made in alternate versions of the program, if they receive widespread use, become available for other developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation. However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License permits making a modified version and letting the public access it on a server without ever releasing its source code to the public. The GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified source code becomes available to the community. It requires the operator of a network server to provide the source code of the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly accessible server, gives the public access to the source code of the modified version. An older license, called the Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license, not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this license. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU Affero General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Remote Network Interaction; Use with the GNU General Public License. Notwithstanding any other provision of this License, if you modify the Program, your modified version must prominently offer all users interacting with it remotely through a computer network (if your version supports such interaction) an opportunity to receive the Corresponding Source of your version by providing access to the Corresponding Source from a network server at no charge, through some standard or customary means of facilitating copying of software. This Corresponding Source shall include the Corresponding Source for any work covered by version 3 of the GNU General Public License that is incorporated pursuant to the following paragraph. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the work with which it is combined will remain governed by version 3 of the GNU General Public License. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU Affero General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU Affero General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU Affero General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU Affero General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If your software can interact with users remotely through a computer network, you should also make sure that it provides a way for users to get its source. For example, if your program is a web application, its interface could display a "Source" link that leads users to an archive of the code. There are many ways you could offer source, and different solutions will be better for different programs; see section 13 for the specific requirements. You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see . ================================================ FILE: LICENSING.md ================================================ # Licensing This repository uses a mixed licensing approach. The default license for this project is [AGPLv3.0](LICENSE). ## MIT The following directory and their subdirectories are licensed under their original ``` apps/origin/ apps/ui/ ``` ================================================ FILE: README.md ================================================ ![coss.com](https://github.com/user-attachments/assets/56dfe7f7-85b7-44ee-b89a-1c30c5c4a156)

coss.com (formerly Origin UI)

The everything but AI company.

## About the Project coss.com is the new holding company of [cal.com](https://cal.com), the pioneers of open source scheduling infrastructure. Our mission is to build a home for amazing open source projects, giving them the support they need to grow and succeed. We're building the coss stack, a one line `npm install @coss` package that includes everything you need to build your application, from email, SMS, calendar APIs, scheduling, video conferencing, notifications and more. ## Repository Overview This repository contains multiple products and applications that make up the coss.com ecosystem: ### Apps and Packages - **`apps/www/`** - Main coss.com website - **`apps/ui/`** - coss ui component library and documentation - **`apps/origin/`** - Legacy Origin UI components (pre-acquisition) - **`packages/ui/`** - Shared UI components package - **`packages/typescript-config/`** - TypeScript configurations - **`biome.json`** - Shared Biome configuration for linting and formatting Each package/app is 100% [TypeScript](https://www.typescriptlang.org/). ### Environment Variables This monorepo contains multiple Next.js applications that are designed to link to each other. For the navigation to work correctly, you must set up environment variables for both local development and production deployments. #### Local Development For local development, create a `.env.local` file in each of the app directories with the corresponding variables. 1. **`www` app** This app needs to know the URLs of the other apps. Create a file at `apps/www/.env.local`: ```sh # apps/www/.env.local NEXT_PUBLIC_APP_URL=http://localhost:3000 NEXT_PUBLIC_COSS_UI_URL=http://localhost:4000/ui ``` 2. **`ui` app** This app needs to know the URLs of the other apps. Create a file at `apps/ui/.env.local`: ```sh # apps/ui/.env.local NEXT_PUBLIC_APP_URL=http://localhost:4000/ui NEXT_PUBLIC_COSS_URL=http://localhost:3000 NEXT_PUBLIC_ORIGIN_URL=http://localhost:4001 ``` 3. **`origin` app** This app needs to know the URLs of the other apps. Create a file at `apps/origin/.env.local`: ```sh # apps/origin/.env.local NEXT_PUBLIC_APP_URL=http://localhost:4001/origin NEXT_PUBLIC_COSS_URL=http://localhost:3000 NEXT_PUBLIC_COSS_UI_URL=http://localhost:4000/ui ``` > [!NOTE] > Turborepo is configured to watch for changes in `.env*` files, so it will automatically invalidate the cache when these variables change. ### Development This Turborepo has some additional tools already setup for you: - [TypeScript](https://www.typescriptlang.org/) for static type checking - [Biome](https://biomejs.dev/) for linting and formatting #### Build To build all apps and packages: ```sh bun run build ``` To build a specific app: ```sh bun run build --filter=www bun run build --filter=ui bun run build --filter=origin ``` #### Develop To develop all apps and packages: ```sh bun run dev ``` To develop a specific app: ```sh bun run dev --filter=www bun run dev --filter=ui bun run dev --filter=origin ``` ## coss ui **coss ui** is a collection of beautifully designed, accessible, and composable components for your React apps. Built on top of [Base UI](https://base-ui.com/) and styled with [Tailwind CSS](https://tailwindcss.com/), it's designed for you to copy, paste, and own. We think Base UI is the best foundation for modern web applications. We've taken its powerful, unstyled primitives and given them a design system that's ready to go, right out of the box. This is the component library we'll be progressively adopting for [cal.com](https://cal.com). We're building it in the open for anyone who wants to create beautiful, reliable user interfaces. ### Origin UI Acquisition This repository also includes the **Origin UI** components as a legacy snapshot. Origin UI was a pre-acquisition collection of Radix-based, shadcn-style components that remains available for use, but with limited support and maintenance. Active development now focuses on the new [Particles](https://coss.com/ui/particles) components built on the coss ui primitives. ### Contributing to coss ui We're always looking for contributors to help improve our UI components. Whether it's a bug report, a new feature, or a documentation update, we appreciate your help. Please see our [Contributing Guidelines](apps/ui/CONTRIBUTING.md) for more information on how to get involved. ## Licensing This repository uses a mixed licensing approach. The default license for this project is [AGPLv3.0](LICENSE). - **MIT**: The `apps/origin/` and `apps/ui/` directories are licensed under their original MIT license - **AGPLv3**: All other directories are licensed under the GNU Affero General Public License v3.0 For detailed information, see our [Licensing documentation](LICENSING.md). ## Acknowledgements Special thanks to: - **[Tailwind CSS](https://tailwindcss.com/)** - For the utility-first CSS framework that powers our design system - **[Base UI](https://base-ui.com/)** - For providing the robust, accessible primitives that form the foundation of our components - **[shadcn/ui](https://ui.shadcn.com/)** - For inspiring our copy-paste approach and component philosophy - **[Fumadocs](https://fumadocs.dev/)** - For providing the documentation framework that powers our component docs ================================================ FILE: apps/examples/calcom/.gitignore ================================================ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. # dependencies /node_modules /.pnp .pnp.* .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/versions # testing /coverage # next.js /.next/ /out/ # production /build # misc .DS_Store *.pem # debug npm-debug.log* yarn-debug.log* yarn-error.log* .pnpm-debug.log* # env files (can opt-in for committing if needed) .env* # vercel .vercel # typescript *.tsbuildinfo next-env.d.ts # fumadocs .source ================================================ FILE: apps/examples/calcom/README.md ================================================ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). ## Getting Started First, run the development server: ```bash npm run dev # or yarn dev # or pnpm dev # or bun run dev ``` Open [http://localhost:4002](http://localhost:4002) with your browser to see the result. You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. ## Learn More To learn more about Next.js, take a look at the following resources: - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! ## Deploy on Vercel The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/booking-skeleton.tsx ================================================ import { Card, CardFrame, CardPanel } from "@coss/ui/components/card"; import { FrameFooter } from "@coss/ui/components/frame"; import { Skeleton } from "@coss/ui/components/skeleton"; import { BookingActionsSkeleton } from "./past/booking-actions"; import { ListItem, ListItemActions, ListItemBadges, ListItemContent, ListItemHeader, } from "@/components/list-item"; export function BookingSkeletonItem() { return (
); } export function BookingsListSkeleton() { return (
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/canceled/bookings-empty.tsx ================================================ "use client"; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@coss/ui/components/empty"; import { CalendarIcon } from "lucide-react"; import { BookingsListSkeleton } from "../booking-skeleton"; import { useLoadingState } from "@/hooks/use-loading-state"; const ARTIFICIAL_DELAY_MS = 400; export function BookingsEmpty() { const showLoading = useLoadingState(ARTIFICIAL_DELAY_MS); if (showLoading) { return ; } return ( No canceled bookings You have no canceled bookings found. Canceled bookings will appear here. ); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/canceled/loading.tsx ================================================ import { BookingsListSkeleton } from "../booking-skeleton"; export default function Loading() { return ; } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/canceled/page.tsx ================================================ import { BookingsEmpty } from "./bookings-empty"; import { BookingsNav } from "@/components/app/bookings-nav"; import { BookingsView } from "@/components/app/bookings-view"; export default function Page() { return ( <>
{/* */}
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/page.tsx ================================================ import { redirect } from "next/navigation"; export default function Page() { redirect("/booking/upcoming"); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/past/booking-actions.tsx ================================================ "use client"; import { Button } from "@coss/ui/components/button"; import { Menu, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuSeparator, MenuTrigger, } from "@coss/ui/components/menu"; import { Skeleton } from "@coss/ui/components/skeleton"; import { Tooltip, TooltipPopup, TooltipTrigger, } from "@coss/ui/components/tooltip"; import { CalendarClockIcon, EllipsisIcon, EyeOffIcon, FlagIcon, InfoIcon, MapPinIcon, PlayCircleIcon, UserPlusIcon, XIcon, } from "lucide-react"; export function BookingActions() { return ( } /> } /> Options Edit event Reschedule booking Request reschedule Edit location Add guests After event View recordings View Session Details Mark as no-show Report booking Cancel event ); } export function BookingActionsSkeleton() { return ; } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/past/bookings-list.tsx ================================================ "use client"; import { Badge } from "@coss/ui/components/badge"; import { Button } from "@coss/ui/components/button"; import { Card, CardFrame, CardFrameFooter, CardPanel, } from "@coss/ui/components/card"; import { Pagination, PaginationContent, PaginationItem, PaginationNext, PaginationPrevious, } from "@coss/ui/components/pagination"; import { Select, SelectItem, SelectPopup, SelectTrigger, SelectValue, } from "@coss/ui/components/select"; import { TooltipProvider } from "@coss/ui/components/tooltip"; import { cn } from "@coss/ui/lib/utils"; import { BanknoteIcon, CircleDashedIcon, CircleXIcon, RefreshCcwIcon, RepeatIcon, UsersIcon, VideoIcon, } from "lucide-react"; import Link from "next/link"; import { useState } from "react"; import { BookingsListSkeleton } from "../booking-skeleton"; import { BookingActions } from "./booking-actions"; import { ItemLabel } from "@/components/item-label"; import { ListItem, ListItemActions, ListItemBadges, ListItemContent, ListItemDescription, ListItemHeader, ListItemTitle, ListItemTitleLink, } from "@/components/list-item"; import { useLoadingState } from "@/hooks/use-loading-state"; import { formatBookingDate, formatBookingTime, getBookingParticipants, getLocationLabel, mockPastBookings, } from "@/lib/mock-bookings-data"; const ARTIFICIAL_DELAY_MS = 800; export function BookingsList() { const showLoading = useLoadingState(ARTIFICIAL_DELAY_MS); const bookings = mockPastBookings; const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(10); const totalCount = bookings.length; const totalPages = Math.ceil(totalCount / pageSize); const startIndex = pageIndex * pageSize; const endIndex = Math.min(startIndex + pageSize, totalCount); const paginatedBookings = bookings.slice(startIndex, endIndex); const hasPreviousPage = pageIndex > 0; const hasNextPage = pageIndex < totalPages - 1; if (showLoading) { return ; } return ( {paginatedBookings.map((booking, _index) => { const dateStr = formatBookingDate(booking.startTime); const timeStr = formatBookingTime( booking.startTime, booking.endTime, ); const participants = getBookingParticipants(booking); const locationLabel = getLocationLabel(booking.location); const eventTypeColorLight = booking.eventType?.eventTypeColor?.lightEventTypeColor; const eventTypeColorDark = booking.eventType?.eventTypeColor?.darkEventTypeColor; const isPaid = booking.paid; const isRecurring = booking.recurringEventId !== null; const isCancelled = booking.status === "CANCELLED"; const isPending = booking.status === "PENDING"; const isRejected = booking.status === "REJECTED"; const isRescheduled = booking.rescheduled; const teamName = booking.eventType?.team?.name; return (
{booking.title} {participants} {isCancelled && ( Cancelled )} {isPending && ( Unconfirmed )} {isRescheduled && ( Rescheduled )} {isRejected && !isRescheduled && ( Rejected )} {teamName && ( {teamName} )} {isPaid && ( Paid )} {isRecurring && ( Recurring )}

{dateStr}

{timeStr}

{locationLabel && ( )}
); })}

rows per page

{startIndex + 1}-{endIndex} of {totalCount}

setPageIndex(pageIndex - 1)} size="sm" variant="outline" /> } /> setPageIndex(pageIndex + 1)} size="sm" variant="outline" /> } />
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/past/loading.tsx ================================================ import { BookingsListSkeleton } from "../booking-skeleton"; export default function Loading() { return ; } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/past/page.tsx ================================================ import { BookingsList } from "./bookings-list"; import { BookingsFilters } from "@/components/app/bookings-filters"; import { BookingsNav } from "@/components/app/bookings-nav"; import { BookingsView } from "@/components/app/bookings-view"; export default function Page() { return ( <>
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/recurring/bookings-empty.tsx ================================================ "use client"; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@coss/ui/components/empty"; import { CalendarIcon } from "lucide-react"; import { BookingsListSkeleton } from "../booking-skeleton"; import { useLoadingState } from "@/hooks/use-loading-state"; const ARTIFICIAL_DELAY_MS = 300; export function BookingsEmpty() { const showLoading = useLoadingState(ARTIFICIAL_DELAY_MS); if (showLoading) { return ; } return ( No recurring bookings You have no recurring bookings found. Recurring booking series will appear here. ); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/recurring/loading.tsx ================================================ import { BookingsListSkeleton } from "../booking-skeleton"; export default function Loading() { return ; } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/recurring/page.tsx ================================================ import { BookingsEmpty } from "./bookings-empty"; import { BookingsNav } from "@/components/app/bookings-nav"; import { BookingsView } from "@/components/app/bookings-view"; export default function Page() { return ( <>
{/* */}
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/unconfirmed/bookings-empty.tsx ================================================ "use client"; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@coss/ui/components/empty"; import { CalendarIcon } from "lucide-react"; import { BookingsListSkeleton } from "../booking-skeleton"; import { useLoadingState } from "@/hooks/use-loading-state"; const ARTIFICIAL_DELAY_MS = 400; export function BookingsEmpty() { const showLoading = useLoadingState(ARTIFICIAL_DELAY_MS); if (showLoading) { return ; } return ( No unconfirmed bookings You have no unconfirmed bookings found. Bookings awaiting your confirmation will appear here. ); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/unconfirmed/loading.tsx ================================================ import { BookingsListSkeleton } from "../booking-skeleton"; export default function Loading() { return ; } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/unconfirmed/page.tsx ================================================ import { BookingsEmpty } from "./bookings-empty"; import { BookingsNav } from "@/components/app/bookings-nav"; import { BookingsView } from "@/components/app/bookings-view"; export default function Page() { return ( <>
{/* */}
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/upcoming/bookings-empty.tsx ================================================ "use client"; import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@coss/ui/components/empty"; import { CalendarIcon } from "lucide-react"; import { BookingsListSkeleton } from "../booking-skeleton"; import { useLoadingState } from "@/hooks/use-loading-state"; const ARTIFICIAL_DELAY_MS = 400; export function BookingsEmpty() { const showLoading = useLoadingState(ARTIFICIAL_DELAY_MS); if (showLoading) { return ; } return ( No upcoming bookings You have no upcoming bookings found. As soon as someone books a time with you, it will show up here. ); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/upcoming/loading.tsx ================================================ import { BookingsListSkeleton } from "../booking-skeleton"; export default function Loading() { return ; } ================================================ FILE: apps/examples/calcom/app/(dashboard)/booking/upcoming/page.tsx ================================================ import { BookingsEmpty } from "./bookings-empty"; import { BookingsNav } from "@/components/app/bookings-nav"; import { BookingsView } from "@/components/app/bookings-view"; export default function Page() { return ( <>
{/* */}
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/event-types/add-event-type-dialog.tsx ================================================ "use client"; import { Button } from "@coss/ui/components/button"; import { Dialog, DialogClose, DialogDescription, DialogFooter, DialogHeader, DialogPanel, DialogPopup, DialogTitle, DialogTrigger, } from "@coss/ui/components/dialog"; import { Field, FieldLabel } from "@coss/ui/components/field"; import { Form } from "@coss/ui/components/form"; import { Input } from "@coss/ui/components/input"; import { InputGroup, InputGroupAddon, InputGroupText, InputGroupTextarea, } from "@coss/ui/components/input-group"; import { NumberField, NumberFieldInput, } from "@coss/ui/components/number-field"; import { Toggle } from "@coss/ui/components/toggle"; import { BoldIcon, ItalicIcon } from "lucide-react"; export function AddEventTypeDialog({ children, className, }: { children: React.ReactNode; className?: string; }) { return ( }> {children}
Add a new event type Set up event types to offer different types of meetings. Title URL Description Duration minutes }>Close
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/event-types/event-type-actions.tsx ================================================ "use client"; import { Button } from "@coss/ui/components/button"; import { Group, GroupSeparator } from "@coss/ui/components/group"; import { Menu, MenuCheckboxItem, MenuGroup, MenuItem, MenuPopup, MenuSeparator, MenuTrigger, } from "@coss/ui/components/menu"; import { Skeleton } from "@coss/ui/components/skeleton"; import { Switch } from "@coss/ui/components/switch"; import { Tooltip, TooltipPopup, TooltipTrigger, } from "@coss/ui/components/tooltip"; import { CodeIcon, CopyIcon, EllipsisIcon, EyeIcon, Link2Icon, PencilIcon, Share2Icon, TrashIcon, } from "lucide-react"; interface EventTypeActionsProps { isHidden: boolean; onHiddenChange: (hidden: boolean) => void; tooltipHandle?: Parameters[0]["handle"]; } export function EventTypeActions({ isHidden, onHiddenChange, tooltipHandle, }: EventTypeActionsProps) { return ( <>
onHiddenChange(!checked)} /> } /> {isHidden ? "Show on profile" : "Hide from profile"} "Preview"} render={ } /> "Copy link"} render={ } /> "More options"} render={ } /> } /> Edit Duplicate Embed Delete
} /> Preview Copy link to event Share Edit Duplicate onHiddenChange(!checked)} variant="switch" > Show on profile Delete ); } export function EventTypeActionsSkeleton() { return (
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/event-types/event-types-list.tsx ================================================ "use client"; import { Badge } from "@coss/ui/components/badge"; import { Card, CardPanel } from "@coss/ui/components/card"; import { Skeleton } from "@coss/ui/components/skeleton"; import { toastManager } from "@coss/ui/components/toast"; import { Tooltip, TooltipCreateHandle, TooltipPopup, TooltipProvider, } from "@coss/ui/components/tooltip"; import { ArmchairIcon, BanknoteIcon, ClipboardCheckIcon, ClockIcon, EyeOffIcon, RepeatIcon, ShuffleIcon, UsersIcon, } from "lucide-react"; import { useRef, useState } from "react"; import { EventTypeActions, EventTypeActionsSkeleton, } from "./event-type-actions"; import { ListItem, ListItemBadges, ListItemContent, ListItemDescription, ListItemDragHandle, ListItemHeader, ListItemTitle, ListItemTitleLink, SortableListItem, sortableListClasses, } from "@/components/list-item"; import { SortableItem, type SortableItemRenderProps, SortableList, } from "@/components/sortable"; import { useLoadingState } from "@/hooks/use-loading-state"; import { type EventType, formatDuration, mockEventTypeGroups, mockEventTypes, } from "@/lib/mock-event-types-data"; const tooltipHandle = TooltipCreateHandle(); const defaultProfile = mockEventTypeGroups[0]?.profile ?? { eventTypesLockedByOrg: false, image: null, name: "User", slug: "user", }; function EventTypeSkeletonItem() { return (
); } const ARTIFICIAL_DELAY_MS = 800; interface EventTypeItemContentProps { eventType: EventType; isHidden: boolean; eventPath: string; onHiddenChange: (hidden: boolean) => void; sortableProps?: SortableItemRenderProps; } function EventTypeItemContent({ eventType, isHidden, eventPath, onHiddenChange, sortableProps, isOverlay = false, }: EventTypeItemContentProps & { isOverlay?: boolean }) { const getSchedulingTypeLabel = (et: EventType) => { if (!et.schedulingType) return null; switch (et.schedulingType) { case "ROUND_ROBIN": return "Round Robin"; case "COLLECTIVE": return "Collective"; case "MANAGED": return "Managed"; default: return null; } }; const getEventTypeColors = (et: EventType) => { if (!et.eventTypeColor) return null; return { dark: et.eventTypeColor.darkEventTypeColor, light: et.eventTypeColor.lightEventTypeColor, }; }; const isRecurring = (et: EventType) => et.recurringEvent !== null; const isPaid = (et: EventType) => et.price > 0; const requiresConfirmation = (et: EventType) => et.requiresConfirmation; const hasSeats = (et: EventType) => et.seatsPerTimeSlot !== null && et.seatsPerTimeSlot > 0; return (
{eventType.title} {eventPath}
{eventType.safeDescription && ( {eventType.safeDescription} )}
{formatDuration(eventType.length)} {getSchedulingTypeLabel(eventType) && ( {eventType.schedulingType === "ROUND_ROBIN" ? ( ) : ( )} {getSchedulingTypeLabel(eventType)} )} {isRecurring(eventType) && ( Recurring )} {isPaid(eventType) && ( ${(eventType.price / 100).toFixed(0)} )} {requiresConfirmation(eventType) && ( Requires confirmation )} {hasSeats(eventType) && ( {eventType.seatsPerTimeSlot} seats )} {isHidden && ( Hidden )}
); } export function EventTypesList() { const showLoading = useLoadingState(ARTIFICIAL_DELAY_MS); const [eventTypes, setEventTypes] = useState(mockEventTypes); const [hiddenStates, setHiddenStates] = useState>( Object.fromEntries(mockEventTypes.map((et) => [et.id, et.hidden])), ); const previousOrderRef = useRef(eventTypes); const currentToastIdRef = useRef(null); const handleReorder = (newOrder: EventType[]) => { if (currentToastIdRef.current) { toastManager.close(currentToastIdRef.current); } const previousOrder = previousOrderRef.current; previousOrderRef.current = newOrder; setEventTypes(newOrder); const toastId = toastManager.add({ actionProps: { children: "Undo", onClick: () => { toastManager.close(toastId); currentToastIdRef.current = null; previousOrderRef.current = previousOrder; setEventTypes(previousOrder); }, }, title: "Event type order updated", type: "success", }); currentToastIdRef.current = toastId; }; const handleHiddenToggle = (id: number, hidden: boolean) => { setHiddenStates((prev) => ({ ...prev, [id]: hidden, })); }; const getEventTypePath = (eventType: EventType) => { return `/${defaultProfile.slug}/${eventType.slug}`; }; if (showLoading) { return ( <>
); } return ( ( {}} /> )} > {eventTypes.map((eventType, _index) => { const isHidden = hiddenStates[eventType.id]; const eventPath = getEventTypePath(eventType); return ( {(sortableProps) => ( handleHiddenToggle(eventType.id, hidden) } sortableProps={sortableProps} /> )} ); })}
No more results
{({ payload: Payload }) => ( {Payload !== undefined && } )}
); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/event-types/page.tsx ================================================ import { InputGroup, InputGroupAddon, InputGroupInput, } from "@coss/ui/components/input-group"; import { PlusIcon, SearchIcon } from "lucide-react"; import { AddEventTypeDialog } from "./add-event-type-dialog"; import { EventTypesList } from "./event-types-list"; import { AppHeader, AppHeaderActions, AppHeaderContent, AppHeaderDescription, } from "@/components/app/app-header"; export default function Page() { return ( <> Create events to share for people to book on your calendar. New ); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/layout.tsx ================================================ "use client"; import { AppMobileFooter } from "@/components/app/app-mobile-footer"; import { AppMobileHeader } from "@/components/app/app-mobile-header"; import { AppSidebar } from "@/components/app/app-sidebar"; import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; export default function DashboardLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ================================================ FILE: apps/examples/calcom/app/(dashboard)/page.tsx ================================================ import { redirect } from "next/navigation"; export default function Page() { redirect("/event-types"); } ================================================ FILE: apps/examples/calcom/app/(settings)/settings/layout.tsx ================================================ "use client"; import { SettingsMobileHeader } from "@/components/settings/settings-mobile-header"; import { SettingsSidebar } from "@/components/settings/settings-sidebar"; import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; export default function SettingsLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return (
{children}
); } ================================================ FILE: apps/examples/calcom/app/(settings)/settings/my-account/general/page.tsx ================================================ "use client"; import { Button } from "@coss/ui/components/button"; import { Card, CardFrame, CardFrameDescription, CardFrameFooter, CardFrameHeader, CardFrameTitle, CardPanel, } from "@coss/ui/components/card"; import { Combobox, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxTrigger, ComboboxValue, } from "@coss/ui/components/combobox"; import { Field, FieldDescription, FieldLabel } from "@coss/ui/components/field"; import { Fieldset, FieldsetLegend } from "@coss/ui/components/fieldset"; import { Label } from "@coss/ui/components/label"; import { Select, SelectButton, SelectItem, SelectPopup, SelectTrigger, SelectValue, } from "@coss/ui/components/select"; import { CalendarIcon, SearchIcon } from "lucide-react"; import { useMemo } from "react"; import { SettingsToggle } from "@/components/settings/settings-toggle"; export default function GeneralSettingsPage() { const languageItems = [ { label: "English", value: "en" }, { label: "Spanish", value: "es" }, { label: "French", value: "fr" }, { label: "German", value: "de" }, { label: "Italian", value: "it" }, ]; const timezones = Intl.supportedValuesOf("timeZone"); const formattedTimezones = useMemo(() => { return timezones .map((timezone) => { const formatter = new Intl.DateTimeFormat("en", { timeZone: timezone, timeZoneName: "shortOffset", }); const parts = formatter.formatToParts(new Date()); const offset = parts.find((part) => part.type === "timeZoneName")?.value || ""; const modifiedOffset = offset === "GMT" ? "GMT+0" : offset; const offsetMatch = offset.match(/GMT([+-]?)(\d+)(?::(\d+))?/); const sign = offsetMatch?.[1] === "-" ? -1 : 1; const hours = Number.parseInt(offsetMatch?.[2] || "0", 10); const minutes = Number.parseInt(offsetMatch?.[3] || "0", 10); const totalMinutes = sign * (hours * 60 + minutes); return { label: `(${modifiedOffset}) ${timezone.replace(/_/g, " ")}`, numericOffset: totalMinutes, value: timezone, }; }) .sort((a, b) => a.numericOffset - b.numericOffset); }, [timezones]); const defaultTimezone = formattedTimezones.find((tz) => tz.value === "Europe/Rome") ?? formattedTimezones[0]; const timeFormatItems = [ { label: "12-hour", value: "12" }, { label: "24-hour", value: "24" }, ]; const startOfWeekItems = [ { label: "Sunday", value: "sunday" }, { label: "Monday", value: "monday" }, { label: "Tuesday", value: "tuesday" }, { label: "Wednesday", value: "wednesday" }, { label: "Thursday", value: "thursday" }, { label: "Friday", value: "friday" }, { label: "Saturday", value: "saturday" }, ]; return (
General Manage settings for your language and timezone
Language
}>
} />
No timezones found. {(item) => ( {item.label} )}
Time format This is an internal setting and will not affect how times are displayed on public booking pages for you or anyone booking you. Start of week
); } ================================================ FILE: apps/examples/calcom/app/(settings)/settings/my-account/page.tsx ================================================ import { redirect } from "next/navigation"; export default function Page() { redirect("/settings/my-account/general"); } ================================================ FILE: apps/examples/calcom/app/(settings)/settings/my-account/profile/page.tsx ================================================ "use client"; import { Avatar, AvatarFallback, AvatarImage, } from "@coss/ui/components/avatar"; import { Badge } from "@coss/ui/components/badge"; import { Button } from "@coss/ui/components/button"; import { Card, CardFrame, CardFrameDescription, CardFrameFooter, CardFrameHeader, CardFrameTitle, CardPanel, } from "@coss/ui/components/card"; import { Field, FieldDescription, FieldLabel } from "@coss/ui/components/field"; import { Fieldset, FieldsetLegend } from "@coss/ui/components/fieldset"; import { Input } from "@coss/ui/components/input"; import { InputGroup, InputGroupAddon, InputGroupInput, InputGroupText, InputGroupTextarea, } from "@coss/ui/components/input-group"; import { Label } from "@coss/ui/components/label"; import { Menu, MenuItem, MenuPopup, MenuTrigger, } from "@coss/ui/components/menu"; import { Toggle } from "@coss/ui/components/toggle"; import { Tooltip, TooltipPopup, TooltipTrigger, } from "@coss/ui/components/tooltip"; import { useCopyToClipboard } from "@coss/ui/hooks/use-copy-to-clipboard"; import { BoldIcon, CheckIcon, CopyIcon, EllipsisIcon, ItalicIcon, LinkIcon, PlusIcon, } from "lucide-react"; function EmailInput({ email, isPrimary, isVerified, }: { email: string; isPrimary?: boolean; isVerified?: boolean; }) { return ( {isPrimary && Primary} {!isVerified && Unverified} } > Make primary Resend verification Remove email ); } interface EmailItem { email: string; isPrimary?: boolean; isVerified?: boolean; } const emails: EmailItem[] = [ { email: "pasquale@cal.com", isPrimary: true, isVerified: true }, { email: "test@sfsfd.com", isPrimary: false, isVerified: false }, ]; export default function ProfileSettingsPage() { const { copyToClipboard, isCopied } = useCopyToClipboard(); return (
Profile Manage settings for your Cal.com profile
PV
Username i.cal.com/ copyToClipboard("https://i.cal.com/pasquale") } size="icon-xs" variant="ghost" /> } > {isCopied ? : }

{isCopied ? "Copied!" : "Copy to clipboard"}

Tip: You can add a '+' between usernames (e.g. cal.com/anna+brian) to meet with multiple people
Full name
{emails.map((item) => ( ))}
About
Danger zone Be careful. Account deletion cannot be undone.
); } ================================================ FILE: apps/examples/calcom/app/(settings)/settings/page.tsx ================================================ import { redirect } from "next/navigation"; export default function Page() { redirect("/settings/my-account/general"); } ================================================ FILE: apps/examples/calcom/app/globals.css ================================================ @import "@coss/ui/globals.css"; :root { --sidebar-foreground: color-mix( in srgb, var(--color-neutral-800) 80%, var(--sidebar) ); } .dark { --sidebar-foreground: color-mix( in srgb, var(--color-neutral-200) 80%, var(--sidebar) ); } ================================================ FILE: apps/examples/calcom/app/layout.tsx ================================================ import "./globals.css"; import { AnchoredToastProvider, ToastProvider, } from "@coss/ui/components/toast"; import { fontHeading, fontSans } from "@coss/ui/fonts"; import { ThemeProvider } from "@coss/ui/shared/theme-provider"; import type { Metadata } from "next"; import { AppCommand } from "@/components/app/app-command"; import { DebugProvider } from "@/components/debug-context"; export const metadata: Metadata = { description: "coss.com - the everything but AI company", metadataBase: new URL("https://coss.com"), title: "coss.com", }; export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode; }>) { return ( {children} ); } ================================================ FILE: apps/examples/calcom/components/app/app-command.tsx ================================================ "use client"; import { useAutocompleteFilter } from "@coss/ui/components/autocomplete"; import { Button } from "@coss/ui/components/button"; import { Command, CommandCollection, CommandCreateHandle, CommandDialog, CommandDialogPopup, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandInput, CommandItem, CommandList, CommandPanel, CommandSeparator, CommandShortcut, } from "@coss/ui/components/command"; import { EmptyMedia } from "@coss/ui/components/empty"; import { Input } from "@coss/ui/components/input"; import { Kbd, KbdGroup } from "@coss/ui/components/kbd"; import { ScrollArea } from "@coss/ui/components/scroll-area"; import { Skeleton } from "@coss/ui/components/skeleton"; import { Spinner } from "@coss/ui/components/spinner"; import { ArrowDownIcon, ArrowLeftIcon, ArrowUpIcon, CircleQuestionMarkIcon, CornerDownLeftIcon, SearchIcon, SparklesIcon, } from "lucide-react"; import Link from "next/link"; import * as React from "react"; import { markdownToSafeHTML } from "@/lib/markdown-to-safe-html"; import { MOCK_AI_RESPONSE, MOCK_REFERENCE_LINKS, type ReferenceLink, } from "@/lib/mock-ai-data"; interface Item { value: string; label: string; shortcut?: string; keywords?: string[]; } interface Group { value: string; items: Item[]; } const commandGroups: Group[] = [ { items: [ { keywords: ["wf"], label: "Workflows", shortcut: "w f", value: "workflows", }, ], value: "Workflows", }, { items: [ { keywords: ["et"], label: "Event Types", shortcut: "e t", value: "event-types", }, { label: "15 Min Meeting", value: "15-min-meeting" }, { label: "30 Min Meeting", value: "30-min-meeting" }, { label: "Secret Meeting", value: "secret-meeting" }, ], value: "Event Types", }, { items: [ { keywords: ["as"], label: "App Store", shortcut: "a s", value: "app-store", }, ], value: "Apps", }, { items: [ { keywords: ["ub"], label: "Upcoming", shortcut: "u b", value: "upcoming", }, { keywords: ["rb"], label: "Recurring", shortcut: "r b", value: "recurring", }, { keywords: ["pb"], label: "Past", shortcut: "p b", value: "past" }, { keywords: ["cb"], label: "Canceled", shortcut: "c b", value: "canceled", }, ], value: "Bookings", }, { items: [ { keywords: ["sa"], label: "Availability", shortcut: "s a", value: "availability", }, ], value: "Availability", }, { items: [ { keywords: ["ps"], label: "Profile", shortcut: "p s", value: "profile", }, { keywords: ["ca"], label: "Change Avatar", shortcut: "c a", value: "change-avatar", }, { keywords: ["ct"], label: "Timezone", shortcut: "c t", value: "timezone", }, { keywords: ["bc"], label: "Brand Color", shortcut: "b c", value: "brand-color", }, { keywords: ["ts"], label: "Teams", shortcut: "t s", value: "teams" }, ], value: "Profile", }, { items: [ { keywords: ["cp"], label: "Change Password", shortcut: "c p", value: "change-password", }, { keywords: ["tfa"], label: "Two factor authentication", shortcut: "t f a", value: "two-factor-auth", }, { keywords: ["ui"], label: "User Impersonation", shortcut: "u i", value: "user-impersonation", }, ], value: "Security", }, { items: [ { keywords: ["ul"], label: "Choose a license", shortcut: "u l", value: "choose-license", }, ], value: "Admin", }, { items: [ { keywords: ["wh"], label: "Webhooks", shortcut: "w h", value: "webhooks", }, { keywords: ["api"], label: "API keys", shortcut: "a p i", value: "api-keys", }, ], value: "Developer", }, { items: [ { keywords: ["mb"], label: "Manage billing", shortcut: "m b", value: "manage-billing", }, ], value: "Billing", }, { items: [ { label: "Alby", value: "alby" }, { label: "Amie", value: "amie" }, { label: "Apple Calendar", value: "apple-calendar" }, { label: "Attio", value: "attio" }, { label: "Autocheckin", value: "autocheckin" }, { label: "BAA for HIPAA", value: "baa-hipaa" }, ], value: "Installable Apps", }, ]; interface AIState { mode: boolean; query: string; submittedQuery: string; response: string; referenceLinks: ReferenceLink[]; isGenerating: boolean; error: string | null; } const initialAIState: AIState = { error: null, isGenerating: false, mode: false, query: "", referenceLinks: [], response: "", submittedQuery: "", }; export const commandHandle: ReturnType = CommandCreateHandle(); export function AppCommand(): React.ReactElement { const [open, setOpen] = React.useState(false); const [aiState, setAIState] = React.useState(initialAIState); const [searchQuery, setSearchQuery] = React.useState(""); const aiInputRef = React.useRef(null); const searchInputRef = React.useRef(null); const abortControllerRef = React.useRef(null); const commandResetKeyRef = React.useRef(0); // Cleanup on unmount React.useEffect((): (() => void) => { return (): void => { abortControllerRef.current?.abort(); }; }, []); const resetAIState = React.useCallback(() => { abortControllerRef.current?.abort(); setAIState(initialAIState); }, []); const handleItemClick = React.useCallback(() => { setOpen(false); }, []); const handleBackToSearch = React.useCallback(() => { resetAIState(); setSearchQuery(""); // Force Command remount to reset Autocomplete's internal query state commandResetKeyRef.current += 1; // Focus search input after state updates searchInputRef.current?.focus(); }, [resetAIState]); const handleGenerateAI = React.useCallback( async (queryOverride?: string) => { const query = queryOverride || aiState.query; if (!query.trim()) return; // Abort any ongoing request abortControllerRef.current?.abort(); const controller = new AbortController(); abortControllerRef.current = controller; setAIState((prev) => ({ ...prev, error: null, isGenerating: true, query: "", referenceLinks: [], response: "", submittedQuery: query, })); try { // Simulate AI response - in production, this would call an API await new Promise((resolve, reject) => { const timeout = setTimeout(resolve, 1500); controller.signal.addEventListener("abort", () => { clearTimeout(timeout); reject(new Error("aborted")); }); }); // Don't update state if request was aborted if (controller.signal.aborted) return; setAIState((prev) => ({ ...prev, isGenerating: false, referenceLinks: MOCK_REFERENCE_LINKS, response: MOCK_AI_RESPONSE, })); } catch (error) { // Ignore abort errors - component cleanup handles this if (error instanceof Error && error.message === "aborted") { return; } // Only update if not aborted if (controller.signal.aborted) return; setAIState((prev) => ({ ...prev, error: "Failed to generate response. Please try again.", isGenerating: false, })); } }, [aiState.query], ); const handleAskAI = React.useCallback(() => { const currentQuery = searchQuery; setSearchQuery(""); if (currentQuery.trim()) { // If there's a query, ask AI immediately setAIState((prev) => ({ ...prev, mode: true })); handleGenerateAI(currentQuery); } else { // If no query, just switch to AI mode setAIState((prev) => ({ ...prev, mode: true, query: "" })); aiInputRef.current?.focus(); } }, [searchQuery, handleGenerateAI]); const { contains } = useAutocompleteFilter({ sensitivity: "base" }); const filterItem = React.useCallback( (itemValue: unknown, query: string): boolean => { if (typeof itemValue !== "object" || itemValue === null) { return false; } const item = itemValue as Item; // Search in label if (contains(item.label, query)) { return true; } // Search in value if (contains(item.value, query)) { return true; } // Search in keywords if (item.keywords?.some((keyword) => contains(keyword, query))) { return true; } return false; }, [contains], ); React.useEffect((): (() => void) => { const down = (e: KeyboardEvent): void => { if (e.key === "k" && (e.metaKey || e.ctrlKey)) { if ( (e.target instanceof HTMLElement && e.target.isContentEditable) || e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement || e.target instanceof HTMLSelectElement ) { return; } e.preventDefault(); setOpen((open) => { if (!open) { setSearchQuery(""); } return !open; }); } }; document.addEventListener("keydown", down); return (): void => document.removeEventListener("keydown", down); }, []); React.useEffect((): (() => void) | undefined => { if (!open || !aiState.mode) return; const handleEscape = (e: KeyboardEvent): void => { if (e.key === "Escape") { e.preventDefault(); e.stopPropagation(); handleBackToSearch(); } }; document.addEventListener("keydown", handleEscape, true); return (): void => document.removeEventListener("keydown", handleEscape, true); }, [open, aiState.mode, handleBackToSearch]); React.useEffect(() => { if (aiState.mode && !aiState.isGenerating) { // Focus AI input when switching to AI mode or after response aiInputRef.current?.focus(); } }, [aiState.mode, aiState.isGenerating]); const hasResults = React.useMemo( () => !searchQuery.trim() || commandGroups.some((group) => group.items.some((item) => filterItem(item, searchQuery)), ), [searchQuery, filterItem], ); const handleOpenChange = React.useCallback( (newOpen: boolean) => { setOpen(newOpen); if (!newOpen) { setSearchQuery(""); resetAIState(); } }, [resetAIState], ); return ( {!aiState.mode ? (
): void => setSearchQuery(e.target.value) } onKeyDown={(e: React.KeyboardEvent): void => { if (e.key === "Tab") { e.preventDefault(); handleAskAI(); } if (e.key === "Enter" && !hasResults && searchQuery.trim()) { e.preventDefault(); handleAskAI(); } }} placeholder="Type a command or search..." ref={searchInputRef} value={searchQuery} />
{searchQuery.trim() && (

No results found.

Press Enter to ask AI about:
{" "} {searchQuery}

)}
{(group: Group): React.ReactElement => ( {group.value} {(item: Item): React.ReactElement => ( {item.label} {item.shortcut && ( {item.shortcut} )} )} )}
{hasResults ? ( <>
Navigate
Open
Esc Close
) : (
Esc Close
)}
) : (
): void => setAIState((prev) => ({ ...prev, query: e.target.value })) } onKeyDown={( e: React.KeyboardEvent, ): void => { if (e.key === "Enter" && !aiState.isGenerating) { handleGenerateAI(); } if (e.key === "Escape") { e.preventDefault(); handleBackToSearch(); } }} placeholder="Ask AI anything…" ref={aiInputRef} size="lg" value={aiState.query} />
{!aiState.isGenerating && !aiState.response && !aiState.error && (

Ask AI anything and press Enter to get started.

)} {aiState.error && (
{aiState.error}
)} {aiState.isGenerating && (
)} {aiState.response && !aiState.isGenerating && ( <>
{aiState.referenceLinks.length > 0 && (
{aiState.referenceLinks.map((link, index) => ( ))}
)} )}
{aiState.isGenerating ? (
Generating response…
) : aiState.response ? (
You asked: "{aiState.submittedQuery}"
) : (
Ask AI
)}
)} ); } ================================================ FILE: apps/examples/calcom/components/app/app-header.tsx ================================================ import { cn } from "@coss/ui/lib/utils"; import type * as React from "react"; export function AppHeader({ className, ...props }: React.ComponentProps<"header">): React.ReactElement { return (
); } export function AppHeaderContent({ children, className, title, ...props }: React.ComponentProps<"div"> & { title: string }): React.ReactElement { return (

{title}

{children}
); } export function AppHeaderDescription({ className, ...props }: React.ComponentProps<"p">): React.ReactElement { return (

); } export function AppHeaderActions({ className, ...props }: React.ComponentProps<"div">): React.ReactElement { return (

); } ================================================ FILE: apps/examples/calcom/components/app/app-mobile-footer.tsx ================================================ "use client"; import { Button } from "@coss/ui/components/button"; import { Menu, MenuGroup, MenuItem, MenuPopup, MenuSeparator, MenuTrigger, } from "@coss/ui/components/menu"; import { cn } from "@coss/ui/lib/utils"; import { EllipsisIcon, PlusIcon } from "lucide-react"; import Link from "next/link"; import type * as React from "react"; import { WorkflowBadge } from "@/components/workflows-badge"; import { useScrollHide } from "@/hooks/use-scroll-hide"; import type { NavItem } from "@/lib/navigation-data"; import { navFooterItems, navMainItems } from "@/lib/navigation-data"; const primaryNavItems: NavItem[] = navMainItems.slice(0, 3); const remainingMainItems: NavItem[] = navMainItems.slice(3); export function AppMobileFooter(): React.ReactElement { const isHidden = useScrollHide(); return (
{primaryNavItems.map((item) => ( ))} } > {remainingMainItems.map((item) => ( }> {item.title} {item.title === "Workflows" && } ))} {navFooterItems.map((item) => ( }> {item.title} ))}
); } ================================================ FILE: apps/examples/calcom/components/app/app-mobile-header.tsx ================================================ import type * as React from "react"; import { HeaderActions } from "@/components/header-actions"; import { Logo } from "@/components/logo"; import { MobileHeader } from "@/components/mobile-header"; export function AppMobileHeader(): React.ReactElement { return ( ); } ================================================ FILE: apps/examples/calcom/components/app/app-sidebar.tsx ================================================ "use client"; import type * as React from "react"; import { NavMain } from "@/components/app/nav-main"; import { NavSecondary } from "@/components/app/nav-secondary"; import { DebugPopover } from "@/components/debug-popover"; import { HeaderActions } from "@/components/header-actions"; import { Logo } from "@/components/logo"; import { Sidebar, SidebarContent, SidebarHeader, SidebarMenuButton, } from "@/components/ui/sidebar"; import { navFooterItems, navMainItems } from "@/lib/navigation-data"; export function AppSidebar({ variant, ...props }: React.ComponentProps & { variant?: never; }): React.ReactElement { return (
) => ( )} />
© 2025 Cal.com, Inc. v.5.9.6-h-2701b4d{" - "}
); } ================================================ FILE: apps/examples/calcom/components/app/bookings-filters.tsx ================================================ "use client"; import { Avatar, AvatarFallback, AvatarImage, } from "@coss/ui/components/avatar"; import { Badge } from "@coss/ui/components/badge"; import { Button, buttonVariants } from "@coss/ui/components/button"; import { Combobox, ComboboxEmpty, ComboboxInput, ComboboxItem, ComboboxList, ComboboxPopup, ComboboxTrigger, } from "@coss/ui/components/combobox"; import { Group, GroupSeparator, GroupText } from "@coss/ui/components/group"; import { Menu, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuSeparator, MenuTrigger, } from "@coss/ui/components/menu"; import { Separator } from "@coss/ui/components/separator"; import { cn } from "@coss/ui/lib/utils"; import { ChevronsUpDownIcon, CopyIcon, EllipsisIcon, FunnelIcon, ListFilterIcon, PencilIcon, SearchIcon, TrashIcon, XIcon, } from "lucide-react"; import type * as React from "react"; import { useEffect, useRef, useState } from "react"; import type { Booking } from "@/lib/mock-bookings-data"; import { mockPastBookings, mockUpcomingBookings, } from "@/lib/mock-bookings-data"; function toKebabCase(str: string): string { return str .toLowerCase() .replace(/[^a-z0-9]+/g, "-") .replace(/(^-|-$)/g, ""); } function getUniqueEventTypes( bookings: Booking[], ): { id: string; label: string }[] { const eventTypeMap = new Map(); for (const booking of bookings) { if (booking.eventType) { const id = toKebabCase(booking.eventType.slug); if (!eventTypeMap.has(id)) { eventTypeMap.set(id, { id, label: booking.eventType.title, }); } } } return Array.from(eventTypeMap.values()).sort((a, b) => a.label.localeCompare(b.label), ); } function getUniqueMembers( bookings: Booking[], ): { avatar: string | null; id: string; label: string }[] { const memberMap = new Map< string, { avatar: string | null; id: string; label: string } >(); for (const booking of bookings) { if (booking.user?.name) { const id = toKebabCase(booking.user.name); if (!memberMap.has(id)) { memberMap.set(id, { avatar: booking.user.avatarUrl, id, label: booking.user.name, }); } } } return Array.from(memberMap.values()).sort((a, b) => a.label.localeCompare(b.label), ); } function getUniqueAttendeeNames( bookings: Booking[], ): { id: string; label: string }[] { const attendeeMap = new Map(); for (const booking of bookings) { for (const attendee of booking.attendees) { const id = toKebabCase(attendee.name); if (!attendeeMap.has(id)) { attendeeMap.set(id, { id, label: attendee.name, }); } } } return Array.from(attendeeMap.values()).sort((a, b) => a.label.localeCompare(b.label), ); } function getUniqueAttendeeEmails( bookings: Booking[], ): { id: string; label: string }[] { const emailMap = new Map(); for (const booking of bookings) { for (const attendee of booking.attendees) { const id = toKebabCase(attendee.email.split("@")[0] ?? attendee.email); if (!emailMap.has(attendee.email)) { emailMap.set(attendee.email, { id, label: attendee.email, }); } } } return Array.from(emailMap.values()).sort((a, b) => a.label.localeCompare(b.label), ); } function getUniqueBookingUids( bookings: Booking[], ): { id: string; label: string }[] { return bookings .map((booking) => ({ id: toKebabCase(booking.uid), label: booking.uid, })) .sort((a, b) => a.label.localeCompare(b.label)); } function getInitials(name: string): string { const parts = name.trim().split(/\s+/); if (parts.length === 1) { return parts[0]?.charAt(0).toUpperCase() ?? ""; } const first = parts[0]?.charAt(0) ?? ""; const last = parts[parts.length - 1]?.charAt(0) ?? ""; return (first + last).toUpperCase(); } function CountBadge({ count }: { count: number }): React.ReactElement { return ( +{count} ); } function SelectionDisplay({ children, label, remainingCount, }: { children?: React.ReactNode; label: string; remainingCount: number; }): React.ReactElement { return (
{children} {label} {remainingCount > 0 && }
); } function MemberAvatar({ name, avatarUrl, className, }: { name: string; avatarUrl?: string | null; className?: string; }): React.ReactElement { return ( {avatarUrl ? : null} {getInitials(name)} ); } const allBookings: Booking[] = [...mockPastBookings, ...mockUpcomingBookings]; function useActiveFilters(): { activeFilters: ActiveFilter[]; addFilter: (columnId: string) => void; clearAll: () => void; removeFilter: (columnId: string) => void; updateFilter: (columnId: string, values: string[]) => void; } { const [activeFilters, setActiveFilters] = useState([]); const addFilter = (columnId: string): void => { if (!activeFilters.some((filter) => filter.f === columnId)) { setActiveFilters([...activeFilters, { f: columnId }]); } }; const updateFilter = (columnId: string, values: string[]): void => { setActiveFilters((prev) => { const exists = prev.some((filter) => filter.f === columnId); if (exists) { return prev.map((filter) => filter.f === columnId ? { ...filter, v: values } : filter, ); } return [...prev, { f: columnId, v: values }]; }); }; const removeFilter = (columnId: string): void => { setActiveFilters((prev) => prev.filter((filter) => filter.f !== columnId)); }; const clearAll = (): void => { setActiveFilters([]); }; return { activeFilters, addFilter, clearAll, removeFilter, updateFilter, }; } function FilterMenu({ hasFilters = false, onSelectFilter, activeFilterIds, }: { hasFilters?: boolean; onSelectFilter: (categoryId: string) => void; activeFilterIds: string[]; }): React.ReactElement | null { const availableCategories = filterCategories.filter( (category) => !activeFilterIds.includes(category.id), ); if (availableCategories.length === 0 && hasFilters) { return null; } return ( }> Add Filter Filter by {availableCategories.map((category) => ( onSelectFilter(category.id)} > {category.label} ))} ); } function ActiveFilterComponent({ filter, category, onUpdate, onRemove, autoOpen = false, }: { filter: ActiveFilter; category: FilterCategory; onUpdate: (values: string[]) => void; onRemove: () => void; autoOpen?: boolean; }): React.ReactElement { const [open, setOpen] = useState(autoOpen); const hasAutoOpened = useRef(false); // Snapshot of sorted items when combobox opens (selected first) const [sortedItems, setSortedItems] = useState( category.options, ); useEffect(() => { if (autoOpen && !hasAutoOpened.current) { setOpen(true); hasAutoOpened.current = true; } }, [autoOpen]); const selectedValues = filter.v ?? []; // Get selected options in the order they were selected (based on filter.v order) const selectedOptions = selectedValues .map((id) => category.options.find((opt) => opt.id === id)) .filter((opt): opt is FilterOption => opt !== undefined); const renderTriggerContent = (): string | React.ReactElement => { if (selectedOptions.length === 0) return "Select"; const firstOption = selectedOptions[0]; const remainingCount = selectedOptions.length - 1; // For members, show avatar + name + badge if (category.id === "userIds") { return ( ); } // For other filters, show text + badge if (remainingCount > 0) { return ( ); } return firstOption?.label ?? "Select"; }; const handleValueChange = ( newValue: FilterOption | FilterOption[] | null, ): void => { if (Array.isArray(newValue)) { // Maintain selection order: keep existing selections in order, append new ones const newIds = newValue.map((v) => v.id); const existingIds = selectedValues.filter((id) => newIds.includes(id)); const addedIds = newIds.filter((id) => !selectedValues.includes(id)); onUpdate([...existingIds, ...addedIds]); } else if (newValue) { onUpdate([newValue.id]); } else { onUpdate([]); } }; const handleOpenChange = (isOpen: boolean): void => { setOpen(isOpen); if (isOpen) { // When opening, sort items: selected first, then unselected const selected = category.options.filter((opt) => selectedValues.includes(opt.id), ); const unselected = category.options.filter( (opt) => !selectedValues.includes(opt.id), ); setSortedItems([...selected, ...unselected]); } // Remove filter if combobox closes with no selection if (!isOpen && selectedValues.length === 0) { onRemove(); } }; return ( {category.label} } > {renderTriggerContent()} {selectedOptions.length === 0 && ( )}
} />
No items found. {(option: FilterOption): React.ReactElement => ( {category.id === "userIds" ? (
{option.label}
) : ( option.label )}
)}
); } type SavedFilter = { id: string; isDefault?: boolean; label: string; }; const savedFilters: SavedFilter[] = [ { id: "my-bookings", isDefault: true, label: "My bookings" }, { id: "team-meetings", label: "Team meetings" }, { id: "client-calls", label: "Client calls" }, ]; function SavedFiltersCombobox(): React.ReactElement { const [selectedFilter, setSelectedFilter] = useState( null, ); const handleClearSelection = (): void => { setSelectedFilter(null); }; // When no filter is selected, show just the combobox trigger if (!selectedFilter) { return ( }> Saved Filters
} />
No saved filters. {(filter: SavedFilter): React.ReactElement => ( {filter.label} )}
); } // When a filter is selected, show Group with combobox and X button, plus edit menu outside return (
}> {selectedFilter.label}
} />
No saved filters. {(filter: SavedFilter): React.ReactElement => ( {filter.label} )}
} > {!selectedFilter.isDefault && ( Rename )} Duplicate {!selectedFilter.isDefault && ( <> Delete )}
); } export type FilterOption = { id: string; label: string; avatar?: string | null; }; export type FilterCategory = { id: string; label: string; options: FilterOption[]; }; export type ActiveFilter = { f: string; v?: string[]; }; export const filterCategories: FilterCategory[] = [ { id: "eventTypeId", label: "Event Type", options: getUniqueEventTypes(allBookings), }, { id: "userIds", label: "Member", options: getUniqueMembers(allBookings), }, { id: "attendeesName", label: "Attendees Name", options: getUniqueAttendeeNames(allBookings), }, { id: "attendeeEmail", label: "Attendee Email", options: getUniqueAttendeeEmails(allBookings), }, { id: "dateRange", label: "Date Range", options: [ { id: "today", label: "Today" }, { id: "yesterday", label: "Yesterday" }, { id: "this-week", label: "This Week" }, { id: "last-week", label: "Last Week" }, { id: "this-month", label: "This Month" }, { id: "last-month", label: "Last Month" }, { id: "custom", label: "Custom Range" }, ], }, { id: "bookingUid", label: "Booking UID", options: getUniqueBookingUids(allBookings), }, ]; export function BookingsFilters(): React.ReactElement { const { activeFilters, addFilter, updateFilter, removeFilter, clearAll } = useActiveFilters(); const [newlyAddedFilter, setNewlyAddedFilter] = useState(null); const handleSelectFilter = (categoryId: string): void => { addFilter(categoryId); setNewlyAddedFilter(categoryId); }; const handleUpdateFilter = (columnId: string, values: string[]): void => { updateFilter(columnId, values); }; const handleRemoveFilter = (columnId: string): void => { removeFilter(columnId); if (newlyAddedFilter === columnId) { setNewlyAddedFilter(null); } }; const hasFilters = activeFilters.length > 0; const activeFilterIds = activeFilters.map((f) => f.f); return (
{activeFilters.map((filter) => { const category = filterCategories.find((c) => c.id === filter.f); if (!category) return null; return ( handleRemoveFilter(filter.f)} onUpdate={(values: string[]): void => handleUpdateFilter(filter.f, values) } /> ); })}
{hasFilters && ( <>
)}
); } ================================================ FILE: apps/examples/calcom/components/app/bookings-nav.tsx ================================================ import { ScrollArea } from "@coss/ui/components/scroll-area"; import type * as React from "react"; import type { Tab } from "@/components/app/tabbed-nav"; import { TabbedNav } from "@/components/app/tabbed-nav"; const bookingTabs: Tab[] = [ { title: "Upcoming", url: "/booking/upcoming" }, { title: "Unconfirmed", url: "/booking/unconfirmed" }, { title: "Recurring", url: "/booking/recurring" }, { title: "Past", url: "/booking/past" }, { title: "Canceled", url: "/booking/canceled" }, ]; function BookingsNav(): React.ReactElement { return (
); } export { BookingsNav }; ================================================ FILE: apps/examples/calcom/components/app/bookings-view.tsx ================================================ "use client"; import { CalendarIcon, LayoutListIcon } from "lucide-react"; import { usePathname } from "next/navigation"; import type * as React from "react"; import { TabbedNav } from "@/components/app/tabbed-nav"; function BookingsView(): React.ReactElement { const pathname = usePathname(); const viewTabs = [ { icon: , title: "List view", url: pathname, }, { icon: , title: "Calendar view", url: `${pathname}?view=calendar`, }, ]; return ; } export { BookingsView }; ================================================ FILE: apps/examples/calcom/components/app/nav-main.tsx ================================================ "use client"; import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@coss/ui/components/collapsible"; import { Menu, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuTrigger, } from "@coss/ui/components/menu"; import { useMediaQuery } from "@coss/ui/hooks/use-media-query"; import { ChevronRightIcon, type LucideIcon } from "lucide-react"; import Link from "next/link"; import { usePathname } from "next/navigation"; import type * as React from "react"; import { useEffect, useMemo, useRef, useState } from "react"; import { SidebarGroup, SidebarMenu, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, useSidebarMenuOpen, } from "@/components/ui/sidebar"; import { WorkflowBadge } from "@/components/workflows-badge"; type BaseNavItem = { title: string; url: string; icon: LucideIcon; isActive?: boolean; matchPath?: string; }; type NavSubItem = { title: string; url: string; }; type NavItemWithChildren = BaseNavItem & { items: NavSubItem[] }; type NavItemLeaf = BaseNavItem & { items?: undefined }; type NavItem = NavItemLeaf | NavItemWithChildren; function hasSubItems(item: NavItem): item is NavItemWithChildren { return Array.isArray(item.items) && item.items.length > 0; } function NavItemWithSubmenu({ item, }: { item: NavItemWithChildren; }): React.ReactElement { const isBetweenMdAndLg = useMediaQuery("md:max-lg"); const { registerMenu } = useSidebarMenuOpen(); const unregisterRef = useRef<(() => void) | null>(null); useEffect(() => { return (): void => { if (unregisterRef.current) { unregisterRef.current(); } }; }, []); /* Collapsible version for expanded sidebar */ const pathname = usePathname(); const isActive = useMemo( () => item.items.some((subItem) => pathname.startsWith(subItem.url)), [item.items, pathname], ); const [isExpanded, setIsExpanded] = useState( !!(isActive || item.isActive), ); // Auto-expand when active useEffect(() => { if (isActive) { setIsExpanded(true); } }, [isActive]); return ( {/* Menu version for collapsed sidebar (md-lg breakpoint) */} { if (open) { unregisterRef.current = registerMenu(); } else { if (unregisterRef.current) { unregisterRef.current(); unregisterRef.current = null; } } }} >
} tooltip={isBetweenMdAndLg ? item.title : undefined} >
{item.title} {item.items.map((subItem) => ( } > {subItem.title} ))}
{/* Collapsible version for expanded sidebar */} } > {item.title} {item.items.map((subItem) => ( } > {subItem.title} ))}
); } function NavItemSimple({ item }: { item: NavItemLeaf }): React.ReactElement { const isBetweenMdAndLg = useMediaQuery("md:max-lg"); const pathname = usePathname(); const isActive = pathname.startsWith(item.matchPath ?? item.url); return ( } tooltip={isBetweenMdAndLg ? item.title : undefined} > {item.title} {item.title === "Workflows" && } ); } export function NavMain({ items }: { items: NavItem[] }): React.ReactElement { return ( {items.map((item) => hasSubItems(item) ? ( ) : ( ), )} ); } ================================================ FILE: apps/examples/calcom/components/app/nav-secondary.tsx ================================================ "use client"; import { useMediaQuery } from "@coss/ui/hooks/use-media-query"; import type { LucideIcon } from "lucide-react"; import Link from "next/link"; import type * as React from "react"; import { SidebarGroup, SidebarMenu, SidebarMenuButton, SidebarMenuItem, } from "@/components/ui/sidebar"; export function NavSecondary({ items, ...props }: { items: { title: string; url: string; icon: LucideIcon; }[]; } & React.ComponentPropsWithoutRef): React.ReactElement { const isBetweenMdAndLg = useMediaQuery("md:max-lg"); return ( {items.map((item) => ( } tooltip={isBetweenMdAndLg ? item.title : undefined} > {item.title} ))} ); } ================================================ FILE: apps/examples/calcom/components/app/tabbed-nav.tsx ================================================ "use client"; import { cn } from "@coss/ui/lib/utils"; import Link from "next/link"; import { usePathname, useSearchParams } from "next/navigation"; import type * as React from "react"; type Tab = { icon?: React.ReactNode; title: string; url: string; }; type TabbedNavProps = { ariaLabel?: string; className?: string; dataSlot?: string; tabs: Tab[]; }; function TabbedNav({ ariaLabel, className, dataSlot, tabs, }: TabbedNavProps): React.ReactElement { const pathname = usePathname(); const searchParams = useSearchParams(); const anyTabHasQuery = tabs.some((t) => t.url.includes("?")); const currentView = searchParams.get("view"); return ( ); } export { TabbedNav }; export type { Tab, TabbedNavProps }; ================================================ FILE: apps/examples/calcom/components/copyable-field.tsx ================================================ "use client"; import { Button } from "@coss/ui/components/button"; import { Field, FieldDescription, FieldLabel } from "@coss/ui/components/field"; import { InputGroup, InputGroupAddon, InputGroupInput, } from "@coss/ui/components/input-group"; import { anchoredToastManager, toastManager } from "@coss/ui/components/toast"; import { Tooltip, TooltipPopup, TooltipTrigger, } from "@coss/ui/components/tooltip"; import { useCopyToClipboard } from "@coss/ui/hooks/use-copy-to-clipboard"; import { cn } from "@coss/ui/lib/utils"; import { CheckIcon, ClipboardIcon } from "lucide-react"; import type * as React from "react"; import { useRef } from "react"; const RESET_DELAY = 2000; interface CopyableFieldProps { label: string; value: string; monospace?: boolean; "aria-label"?: string; description?: React.ReactNode; copyTooltip?: string; copiedTooltip?: string; onCopySuccess?: () => void; "data-testid"?: string; } export function CopyableField({ label, value, monospace = false, "aria-label": ariaLabel, description, copyTooltip = "Copy to clipboard", copiedTooltip = "Copied!", onCopySuccess, "data-testid": dataTestId, }: CopyableFieldProps): React.ReactElement { const buttonRef = useRef(null); const { copyToClipboard, isCopied } = useCopyToClipboard({ onCopy: () => { if (buttonRef.current) { anchoredToastManager.add({ data: { tooltipStyle: true }, positionerProps: { anchor: buttonRef.current }, timeout: RESET_DELAY, title: copiedTooltip, type: "success", }); } else { toastManager.add({ title: copiedTooltip, type: "success" }); } onCopySuccess?.(); }, timeout: RESET_DELAY, }); const handleCopy = (): void => { if (isCopied) { return; } copyToClipboard(value); }; return ( {label} } > {isCopied ? ( ) : ( )}

{isCopied ? copiedTooltip : copyTooltip}

{description && {description}}
); } ================================================ FILE: apps/examples/calcom/components/debug-context.tsx ================================================ "use client"; import type * as React from "react"; import type { Context } from "react"; import { createContext, type ReactNode, useContext, useState } from "react"; interface DebugContextValue { enableArtificialDelay: boolean; isLoadingOverride: boolean | null; setEnableArtificialDelay: (value: boolean) => void; setIsLoadingOverride: (value: boolean | null) => void; } const DebugContext: Context = createContext(null); export function DebugProvider({ children, }: { children: ReactNode; }): React.ReactElement { const [isLoadingOverride, setIsLoadingOverride] = useState( null, ); const [enableArtificialDelay, setEnableArtificialDelay] = useState(false); return ( {children} ); } export function useDebug(): DebugContextValue { const context = useContext(DebugContext); if (!context) { throw new Error("useDebug must be used within a DebugProvider"); } return context; } ================================================ FILE: apps/examples/calcom/components/debug-popover.tsx ================================================ "use client"; import { Label } from "@coss/ui/components/label"; import { Popover, PopoverPopup, PopoverTrigger, } from "@coss/ui/components/popover"; import { Switch } from "@coss/ui/components/switch"; import type * as React from "react"; import { useDebug } from "./debug-context"; export function DebugPopover(): React.ReactElement { const { enableArtificialDelay, isLoadingOverride, setEnableArtificialDelay, setIsLoadingOverride, } = useDebug(); return ( Debug
setIsLoadingOverride(checked ? true : null) } />
); } ================================================ FILE: apps/examples/calcom/components/header-actions.tsx ================================================ "use client"; import { Avatar, AvatarFallback, AvatarImage, } from "@coss/ui/components/avatar"; import { CommandDialogTrigger } from "@coss/ui/components/command"; import { SearchIcon } from "lucide-react"; import Link from "next/link"; import type * as React from "react"; import { commandHandle } from "@/components/app/app-command"; import { SidebarMenuButton } from "@/components/ui/sidebar"; import { UserMenu } from "@/components/user-menu"; export function HeaderActions(): React.ReactElement { return (
} > CC } />
); } ================================================ FILE: apps/examples/calcom/components/item-label.tsx ================================================ import { cn } from "@coss/ui/lib/utils"; import type * as React from "react"; import type { CSSProperties } from "react"; interface ItemLabelProps { colorLight?: string; colorDark?: string; className?: string; } export function ItemLabel({ colorLight, colorDark, className, }: ItemLabelProps): React.ReactElement | null { const hasColor = colorLight || colorDark; if (!hasColor) return null; const style = { "--label-color-dark": colorDark || "transparent", "--label-color-light": colorLight || "transparent", } as CSSProperties; return ( \n \n \n \n Click to copy\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "copy" ] } } ================================================ FILE: apps/origin/public/r/comp-106.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-106", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-106.tsx", "content": "import { FlipHorizontalIcon, FlipVerticalIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "toggle group" ] } } ================================================ FILE: apps/origin/public/r/comp-107.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-107", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/toggle-group.json" ], "files": [ { "path": "registry/default/components/comp-107.tsx", "content": "\"use client\";\n\nimport {\n AlignCenterIcon,\n AlignJustifyIcon,\n AlignLeftIcon,\n AlignRightIcon,\n} from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nexport default function Component() {\n const [value, setValue] = useState(\"center\");\n\n return (\n {\n if (value) setValue(value);\n }}\n type=\"single\"\n value={value}\n >\n \n \n \n \n \n \n \n \n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "toggle group" ] } } ================================================ FILE: apps/origin/public/r/comp-108.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-108", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-108.tsx", "content": "import { EllipsisIcon, FilesIcon, FilmIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n Files\n \n \n \n Media\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "toggle group", "dropdown" ] } } ================================================ FILE: apps/origin/public/r/comp-109.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-109", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/toggle-group.json" ], "files": [ { "path": "registry/default/components/comp-109.tsx", "content": "import {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nexport default function Component() {\n return (\n \n Left\n Center\n Right\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "toggle group" ] } } ================================================ FILE: apps/origin/public/r/comp-11.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-11", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-11.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n https://\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-110.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-110", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/toggle-group.json" ], "files": [ { "path": "registry/default/components/comp-110.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport {\n ToggleGroup,\n ToggleGroupItem,\n} from \"@/registry/default/ui/toggle-group\";\n\nexport default function Component() {\n const [value, setValue] = useState(\"left\");\n\n return (\n {\n if (value) setValue(value);\n }}\n type=\"single\"\n value={value}\n variant=\"outline\"\n >\n \n Left\n \n \n Center\n \n \n Right\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "toggle group" ] } } ================================================ FILE: apps/origin/public/r/comp-111.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-111", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-111.tsx", "content": "import { QrCodeIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button" ] } } ================================================ FILE: apps/origin/public/r/comp-112.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-112", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-112.tsx", "content": "import { SquareArrowOutUpRightIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n Preview\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button" ] } } ================================================ FILE: apps/origin/public/r/comp-113.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-113", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-113.tsx", "content": "import { ChevronDownIcon, PinIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "dropdown" ] } } ================================================ FILE: apps/origin/public/r/comp-114.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-114", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-114.tsx", "content": "import { ChevronDownIcon, GitForkIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "dropdown", "counter" ] } } ================================================ FILE: apps/origin/public/r/comp-115.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-115", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-115.tsx", "content": "import { ChevronLeftIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "previous" ] } } ================================================ FILE: apps/origin/public/r/comp-116.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-116", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-116.tsx", "content": "import { ChevronRightIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "next" ] } } ================================================ FILE: apps/origin/public/r/comp-117.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-117", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-117.tsx", "content": "import { ThumbsUpIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "like", "counter" ] } } ================================================ FILE: apps/origin/public/r/comp-118.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-118", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-118.tsx", "content": "import { StarIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "like", "counter" ] } } ================================================ FILE: apps/origin/public/r/comp-119.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-119", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-119.tsx", "content": "import {\n RiFacebookFill,\n RiGithubFill,\n RiGoogleFill,\n RiTwitterXFill,\n} from \"@remixicon/react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "social", "login", "authentication" ] } } ================================================ FILE: apps/origin/public/r/comp-12.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-12", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-12.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n .com\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-120.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-120", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-120.tsx", "content": "import {\n RiFacebookFill,\n RiGithubFill,\n RiGoogleFill,\n RiTwitterXFill,\n} from \"@remixicon/react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "social", "login", "authentication" ] } } ================================================ FILE: apps/origin/public/r/comp-121.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-121", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-121.tsx", "content": "import {\n RiFacebookFill,\n RiGithubFill,\n RiGoogleFill,\n RiTwitterXFill,\n} from \"@remixicon/react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "social", "login", "authentication" ] } } ================================================ FILE: apps/origin/public/r/comp-122.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-122", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-122.tsx", "content": "import {\n RiFacebookFill,\n RiGithubFill,\n RiGoogleFill,\n RiTwitterXFill,\n} from \"@remixicon/react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "social", "login", "authentication" ] } } ================================================ FILE: apps/origin/public/r/comp-123.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-123", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-123.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isExpanded, setIsExpanded] = useState(false);\n\n const toggleExpand = () => {\n setIsExpanded((prevState) => !prevState);\n };\n\n return (\n \n {isExpanded ? \"Show less\" : \"Show more\"}\n {isExpanded ? (\n \n ) : (\n \n )}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "collapsible" ] } } ================================================ FILE: apps/origin/public/r/comp-124.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-124", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-124.tsx", "content": "import { ChevronLeftIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "back" ] } } ================================================ FILE: apps/origin/public/r/comp-125.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-125", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-125.tsx", "content": "\"use client\";\n\nimport { CircleUserRoundIcon } from \"lucide-react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [{ files }, { removeFile, openFileDialog, getInputProps }] =\n useFileUpload({\n accept: \"image/*\",\n });\n\n const previewUrl = files[0]?.preview || null;\n const fileName = files[0]?.file.name || null;\n\n return (\n
\n
\n \n {previewUrl ? (\n \n ) : (\n
\n \n
\n )}\n
\n
\n \n \n
\n
\n {fileName && (\n
\n

\n {fileName}\n

{\" \"}\n removeFile(files[0]?.id)}\n type=\"button\"\n >\n Remove\n \n
\n )}\n \n Basic image uploader ∙{\" \"}\n \n Docs\n \n

\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "style": 2, "tags": [ "button", "upload", "user", "avatar", "profile", "image" ] } } ================================================ FILE: apps/origin/public/r/comp-126.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-126", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-126.tsx", "content": "\"use client\";\n\nimport { CircleUserRoundIcon, XIcon } from \"lucide-react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [{ files }, { removeFile, openFileDialog, getInputProps }] =\n useFileUpload({\n accept: \"image/*\",\n });\n\n const previewUrl = files[0]?.preview || null;\n const fileName = files[0]?.file.name || null;\n\n return (\n
\n
\n \n {previewUrl ? (\n \n ) : (\n
\n \n
\n )}\n \n {previewUrl && (\n removeFile(files[0]?.id)}\n size=\"icon\"\n >\n \n \n )}\n \n
\n {fileName &&

{fileName}

}\n \n Avatar upload button\n

\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "style": 2, "tags": [ "button", "upload", "user", "avatar", "profile", "image" ] } } ================================================ FILE: apps/origin/public/r/comp-127.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-127", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-127.tsx", "content": "import {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n \n
\n \n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button" ] } } ================================================ FILE: apps/origin/public/r/comp-128.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-128", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-128.tsx", "content": "import { ChevronRightIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button" ] } } ================================================ FILE: apps/origin/public/r/comp-129.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-129", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-129.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [count, setCount] = useState(3);\n\n const handleClick = () => {\n setCount(0);\n };\n\n return (\n \n \n {count > 0 && (\n \n {count > 99 ? \"99+\" : count}\n \n )}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "dropdown", "notification" ] } } ================================================ FILE: apps/origin/public/r/comp-13.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-13", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-13.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n €\n \n \n EUR\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-130.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-130", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/toggle.json" ], "files": [ { "path": "registry/default/components/comp-130.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Toggle } from \"@/registry/default/ui/toggle\";\n\nexport default function Component() {\n const [theme, setTheme] = useState(\"light\");\n\n return (\n
\n \n setTheme((prev) => (prev === \"dark\" ? \"light\" : \"dark\"))\n }\n pressed={theme === \"dark\"}\n variant=\"outline\"\n >\n {/* Note: After dark mode implementation, rely on dark: prefix rather than group-data-[state=on]: */}\n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "toggle", "darkmode" ] } } ================================================ FILE: apps/origin/public/r/comp-131.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-131", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-131.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nconst options = [\n {\n description:\n \"All commits from this branch will be added to the base branch via a commit version.\",\n label: \"Merge pull request\",\n },\n {\n description:\n \"The 6 commits from this branch will be combined into one commit in the base branch.\",\n label: \"Squash and merge\",\n },\n {\n description:\n \"The 6 commits from this branch will be rebased and added to the base branch.\",\n label: \"Rebase and merge\",\n },\n];\n\nexport default function Component() {\n const [selectedIndex, setSelectedIndex] = useState(\"0\");\n\n return (\n
\n \n \n \n \n \n \n \n \n \n {options.map((option, index) => (\n span]:pt-1.5\"\n key={option.label}\n value={String(index)}\n >\n
\n {option.label}\n \n {option.description}\n \n
\n \n ))}\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 2, "tags": [ "button", "dropdown" ] } } ================================================ FILE: apps/origin/public/r/comp-132.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-132", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-132.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-133.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-133", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-133.tsx", "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(\n \"indeterminate\",\n );\n\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-134.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-134", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-134.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-135.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-135", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-135.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "disabled", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-136.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-136", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-136.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-137.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-137", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-137.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n Fancy todo item\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-138.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-138", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-138.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "login", "authentication", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-139.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-139", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-139.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-14.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-14", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-14.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n https://\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-140.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-140", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-140.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-141.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-141", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-141.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n

\n You can use this checkbox with a label and a description.\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-142.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-142", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-142.tsx", "content": "\"use client\";\n\nimport { useEffect, useId, useRef, useState } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const checkboxId = useId();\n const inputId = useId();\n const [checked, setChecked] = useState(false);\n const inputRef = useRef(null);\n\n useEffect(() => {\n if (checked === true && inputRef.current) {\n inputRef.current.focus();\n }\n }, [checked]);\n\n return (\n
\n
\n \n
\n
\n \n \n You can use this checkbox with a label and a description.\n

\n
\n {/* Expandable field */}\n \n
\n
\n \n
\n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "collapsible", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-143.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-143", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-143.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n

\n You can use this checkbox with a label and a description.\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-144.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-144", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-144.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n

\n A short description goes here.\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-145.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-145", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-145.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n
\n \n

\n A short description goes here.\n

\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-146.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-146", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-146.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n

\n A short description goes here.\n

\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-147.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-147", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-147.tsx", "content": "import { Brush, Eraser, Scissors, SwatchBook } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { defaultChecked: true, Icon: SwatchBook, label: \"Palette\", value: \"1\" },\n { Icon: Brush, label: \"Brush\", value: \"2\" },\n { Icon: Eraser, label: \"Eraser\", value: \"3\" },\n { Icon: Scissors, label: \"Cut\", value: \"4\" },\n ];\n\n return (\n
\n {items.map((item) => (\n \n
\n \n \n
\n \n
\n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-148.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-148", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/checkbox-tree.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-148.tsx", "content": "\"use client\";\n\nimport { Fragment, useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { CheckboxTree } from \"@/registry/default/ui/checkbox-tree\";\nimport { Label } from \"@/registry/default/ui/label\";\n\ninterface TreeNode {\n id: string;\n label: string;\n defaultChecked?: boolean;\n children?: TreeNode[];\n}\n\nconst initialTree: TreeNode = {\n children: [\n { defaultChecked: true, id: \"2\", label: \"Mountains\" },\n {\n children: [\n { id: \"4\", label: \"Niagara Falls\" },\n { defaultChecked: true, id: \"5\", label: \"Angel Falls\" },\n ],\n id: \"3\",\n label: \"Waterfalls\",\n },\n { id: \"6\", label: \"Grand Canyon\" },\n ],\n id: \"1\",\n label: \"Natural Wonders\",\n};\n\nexport default function Component() {\n const id = useId();\n return (\n
\n (\n \n
\n \n \n
\n {children &&
{children}
}\n
\n )}\n tree={initialTree}\n />\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "tree", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-149.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-149", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json" ], "files": [ { "path": "registry/default/components/comp-149.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { defaultChecked: true, label: \"Monday\", value: \"1\" },\n { defaultChecked: true, label: \"Tuesday\", value: \"2\" },\n { label: \"Wednesday\", value: \"3\" },\n { defaultChecked: true, label: \"Thursday\", value: \"4\" },\n { defaultChecked: true, label: \"Friday\", value: \"5\" },\n { label: \"Saturday\", value: \"6\" },\n { disabled: true, label: \"Sunday\", value: \"7\" },\n ];\n\n return (\n
\n \n Days of the week\n \n
\n {items.map((item) => (\n \n \n \n {item.label[0]}\n \n {item.label}\n \n ))}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "week", "calendar", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-15.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-15", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-15.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n .com\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-150.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-150", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-150.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nexport default function Component() {\n const id = useId();\n const [theme, setTheme] = useState(\"light\");\n\n return (\n
\n \n Dark mode toggle checkbox\n \n
\n \n setTheme((prev) => (prev === \"dark\" ? \"light\" : \"dark\"))\n }\n type=\"checkbox\"\n />\n \n {/* Note: After dark mode implementation, rely on dark: prefix rather than group-peer-checked: */}\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "toggle", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-151.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-151", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-151.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "checkbox", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-152.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-152", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-152.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-153.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-153", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-153.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-154.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-154", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-154.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-155.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-155", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-155.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n
\n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-156.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-156", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-156.tsx", "content": "\"use client\";\n\nimport { useEffect, useId, useRef, useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const radioId = useId();\n const inputId = useId();\n const [selectedValue, setSelectedValue] = useState(\"without-expansion\");\n const inputRef = useRef(null);\n\n useEffect(() => {\n if (selectedValue === \"with-expansion\" && inputRef.current) {\n inputRef.current.focus();\n }\n }, [selectedValue]);\n\n return (\n \n
\n
\n \n
\n
\n \n \n You can use this radio with a label and a description.\n

\n
\n {/* Expandable field */}\n \n
\n
\n \n
\n
\n
\n
\n
\n \n\n
\n \n
\n \n \n You can use this checkbox with a label and a description.\n

\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "collapsible", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-157.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-157", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-157.tsx", "content": "import { RiStarFill } from \"@remixicon/react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "rating", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-158.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-158", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-158.tsx", "content": "import { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n return (\n
\n \n Choose a color\n \n \n \n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "color", "picker", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-159.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-159", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-159.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n {/* Radio card #1 */}\n
\n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n {/* Radio card #2 */}\n
\n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-16.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-16", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-16.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n €\n \n \n \n EUR\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-160.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-160", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-160.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n {/* Radio card #1 */}\n
\n \n
\n \n \n \n \n \n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n {/* Radio card #2 */}\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-161.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-161", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-161.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n {/* Radio card #1 */}\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n {/* Radio card #2 */}\n
\n \n
\n \n \n \n \n
\n \n \n You can use this card with a label and a description.\n

\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-162.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-162", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-162.tsx", "content": "import { Brush, Eraser, Scissors, SwatchBook } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { Icon: SwatchBook, label: \"Palette\", value: \"1\" },\n { Icon: Brush, label: \"Brush\", value: \"2\" },\n { Icon: Eraser, label: \"Eraser\", value: \"3\" },\n { Icon: Scissors, label: \"Cut\", value: \"4\" },\n ];\n\n return (\n \n {items.map((item) => (\n \n
\n \n \n
\n \n \n ))}\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-163.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-163", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-163.tsx", "content": "import { RiAppleLine, RiBankCardLine, RiPaypalLine } from \"@remixicon/react\";\nimport { useId } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n {/* Credit card */}\n
\n \n \n \n Card\n \n
\n {/* PayPal */}\n
\n \n \n \n PayPal\n \n
\n {/* Apple Pay */}\n
\n \n \n \n Apple Pay\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "checkout", "payment", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-164.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-164", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-164.tsx", "content": "import { useId } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { label: \"2 CPU\", value: \"1\" },\n { label: \"4 CPU\", value: \"2\" },\n { label: \"6 CPU\", value: \"3\" },\n { label: \"8 CPU\", value: \"4\" },\n { label: \"12 CPU\", value: \"5\" },\n { disabled: true, label: \"16 CPU\", value: \"6\" },\n ];\n\n return (\n
\n \n CPU Cores\n \n \n {items.map((item) => (\n \n \n

\n {item.label}\n

\n \n ))}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "pricing", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-165.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-165", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-165.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { label: \"USA\", value: \"1\" },\n { label: \"UK\", value: \"2\" },\n { label: \"France\", value: \"3\" },\n ];\n\n return (\n
\n \n Server location\n \n \n {items.map((item) => (\n \n
\n \n \n
\n \n ))}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-166.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-166", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-166.tsx", "content": "import { useId } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { label: \"Hobby\", price: \"$9/mo\", value: \"1\" },\n { label: \"Plus\", price: \"$29/mo\", value: \"2\" },\n { label: \"Team\", price: \"$49/mo\", value: \"3\" },\n { label: \"Enterprise\", price: \"Custom\", value: \"4\" },\n ];\n\n return (\n
\n \n Choose plan\n \n \n {items.map((item) => (\n \n
\n
\n \n \n {item.label}\n {item.value === \"2\" && (\n Popular\n )}\n \n
\n \n {item.price}\n
\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "pricing", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-167.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-167", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-167.tsx", "content": "import { useId } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n\n const items = [\n { icon: \"😠\", label: \"Angry\", value: \"1\" },\n { icon: \"🙁\", label: \"Sad\", value: \"2\" },\n { icon: \"😐\", label: \"Neutral\", value: \"3\" },\n { icon: \"🙂\", label: \"Happy\", value: \"4\" },\n { icon: \"😀\", label: \"Laughing\", value: \"5\" },\n ];\n\n return (\n
\n \n How did it go?\n \n \n {items.map((item) => (\n \n \n {item.icon}\n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "rating", "vote", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-168.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-168", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-168.tsx", "content": "import { useId } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n <>\n
\n \n How likely are you to recommend us?\n \n \n {[\"0\", \"1\", \"2\", \"3\", \"4\", \"5\"].map((value) => (\n \n \n {value}\n \n ))}\n \n
\n
\n

\n 😡 Not likely\n

\n

\n Very Likely 😍\n

\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "rating", "vote", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-169.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-169", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-169.tsx", "content": "import { CheckIcon, MinusIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nconst items = [\n { image: \"/origin/ui-light.png\", label: \"Light\", value: \"1\" },\n { image: \"/origin/ui-dark.png\", label: \"Dark\", value: \"2\" },\n { image: \"/origin/ui-system.png\", label: \"System\", value: \"3\" },\n];\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Choose a theme\n \n \n {items.map((item) => (\n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "radio", "label", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-17.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-17", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/select-native.json" ], "files": [ { "path": "registry/default/components/comp-17.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-170.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-170", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-170.tsx", "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n const [selectedValue, setSelectedValue] = useState(\"on\");\n\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "radio", "label", "pricing", "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-171.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-171", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-171.tsx", "content": "\"use client\";\n\nimport { RiStarFill } from \"@remixicon/react\";\nimport { useId, useState } from \"react\";\n\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n const [hoverRating, setHoverRating] = useState(\"\");\n const [currentRating, setCurrentRating] = useState(\"\");\n\n return (\n
\n \n Rate your experience\n \n \n {[\"1\", \"2\", \"3\", \"4\", \"5\"].map((value) => (\n setHoverRating(value)}\n onMouseLeave={() => setHoverRating(\"\")}\n >\n \n = value\n ? \"text-amber-500\"\n : \"text-input\"\n } group-hover:scale-110`}\n size={24}\n />\n \n {value} star{value === \"1\" ? \"\" : \"s\"}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "radio", "label", "rating", "vote", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-172.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-172", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-172.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-173.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-173", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-173.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-174.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-174", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-174.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-175.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-175", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-175.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-176.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-176", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-176.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-177.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-177", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-177.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-178.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-178", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-178.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-179.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-179", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-179.tsx", "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(true);\n\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-18.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-18", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/select-native.json" ], "files": [ { "path": "registry/default/components/comp-18.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-180.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-180", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json" ], "files": [ { "path": "registry/default/components/comp-180.tsx", "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\n\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(false);\n\n const toggleSwitch = () => setChecked((prev) => !prev);\n\n return (\n \n setChecked(false)}\n >\n Off\n \n \n setChecked(true)}\n >\n On\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-181.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-181", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-181.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(true);\n\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-182.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-182", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json" ], "files": [ { "path": "registry/default/components/comp-182.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(false);\n\n const toggleSwitch = () => setChecked((prev) => !prev);\n\n return (\n \n setChecked(false)}\n >\n \n \n \n setChecked(true)}\n >\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-183.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-183", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-183.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(true);\n\n return (\n
\n
\n \n \n \n \n \n \n \n
\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-184.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-184", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-184.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(true);\n\n return (\n
\n
\n \n \n \n \n \n \n \n
\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-185.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-185", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-185.tsx", "content": "\"use client\";\n\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n const [checked, setChecked] = useState(true);\n\n return (\n
\n
\n \n \n Off\n \n \n On\n \n
\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-186.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-186", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-186.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n

\n A short description goes here.\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-187.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-187", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-187.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n
\n \n

\n A short description goes here.\n

\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-188.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-188", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/switch.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-188.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Switch } from \"@/registry/default/ui/switch\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n \n

\n A short description goes here.\n

\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "switch", "label", "card", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-189.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-189", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-189.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-19.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-19", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-19.tsx", "content": "import { SendIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-190.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-190", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-190.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-191.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-191", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-191.tsx", "content": "import { ClockIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n
\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select", "time" ] } } ================================================ FILE: apps/origin/public/r/comp-192.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-192", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-192.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n \n Tell us what‘s your favorite Select framework\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-193.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-193", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-193.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-194.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-194", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-194.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n \n Selected option is invalid\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select", "error" ] } } ================================================ FILE: apps/origin/public/r/comp-195.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-195", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-195.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-196.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-196", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-196.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select", "disabled" ] } } ================================================ FILE: apps/origin/public/r/comp-197.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-197", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-197.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-198.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-198", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-198.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-199.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-199", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-199.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-20.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-20", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-20.tsx", "content": "import { DownloadIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-200.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-200", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-200.tsx", "content": "import { useId, useMemo } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n\n const timezones = Intl.supportedValuesOf(\"timeZone\");\n\n const formattedTimezones = useMemo(() => {\n return timezones\n .map((timezone) => {\n const formatter = new Intl.DateTimeFormat(\"en\", {\n timeZone: timezone,\n timeZoneName: \"shortOffset\",\n });\n const parts = formatter.formatToParts(new Date());\n const offset =\n parts.find((part) => part.type === \"timeZoneName\")?.value || \"\";\n const modifiedOffset = offset === \"GMT\" ? \"GMT+0\" : offset;\n\n return {\n label: `(${modifiedOffset}) ${timezone.replace(/_/g, \" \")}`,\n numericOffset: Number.parseInt(\n offset.replace(\"GMT\", \"\").replace(\"+\", \"\") || \"0\",\n 10,\n ),\n value: timezone,\n };\n })\n .sort((a, b) => a.numericOffset - b.numericOffset);\n }, [timezones]);\n\n return (\n
\n \n \n {formattedTimezones.map(({ value, label }) => (\n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select", "timezone", "time" ] } } ================================================ FILE: apps/origin/public/r/comp-201.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-201", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json" ], "files": [ { "path": "registry/default/components/comp-201.tsx", "content": "import { useId } from \"react\";\n\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Select with overlapping label (native)\n \n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-202.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-202", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select-native.json" ], "files": [ { "path": "registry/default/components/comp-202.tsx", "content": "import { useId } from \"react\";\n\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Select with inset label (native)\n \n \n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-203.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-203", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-203.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-204.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-204", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-204.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-205.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-205", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-205.tsx", "content": "import { ClockIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-206.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-206", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-206.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n Tell us what‘s your favorite Select framework\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "helper", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-207.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-207", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-207.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-208.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-208", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-208.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n Selected option is invalid\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-209.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-209", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-209.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-21.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-21", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-21.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n Send\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-210.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-210", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-210.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "disabled", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-211.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-211", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-211.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "required", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-212.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-212", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-212.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-213.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-213", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-213.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-214.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-214", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-214.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectSeparator,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-215.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-215", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-215.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "disabled", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-216.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-216", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-216.tsx", "content": "import { useId } from \"react\";\n\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Select with overlapping label\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-217.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-217", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-217.tsx", "content": "import { useId } from \"react\";\n\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Select with inset label\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-218.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-218", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-218.tsx", "content": "import { useId, useMemo } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n\n const timezones = Intl.supportedValuesOf(\"timeZone\");\n\n const formattedTimezones = useMemo(() => {\n return timezones\n .map((timezone) => {\n const formatter = new Intl.DateTimeFormat(\"en\", {\n timeZone: timezone,\n timeZoneName: \"shortOffset\",\n });\n const parts = formatter.formatToParts(new Date());\n const offset =\n parts.find((part) => part.type === \"timeZoneName\")?.value || \"\";\n const modifiedOffset = offset === \"GMT\" ? \"GMT+0\" : offset;\n\n return {\n label: `(${modifiedOffset}) ${timezone.replace(/_/g, \" \")}`,\n numericOffset: Number.parseInt(\n offset.replace(\"GMT\", \"\").replace(\"+\", \"\") || \"0\",\n 10,\n ),\n value: timezone,\n };\n })\n .sort((a, b) => a.numericOffset - b.numericOffset);\n }, [timezones]);\n\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "timezone", "time", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-219.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-219", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-219.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-22.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-22", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-22.tsx", "content": "import { useId } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-220.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-220", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-220.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nfunction StatusDot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "status", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-221.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-221", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-221.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-222.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-222", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-222.tsx", "content": "import { RiGatsbyLine, RiNextjsLine, RiReactjsLine } from \"@remixicon/react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-223.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-223", "type": "registry:component", "dependencies": [ "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-223.tsx", "content": "import { RiGatsbyLine, RiNextjsLine, RiReactjsLine } from \"@remixicon/react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-224.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-224", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-224.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-225.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-225", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-225.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nconst countries = [\n {\n continent: \"America\",\n items: [\n { flag: \"🇺🇸\", label: \"United States\", value: \"1\" },\n { flag: \"🇨🇦\", label: \"Canada\", value: \"2\" },\n { flag: \"🇲🇽\", label: \"Mexico\", value: \"3\" },\n ],\n },\n {\n continent: \"Africa\",\n items: [\n { flag: \"🇿🇦\", label: \"South Africa\", value: \"4\" },\n { flag: \"🇳🇬\", label: \"Nigeria\", value: \"5\" },\n { flag: \"🇲🇦\", label: \"Morocco\", value: \"6\" },\n ],\n },\n {\n continent: \"Asia\",\n items: [\n { flag: \"🇨🇳\", label: \"China\", value: \"7\" },\n { flag: \"🇯🇵\", label: \"Japan\", value: \"8\" },\n { flag: \"🇮🇳\", label: \"India\", value: \"9\" },\n ],\n },\n {\n continent: \"Europe\",\n items: [\n { flag: \"🇬🇧\", label: \"United Kingdom\", value: \"10\" },\n { flag: \"🇫🇷\", label: \"France\", value: \"11\" },\n { flag: \"🇩🇪\", label: \"Germany\", value: \"12\" },\n ],\n },\n {\n continent: \"Oceania\",\n items: [\n { flag: \"🇦🇺\", label: \"Australia\", value: \"13\" },\n { flag: \"🇳🇿\", label: \"New Zealand\", value: \"14\" },\n ],\n },\n];\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "flag", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-226.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-226", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-226.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "user", "avatar", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-227.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-227", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-227.tsx", "content": "import { useId } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nconst Square = ({\n className,\n children,\n}: {\n className?: string;\n children: React.ReactNode;\n}) => (\n \n {children}\n \n);\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "user", "avatar", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-228.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-228", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-228.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "user", "avatar", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-229.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-229", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/command.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-229.tsx", "content": "\"use client\";\n\nimport { CheckIcon, ChevronDownIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@/registry/default/ui/command\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst frameworks = [\n {\n label: \"Next.js\",\n value: \"next.js\",\n },\n {\n label: \"SvelteKit\",\n value: \"sveltekit\",\n },\n {\n label: \"Nuxt.js\",\n value: \"nuxt.js\",\n },\n {\n label: \"Remix\",\n value: \"remix\",\n },\n {\n label: \"Astro\",\n value: \"astro\",\n },\n {\n label: \"Angular\",\n value: \"angular\",\n },\n {\n label: \"Vue.js\",\n value: \"vue\",\n },\n {\n label: \"React\",\n value: \"react\",\n },\n {\n label: \"Ember.js\",\n value: \"ember\",\n },\n {\n label: \"Gatsby\",\n value: \"gatsby\",\n },\n {\n label: \"Eleventy\",\n value: \"eleventy\",\n },\n {\n label: \"SolidJS\",\n value: \"solid\",\n },\n {\n label: \"Preact\",\n value: \"preact\",\n },\n {\n label: \"Qwik\",\n value: \"qwik\",\n },\n {\n label: \"Alpine.js\",\n value: \"alpine\",\n },\n {\n label: \"Lit\",\n value: \"lit\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [open, setOpen] = useState(false);\n const [value, setValue] = useState(\"\");\n\n return (\n
\n \n \n \n \n \n {value\n ? frameworks.find((framework) => framework.value === value)\n ?.label\n : \"Select framework\"}\n \n \n \n \n \n \n \n \n No framework found.\n \n {frameworks.map((framework) => (\n {\n setValue(currentValue === value ? \"\" : currentValue);\n setOpen(false);\n }}\n value={framework.value}\n >\n {framework.label}\n {value === framework.value && (\n \n )}\n \n ))}\n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "command", "combobox", "popover", "search", "autocomplete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-23.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-23", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-23.tsx", "content": "\"use client\";\n\nimport { EyeIcon, EyeOffIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [isVisible, setIsVisible] = useState(false);\n\n const toggleVisibility = () => setIsVisible((prevState) => !prevState);\n\n return (\n
\n \n
\n \n \n {isVisible ? (\n \n ) : (\n \n )}\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button", "password" ] } } ================================================ FILE: apps/origin/public/r/comp-230.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-230", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/command.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-230.tsx", "content": "\"use client\";\n\nimport { CheckIcon, ChevronDownIcon, PlusIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n} from \"@/registry/default/ui/command\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst organizations = [\n {\n label: \"coss.com\",\n value: \"coss\",\n },\n {\n label: \"Cruip\",\n value: \"cruip\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [open, setOpen] = useState(false);\n const [value, setValue] = useState(\"coss\");\n\n return (\n
\n \n \n \n \n \n {value\n ? organizations.find(\n (organization) => organization.value === value,\n )?.label\n : \"Select organization\"}\n \n \n \n \n \n \n \n \n No organization found.\n \n {organizations.map((organization) => (\n {\n setValue(currentValue === value ? \"\" : currentValue);\n setOpen(false);\n }}\n value={organization.value}\n >\n {organization.label}\n {value === organization.value && (\n \n )}\n \n ))}\n \n \n \n \n \n New organization\n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "command", "combobox", "popover", "search", "autocomplete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-231.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-231", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/command.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-231.tsx", "content": "\"use client\";\n\nimport { CheckIcon, ChevronDownIcon } from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@/registry/default/ui/command\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nexport default function Component() {\n const id = useId();\n const [open, setOpen] = useState(false);\n const [value, setValue] = useState(\"Europe/London\");\n\n const timezones = Intl.supportedValuesOf(\"timeZone\");\n\n const formattedTimezones = useMemo(() => {\n return timezones\n .map((timezone) => {\n const formatter = new Intl.DateTimeFormat(\"en\", {\n timeZone: timezone,\n timeZoneName: \"shortOffset\",\n });\n const parts = formatter.formatToParts(new Date());\n const offset =\n parts.find((part) => part.type === \"timeZoneName\")?.value || \"\";\n const modifiedOffset = offset === \"GMT\" ? \"GMT+0\" : offset;\n\n return {\n label: `(${modifiedOffset}) ${timezone.replace(/_/g, \" \")}`,\n numericOffset: Number.parseInt(\n offset.replace(\"GMT\", \"\").replace(\"+\", \"\") || \"0\",\n 10,\n ),\n value: timezone,\n };\n })\n .sort((a, b) => a.numericOffset - b.numericOffset);\n }, [timezones]);\n\n return (\n
\n \n \n \n \n \n {value\n ? formattedTimezones.find(\n (timezone) => timezone.value === value,\n )?.label\n : \"Select timezone\"}\n \n \n \n \n \n {\n const normalizedValue = value.toLowerCase();\n const normalizedSearch = search.toLowerCase().replace(/\\s+/g, \"\");\n return normalizedValue.includes(normalizedSearch) ? 1 : 0;\n }}\n >\n \n \n No timezone found.\n \n {formattedTimezones.map(({ value: itemValue, label }) => (\n {\n setValue(currentValue === value ? \"\" : currentValue);\n setOpen(false);\n }}\n value={itemValue}\n >\n {label}\n {value === itemValue && (\n \n )}\n \n ))}\n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "command", "combobox", "popover", "search", "autocomplete", "timezone", "time", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-232.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-232", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/command.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-232.tsx", "content": "\"use client\";\n\nimport { CheckIcon, ChevronDownIcon } from \"lucide-react\";\nimport { Fragment, useId, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@/registry/default/ui/command\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst countries = [\n {\n continent: \"America\",\n items: [\n { flag: \"🇺🇸\", value: \"United States\" },\n { flag: \"🇨🇦\", value: \"Canada\" },\n { flag: \"🇲🇽\", value: \"Mexico\" },\n ],\n },\n {\n continent: \"Africa\",\n items: [\n { flag: \"🇿🇦\", value: \"South Africa\" },\n { flag: \"🇳🇬\", value: \"Nigeria\" },\n { flag: \"🇲🇦\", value: \"Morocco\" },\n ],\n },\n {\n continent: \"Asia\",\n items: [\n { flag: \"🇨🇳\", value: \"China\" },\n { flag: \"🇯🇵\", value: \"Japan\" },\n { flag: \"🇮🇳\", value: \"India\" },\n ],\n },\n {\n continent: \"Europe\",\n items: [\n { flag: \"🇬🇧\", value: \"United Kingdom\" },\n { flag: \"🇫🇷\", value: \"France\" },\n { flag: \"🇩🇪\", value: \"Germany\" },\n ],\n },\n {\n continent: \"Oceania\",\n items: [\n { flag: \"🇦🇺\", value: \"Australia\" },\n { flag: \"🇳🇿\", value: \"New Zealand\" },\n ],\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [open, setOpen] = useState(false);\n const [value, setValue] = useState(\"\");\n\n return (\n
\n \n \n \n \n {value ? (\n \n \n {\n countries\n .map((group) =>\n group.items.find((item) => item.value === value),\n )\n .filter(Boolean)[0]?.flag\n }\n \n {value}\n \n ) : (\n Select country\n )}\n \n \n \n \n \n \n \n No country found.\n {countries.map((group) => (\n \n \n {group.items.map((country) => (\n {\n setValue(currentValue);\n setOpen(false);\n }}\n value={country.value}\n >\n \n {country.flag}\n {\" \"}\n {country.value}\n {value === country.value && (\n \n )}\n \n ))}\n \n \n ))}\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "command", "combobox", "popover", "search", "autocomplete", "flag", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-233.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-233", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/command.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-233.tsx", "content": "\"use client\";\n\nimport {\n BlocksIcon,\n BrainIcon,\n ChevronDownIcon,\n CpuIcon,\n DatabaseIcon,\n GlobeIcon,\n LayoutIcon,\n LineChartIcon,\n NetworkIcon,\n SearchIcon,\n ServerIcon,\n} from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Command,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n} from \"@/registry/default/ui/command\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst items = [\n {\n icon: LineChartIcon,\n label: \"Analytics Platform\",\n number: 2451,\n value: \"analytics platform\",\n },\n {\n icon: BrainIcon,\n label: \"AI Services\",\n number: 1832,\n value: \"ai services\",\n },\n {\n icon: DatabaseIcon,\n label: \"Database Systems\",\n number: 1654,\n value: \"database systems\",\n },\n {\n icon: CpuIcon,\n label: \"Compute Resources\",\n number: 943,\n value: \"compute resources\",\n },\n {\n icon: NetworkIcon,\n label: \"Network Services\",\n number: 832,\n value: \"network services\",\n },\n {\n icon: GlobeIcon,\n label: \"Web Services\",\n number: 654,\n value: \"web services\",\n },\n {\n icon: SearchIcon,\n label: \"Monitoring Tools\",\n number: 432,\n value: \"monitoring tools\",\n },\n {\n icon: ServerIcon,\n label: \"Server Management\",\n number: 321,\n value: \"server management\",\n },\n {\n icon: BlocksIcon,\n label: \"Infrastructure\",\n number: 234,\n value: \"infrastructure\",\n },\n {\n icon: LayoutIcon,\n label: \"Frontend Services\",\n number: 123,\n value: \"frontend services\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [open, setOpen] = useState(false);\n const [value, setValue] = useState(\"\");\n\n return (\n
\n \n \n \n \n {value ? (\n \n {(() => {\n const selectedItem = items.find(\n (item) => item.value === value,\n );\n if (selectedItem) {\n const Icon = selectedItem.icon;\n return ;\n }\n return null;\n })()}\n \n {items.find((item) => item.value === value)?.label}\n \n \n ) : (\n \n Select service category\n \n )}\n \n \n \n \n \n \n \n No service found.\n \n {items.map((item) => (\n {\n setValue(currentValue === value ? \"\" : currentValue);\n setOpen(false);\n }}\n value={item.value}\n >\n
\n \n {item.label}\n
\n \n {item.number.toLocaleString()}\n \n \n ))}\n
\n
\n
\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "command", "combobox", "popover", "search", "autocomplete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-234.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-234", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/multiselect.json" ], "files": [ { "path": "registry/default/components/comp-234.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport MultipleSelector, {\n type Option,\n} from \"@/registry/default/ui/multiselect\";\n\nconst frameworks: Option[] = [\n {\n label: \"Next.js\",\n value: \"next.js\",\n },\n {\n label: \"SvelteKit\",\n value: \"sveltekit\",\n },\n {\n disable: true,\n label: \"Nuxt.js\",\n value: \"nuxt.js\",\n },\n {\n label: \"Remix\",\n value: \"remix\",\n },\n {\n label: \"Astro\",\n value: \"astro\",\n },\n {\n label: \"Angular\",\n value: \"angular\",\n },\n {\n label: \"Vue.js\",\n value: \"vue\",\n },\n {\n label: \"React\",\n value: \"react\",\n },\n {\n label: \"Ember.js\",\n value: \"ember\",\n },\n {\n label: \"Gatsby\",\n value: \"gatsby\",\n },\n {\n disable: true,\n label: \"Eleventy\",\n value: \"eleventy\",\n },\n {\n label: \"SolidJS\",\n value: \"solid\",\n },\n {\n label: \"Preact\",\n value: \"preact\",\n },\n {\n label: \"Qwik\",\n value: \"qwik\",\n },\n {\n label: \"Alpine.js\",\n value: \"alpine\",\n },\n {\n label: \"Lit\",\n value: \"lit\",\n },\n];\n\nexport default function Component() {\n const _id = useId();\n return (\n
\n \n No results found

}\n hideClearAllButton\n hidePlaceholderWhenSelected\n placeholder=\"Select frameworks\"\n value={frameworks.slice(0, 2)}\n />\n \n Inspired by{\" \"}\n \n shadcn/ui expansions\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "multiselect", "tag", "input", "search", "autocomplete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-235.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-235", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/multiselect.json" ], "files": [ { "path": "registry/default/components/comp-235.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport MultipleSelector, {\n type Option,\n} from \"@/registry/default/ui/multiselect\";\n\nconst frameworks: Option[] = [\n {\n label: \"Next.js\",\n value: \"next.js\",\n },\n {\n label: \"SvelteKit\",\n value: \"sveltekit\",\n },\n {\n label: \"Nuxt.js\",\n value: \"nuxt.js\",\n },\n {\n label: \"Remix\",\n value: \"remix\",\n },\n {\n label: \"Astro\",\n value: \"astro\",\n },\n {\n label: \"Angular\",\n value: \"angular\",\n },\n {\n label: \"Vue.js\",\n value: \"vue\",\n },\n {\n label: \"React\",\n value: \"react\",\n },\n {\n label: \"Ember.js\",\n value: \"ember\",\n },\n {\n label: \"Gatsby\",\n value: \"gatsby\",\n },\n {\n label: \"Eleventy\",\n value: \"eleventy\",\n },\n {\n label: \"SolidJS\",\n value: \"solid\",\n },\n {\n label: \"Preact\",\n value: \"preact\",\n },\n {\n label: \"Qwik\",\n value: \"qwik\",\n },\n {\n label: \"Alpine.js\",\n value: \"alpine\",\n },\n {\n label: \"Lit\",\n value: \"lit\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n No results found

}\n placeholder=\"Select frameworks\"\n />\n \n Inspired by{\" \"}\n \n shadcn/ui expansions\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "multiselect", "tag", "input", "search", "autocomplete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-236.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-236", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/select-native.json" ], "files": [ { "path": "registry/default/components/comp-236.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { SelectNative } from \"@/registry/default/ui/select-native\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "multiselect", "native select" ] } } ================================================ FILE: apps/origin/public/r/comp-237.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-237", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-237.tsx", "content": "\"use client\";\n\nimport { ListBox, ListBoxItem } from \"react-aria-components\";\n\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n \n React\n \n \n Vue\n \n \n Angular\n \n \n Svelte\n \n \n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "multiselect", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-238.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-238", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-238.tsx", "content": "\"use client\";\n\nimport { ListBox, ListBoxItem } from \"react-aria-components\";\n\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n \n React\n \n \n Vue\n \n \n Angular\n \n \n Svelte\n \n \n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "multiselect", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-239.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-239", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-239.tsx", "content": "\"use client\";\n\nimport {\n Header,\n ListBox,\n ListBoxItem,\n ListBoxSection,\n Separator,\n} from \"react-aria-components\";\n\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n \n
\n Veggies\n
\n \n Lettuce\n \n \n Tomato\n \n \n Onion\n \n
\n \n \n
\n Protein\n
\n \n Ham\n \n \n Tuna\n \n \n Tofu\n \n
\n \n \n
\n Condiments\n
\n \n Mayonaise\n \n \n Mustard\n \n \n Ranch\n \n
\n \n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "label", "select", "multiselect", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-24.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-24", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-24.tsx", "content": "\"use client\";\n\nimport { CircleXIcon } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [inputValue, setInputValue] = useState(\"Click to clear\");\n const inputRef = useRef(null);\n\n const handleClearInput = () => {\n setInputValue(\"\");\n if (inputRef.current) {\n inputRef.current.focus();\n }\n };\n\n return (\n
\n \n
\n setInputValue(e.target.value)}\n placeholder=\"Type something...\"\n ref={inputRef}\n type=\"text\"\n value={inputValue}\n />\n {inputValue && (\n \n \n \n )}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-240.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-240", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-240.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-241.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-241", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-241.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "disabled", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-242.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-242", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-242.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n :last-child>span]:rounded\"\n defaultValue={[25]}\n max={100}\n step={10}\n />\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-243.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-243", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-243.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n :first-child>span]:opacity-70 [&>:last-child>span]:bg-primary\"\n defaultValue={[25]}\n />\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-244.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-244", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-244.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n :last-child>span]:h-6 [&>:last-child>span]:w-2.5 [&>:last-child>span]:border-[3px] [&>:last-child>span]:border-background [&>:last-child>span]:bg-primary [&>:last-child>span]:ring-offset-0\"\n defaultValue={[25]}\n />\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-245.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-245", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-245.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n \n 5 GB\n 20 GB\n 35 GB\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-246.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-246", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-246.tsx", "content": "import { cn } from \"@/registry/default/lib/utils\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const max = 12;\n const skipInterval = 2; // Set to 1 to allow no text skipping\n const ticks = [...Array(max + 1)].map((_, i) => i);\n\n return (\n
\n \n
\n \n \n {ticks.map((_, i) => (\n \n \n \n {i}\n \n \n ))}\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-247.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-247", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-247.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const [value, setValue] = useState([25]);\n\n return (\n
\n
\n \n {value[0]}\n
\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-248.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-248", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-248.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n Low\n High\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-249.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-249", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-249.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n Low\n High\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-25.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-25", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-25.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n
\n \n ⌘K\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "search", "kbd" ] } } ================================================ FILE: apps/origin/public/r/comp-250.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-250", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-250.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "range slider", "label", "range", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-251.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-251", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-251.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const [value, setValue] = useState([25, 75]);\n\n return (\n
\n
\n \n \n {value[0]} - {value[1]}\n \n
\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "range slider", "label", "range", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-252.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-252", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-252.tsx", "content": "\"use client\";\n\nimport { Volume2Icon, VolumeXIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const [value, setValue] = useState([25]);\n\n return (\n
\n
\n \n {value[0]}\n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "volume", "controls", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-253.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-253", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-253.tsx", "content": "\"use client\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n `${value}%`}\n />\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "range slider", "label", "range", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-254.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-254", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-254.tsx", "content": "\"use client\";\n\nimport { RotateCcwIcon } from \"lucide-react\";\n\nimport { useSliderWithInput } from \"@/registry/default/hooks/use-slider-with-input\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n const minValue = 0;\n const maxValue = 2;\n const initialValue = [1.25];\n const defaultValue = [1];\n\n const {\n sliderValue,\n inputValues,\n validateAndUpdateValue,\n handleInputChange,\n handleSliderChange,\n resetToDefault,\n showReset,\n } = useSliderWithInput({ defaultValue, initialValue, maxValue, minValue });\n\n return (\n
\n
\n \n
\n \n \n \n \n \n \n \n \n Reset to default\n \n \n \n validateAndUpdateValue(inputValues[0] ?? \"\", 0)}\n onChange={(e) => handleInputChange(e, 0)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[0] ?? \"\", 0);\n }\n }}\n type=\"text\"\n value={inputValues[0]}\n />\n
\n
\n
\n \n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-slider-with-input.ts", "content": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\ntype UseSliderWithInputProps = {\n minValue?: number;\n maxValue?: number;\n initialValue?: number[];\n defaultValue?: number[];\n};\n\nexport function useSliderWithInput({\n minValue = 0,\n maxValue = 100,\n initialValue = [minValue],\n defaultValue = [minValue],\n}: UseSliderWithInputProps) {\n const [sliderValue, setSliderValue] = useState(initialValue);\n const [inputValues, setInputValues] = useState(\n initialValue.map((v) => v.toString()),\n );\n\n const showReset =\n sliderValue.length === defaultValue.length &&\n !sliderValue.every((value, index) => value === defaultValue[index]);\n\n const validateAndUpdateValue = useCallback(\n (rawValue: string, index: number) => {\n if (rawValue === \"\" || rawValue === \"-\") {\n const newInputValues = [...inputValues];\n newInputValues[index] = \"0\";\n setInputValues(newInputValues);\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = 0;\n setSliderValue(newSliderValues);\n return;\n }\n\n const numValue = Number.parseFloat(rawValue);\n\n if (Number.isNaN(numValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = sliderValue[index]?.toString();\n setInputValues(newInputValues);\n return;\n }\n\n let clampedValue = Math.min(maxValue, Math.max(minValue, numValue));\n\n if (sliderValue.length > 1) {\n if (index === 0) {\n clampedValue = Math.min(clampedValue, sliderValue[1]);\n } else {\n clampedValue = Math.max(clampedValue, sliderValue[0]);\n }\n }\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = clampedValue;\n setSliderValue(newSliderValues);\n\n const newInputValues = [...inputValues];\n newInputValues[index] = clampedValue.toString();\n setInputValues(newInputValues);\n },\n [sliderValue, inputValues, minValue, maxValue],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent, index: number) => {\n const newValue = e.target.value;\n if (newValue === \"\" || /^-?\\d*\\.?\\d*$/.test(newValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = newValue;\n setInputValues(newInputValues);\n }\n },\n [inputValues],\n );\n\n const handleSliderChange = useCallback((newValue: number[]) => {\n setSliderValue(newValue);\n setInputValues(newValue.map((v) => v.toString()));\n }, []);\n\n const resetToDefault = useCallback(() => {\n setSliderValue(defaultValue);\n setInputValues(defaultValue.map((v) => v.toString()));\n }, [defaultValue]);\n\n return {\n handleInputChange,\n handleSliderChange,\n inputValues,\n resetToDefault,\n showReset,\n sliderValue,\n validateAndUpdateValue,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "slider", "label", "button", "input", "tooltip", "reset", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-255.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-255", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-255.tsx", "content": "\"use client\";\n\nimport { useSliderWithInput } from \"@/registry/default/hooks/use-slider-with-input\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const minValue = 0;\n const maxValue = 100;\n const initialValue = [25];\n\n const {\n sliderValue,\n inputValues,\n validateAndUpdateValue,\n handleInputChange,\n handleSliderChange,\n } = useSliderWithInput({ initialValue, maxValue, minValue });\n\n return (\n
\n \n
\n \n validateAndUpdateValue(inputValues[0], 0)}\n onChange={(e) => handleInputChange(e, 0)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[0], 0);\n }\n }}\n type=\"text\"\n value={inputValues[0]}\n />\n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-slider-with-input.ts", "content": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\ntype UseSliderWithInputProps = {\n minValue?: number;\n maxValue?: number;\n initialValue?: number[];\n defaultValue?: number[];\n};\n\nexport function useSliderWithInput({\n minValue = 0,\n maxValue = 100,\n initialValue = [minValue],\n defaultValue = [minValue],\n}: UseSliderWithInputProps) {\n const [sliderValue, setSliderValue] = useState(initialValue);\n const [inputValues, setInputValues] = useState(\n initialValue.map((v) => v.toString()),\n );\n\n const showReset =\n sliderValue.length === defaultValue.length &&\n !sliderValue.every((value, index) => value === defaultValue[index]);\n\n const validateAndUpdateValue = useCallback(\n (rawValue: string, index: number) => {\n if (rawValue === \"\" || rawValue === \"-\") {\n const newInputValues = [...inputValues];\n newInputValues[index] = \"0\";\n setInputValues(newInputValues);\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = 0;\n setSliderValue(newSliderValues);\n return;\n }\n\n const numValue = Number.parseFloat(rawValue);\n\n if (Number.isNaN(numValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = sliderValue[index]?.toString();\n setInputValues(newInputValues);\n return;\n }\n\n let clampedValue = Math.min(maxValue, Math.max(minValue, numValue));\n\n if (sliderValue.length > 1) {\n if (index === 0) {\n clampedValue = Math.min(clampedValue, sliderValue[1]);\n } else {\n clampedValue = Math.max(clampedValue, sliderValue[0]);\n }\n }\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = clampedValue;\n setSliderValue(newSliderValues);\n\n const newInputValues = [...inputValues];\n newInputValues[index] = clampedValue.toString();\n setInputValues(newInputValues);\n },\n [sliderValue, inputValues, minValue, maxValue],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent, index: number) => {\n const newValue = e.target.value;\n if (newValue === \"\" || /^-?\\d*\\.?\\d*$/.test(newValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = newValue;\n setInputValues(newInputValues);\n }\n },\n [inputValues],\n );\n\n const handleSliderChange = useCallback((newValue: number[]) => {\n setSliderValue(newValue);\n setInputValues(newValue.map((v) => v.toString()));\n }, []);\n\n const resetToDefault = useCallback(() => {\n setSliderValue(defaultValue);\n setInputValues(defaultValue.map((v) => v.toString()));\n }, [defaultValue]);\n\n return {\n handleInputChange,\n handleSliderChange,\n inputValues,\n resetToDefault,\n showReset,\n sliderValue,\n validateAndUpdateValue,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "slider", "label", "input", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-256.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-256", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-256.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const [value, setValue] = useState([3]);\n\n const labels = [\"Awful\", \"Poor\", \"Okay\", \"Good\", \"Amazing\"];\n\n return (\n
\n
\n \n {labels[value[0] - 1]}\n
\n
\n 😡\n \n 😍\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "vote", "rating", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-257.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-257", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-257.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const [value, setValue] = useState([3]);\n\n const emojis = [\"😡\", \"🙁\", \"😐\", \"🙂\", \"😍\"];\n const labels = [\"Awful\", \"Poor\", \"Okay\", \"Good\", \"Amazing\"];\n\n return (\n
\n \n
\n labels[value - 1]}\n value={value}\n />\n {emojis[value[0] - 1]}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "vote", "rating", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-258.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-258", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-258.tsx", "content": "\"use client\";\n\nimport { useSliderWithInput } from \"@/registry/default/hooks/use-slider-with-input\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const minValue = 0;\n const maxValue = 200;\n const initialValue = [50, 150];\n\n const {\n sliderValue,\n inputValues,\n validateAndUpdateValue,\n handleInputChange,\n handleSliderChange,\n } = useSliderWithInput({ initialValue, maxValue, minValue });\n\n return (\n
\n \n
\n validateAndUpdateValue(inputValues[0], 0)}\n onChange={(e) => handleInputChange(e, 0)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[0], 0);\n }\n }}\n type=\"text\"\n value={inputValues[0]}\n />\n \n validateAndUpdateValue(inputValues[1], 1)}\n onChange={(e) => handleInputChange(e, 1)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[1], 1);\n }\n }}\n type=\"text\"\n value={inputValues[1]}\n />\n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-slider-with-input.ts", "content": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\ntype UseSliderWithInputProps = {\n minValue?: number;\n maxValue?: number;\n initialValue?: number[];\n defaultValue?: number[];\n};\n\nexport function useSliderWithInput({\n minValue = 0,\n maxValue = 100,\n initialValue = [minValue],\n defaultValue = [minValue],\n}: UseSliderWithInputProps) {\n const [sliderValue, setSliderValue] = useState(initialValue);\n const [inputValues, setInputValues] = useState(\n initialValue.map((v) => v.toString()),\n );\n\n const showReset =\n sliderValue.length === defaultValue.length &&\n !sliderValue.every((value, index) => value === defaultValue[index]);\n\n const validateAndUpdateValue = useCallback(\n (rawValue: string, index: number) => {\n if (rawValue === \"\" || rawValue === \"-\") {\n const newInputValues = [...inputValues];\n newInputValues[index] = \"0\";\n setInputValues(newInputValues);\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = 0;\n setSliderValue(newSliderValues);\n return;\n }\n\n const numValue = Number.parseFloat(rawValue);\n\n if (Number.isNaN(numValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = sliderValue[index]?.toString();\n setInputValues(newInputValues);\n return;\n }\n\n let clampedValue = Math.min(maxValue, Math.max(minValue, numValue));\n\n if (sliderValue.length > 1) {\n if (index === 0) {\n clampedValue = Math.min(clampedValue, sliderValue[1]);\n } else {\n clampedValue = Math.max(clampedValue, sliderValue[0]);\n }\n }\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = clampedValue;\n setSliderValue(newSliderValues);\n\n const newInputValues = [...inputValues];\n newInputValues[index] = clampedValue.toString();\n setInputValues(newInputValues);\n },\n [sliderValue, inputValues, minValue, maxValue],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent, index: number) => {\n const newValue = e.target.value;\n if (newValue === \"\" || /^-?\\d*\\.?\\d*$/.test(newValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = newValue;\n setInputValues(newInputValues);\n }\n },\n [inputValues],\n );\n\n const handleSliderChange = useCallback((newValue: number[]) => {\n setSliderValue(newValue);\n setInputValues(newValue.map((v) => v.toString()));\n }, []);\n\n const resetToDefault = useCallback(() => {\n setSliderValue(defaultValue);\n setInputValues(defaultValue.map((v) => v.toString()));\n }, [defaultValue]);\n\n return {\n handleInputChange,\n handleSliderChange,\n inputValues,\n resetToDefault,\n showReset,\n sliderValue,\n validateAndUpdateValue,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "slider", "range slider", "label", "input", "range", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-259.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-259", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-259.tsx", "content": "\"use client\";\n\nimport { MinusIcon, PlusIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const minValue = 0;\n const maxValue = 200;\n const steps = 5;\n const [value, setValue] = useState([100]);\n\n const decreaseValue = () =>\n setValue((prev) => [Math.max(minValue, prev[0] - steps)]);\n const increaseValue = () =>\n setValue((prev) => [Math.min(maxValue, prev[0] + steps)]);\n\n return (\n
\n \n
\n
\n \n \n \n
\n \n
\n \n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "button", "pricing", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-26.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-26", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-26.tsx", "content": "import { ArrowRightIcon, SearchIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n
\n \n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button", "search" ] } } ================================================ FILE: apps/origin/public/r/comp-260.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-260", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-260.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const min_price = 5;\n const max_price = 1240;\n const [value, setValue] = useState([min_price, max_price]);\n\n const formatPrice = (price: number) => {\n return price === max_price\n ? `$${price.toLocaleString()}+`\n : `$${price.toLocaleString()}`;\n };\n\n return (\n
\n \n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "range slider", "label", "button", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-261.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-261", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-261.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "vertical slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-262.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-262", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-262.tsx", "content": "\"use client\";\n\nimport { useSliderWithInput } from \"@/registry/default/hooks/use-slider-with-input\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const minValue = 0;\n const maxValue = 100;\n const initialValue = [25];\n\n const {\n sliderValue,\n inputValues,\n validateAndUpdateValue,\n handleInputChange,\n handleSliderChange,\n } = useSliderWithInput({ initialValue, maxValue, minValue });\n\n return (\n
\n \n
\n \n validateAndUpdateValue(inputValues[0], 0)}\n onChange={(e) => handleInputChange(e, 0)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[0], 0);\n }\n }}\n type=\"text\"\n value={inputValues[0]}\n />\n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-slider-with-input.ts", "content": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\ntype UseSliderWithInputProps = {\n minValue?: number;\n maxValue?: number;\n initialValue?: number[];\n defaultValue?: number[];\n};\n\nexport function useSliderWithInput({\n minValue = 0,\n maxValue = 100,\n initialValue = [minValue],\n defaultValue = [minValue],\n}: UseSliderWithInputProps) {\n const [sliderValue, setSliderValue] = useState(initialValue);\n const [inputValues, setInputValues] = useState(\n initialValue.map((v) => v.toString()),\n );\n\n const showReset =\n sliderValue.length === defaultValue.length &&\n !sliderValue.every((value, index) => value === defaultValue[index]);\n\n const validateAndUpdateValue = useCallback(\n (rawValue: string, index: number) => {\n if (rawValue === \"\" || rawValue === \"-\") {\n const newInputValues = [...inputValues];\n newInputValues[index] = \"0\";\n setInputValues(newInputValues);\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = 0;\n setSliderValue(newSliderValues);\n return;\n }\n\n const numValue = Number.parseFloat(rawValue);\n\n if (Number.isNaN(numValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = sliderValue[index]?.toString();\n setInputValues(newInputValues);\n return;\n }\n\n let clampedValue = Math.min(maxValue, Math.max(minValue, numValue));\n\n if (sliderValue.length > 1) {\n if (index === 0) {\n clampedValue = Math.min(clampedValue, sliderValue[1]);\n } else {\n clampedValue = Math.max(clampedValue, sliderValue[0]);\n }\n }\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = clampedValue;\n setSliderValue(newSliderValues);\n\n const newInputValues = [...inputValues];\n newInputValues[index] = clampedValue.toString();\n setInputValues(newInputValues);\n },\n [sliderValue, inputValues, minValue, maxValue],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent, index: number) => {\n const newValue = e.target.value;\n if (newValue === \"\" || /^-?\\d*\\.?\\d*$/.test(newValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = newValue;\n setInputValues(newInputValues);\n }\n },\n [inputValues],\n );\n\n const handleSliderChange = useCallback((newValue: number[]) => {\n setSliderValue(newValue);\n setInputValues(newValue.map((v) => v.toString()));\n }, []);\n\n const resetToDefault = useCallback(() => {\n setSliderValue(defaultValue);\n setInputValues(defaultValue.map((v) => v.toString()));\n }, [defaultValue]);\n\n return {\n handleInputChange,\n handleSliderChange,\n inputValues,\n resetToDefault,\n showReset,\n sliderValue,\n validateAndUpdateValue,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "slider", "vertical slider", "label", "input", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-263.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-263", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-263.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n \n
\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "vertical slider", "range slider", "label", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-264.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-264", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-264.tsx", "content": "\"use client\";\n\nimport { RotateCcwIcon } from \"lucide-react\";\nimport React, { useRef } from \"react\";\n\nimport { useSliderWithInput } from \"@/registry/default/hooks/use-slider-with-input\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n // Create refs to store reset functions\n const resetFunctionsRef = useRef<(() => void)[]>([]);\n\n // Function to reset all sliders to default\n const resetAll = () => {\n for (const resetFn of resetFunctionsRef.current) {\n resetFn();\n }\n };\n\n // Function to register reset functions\n const registerResetFunction = (resetFn: () => void, index: number) => {\n resetFunctionsRef.current[index] = resetFn;\n };\n\n return (\n
\n \n Object position\n \n
\n registerResetFunction(resetFn, 0)}\n />\n registerResetFunction(resetFn, 1)}\n />\n registerResetFunction(resetFn, 2)}\n />\n
\n \n
\n );\n}\n\nfunction SliderWithInput({\n minValue,\n maxValue,\n initialValue,\n defaultValue,\n label,\n onRegisterReset,\n}: {\n minValue: number;\n maxValue: number;\n initialValue: number[];\n defaultValue: number[];\n label: string;\n onRegisterReset: (resetFn: () => void) => void;\n}) {\n const {\n sliderValue,\n inputValues,\n validateAndUpdateValue,\n handleInputChange,\n handleSliderChange,\n resetToDefault,\n } = useSliderWithInput({ defaultValue, initialValue, maxValue, minValue });\n\n // Register the reset function when the component mounts\n React.useEffect(() => {\n onRegisterReset(resetToDefault);\n }, [onRegisterReset, resetToDefault]);\n\n return (\n
\n \n :last-child>span]:rounded\"\n max={maxValue}\n min={minValue}\n onValueChange={handleSliderChange}\n value={sliderValue}\n />\n validateAndUpdateValue(inputValues[0], 0)}\n onChange={(e) => handleInputChange(e, 0)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[0], 0);\n }\n }}\n type=\"text\"\n value={inputValues[0]}\n />\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-slider-with-input.ts", "content": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\ntype UseSliderWithInputProps = {\n minValue?: number;\n maxValue?: number;\n initialValue?: number[];\n defaultValue?: number[];\n};\n\nexport function useSliderWithInput({\n minValue = 0,\n maxValue = 100,\n initialValue = [minValue],\n defaultValue = [minValue],\n}: UseSliderWithInputProps) {\n const [sliderValue, setSliderValue] = useState(initialValue);\n const [inputValues, setInputValues] = useState(\n initialValue.map((v) => v.toString()),\n );\n\n const showReset =\n sliderValue.length === defaultValue.length &&\n !sliderValue.every((value, index) => value === defaultValue[index]);\n\n const validateAndUpdateValue = useCallback(\n (rawValue: string, index: number) => {\n if (rawValue === \"\" || rawValue === \"-\") {\n const newInputValues = [...inputValues];\n newInputValues[index] = \"0\";\n setInputValues(newInputValues);\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = 0;\n setSliderValue(newSliderValues);\n return;\n }\n\n const numValue = Number.parseFloat(rawValue);\n\n if (Number.isNaN(numValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = sliderValue[index]?.toString();\n setInputValues(newInputValues);\n return;\n }\n\n let clampedValue = Math.min(maxValue, Math.max(minValue, numValue));\n\n if (sliderValue.length > 1) {\n if (index === 0) {\n clampedValue = Math.min(clampedValue, sliderValue[1]);\n } else {\n clampedValue = Math.max(clampedValue, sliderValue[0]);\n }\n }\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = clampedValue;\n setSliderValue(newSliderValues);\n\n const newInputValues = [...inputValues];\n newInputValues[index] = clampedValue.toString();\n setInputValues(newInputValues);\n },\n [sliderValue, inputValues, minValue, maxValue],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent, index: number) => {\n const newValue = e.target.value;\n if (newValue === \"\" || /^-?\\d*\\.?\\d*$/.test(newValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = newValue;\n setInputValues(newInputValues);\n }\n },\n [inputValues],\n );\n\n const handleSliderChange = useCallback((newValue: number[]) => {\n setSliderValue(newValue);\n setInputValues(newValue.map((v) => v.toString()));\n }, []);\n\n const resetToDefault = useCallback(() => {\n setSliderValue(defaultValue);\n setInputValues(defaultValue.map((v) => v.toString()));\n }, [defaultValue]);\n\n return {\n handleInputChange,\n handleSliderChange,\n inputValues,\n resetToDefault,\n showReset,\n sliderValue,\n validateAndUpdateValue,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "slider", "label", "input", "button", "reset", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-265.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-265", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-265.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\n\nimport { useSliderWithInput } from \"@/registry/default/hooks/use-slider-with-input\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nconst items = [\n { id: 1, price: 80 },\n { id: 2, price: 95 },\n { id: 3, price: 110 },\n { id: 4, price: 125 },\n { id: 5, price: 130 },\n { id: 6, price: 140 },\n { id: 7, price: 145 },\n { id: 8, price: 150 },\n { id: 9, price: 155 },\n { id: 10, price: 165 },\n { id: 11, price: 175 },\n { id: 12, price: 185 },\n { id: 13, price: 195 },\n { id: 14, price: 205 },\n { id: 15, price: 215 },\n { id: 16, price: 225 },\n { id: 17, price: 235 },\n { id: 18, price: 245 },\n { id: 19, price: 255 },\n { id: 20, price: 260 },\n { id: 21, price: 265 },\n { id: 22, price: 270 },\n { id: 23, price: 275 },\n { id: 24, price: 280 },\n { id: 25, price: 285 },\n { id: 26, price: 290 },\n { id: 27, price: 290 },\n { id: 28, price: 295 },\n { id: 29, price: 295 },\n { id: 30, price: 295 },\n { id: 31, price: 298 },\n { id: 32, price: 299 },\n { id: 33, price: 300 },\n { id: 34, price: 305 },\n { id: 35, price: 310 },\n { id: 36, price: 315 },\n { id: 37, price: 320 },\n { id: 38, price: 325 },\n { id: 39, price: 330 },\n { id: 40, price: 335 },\n { id: 41, price: 340 },\n { id: 42, price: 345 },\n { id: 43, price: 350 },\n { id: 44, price: 355 },\n { id: 45, price: 360 },\n { id: 46, price: 365 },\n { id: 47, price: 365 },\n { id: 48, price: 375 },\n { id: 49, price: 380 },\n { id: 50, price: 385 },\n { id: 51, price: 390 },\n { id: 52, price: 395 },\n { id: 53, price: 400 },\n { id: 54, price: 405 },\n { id: 55, price: 410 },\n { id: 56, price: 415 },\n { id: 57, price: 420 },\n { id: 58, price: 425 },\n { id: 59, price: 430 },\n { id: 60, price: 435 },\n { id: 61, price: 440 },\n { id: 62, price: 445 },\n { id: 63, price: 450 },\n { id: 64, price: 455 },\n { id: 65, price: 460 },\n { id: 66, price: 465 },\n { id: 67, price: 470 },\n { id: 68, price: 475 },\n { id: 69, price: 480 },\n { id: 70, price: 485 },\n { id: 71, price: 490 },\n { id: 72, price: 495 },\n { id: 73, price: 495 },\n { id: 74, price: 498 },\n { id: 75, price: 499 },\n { id: 76, price: 500 },\n { id: 77, price: 500 },\n { id: 78, price: 500 },\n { id: 79, price: 515 },\n { id: 80, price: 530 },\n { id: 81, price: 545 },\n { id: 82, price: 560 },\n { id: 83, price: 575 },\n { id: 84, price: 590 },\n { id: 85, price: 605 },\n { id: 86, price: 620 },\n { id: 87, price: 635 },\n { id: 88, price: 650 },\n { id: 89, price: 655 },\n { id: 90, price: 660 },\n { id: 91, price: 665 },\n { id: 92, price: 670 },\n { id: 93, price: 675 },\n { id: 94, price: 680 },\n { id: 95, price: 685 },\n { id: 96, price: 690 },\n { id: 97, price: 695 },\n { id: 98, price: 700 },\n { id: 99, price: 700 },\n { id: 100, price: 700 },\n { id: 101, price: 700 },\n { id: 102, price: 700 },\n { id: 103, price: 700 },\n { id: 104, price: 725 },\n { id: 105, price: 750 },\n { id: 106, price: 775 },\n { id: 107, price: 800 },\n { id: 108, price: 815 },\n { id: 109, price: 830 },\n { id: 110, price: 845 },\n { id: 111, price: 845 },\n { id: 112, price: 845 },\n { id: 113, price: 870 },\n { id: 114, price: 875 },\n { id: 115, price: 880 },\n { id: 116, price: 885 },\n { id: 117, price: 890 },\n { id: 118, price: 895 },\n { id: 119, price: 898 },\n { id: 120, price: 900 },\n];\n\nexport default function Component() {\n const id = useId();\n\n // Define the number of ticks\n const tick_count = 40;\n // Find the min and max values across all items\n const minValue = Math.min(...items.map((item) => item.price));\n const maxValue = Math.max(...items.map((item) => item.price));\n\n const {\n sliderValue,\n inputValues,\n validateAndUpdateValue,\n handleInputChange,\n handleSliderChange,\n } = useSliderWithInput({ initialValue: [200, 780], maxValue, minValue }); // set initialValue: [minValue, maxValue] to show all items by default\n\n // Calculate the price step based on the min and max prices\n const priceStep = (maxValue - minValue) / tick_count;\n\n // Calculate item counts for each price range\n const itemCounts = Array(tick_count)\n .fill(0)\n .map((_, tick) => {\n const rangeMin = minValue + tick * priceStep;\n const rangeMax = minValue + (tick + 1) * priceStep;\n return items.filter(\n (item) => item.price >= rangeMin && item.price < rangeMax,\n ).length;\n });\n\n // Find maximum count for scaling\n const maxCount = Math.max(...itemCounts);\n\n const handleSliderValueChange = (values: number[]) => {\n handleSliderChange(values);\n };\n\n // Function to count items in the selected range\n const countItemsInRange = (min: number, max: number) => {\n return items.filter((item) => item.price >= min && item.price <= max)\n .length;\n };\n\n const isBarInSelectedRange = (\n index: number,\n minValue: number,\n priceStep: number,\n sliderValue: number[],\n ) => {\n const rangeMin = minValue + index * priceStep;\n const rangeMax = minValue + (index + 1) * priceStep;\n return (\n countItemsInRange(sliderValue[0], sliderValue[1]) > 0 &&\n rangeMin <= sliderValue[1] &&\n rangeMax >= sliderValue[0]\n );\n };\n\n return (\n
\n \n
\n {/* Histogram bars */}\n
\n {itemCounts.map((count, i) => (\n \n \n
\n ))}\n
\n \n
\n\n {/* Inputs */}\n
\n
\n \n
\n validateAndUpdateValue(inputValues[0], 0)}\n onChange={(e) => handleInputChange(e, 0)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[0], 0);\n }\n }}\n type=\"text\"\n value={inputValues[0]}\n />\n \n $\n \n
\n
\n
\n \n
\n validateAndUpdateValue(inputValues[1], 1)}\n onChange={(e) => handleInputChange(e, 1)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n validateAndUpdateValue(inputValues[1], 1);\n }\n }}\n type=\"text\"\n value={inputValues[1]}\n />\n \n $\n \n
\n
\n
\n\n {/* Button */}\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-slider-with-input.ts", "content": "\"use client\";\n\nimport { useCallback, useState } from \"react\";\n\ntype UseSliderWithInputProps = {\n minValue?: number;\n maxValue?: number;\n initialValue?: number[];\n defaultValue?: number[];\n};\n\nexport function useSliderWithInput({\n minValue = 0,\n maxValue = 100,\n initialValue = [minValue],\n defaultValue = [minValue],\n}: UseSliderWithInputProps) {\n const [sliderValue, setSliderValue] = useState(initialValue);\n const [inputValues, setInputValues] = useState(\n initialValue.map((v) => v.toString()),\n );\n\n const showReset =\n sliderValue.length === defaultValue.length &&\n !sliderValue.every((value, index) => value === defaultValue[index]);\n\n const validateAndUpdateValue = useCallback(\n (rawValue: string, index: number) => {\n if (rawValue === \"\" || rawValue === \"-\") {\n const newInputValues = [...inputValues];\n newInputValues[index] = \"0\";\n setInputValues(newInputValues);\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = 0;\n setSliderValue(newSliderValues);\n return;\n }\n\n const numValue = Number.parseFloat(rawValue);\n\n if (Number.isNaN(numValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = sliderValue[index]?.toString();\n setInputValues(newInputValues);\n return;\n }\n\n let clampedValue = Math.min(maxValue, Math.max(minValue, numValue));\n\n if (sliderValue.length > 1) {\n if (index === 0) {\n clampedValue = Math.min(clampedValue, sliderValue[1]);\n } else {\n clampedValue = Math.max(clampedValue, sliderValue[0]);\n }\n }\n\n const newSliderValues = [...sliderValue];\n newSliderValues[index] = clampedValue;\n setSliderValue(newSliderValues);\n\n const newInputValues = [...inputValues];\n newInputValues[index] = clampedValue.toString();\n setInputValues(newInputValues);\n },\n [sliderValue, inputValues, minValue, maxValue],\n );\n\n const handleInputChange = useCallback(\n (e: React.ChangeEvent, index: number) => {\n const newValue = e.target.value;\n if (newValue === \"\" || /^-?\\d*\\.?\\d*$/.test(newValue)) {\n const newInputValues = [...inputValues];\n newInputValues[index] = newValue;\n setInputValues(newInputValues);\n }\n },\n [inputValues],\n );\n\n const handleSliderChange = useCallback((newValue: number[]) => {\n setSliderValue(newValue);\n setInputValues(newValue.map((v) => v.toString()));\n }, []);\n\n const resetToDefault = useCallback(() => {\n setSliderValue(defaultValue);\n setInputValues(defaultValue.map((v) => v.toString()));\n }, [defaultValue]);\n\n return {\n handleInputChange,\n handleSliderChange,\n inputValues,\n resetToDefault,\n showReset,\n sliderValue,\n validateAndUpdateValue,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "slider", "label", "input", "button", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-266.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-266", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-266.tsx", "content": "import { Label } from \"@/registry/default/ui/label\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n return (\n
\n Equalizer\n
\n
\n :last-child>span]:h-6 [&>:last-child>span]:w-4 [&>:last-child>span]:rounded\"\n defaultValue={[2]}\n max={5}\n min={-5}\n orientation=\"vertical\"\n showTooltip\n />\n \n
\n
\n :last-child>span]:h-6 [&>:last-child>span]:w-4 [&>:last-child>span]:rounded\"\n defaultValue={[1]}\n max={5}\n min={-5}\n orientation=\"vertical\"\n showTooltip\n />\n \n
\n
\n :last-child>span]:h-6 [&>:last-child>span]:w-4 [&>:last-child>span]:rounded\"\n defaultValue={[-1]}\n max={5}\n min={-5}\n orientation=\"vertical\"\n showTooltip\n />\n \n
\n
\n :last-child>span]:h-6 [&>:last-child>span]:w-4 [&>:last-child>span]:rounded\"\n defaultValue={[-3]}\n max={5}\n min={-5}\n orientation=\"vertical\"\n showTooltip\n />\n \n
\n
\n :last-child>span]:h-6 [&>:last-child>span]:w-4 [&>:last-child>span]:rounded\"\n defaultValue={[2]}\n max={5}\n min={-5}\n orientation=\"vertical\"\n showTooltip\n />\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "slider", "label", "equalizer", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-267.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-267", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-267.tsx", "content": "import { TriangleAlert } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Some information is missing!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-268.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-268", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-268.tsx", "content": "import { TriangleAlert } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Some information is missing!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-269.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-269", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-269.tsx", "content": "import { CircleAlert } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n An error occurred!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "error" ] } } ================================================ FILE: apps/origin/public/r/comp-27.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-27", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-27.tsx", "content": "\"use client\";\n\nimport { LoaderCircleIcon, MicIcon, SearchIcon } from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [inputValue, setInputValue] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n\n useEffect(() => {\n if (inputValue) {\n setIsLoading(true);\n const timer = setTimeout(() => {\n setIsLoading(false);\n }, 500);\n return () => clearTimeout(timer);\n }\n setIsLoading(false);\n }, [inputValue]);\n\n return (\n
\n \n
\n setInputValue(e.target.value)}\n placeholder=\"Search...\"\n type=\"search\"\n value={inputValue}\n />\n
\n {isLoading ? (\n \n ) : (\n \n )}\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button", "search" ] } } ================================================ FILE: apps/origin/public/r/comp-270.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-270", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-270.tsx", "content": "import { CircleAlert } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n An error occurred!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "error" ] } } ================================================ FILE: apps/origin/public/r/comp-271.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-271", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-271.tsx", "content": "import { CircleCheckIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Completed successfully!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-272.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-272", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-272.tsx", "content": "import { CircleCheckIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Completed successfully!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-273.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-273", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-273.tsx", "content": "import { InfoIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Just a quick note!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "info" ] } } ================================================ FILE: apps/origin/public/r/comp-274.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-274", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-274.tsx", "content": "import { InfoIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Just a quick note!\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "info" ] } } ================================================ FILE: apps/origin/public/r/comp-275.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-275", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-275.tsx", "content": "import { ArrowRightIcon, TriangleAlert } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n
\n \n
\n

Some information is missing!

\n \n Link\n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-276.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-276", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-276.tsx", "content": "import { ArrowRightIcon, TriangleAlert } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n
\n \n
\n

Some information is missing!

\n \n Link\n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-277.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-277", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-277.tsx", "content": "import { CircleAlertIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n
\n \n
\n

\n Password does not meet requirements:\n

\n
    \n
  • Minimum 8 characters
  • \n
  • Inlcude a special character
  • \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "error", "signup", "authentication" ] } } ================================================ FILE: apps/origin/public/r/comp-278.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-278", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-278.tsx", "content": "import { CircleAlertIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n
\n \n
\n

\n Password does not meet requirements:\n

\n
    \n
  • Minimum 8 characters
  • \n
  • Inlcude a special character
  • \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "alert", "error", "signup", "authentication" ] } } ================================================ FILE: apps/origin/public/r/comp-279.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-279", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-279.tsx", "content": "import { TriangleAlert, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n

\n \n Some information is missing!\n

\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-28.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-28", "type": "registry:component", "dependencies": [ "react-aria-components" ], "files": [ { "path": "registry/default/components/comp-28.tsx", "content": "\"use client\";\n\nimport { MinusIcon, PlusIcon } from \"lucide-react\";\nimport {\n Button,\n Group,\n Input,\n Label,\n NumberField,\n} from \"react-aria-components\";\n\nexport default function Component() {\n return (\n \n
\n \n \n \n \n \n \n \n \n \n \n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button", "number", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-280.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-280", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-280.tsx", "content": "import { CircleCheckIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n

\n \n An error occurred!\n

\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "error" ] } } ================================================ FILE: apps/origin/public/r/comp-281.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-281", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-281.tsx", "content": "import { CircleCheckIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n

\n \n Completed successfully!\n

\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-282.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-282", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-282.tsx", "content": "import { InfoIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n

\n \n Just a quick note!\n

\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "info" ] } } ================================================ FILE: apps/origin/public/r/comp-283.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-283", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-283.tsx", "content": "import { ArrowRightIcon, TriangleAlert, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n

Some information is missing!

\n \n Link\n \n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-284.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-284", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-284.tsx", "content": "import { ArrowRightIcon, CircleAlert, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n

An error occurred!

\n \n Link\n \n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "error" ] } } ================================================ FILE: apps/origin/public/r/comp-285.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-285", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-285.tsx", "content": "import { ArrowRightIcon, CircleCheckIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n

Completed successfully!

\n \n Link\n \n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-286.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-286", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-286.tsx", "content": "import { ArrowRightIcon, InfoIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n

Just a quick note!

\n \n Link\n \n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "info" ] } } ================================================ FILE: apps/origin/public/r/comp-287.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-287", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-287.tsx", "content": "import { CircleCheckIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n

You‘ve made changes!

\n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-288.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-288", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-288.tsx", "content": "import { CircleCheckIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n

Message sent

\n
\n \n View\n {\" \"}\n ·{\" \"}\n \n Undo\n \n
\n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-289.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-289", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-289.tsx", "content": "import { TriangleAlertIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n
\n

\n Something requires your action!\n

\n

\n It conveys that a specific action is needed to resolve or\n address a situation.\n

\n
\n
\n \n
\n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "warning" ] } } ================================================ FILE: apps/origin/public/r/comp-29.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-29", "type": "registry:component", "dependencies": [ "react-aria-components" ], "files": [ { "path": "registry/default/components/comp-29.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport {\n Button,\n Group,\n Input,\n Label,\n NumberField,\n} from \"react-aria-components\";\n\nexport default function Component() {\n return (\n \n
\n \n \n \n
\n \n \n \n \n \n \n
\n
\n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "button", "number", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-290.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-290", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-290.tsx", "content": "import { CircleAlertIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n
\n

\n We couldn‘t complete your request!\n

\n

\n It indicates that an issue has prevented the processing of the\n request.\n

\n
\n
\n \n
\n
\n \n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "error" ] } } ================================================ FILE: apps/origin/public/r/comp-291.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-291", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-291.tsx", "content": "import { CircleCheckIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n
\n

Your request was completed!

\n

\n It demonstrates that the task or request has been processed.\n

\n
\n
\n \n
\n
\n \n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "success" ] } } ================================================ FILE: apps/origin/public/r/comp-292.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-292", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-292.tsx", "content": "import { Info, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n \n
\n
\n

\n Here is some helpful information!\n

\n

\n It aims to provide clarity or support for better\n decision-making.\n

\n
\n
\n \n
\n
\n \n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "info" ] } } ================================================ FILE: apps/origin/public/r/comp-293.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-293", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-293.tsx", "content": "import { XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n
\n
\n

We Value Your Privacy 🍪

\n

\n We use cookies to improve your experience, and show personalized\n content.\n

\n
\n
\n \n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "cookies", "gdpr", "privacy" ] } } ================================================ FILE: apps/origin/public/r/comp-294.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-294", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-294.tsx", "content": "import { RefreshCwIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n \n \n
\n
\n
\n

Version 1.4 is now available!

\n

\n This update contains several bug fixes and performance\n improvements.\n

\n
\n
\n \n \n
\n
\n \n \n \n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button", "info" ] } } ================================================ FILE: apps/origin/public/r/comp-295.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-295", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-295.tsx", "content": "import { XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n \n
\n
\n

\n \n Mary Palmer\n {\" \"}\n mentioned you in{\" \"}\n \n project-campaign-02\n \n .\n

\n

2 min ago

\n
\n
\n \n \n
\n
\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-296.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-296", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-296.tsx", "content": "import { RadioIcon, XIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 right-4` to the container element.\n
\n
\n \n \n
\n
\n
\n

Live in 27 hours

\n

\n November 20 at 8:00 PM.\n

\n
\n \n
\n \n \n \n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-297.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-297", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/toast.json" ], "files": [ { "path": "registry/default/components/comp-297.tsx", "content": "\"use client\";\n\nimport { useToast } from \"@/registry/default/hooks/use-toast\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { ToastAction } from \"@/registry/default/ui/toast\";\n\nexport default function Component() {\n const { toast } = useToast();\n\n return (\n {\n toast({\n action: Try again,\n description: \"There was a problem with your request.\",\n title: \"We couldn't complete your request!\",\n });\n }}\n variant=\"outline\"\n >\n Show toast\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-toast.ts", "content": "\"use client\";\n\n// Inspired by react-hot-toast library\nimport * as React from \"react\";\n\nimport type {\n ToastActionElement,\n ToastProps,\n} from \"@/registry/default/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n toastId: toastId,\n type: \"REMOVE_TOAST\",\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n for (const toast of state.toasts) {\n addToRemoveQueue(toast.id);\n }\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n for (const listener of listeners) {\n listener(memoryState);\n }\n}\n\ntype Toast = Omit;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n toast: { ...props, id },\n type: \"UPDATE_TOAST\",\n });\n const dismiss = () => dispatch({ toastId: id, type: \"DISMISS_TOAST\" });\n\n dispatch({\n toast: {\n ...props,\n id,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n open: true,\n },\n type: \"ADD_TOAST\",\n });\n\n return {\n dismiss,\n id: id,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, []);\n\n return {\n ...state,\n dismiss: (toastId?: string) => dispatch({ toastId, type: \"DISMISS_TOAST\" }),\n toast,\n };\n}\n\nexport { toast, useToast };\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "toast", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-298.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-298", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/toast.json" ], "files": [ { "path": "registry/default/components/comp-298.tsx", "content": "\"use client\";\n\nimport { CircleCheckIcon, XIcon } from \"lucide-react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Toast,\n ToastAction,\n ToastClose,\n ToastDescription,\n ToastProvider,\n ToastTitle,\n ToastViewport,\n} from \"@/registry/default/ui/toast\";\n\ninterface UseProgressTimerProps {\n duration: number;\n interval?: number;\n onComplete?: () => void;\n}\n\nfunction useProgressTimer({\n duration,\n interval = 100,\n onComplete,\n}: UseProgressTimerProps) {\n const [progress, setProgress] = useState(duration);\n const timerRef = useRef(0);\n const timerState = useRef({\n isPaused: false,\n remaining: duration,\n startTime: 0,\n });\n\n const cleanup = useCallback(() => {\n window.clearInterval(timerRef.current);\n }, []);\n\n const reset = useCallback(() => {\n cleanup();\n setProgress(duration);\n timerState.current = {\n isPaused: false,\n remaining: duration,\n startTime: 0,\n };\n }, [duration, cleanup]);\n\n const start = useCallback(() => {\n const state = timerState.current;\n state.startTime = Date.now();\n state.isPaused = false;\n\n timerRef.current = window.setInterval(() => {\n const elapsedTime = Date.now() - state.startTime;\n const remaining = Math.max(0, state.remaining - elapsedTime);\n\n setProgress(remaining);\n\n if (remaining <= 0) {\n cleanup();\n onComplete?.();\n }\n }, interval);\n }, [interval, cleanup, onComplete]);\n\n const pause = useCallback(() => {\n const state = timerState.current;\n if (!state.isPaused) {\n cleanup();\n state.remaining = Math.max(\n 0,\n state.remaining - (Date.now() - state.startTime),\n );\n state.isPaused = true;\n }\n }, [cleanup]);\n\n const resume = useCallback(() => {\n const state = timerState.current;\n if (state.isPaused && state.remaining > 0) {\n start();\n }\n }, [start]);\n\n useEffect(() => {\n return cleanup;\n }, [cleanup]);\n\n return {\n pause,\n progress,\n reset,\n resume,\n start,\n };\n}\n\nexport default function Component() {\n const [open, setOpen] = useState(false);\n const toastDuration = 5000;\n const { progress, start, pause, resume, reset } = useProgressTimer({\n duration: toastDuration,\n onComplete: () => setOpen(false),\n });\n\n const handleOpenChange = useCallback(\n (isOpen: boolean) => {\n setOpen(isOpen);\n if (isOpen) {\n reset();\n start();\n }\n },\n [reset, start],\n );\n\n const handleButtonClick = useCallback(() => {\n if (open) {\n setOpen(false);\n // Wait for the close animation to finish\n window.setTimeout(() => {\n handleOpenChange(true);\n }, 150);\n } else {\n handleOpenChange(true);\n }\n }, [open, handleOpenChange]);\n\n return (\n \n \n \n
\n \n
\n
\n Your request was completed!\n \n It demonstrates that the task or request has been processed.\n \n
\n
\n \n \n \n
\n
\n \n \n \n \n \n
\n
\n \n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "toast", "success", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-299.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-299", "type": "registry:component", "dependencies": [ "sonner" ], "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-299.tsx", "content": "\"use client\";\n\nimport { toast } from \"sonner\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n {\n toast(\"Your request was completed!\", {\n action: {\n label: \"Undo\",\n onClick: () => console.log(\"Undo\"),\n },\n description: \"It was a long journey, but we made it!\",\n });\n }}\n variant=\"outline\"\n >\n Show sonner\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "toast", "sonner", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-30.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-30", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-30.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "file" ] } } ================================================ FILE: apps/origin/public/r/comp-300.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-300", "type": "registry:component", "dependencies": [ "sonner" ], "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-300.tsx", "content": "\"use client\";\n\nimport { CircleCheckIcon, XIcon } from \"lucide-react\";\nimport { toast } from \"sonner\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n {\n toast.custom((t) => (\n
\n
\n
\n \n
\n

Message sent

\n
\n \n View\n {\" \"}\n ·{\" \"}\n toast.dismiss(t)}\n type=\"button\"\n >\n Undo\n \n
\n
\n
\n toast.dismiss(t)}\n variant=\"ghost\"\n >\n \n \n
\n
\n ));\n }}\n variant=\"outline\"\n >\n Custom sonner\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "notification", "toast", "sonner", "success", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-301.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-301", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-301.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n // To make the notification fixed, add classes like `fixed bottom-4 inset-x-4` to the container element.\n
\n
\n

\n We use cookies to improve your experience, analyze site usage, and\n show personalized content.\n

\n
\n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner", "cookies", "gdpr", "privacy" ] } } ================================================ FILE: apps/origin/public/r/comp-302.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-302", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-302.tsx", "content": "import { ArrowRightIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-303.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-303", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-303.tsx", "content": "import { EclipseIcon } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n

\n \n Get the most out of your app with real-time updates and analytics{\" \"}\n ·{\" \"}\n \n Upgrade\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-304.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-304", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-304.tsx", "content": "import { ArrowRightIcon, Eclipse } from \"lucide-react\";\n\nexport default function Component() {\n return (\n
\n
\n
\n \n
\n

\n We just added something awesome to make your experience even\n better.\n

\n \n Learn more\n \n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-305.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-305", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-305.tsx", "content": "\"use client\";\n\nimport { ArrowRightIcon, Eclipse, XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isVisible, setIsVisible] = useState(true);\n\n if (!isVisible) return null;\n\n return (\n
\n
\n
\n \n
\n

\n We just added something awesome to make your experience even\n better.\n

\n \n Learn more\n \n \n
\n
\n setIsVisible(false)}\n variant=\"ghost\"\n >\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-306.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-306", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-306.tsx", "content": "\"use client\";\n\nimport { EclipseIcon, XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isVisible, setIsVisible] = useState(true);\n\n if (!isVisible) return null;\n\n return (\n
\n
\n
\n \n
\n

\n It‘s live and ready to use! Start exploring the latest\n addition to your toolkit.\n

\n
\n \n \n
\n
\n
\n setIsVisible(false)}\n variant=\"ghost\"\n >\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-307.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-307", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-307.tsx", "content": "\"use client\";\n\nimport { Eclipse, XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isVisible, setIsVisible] = useState(true);\n\n if (!isVisible) return null;\n\n return (\n
\n
\n
\n \n
\n

\n It‘s live and ready to use! Start exploring the latest\n addition to your toolkit.\n

\n
\n \n \n
\n
\n
\n setIsVisible(false)}\n variant=\"ghost\"\n >\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-308.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-308", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-308.tsx", "content": "\"use client\";\n\nimport { Eclipse, XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isVisible, setIsVisible] = useState(true);\n\n if (!isVisible) return null;\n\n return (\n
\n
\n
\n \n
\n

\n It‘s live and ready to use! Start exploring the latest\n addition to your toolkit.\n

\n
\n \n
\n
\n
\n setIsVisible(false)}\n variant=\"ghost\"\n >\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-309.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-309", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-309.tsx", "content": "\"use client\";\n\nimport { RocketIcon, XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isVisible, setIsVisible] = useState(true);\n\n if (!isVisible) return null;\n\n return (\n
\n
\n
\n \n \n
\n
\n
\n

\n Boost your experience with coss.com\n

\n

\n The new feature is live! Try it out and let us know what you\n think.\n

\n
\n
\n \n
\n
\n
\n setIsVisible(false)}\n variant=\"ghost\"\n >\n \n \n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-31.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-31", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-31.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Input with overlapping label\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-310.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-310", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-310.tsx", "content": "\"use client\";\n\nimport { TicketPercent, XIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Define the sale end date - eg: new Date('2024-12-31T23:59:59');\nconst saleEndDate = new Date(\n Date.now() + 9 * 60 * 60 * 1000 + 45 * 60 * 1000 + 24 * 1000,\n); // Setting 9h 45m 24s from now for demo purposes\n\ninterface TimeLeft {\n days: number;\n hours: number;\n minutes: number;\n seconds: number;\n isExpired: boolean;\n}\n\nexport default function Component() {\n const [isVisible, setIsVisible] = useState(true);\n const [timeLeft, setTimeLeft] = useState({\n days: 0,\n hours: 0,\n isExpired: false,\n minutes: 0,\n seconds: 0,\n });\n\n useEffect(() => {\n const calculateTimeLeft = () => {\n const now = new Date();\n const difference = saleEndDate.getTime() - now.getTime();\n\n if (difference <= 0) {\n setTimeLeft({\n days: 0,\n hours: 0,\n isExpired: true,\n minutes: 0,\n seconds: 0,\n });\n return;\n }\n\n const days = Math.floor(difference / (1000 * 60 * 60 * 24));\n const hours = Math.floor(\n (difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60),\n );\n const minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));\n const seconds = Math.floor((difference % (1000 * 60)) / 1000);\n\n setTimeLeft({\n days,\n hours,\n isExpired: false,\n minutes,\n seconds,\n });\n };\n\n // Calculate immediately and then every second\n calculateTimeLeft();\n const timer = setInterval(calculateTimeLeft, 1000);\n\n return () => clearInterval(timer);\n }, []);\n\n if (!isVisible || timeLeft.isExpired) return null;\n\n return (\n
\n
\n
\n \n \n
\n
\n
\n

Black Friday Sale!

\n

\n It kicks off today and is available for just 24\n hours—don‘t miss out!\n

\n
\n
\n
\n {timeLeft.days > 0 && (\n \n {timeLeft.days}\n d\n \n )}\n \n {timeLeft.hours.toString().padStart(2, \"0\")}\n h\n \n \n {timeLeft.minutes.toString().padStart(2, \"0\")}\n m\n \n \n {timeLeft.seconds.toString().padStart(2, \"0\")}\n s\n \n
\n \n
\n
\n
\n setIsVisible(false)}\n variant=\"ghost\"\n >\n \n \n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner", "countdown", "sale" ] } } ================================================ FILE: apps/origin/public/r/comp-311.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-311", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-311.tsx", "content": "export default function Component() {\n return (\n
\n

\n 📫 Subscribe to our\n newsletter and get 10% off your first order!{\" \"}\n ·{\" \"}\n \n Subscribe\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner", "newsletter", "subscribe" ] } } ================================================ FILE: apps/origin/public/r/comp-312.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-312", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-312.tsx", "content": "\"use client\";\n\nimport { DownloadIcon, LoaderCircleIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [isDownloading, setIsDownloading] = useState(false);\n\n const handleDownload = () => {\n setIsDownloading(true);\n // Simulate download\n setTimeout(() => {\n setIsDownloading(false);\n }, 2000);\n };\n\n return (\n
\n
\n

\n v2.1.0\n \n New features and improvements available\n

\n \n {isDownloading ? (\n <>\n \n Updating...\n \n ) : (\n <>\n \n Update now\n \n )}\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "banner" ] } } ================================================ FILE: apps/origin/public/r/comp-313.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-313", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/alert-dialog.json", "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-313.tsx", "content": "import {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function AlertComponent() {\n return (\n \n \n \n \n \n \n Are you sure?\n \n Take a moment to review the details provided to ensure you\n understand the implications.\n \n \n \n Cancel\n Okay\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "alert", "alert dialog", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-314.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-314", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/alert-dialog.json", "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-314.tsx", "content": "import { CircleAlertIcon } from \"lucide-react\";\n\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function AlertComponent() {\n return (\n \n \n \n \n \n
\n \n \n
\n \n Are you sure?\n \n Are you sure you want to delete your account? All your data will\n be removed.\n \n \n \n \n Cancel\n Confirm\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "alert", "alert dialog", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-315.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-315", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json" ], "files": [ { "path": "registry/default/components/comp-315.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\n\nexport default function Component() {\n return (\n \n \n \n \n button:last-child]:hidden\">\n
\n \n \n Frequently Asked Questions (FAQ)\n \n \n
\n
\n
\n

\n Account Management\n

\n

\n Navigate to the registration page, provide required\n information, and verify your email address. You can sign\n up using your email or through social media platforms.\n

\n
\n
\n

\n Password Reset Process\n

\n

\n Users can reset their password through the account\n settings page. Click "Forgot Password" and\n follow the email verification steps to regain account\n access quickly and securely.\n

\n
\n
\n

\n Service Pricing Tiers\n

\n

\n We offer three primary subscription levels designed to\n meet diverse user needs: Basic (free with limited\n features), Professional (monthly fee with comprehensive\n access), and Enterprise (custom pricing with full platform\n capabilities).\n

\n
\n
\n

\n Technical Support Channels\n

\n

\n Customer support is accessible through multiple\n communication methods including email support, live chat\n during business hours, an integrated support ticket\n system, and phone support specifically for\n enterprise-level customers.\n

\n
\n
\n

\n Data Protection Strategies\n

\n

\n Our platform implements rigorous security measures\n including 256-bit SSL encryption, regular comprehensive\n security audits, strict data access controls, and\n compliance with international privacy protection\n standards.\n

\n
\n
\n

\n Platform Compatibility\n

\n

\n The service supports multiple device and operating system\n environments, including web browsers like Chrome and\n Firefox, mobile applications for iOS and Android, and\n desktop applications compatible with Windows and macOS.\n

\n
\n
\n

\n Subscription Management\n

\n

\n Subscriptions can be cancelled at any time through account\n settings, with pro-rated refunds available within 30 days\n of payment. Both monthly and annual billing options are\n provided, with special discounts offered for annual\n commitments.\n

\n
\n
\n

\n Payment Method Options\n

\n

\n We accept a wide range of payment methods including major\n credit cards such as Visa, MasterCard, and American\n Express, digital payment platforms like PayPal, and direct\n bank transfers. Regional payment options may also be\n available depending on user location.\n

\n
\n
\n

\n Customer Support\n

\n

\n Our dedicated customer support team is available 24/7,\n providing quick and efficient assistance to address any\n inquiries or issues you may have.\n

\n
\n
\n

\n Privacy Policy\n

\n

\n Our privacy policy outlines how we collect, use, and\n protect your personal data, ensuring your privacy is\n protected at all times.\n

\n
\n
\n
\n
\n
\n \n \n \n \n \n \n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-316.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-316", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/scroll-area.json" ], "files": [ { "path": "registry/default/components/comp-316.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { ScrollArea } from \"@/registry/default/ui/scroll-area\";\n\nexport default function Component() {\n return (\n \n \n \n \n button:last-child]:hidden\">\n \n \n \n Frequently Asked Questions (FAQ)\n \n \n
\n
\n
\n

\n Account Management\n

\n

\n Navigate to the registration page, provide required\n information, and verify your email address. You can sign\n up using your email or through social media platforms.\n

\n
\n
\n

\n Password Reset Process\n

\n

\n Users can reset their password through the account\n settings page. Click "Forgot Password" and\n follow the email verification steps to regain account\n access quickly and securely.\n

\n
\n
\n

\n Service Pricing Tiers\n

\n

\n We offer three primary subscription levels designed to\n meet diverse user needs: Basic (free with limited\n features), Professional (monthly fee with comprehensive\n access), and Enterprise (custom pricing with full platform\n capabilities).\n

\n
\n
\n

\n Technical Support Channels\n

\n

\n Customer support is accessible through multiple\n communication methods including email support, live chat\n during business hours, an integrated support ticket\n system, and phone support specifically for\n enterprise-level customers.\n

\n
\n
\n

\n Data Protection Strategies\n

\n

\n Our platform implements rigorous security measures\n including 256-bit SSL encryption, regular comprehensive\n security audits, strict data access controls, and\n compliance with international privacy protection\n standards.\n

\n
\n
\n

\n Platform Compatibility\n

\n

\n The service supports multiple device and operating system\n environments, including web browsers like Chrome and\n Firefox, mobile applications for iOS and Android, and\n desktop applications compatible with Windows and macOS.\n

\n
\n
\n

\n Subscription Management\n

\n

\n Subscriptions can be cancelled at any time through account\n settings, with pro-rated refunds available within 30 days\n of payment. Both monthly and annual billing options are\n provided, with special discounts offered for annual\n commitments.\n

\n
\n
\n

\n Payment Method Options\n

\n

\n We accept a wide range of payment methods including major\n credit cards such as Visa, MasterCard, and American\n Express, digital payment platforms like PayPal, and direct\n bank transfers. Regional payment options may also be\n available depending on user location.\n

\n
\n
\n

\n Customer Support\n

\n

\n Our dedicated customer support team is available 24/7,\n providing quick and efficient assistance to address any\n inquiries or issues you may have.\n

\n
\n
\n

\n Privacy Policy\n

\n

\n Our privacy policy outlines how we collect, use, and\n protect your personal data, ensuring your privacy is\n protected at all times.\n

\n
\n
\n
\n
\n
\n \n \n \n \n \n \n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-317.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-317", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json" ], "files": [ { "path": "registry/default/components/comp-317.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\n\nexport default function Component() {\n return (\n \n \n \n \n button:last-child]:top-3.5\">\n \n \n Frequently Asked Questions (FAQ)\n \n
\n \n
\n
\n
\n

\n Account Management\n

\n

\n Navigate to the registration page, provide required\n information, and verify your email address. You can sign\n up using your email or through social media platforms.\n

\n
\n
\n

\n Password Reset Process\n

\n

\n Users can reset their password through the account\n settings page. Click "Forgot Password" and\n follow the email verification steps to regain account\n access quickly and securely.\n

\n
\n
\n

\n Service Pricing Tiers\n

\n

\n We offer three primary subscription levels designed to\n meet diverse user needs: Basic (free with limited\n features), Professional (monthly fee with comprehensive\n access), and Enterprise (custom pricing with full platform\n capabilities).\n

\n
\n
\n

\n Technical Support Channels\n

\n

\n Customer support is accessible through multiple\n communication methods including email support, live chat\n during business hours, an integrated support ticket\n system, and phone support specifically for\n enterprise-level customers.\n

\n
\n
\n

\n Data Protection Strategies\n

\n

\n Our platform implements rigorous security measures\n including 256-bit SSL encryption, regular comprehensive\n security audits, strict data access controls, and\n compliance with international privacy protection\n standards.\n

\n
\n
\n

\n Platform Compatibility\n

\n

\n The service supports multiple device and operating system\n environments, including web browsers like Chrome and\n Firefox, mobile applications for iOS and Android, and\n desktop applications compatible with Windows and macOS.\n

\n
\n
\n

\n Subscription Management\n

\n

\n Subscriptions can be cancelled at any time through account\n settings, with pro-rated refunds available within 30 days\n of payment. Both monthly and annual billing options are\n provided, with special discounts offered for annual\n commitments.\n

\n
\n
\n

\n Payment Method Options\n

\n

\n We accept a wide range of payment methods including major\n credit cards such as Visa, MasterCard, and American\n Express, digital payment platforms like PayPal, and direct\n bank transfers. Regional payment options may also be\n available depending on user location.\n

\n
\n
\n

\n Customer Support\n

\n

\n Our dedicated customer support team is available 24/7,\n providing quick and efficient assistance to address any\n inquiries or issues you may have.\n

\n
\n
\n

\n Privacy Policy\n

\n

\n Our privacy policy outlines how we collect, use, and\n protect your personal data, ensuring your privacy is\n protected at all times.\n

\n
\n
\n
\n
\n \n \n \n \n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-318.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-318", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json" ], "files": [ { "path": "registry/default/components/comp-318.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\n\nexport default function Component() {\n return (\n \n \n \n \n button:last-child]:hidden\">\n
\n \n \n Frequently Asked Questions (FAQ)\n \n \n
\n
\n
\n

\n Account Management\n

\n

\n Navigate to the registration page, provide required\n information, and verify your email address. You can sign\n up using your email or through social media platforms.\n

\n
\n
\n

\n Password Reset Process\n

\n

\n Users can reset their password through the account\n settings page. Click "Forgot Password" and\n follow the email verification steps to regain account\n access quickly and securely.\n

\n
\n
\n

\n Service Pricing Tiers\n

\n

\n We offer three primary subscription levels designed to\n meet diverse user needs: Basic (free with limited\n features), Professional (monthly fee with comprehensive\n access), and Enterprise (custom pricing with full platform\n capabilities).\n

\n
\n
\n

\n Technical Support Channels\n

\n

\n Customer support is accessible through multiple\n communication methods including email support, live chat\n during business hours, an integrated support ticket\n system, and phone support specifically for\n enterprise-level customers.\n

\n
\n
\n

\n Data Protection Strategies\n

\n

\n Our platform implements rigorous security measures\n including 256-bit SSL encryption, regular comprehensive\n security audits, strict data access controls, and\n compliance with international privacy protection\n standards.\n

\n
\n
\n

\n Platform Compatibility\n

\n

\n The service supports multiple device and operating system\n environments, including web browsers like Chrome and\n Firefox, mobile applications for iOS and Android, and\n desktop applications compatible with Windows and macOS.\n

\n
\n
\n

\n Subscription Management\n

\n

\n Subscriptions can be cancelled at any time through account\n settings, with pro-rated refunds available within 30 days\n of payment. Both monthly and annual billing options are\n provided, with special discounts offered for annual\n commitments.\n

\n
\n
\n

\n Payment Method Options\n

\n

\n We accept a wide range of payment methods including major\n credit cards such as Visa, MasterCard, and American\n Express, digital payment platforms like PayPal, and direct\n bank transfers. Regional payment options may also be\n available depending on user location.\n

\n
\n
\n

\n Customer Support\n

\n

\n Our dedicated customer support team is available 24/7,\n providing quick and efficient assistance to address any\n inquiries or issues you may have.\n

\n
\n
\n

\n Privacy Policy\n

\n

\n Our privacy policy outlines how we collect, use, and\n protect your personal data, ensuring your privacy is\n protected at all times.\n

\n
\n
\n
\n
\n
\n
\n \n \n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-319.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-319", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json" ], "files": [ { "path": "registry/default/components/comp-319.tsx", "content": "\"use client\";\n\nimport { useRef, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\n\nexport default function Component() {\n const [hasReadToBottom, setHasReadToBottom] = useState(false);\n const contentRef = useRef(null);\n\n const handleScroll = () => {\n const content = contentRef.current;\n if (!content) return;\n\n const scrollPercentage =\n content.scrollTop / (content.scrollHeight - content.clientHeight);\n if (scrollPercentage >= 0.99 && !hasReadToBottom) {\n setHasReadToBottom(true);\n }\n };\n\n return (\n \n \n \n \n button:last-child]:top-3.5\">\n \n \n Terms & Conditions\n \n \n \n
\n
\n
\n
\n

\n Acceptance of Terms\n

\n

\n By accessing and using this website, users agree to\n comply with and be bound by these Terms of Service.\n Users who do not agree with these terms should\n discontinue use of the website immediately.\n

\n
\n\n
\n

\n User Account Responsibilities\n

\n

\n Users are responsible for maintaining the\n confidentiality of their account credentials. Any\n activities occurring under a user‘s account are\n the sole responsibility of the account holder. Users\n must notify the website administrators immediately of\n any unauthorized account access.\n

\n
\n\n
\n

\n Content Usage and Restrictions\n

\n

\n The website and its original content are protected by\n intellectual property laws. Users may not reproduce,\n distribute, modify, create derivative works, or\n commercially exploit any content without explicit\n written permission from the website owners.\n

\n
\n\n
\n

\n Limitation of Liability\n

\n

\n The website provides content “as is“ without\n any warranties. The website owners shall not be liable\n for direct, indirect, incidental, consequential, or\n punitive damages arising from user interactions with the\n platform.\n

\n
\n\n
\n

\n User Conduct Guidelines\n

\n
    \n
  • Not upload harmful or malicious content
  • \n
  • Respect the rights of other users
  • \n
  • \n Avoid activities that could disrupt website\n functionality\n
  • \n
  • \n Comply with applicable local and international laws\n
  • \n
\n
\n\n
\n

\n Modifications to Terms\n

\n

\n The website reserves the right to modify these terms at\n any time. Continued use of the website after changes\n constitutes acceptance of the new terms.\n

\n
\n\n
\n

\n Termination Clause\n

\n

\n The website may terminate or suspend user access without\n prior notice for violations of these terms or for any\n other reason deemed appropriate by the administration.\n

\n
\n\n
\n

\n Governing Law\n

\n

\n These terms are governed by the laws of the jurisdiction\n where the website is primarily operated, without regard\n to conflict of law principles.\n

\n
\n
\n
\n
\n
\n \n
\n \n {!hasReadToBottom && (\n \n Read all terms before accepting.\n \n )}\n \n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-32.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-32", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-32.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n Input with label animation\n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-320.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-320", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-320.tsx", "content": "\"use client\";\n\nimport { CircleAlertIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nconst PROJECT_NAME = \"coss-ui\";\n\nexport default function Component() {\n const id = useId();\n const [inputValue, setInputValue] = useState(\"\");\n\n return (\n \n \n \n \n \n
\n \n \n
\n \n \n Final confirmation\n \n \n This action cannot be undone. To confirm, please enter the project\n name coss-ui.\n \n \n \n\n \n
\n \n setInputValue(e.target.value)}\n placeholder=\"Type coss-ui to confirm\"\n type=\"text\"\n value={inputValue}\n />\n
\n \n \n \n \n \n Delete\n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "delete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-321.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-321", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-321.tsx", "content": "import { MailIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n
\n \n \n \n \n
\n \n \n Never miss an update\n \n \n Subscribe to receive news and special offers.\n \n \n \n\n
\n
\n
\n \n
\n \n
\n
\n
\n \n
\n\n

\n By subscribing you agree to our{\" \"}\n \n Privacy Policy\n \n .\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "newsletter", "subscribe", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-322.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-322", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/textarea.json" ], "files": [ { "path": "registry/default/components/comp-322.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n Send us feedback\n \n Watch{\" \"}\n \n tutorials\n \n , read coss.com‘s{\" \"}\n \n documentation\n \n , or join our{\" \"}\n \n Discord\n {\" \"}\n for community help.\n \n \n
\n \n
\n \n
\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "feedback", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-323.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-323", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json", "https://coss.com/origin/r/textarea.json" ], "files": [ { "path": "registry/default/components/comp-323.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Component() {\n return (\n \n \n \n \n button:last-child]:top-3.5\">\n \n \n Help us improve\n \n \n
\n
\n
\n
\n
\n \n How hard was it to set up your account?\n \n \n {[0, 1, 2, 3, 4, 5, 6, 7, 8].map((number) => (\n \n \n {number}\n \n ))}\n \n
\n
\n

Very easy

\n

Very dificult

\n
\n
\n\n
\n \n \n
\n
\n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "rating", "feedback", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-324.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-324", "type": "registry:component", "dependencies": [ "input-otp" ], "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json" ], "files": [ { "path": "registry/default/components/comp-324.tsx", "content": "\"use client\";\n\nimport { OTPInput, type SlotProps } from \"input-otp\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\n\nconst CORRECT_CODE = \"6548\";\n\nexport default function Component() {\n const [value, setValue] = useState(\"\");\n const [hasGuessed, setHasGuessed] = useState(undefined);\n const inputRef = useRef(null);\n const closeButtonRef = useRef(null);\n\n useEffect(() => {\n if (hasGuessed) {\n closeButtonRef.current?.focus();\n }\n }, [hasGuessed]);\n\n async function onSubmit(e?: React.FormEvent) {\n e?.preventDefault?.();\n\n inputRef.current?.select();\n await new Promise((r) => setTimeout(r, 1_00));\n\n setHasGuessed(value === CORRECT_CODE);\n\n setValue(\"\");\n setTimeout(() => {\n inputRef.current?.blur();\n }, 20);\n }\n\n return (\n \n \n \n \n \n
\n \n \n \n \n
\n \n \n {hasGuessed ? \"Code verified!\" : \"Enter confirmation code\"}\n \n \n {hasGuessed\n ? \"Your code has been successfully verified.\"\n : `Check your email and enter the code - Try ${CORRECT_CODE}`}\n \n \n \n\n {hasGuessed ? (\n
\n \n \n \n
\n ) : (\n
\n
\n setHasGuessed(undefined)}\n ref={inputRef}\n render={({ slots }) => (\n
\n {slots.map((slot, idx) => (\n \n ))}\n
\n )}\n value={value}\n />\n
\n {hasGuessed === false && (\n \n Invalid code. Please try again.\n

\n )}\n

\n \n Resend code\n \n

\n
\n )}\n
\n
\n );\n}\n\nfunction Slot(props: SlotProps) {\n return (\n \n {props.char !== null &&
{props.char}
}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "otp", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-325.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-325", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-325.tsx", "content": "import { useId } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n \n \n \n \n
\n \n \n \n \n
\n \n \n Sign up coss.com\n \n \n We just need a few details to get you started.\n \n \n \n\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n
\n\n
\n Or\n
\n\n \n\n

\n By signing up you agree to our{\" \"}\n \n Terms\n \n .\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "signup", "authentication", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-326.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-326", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-326.tsx", "content": "import { useId } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n \n \n \n \n
\n \n \n \n \n
\n \n Welcome back\n \n Enter your credentials to login to your account.\n \n \n \n\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n
\n \n \n Remember me\n \n
\n \n Forgot password?\n \n
\n \n
\n\n
\n Or\n
\n\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "login", "authentication", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-327.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-327", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-327.tsx", "content": "\"use client\";\n\nimport { CheckIcon, CopyIcon, UserRoundPlusIcon } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n const id = useId();\n const [emails, setEmails] = useState([\n \"mark@yourcompany.com\",\n \"jane@yourcompany.com\",\n \"\",\n ]);\n const [copied, setCopied] = useState(false);\n const inputRef = useRef(null);\n const lastInputRef = useRef(null);\n\n const addEmail = () => {\n setEmails([...emails, \"\"]);\n };\n\n const handleEmailChange = (index: number, value: string) => {\n const newEmails = [...emails];\n newEmails[index] = value;\n setEmails(newEmails);\n };\n\n const handleCopy = () => {\n if (inputRef.current) {\n navigator.clipboard.writeText(inputRef.current.value);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n }\n };\n\n return (\n \n \n \n \n {\n e.preventDefault();\n lastInputRef.current?.focus();\n }}\n >\n
\n \n \n
\n \n Invite team members\n \n Invite teammates to earn free components.\n \n \n \n\n
\n
\n
\n \n
\n {emails.map((email, index) => (\n handleEmailChange(index, e.target.value)}\n placeholder=\"hi@yourcompany.com\"\n ref={index === emails.length - 1 ? lastInputRef : undefined}\n type=\"email\"\n value={email}\n />\n ))}\n
\n
\n \n + Add another\n \n
\n \n
\n\n
\n\n
\n \n
\n \n \n \n \n \n \n \n
\n \n \n
\n \n \n \n Copy to clipboard\n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "form", "user", "team", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-328.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-328", "type": "registry:component", "dependencies": [ "react-payment-inputs" ], "devDependencies": [ "@types/react-payment-inputs" ], "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-328.tsx", "content": "\"use client\";\n\nimport { CreditCardIcon, WalletIcon } from \"lucide-react\";\nimport { useId } from \"react\";\nimport { usePaymentInputs } from \"react-payment-inputs\";\nimport images, { type CardImages } from \"react-payment-inputs/images\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const {\n meta,\n getCardNumberProps,\n getExpiryDateProps,\n getCVCProps,\n getCardImageProps,\n } = usePaymentInputs();\n\n return (\n \n \n \n \n \n
\n \n \n
\n \n Update your card\n \n Your new card will replace your current card.\n \n \n \n\n
\n
\n
\n \n \n
\n
\n \n
\n \n
\n {meta.cardType ? (\n \n ) : (\n \n )}\n
\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n
\n \n \n Set as default payment method\n \n
\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "checkout", "payment", "credit card", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-329.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-329", "type": "registry:component", "dependencies": [ "react-payment-inputs" ], "devDependencies": [ "@types/react-payment-inputs" ], "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-329.tsx", "content": "\"use client\";\n\nimport { CreditCardIcon, StoreIcon } from \"lucide-react\";\nimport { useEffect, useId, useRef, useState } from \"react\";\nimport { usePaymentInputs } from \"react-payment-inputs\";\nimport images, { type CardImages } from \"react-payment-inputs/images\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n const {\n meta,\n getCardNumberProps,\n getExpiryDateProps,\n getCVCProps,\n getCardImageProps,\n } = usePaymentInputs();\n const couponInputRef = useRef(null);\n const [showCouponInput, setShowCouponInput] = useState(false);\n const [couponCode, setCouponCode] = useState(\"\");\n\n // Auto-focus the coupon input when it's shown\n useEffect(() => {\n if (showCouponInput && couponInputRef.current) {\n couponInputRef.current.focus();\n }\n }, [showCouponInput]);\n\n return (\n \n \n \n \n \n
\n \n \n
\n \n Confirm and pay\n \n Pay securely and cancel any time.\n \n \n \n\n
\n
\n \n {/* Monthly */}\n \n {/* Yearly */}\n \n \n
\n \n \n
\n
\n \n Card Details\n \n
\n
\n \n
\n {meta.cardType ? (\n \n ) : (\n \n )}\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n
\n {!showCouponInput ? (\n setShowCouponInput(true)}\n type=\"button\"\n >\n + Add coupon\n \n ) : (\n
\n \n setCouponCode(e.target.value)}\n placeholder=\"Enter your code\"\n ref={couponInputRef}\n value={couponCode}\n />\n
\n )}\n
\n \n
\n\n

\n Payments are non-refundable. Cancel anytime.\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "checkout", "payment", "credit card", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-33.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-33", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-33.tsx", "content": "import { useId } from \"react\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n Input with inset label\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-330.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-330", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/radio-group.json" ], "files": [ { "path": "registry/default/components/comp-330.tsx", "content": "import { CheckIcon, RefreshCcwIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n \n \n \n \n
\n \n \n
\n \n Change your plan\n \n Pick one of the following plans.\n \n \n \n\n
\n \n {/* Radio card #1 */}\n
\n \n
\n \n \n $4 per member/month\n

\n
\n
\n {/* Radio card #2 */}\n
\n \n
\n \n \n $19 per member/month\n

\n
\n
\n {/* Radio card #3 */}\n
\n \n
\n \n \n $32 per member/month\n

\n
\n
\n
\n\n
\n

\n Features include:\n

\n
    \n
  • \n \n Create unlimited projects.\n
  • \n
  • \n \n Remove watermarks.\n
  • \n
  • \n \n Add unlimited users and free viewers.\n
  • \n
  • \n \n Upload unlimited files.\n
  • \n
  • \n \n 7-day money back guarantee.\n
  • \n
  • \n \n Advanced permissions.\n
  • \n
\n
\n\n
\n \n \n \n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "user", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-331.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-331", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/textarea.json" ], "files": [ { "path": "registry/default/components/comp-331.tsx", "content": "\"use client\";\n\nimport { CheckIcon, ImagePlusIcon, XIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { useCharacterLimit } from \"@/registry/default/hooks/use-character-limit\";\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\n// Pretend we have initial image files\nconst initialBgImage = [\n {\n id: \"profile-bg-123456789\",\n name: \"profile-bg.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"/origin/profile-bg.jpg\",\n },\n];\n\nconst initialAvatarImage = [\n {\n id: \"avatar-123456789\",\n name: \"avatar-72-01.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"/origin/avatar-72-01.jpg\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n\n const maxLength = 180;\n const {\n value,\n characterCount,\n handleChange,\n maxLength: limit,\n } = useCharacterLimit({\n initialValue:\n \"Hey, I am Margaret, a web developer who loves turning ideas into amazing websites!\",\n maxLength,\n });\n\n return (\n \n \n \n \n button:last-child]:top-3.5\">\n \n \n Edit profile\n \n \n \n Make changes to your profile here. You can change your photo and set a\n username.\n \n
\n \n \n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n
\n \n
\n \n
\n \n
\n
\n
\n
\n \n
\n \n https://\n \n \n
\n
\n
\n \n \n \n {limit - characterCount}{\" \"}\n characters left\n

\n
\n
\n
\n
\n \n \n \n \n \n \n \n \n
\n
\n );\n}\n\nfunction ProfileBg() {\n const [{ files }, { removeFile, openFileDialog, getInputProps }] =\n useFileUpload({\n accept: \"image/*\",\n initialFiles: initialBgImage,\n });\n\n const currentImage = files[0]?.preview || null;\n\n return (\n
\n
\n {currentImage && (\n \n )}\n
\n \n \n \n {currentImage && (\n removeFile(files[0]?.id)}\n type=\"button\"\n >\n \n \n )}\n
\n
\n \n
\n );\n}\n\nfunction Avatar() {\n const [{ files }, { openFileDialog, getInputProps }] = useFileUpload({\n accept: \"image/*\",\n initialFiles: initialAvatarImage,\n });\n\n const currentImage = files[0]?.preview || null;\n\n return (\n
\n
\n {currentImage && (\n \n )}\n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-character-limit.ts", "content": "\"use client\";\n\nimport { type ChangeEvent, useState } from \"react\";\n\ntype UseCharacterLimitProps = {\n maxLength: number;\n initialValue?: string;\n};\n\nexport function useCharacterLimit({\n maxLength,\n initialValue = \"\",\n}: UseCharacterLimitProps) {\n const [value, setValue] = useState(initialValue);\n const [characterCount, setCharacterCount] = useState(initialValue.length);\n\n const handleChange = (\n e: ChangeEvent,\n ) => {\n const newValue = e.target.value;\n if (newValue.length <= maxLength) {\n setValue(newValue);\n setCharacterCount(newValue.length);\n }\n };\n\n return {\n characterCount,\n handleChange,\n maxLength,\n value,\n };\n}\n", "type": "registry:hook" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "user", "profile", "image", "avatar", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-332.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-332", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dialog.json" ], "files": [ { "path": "registry/default/components/comp-332.tsx", "content": "\"use client\";\n\nimport { ArrowRightIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Dialog,\n DialogClose,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n DialogTrigger,\n} from \"@/registry/default/ui/dialog\";\n\nexport default function Component() {\n const [step, setStep] = useState(1);\n\n const stepContent = [\n {\n description:\n \"Discover a powerful collection of components designed to enhance your development workflow.\",\n title: \"Welcome to coss.com\",\n },\n {\n description:\n \"Each component is fully customizable and built with modern web standards in mind.\",\n title: \"Customizable Components\",\n },\n {\n description:\n \"Begin building amazing interfaces with our comprehensive component library.\",\n title: \"Ready to Start?\",\n },\n {\n description:\n \"Access our extensive documentation and community resources to make the most of coss.com.\",\n title: \"Get Support\",\n },\n ];\n\n const totalSteps = stepContent.length;\n\n const handleContinue = () => {\n if (step < totalSteps) {\n setStep(step + 1);\n }\n };\n\n return (\n {\n if (open) setStep(1);\n }}\n >\n \n \n \n button:last-child]:text-white\">\n
\n \n
\n
\n \n {stepContent[step - 1].title}\n \n {stepContent[step - 1].description}\n \n \n
\n
\n {[...Array(totalSteps)].map((_, index) => (\n \n ))}\n
\n \n \n \n \n {step < totalSteps ? (\n \n Next\n \n \n ) : (\n \n \n \n )}\n \n
\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "onboarding", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-333.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-333", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/command.json" ], "files": [ { "path": "registry/default/components/comp-333.tsx", "content": "\"use client\";\n\nimport {\n ArrowUpRightIcon,\n CircleFadingPlusIcon,\n FileInputIcon,\n FolderPlusIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport * as React from \"react\";\n\nimport {\n CommandDialog,\n CommandEmpty,\n CommandGroup,\n CommandInput,\n CommandItem,\n CommandList,\n CommandSeparator,\n CommandShortcut,\n} from \"@/registry/default/ui/command\";\n\nexport default function Component() {\n const [open, setOpen] = React.useState(false);\n\n React.useEffect(() => {\n const down = (e: KeyboardEvent) => {\n if (e.key === \"k\" && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n setOpen((open) => !open);\n }\n };\n\n document.addEventListener(\"keydown\", down);\n return () => document.removeEventListener(\"keydown\", down);\n }, []);\n\n return (\n <>\n setOpen(true)}\n type=\"button\"\n >\n \n \n Search\n \n \n ⌘K\n \n \n \n \n \n No results found.\n \n \n \n New folder\n ⌘N\n \n \n \n Import document\n ⌘I\n \n \n \n Add block\n ⌘B\n \n \n \n \n \n \n Go to dashboard\n \n \n \n Go to apps\n \n \n \n Go to connections\n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dialog", "modal", "command", "combobox", "popover", "search", "radix", "autocomplete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-334.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-334", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-334.tsx", "content": "import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ chevron

\n \n {items.map((item) => (\n \n \n {item.title}\n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-335.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-335", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-335.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n {item.title}\n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-336.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-336", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-336.tsx", "content": "import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ left chevron

\n \n {items.map((item) => (\n \n svg]:-order-1 justify-start gap-3 py-2 text-[15px] leading-6 hover:no-underline\">\n {item.title}\n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-337.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-337", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-337.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ left plus-minus

\n \n {items.map((item) => (\n \n \n svg]:-order-1 flex flex-1 items-center gap-4 rounded-md py-2 text-left font-semibold text-[15px] text-sm leading-6 outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&>svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n {item.title}\n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-338.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-338", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-338.tsx", "content": "import { AtSignIcon, CommandIcon, EclipseIcon, ZapIcon } from \"lucide-react\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n icon: CommandIcon,\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n icon: EclipseIcon,\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n icon: ZapIcon,\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n icon: AtSignIcon,\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ icon and chevron

\n \n {items.map((item) => (\n \n \n \n \n {item.title}\n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-339.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-339", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-339.tsx", "content": "import {\n AtSignIcon,\n CommandIcon,\n EclipseIcon,\n PlusIcon,\n ZapIcon,\n} from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n icon: CommandIcon,\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n icon: EclipseIcon,\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n icon: ZapIcon,\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n icon: AtSignIcon,\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ icon and plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n \n \n {item.title}\n \n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-34.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-34", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-34.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\n\nimport { useCharacterLimit } from \"@/registry/default/hooks/use-character-limit\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const maxLength = 50;\n const {\n value,\n characterCount,\n handleChange,\n maxLength: limit,\n } = useCharacterLimit({ maxLength });\n\n return (\n
\n \n
\n \n \n {characterCount}/{limit}\n
\n
\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-character-limit.ts", "content": "\"use client\";\n\nimport { type ChangeEvent, useState } from \"react\";\n\ntype UseCharacterLimitProps = {\n maxLength: number;\n initialValue?: string;\n};\n\nexport function useCharacterLimit({\n maxLength,\n initialValue = \"\",\n}: UseCharacterLimitProps) {\n const [value, setValue] = useState(initialValue);\n const [characterCount, setCharacterCount] = useState(initialValue.length);\n\n const handleChange = (\n e: ChangeEvent,\n ) => {\n const newValue = e.target.value;\n if (newValue.length <= maxLength) {\n setValue(newValue);\n setCharacterCount(newValue.length);\n }\n };\n\n return {\n characterCount,\n handleChange,\n maxLength,\n value,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-340.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-340", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-340.tsx", "content": "import { ChevronDownIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"Connect your accounts from Google, GitHub, or Microsoft to enable single sign-on and streamline your workflow. Connected accounts can be used for quick login and importing your preferences across platforms. You can revoke access to any connected account at any time.\",\n id: \"1\",\n sub: \"Manage your linked social and work accounts\",\n title: \"Connected accounts\",\n },\n {\n content:\n \"Choose which updates you want to receive. You can get notifications for: security alerts, billing updates, newsletter and product announcements, usage reports, and scheduled maintenance. Notifications can be delivered via email, SMS, or push notifications on your devices.\",\n id: \"2\",\n sub: \"Customize your notification preferences\",\n title: \"Notifications\",\n },\n {\n content:\n \"Protect your account with two-factor authentication. You can use authenticator apps like Google Authenticator or Authy, receive SMS codes, or use security keys like YubiKey. We recommend using an authenticator app for the most secure experience.\",\n id: \"3\",\n sub: \"Add an extra layer of security to your account\",\n title: \"2-step verification\",\n },\n {\n content:\n \"Our support team is available around the ClockIcon to assist you. For billing inquiries, technical issues, or general questions, you can reach us through live chat, email at support@example.com, or schedule a call with our technical team. Premium support is available for enterprise customers.\",\n id: \"4\",\n sub: \"We're here to help 24/7\",\n title: \"Contact support\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ sub-header and chevron

\n \n {items.map((item) => (\n \n \n svg]:rotate-180\">\n \n {item.title}\n {item.sub && (\n {item.sub}\n )}\n \n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-341.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-341", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-341.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"Connect your accounts from Google, GitHub, or Microsoft to enable single sign-on and streamline your workflow. Connected accounts can be used for quick login and importing your preferences across platforms. You can revoke access to any connected account at any time.\",\n id: \"1\",\n sub: \"Manage your linked social and work accounts\",\n title: \"Connected accounts\",\n },\n {\n content:\n \"Choose which updates you want to receive. You can get notifications for: security alerts, billing updates, newsletter and product announcements, usage reports, and scheduled maintenance. Notifications can be delivered via email, SMS, or push notifications on your devices.\",\n id: \"2\",\n sub: \"Customize your notification preferences\",\n title: \"Notifications\",\n },\n {\n content:\n \"Protect your account with two-factor authentication. You can use authenticator apps like Google Authenticator or Authy, receive SMS codes, or use security keys like YubiKey. We recommend using an authenticator app for the most secure experience.\",\n id: \"3\",\n sub: \"Add an extra layer of security to your account\",\n title: \"2-step verification\",\n },\n {\n content:\n \"Our support team is available around the ClockIcon to assist you. For billing inquiries, technical issues, or general questions, you can reach us through live chat, email at support@example.com, or schedule a call with our technical team. Premium support is available for enterprise customers.\",\n id: \"4\",\n sub: \"We're here to help 24/7\",\n title: \"Contact support\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ sub-header and plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n \n {item.title}\n {item.sub && (\n {item.sub}\n )}\n \n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-342.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-342", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-342.tsx", "content": "import {\n BellIcon,\n ChevronDownIcon,\n LifeBuoyIcon,\n Link2Icon,\n ShieldCheckIcon,\n} from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"Connect your accounts from Google, GitHub, or Microsoft to enable single sign-on and streamline your workflow. Connected accounts can be used for quick login and importing your preferences across platforms. You can revoke access to any connected account at any time.\",\n icon: Link2Icon,\n id: \"1\",\n sub: \"Manage your linked social and work accounts\",\n title: \"Connected accounts\",\n },\n {\n content:\n \"Choose which updates you want to receive. You can get notifications for: security alerts, billing updates, newsletter and product announcements, usage reports, and scheduled maintenance. Notifications can be delivered via email, SMS, or push notifications on your devices.\",\n icon: BellIcon,\n id: \"2\",\n sub: \"Customize your notification preferences\",\n title: \"Notifications\",\n },\n {\n content:\n \"Protect your account with two-factor authentication. You can use authenticator apps like Google Authenticator or Authy, receive SMS codes, or use security keys like YubiKey. We recommend using an authenticator app for the most secure experience.\",\n icon: ShieldCheckIcon,\n id: \"3\",\n sub: \"Add an extra layer of security to your account\",\n title: \"2-step verification\",\n },\n {\n content:\n \"Our support team is available around the ClockIcon to assist you. For billing inquiries, technical issues, or general questions, you can reach us through live chat, email at support@example.com, or schedule a call with our technical team. Premium support is available for enterprise customers.\",\n icon: LifeBuoyIcon,\n id: \"4\",\n sub: \"We're here to help 24/7\",\n title: \"Contact support\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ icon, sub-header, and chevron

\n \n {items.map((item) => (\n \n \n svg]:rotate-180\">\n \n \n \n \n \n {item.title}\n {item.sub && (\n {item.sub}\n )}\n \n \n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-343.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-343", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-343.tsx", "content": "import {\n BellIcon,\n LifeBuoyIcon,\n Link2Icon,\n PlusIcon,\n ShieldCheckIcon,\n} from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"Connect your accounts from Google, GitHub, or Microsoft to enable single sign-on and streamline your workflow. Connected accounts can be used for quick login and importing your preferences across platforms. You can revoke access to any connected account at any time.\",\n icon: Link2Icon,\n id: \"1\",\n sub: \"Manage your linked social and work accounts\",\n title: \"Connected accounts\",\n },\n {\n content:\n \"Choose which updates you want to receive. You can get notifications for: security alerts, billing updates, newsletter and product announcements, usage reports, and scheduled maintenance. Notifications can be delivered via email, SMS, or push notifications on your devices.\",\n icon: BellIcon,\n id: \"2\",\n sub: \"Customize your notification preferences\",\n title: \"Notifications\",\n },\n {\n content:\n \"Protect your account with two-factor authentication. You can use authenticator apps like Google Authenticator or Authy, receive SMS codes, or use security keys like YubiKey. We recommend using an authenticator app for the most secure experience.\",\n icon: ShieldCheckIcon,\n id: \"3\",\n sub: \"Add an extra layer of security to your account\",\n title: \"2-step verification\",\n },\n {\n content:\n \"Our support team is available around the ClockIcon to assist you. For billing inquiries, technical issues, or general questions, you can reach us through live chat, email at support@example.com, or schedule a call with our technical team. Premium support is available for enterprise customers.\",\n icon: LifeBuoyIcon,\n id: \"4\",\n sub: \"We're here to help 24/7\",\n title: \"Contact support\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

W/ icon, sub-header, and plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n \n \n \n \n \n {item.title}\n {item.sub && (\n {item.sub}\n )}\n \n \n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-344.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-344", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-344.tsx", "content": "import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Tabs w/ chevron

\n \n {items.map((item) => (\n \n \n {item.title}\n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-345.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-345", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-345.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Tabs w/ plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n {item.title}\n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-346.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-346", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-346.tsx", "content": "import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Tabs w/ left chevron

\n \n {items.map((item) => (\n \n svg]:-order-1 justify-start gap-3 py-2 text-[15px] leading-6 hover:no-underline focus-visible:ring-0\">\n {item.title}\n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-347.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-347", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-347.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Tabs w/ left plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n {item.title}\n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-348.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-348", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-348.tsx", "content": "import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Table w/ chevron

\n \n {items.map((item) => (\n \n \n {item.title}\n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-349.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-349", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-349.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Table w/ plus-minus

\n \n {items.map((item) => (\n \n \n svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n {item.title}\n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-35.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-35", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-35.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\n\nimport { useCharacterLimit } from \"@/registry/default/hooks/use-character-limit\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const maxLength = 8;\n const {\n value,\n characterCount,\n handleChange,\n maxLength: limit,\n } = useCharacterLimit({ maxLength });\n\n return (\n
\n \n \n \n {limit - characterCount}{\" \"}\n characters left\n

\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-character-limit.ts", "content": "\"use client\";\n\nimport { type ChangeEvent, useState } from \"react\";\n\ntype UseCharacterLimitProps = {\n maxLength: number;\n initialValue?: string;\n};\n\nexport function useCharacterLimit({\n maxLength,\n initialValue = \"\",\n}: UseCharacterLimitProps) {\n const [value, setValue] = useState(initialValue);\n const [characterCount, setCharacterCount] = useState(initialValue.length);\n\n const handleChange = (\n e: ChangeEvent,\n ) => {\n const newValue = e.target.value;\n if (newValue.length <= maxLength) {\n setValue(newValue);\n setCharacterCount(newValue.length);\n }\n };\n\n return {\n characterCount,\n handleChange,\n maxLength,\n value,\n };\n}\n", "type": "registry:hook" } ], "meta": { "tags": [ "input", "label" ] } } ================================================ FILE: apps/origin/public/r/comp-350.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-350", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-350.tsx", "content": "import {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Table w/ left chevron

\n \n {items.map((item) => (\n \n svg]:-order-1 justify-start gap-3 rounded-md py-2 text-[15px] leading-6 outline-none hover:no-underline focus-visible:ring-0\">\n {item.title}\n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-351.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-351", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json" ], "files": [ { "path": "registry/default/components/comp-351.tsx", "content": "import { PlusIcon } from \"lucide-react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n} from \"@/registry/default/ui/accordion\";\n\nconst items = [\n {\n content:\n \"coss ui focuses on developer experience and performance. Built with TypeScript, it offers excellent type safety, follows accessibility standards, and provides comprehensive documentation with regular updates.\",\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n content:\n \"Use our CSS variables for global styling, or className and style props for component-specific changes. We support CSS modules, Tailwind, and dark mode out of the box.\",\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n content:\n \"Yes, with tree-shaking, code splitting, and minimal runtime overhead. Most components are under 5KB gzipped.\",\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n content:\n \"All components follow WAI-ARIA standards, featuring proper ARIA attributes, keyboard navigation, and screen reader support. Regular testing ensures compatibility with NVDA, VoiceOver, and JAWS.\",\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Table w/ left plus-minus

\n \n {items.map((item) => (\n \n \n svg]:-order-1 flex flex-1 items-center gap-4 rounded-md py-2 text-left font-semibold text-[15px] text-sm leading-6 outline-none transition-all focus-visible:ring-0 [&>svg>path:last-child]:origin-center [&>svg>path:last-child]:transition-all [&>svg>path:last-child]:duration-200 [&[data-state=open]>svg>path:last-child]:rotate-90 [&[data-state=open]>svg>path:last-child]:opacity-0 [&[data-state=open]>svg]:rotate-180\">\n {item.title}\n \n \n \n \n {item.content}\n \n \n ))}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-352.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-352", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json", "https://coss.com/origin/r/collapsible.json" ], "files": [ { "path": "registry/default/components/comp-352.tsx", "content": "import { ChevronDownIcon } from \"lucide-react\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/registry/default/ui/collapsible\";\n\nconst items = [\n {\n collapsibles: [\n {\n content:\n \"We optimize every component for maximum performance and minimal bundle size.\",\n title: \"What about performance?\",\n },\n {\n content:\n \"Our documentation is comprehensive and includes live examples for every component.\",\n title: \"How is the documentation?\",\n },\n ],\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n collapsibles: [\n {\n content:\n \"Yes, our theming system is fully customizable and supports both light and dark modes.\",\n title: \"Can I use custom themes?\",\n },\n {\n content:\n \"We have first-class support for Tailwind CSS with custom utility classes.\",\n title: \"What about Tailwind support?\",\n },\n ],\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n collapsibles: [\n {\n content:\n \"Our components are tree-shakeable and typically add minimal overhead to your bundle.\",\n open: true,\n title: \"What's the bundle size impact?\",\n },\n {\n content:\n \"We support automatic code splitting for optimal loading performance.\",\n title: \"How is code splitting handled?\",\n },\n ],\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n collapsibles: [\n {\n content:\n \"We test with NVDA, VoiceOver, and JAWS to ensure broad compatibility.\",\n title: \"Which screen readers are supported?\",\n },\n {\n content:\n \"Full keyboard navigation support is implemented following WAI-ARIA best practices.\",\n title: \"What about keyboard navigation?\",\n },\n ],\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Multi-level

\n \n {items.map((item) => (\n \n \n {item.title}\n \n \n {item.collapsibles.map((collapsible, _index) => (\n \n ))}\n \n \n ))}\n \n
\n );\n}\n\nfunction CollapsibleDemo({\n title,\n content,\n open,\n}: {\n title: string;\n content: string;\n open?: boolean;\n}) {\n return (\n \n svg]:rotate-180\">\n \n {title}\n \n \n {content}\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "collapsible", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-353.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-353", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/accordion.json", "https://coss.com/origin/r/collapsible.json" ], "files": [ { "path": "registry/default/components/comp-353.tsx", "content": "import {\n AtSignIcon,\n ChevronDownIcon,\n CircleDashedIcon,\n CommandIcon,\n EclipseIcon,\n GaugeIcon,\n type LucideIcon,\n ZapIcon,\n} from \"lucide-react\";\n\nimport {\n Accordion,\n AccordionContent,\n AccordionItem,\n AccordionTrigger,\n} from \"@/registry/default/ui/accordion\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/registry/default/ui/collapsible\";\n\nconst items = [\n {\n collapsibles: [\n {\n content:\n \"We optimize every component for maximum performance and minimal bundle size.\",\n icon: GaugeIcon,\n title: \"What about performance?\",\n },\n {\n content:\n \"Our documentation is comprehensive and includes live examples for every component.\",\n icon: CircleDashedIcon,\n title: \"How is the documentation?\",\n },\n ],\n icon: CommandIcon,\n id: \"1\",\n title: \"What makes coss ui different?\",\n },\n {\n collapsibles: [\n {\n content:\n \"Yes, our theming system is fully customizable and supports both light and dark modes.\",\n icon: GaugeIcon,\n title: \"Can I use custom themes?\",\n },\n {\n content:\n \"We have first-class support for Tailwind CSS with custom utility classes.\",\n icon: CircleDashedIcon,\n title: \"What about Tailwind support?\",\n },\n ],\n icon: EclipseIcon,\n id: \"2\",\n title: \"How can I customize the components?\",\n },\n {\n collapsibles: [\n {\n content:\n \"Our components are tree-shakeable and typically add minimal overhead to your bundle.\",\n icon: GaugeIcon,\n open: true,\n title: \"What's the bundle size impact?\",\n },\n {\n content:\n \"We support automatic code splitting for optimal loading performance.\",\n icon: CircleDashedIcon,\n title: \"How is code splitting handled?\",\n },\n ],\n icon: ZapIcon,\n id: \"3\",\n title: \"Is coss ui optimized for performance?\",\n },\n {\n collapsibles: [\n {\n content:\n \"We test with NVDA, VoiceOver, and JAWS to ensure broad compatibility.\",\n icon: GaugeIcon,\n title: \"Which screen readers are supported?\",\n },\n {\n content:\n \"Full keyboard navigation support is implemented following WAI-ARIA best practices.\",\n icon: CircleDashedIcon,\n title: \"What about keyboard navigation?\",\n },\n ],\n icon: AtSignIcon,\n id: \"4\",\n title: \"How accessible are the components?\",\n },\n];\n\nexport default function Component() {\n return (\n
\n

Multi-level w/ icon

\n \n {items.map((item) => (\n \n svg]:-order-1 justify-start gap-3 rounded-md text-[15px] leading-6 outline-none hover:no-underline focus-visible:ring-0\">\n \n \n {item.title}\n \n \n \n {item.collapsibles.map((collapsible, _index) => (\n \n ))}\n \n \n ))}\n \n
\n );\n}\n\nfunction CollapsibleDemo({\n title,\n content,\n open,\n icon: Icon,\n}: {\n title: string;\n content: string;\n open?: boolean;\n icon: LucideIcon;\n}) {\n return (\n \n svg]:rotate-180\">\n \n \n \n {title}\n \n \n \n {content}\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "accordion", "collapsible", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-354.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-354", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-354.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n This is a simple tooltip\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-355.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-355", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-355.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n This tooltip will be always dark\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-356.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-356", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-356.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n This tooltip has an arrow\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-357.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-357", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-357.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n
\n

Tooltip with title

\n

\n Tooltips are made to be highly customizable, with features like\n dynamic placement, rich content, and a robust API. You can even\n use them as a full-featured dropdown menu by setting the{\" \"}\n trigger prop to click.\n

\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-358.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-358", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-358.tsx", "content": "import { GlobeIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n
\n \n
\n

\n Tooltip with title and icon\n

\n

\n Tooltips are made to be highly customizable, with features like\n dynamic placement, rich content, and a robust API.\n

\n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-359.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-359", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-359.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n
\n \n
\n

\n Tooltip with title and icon\n

\n

\n Tooltips are made to be highly customizable, with features like\n dynamic placement, rich content, and a robust API.\n

\n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "image", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-36.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-36", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-36.tsx", "content": "\"use client\";\n\nimport { Label } from \"react-aria-components\";\n\nimport { DateField, DateInput } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n \n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-360.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-360", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-360.tsx", "content": "import {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n \n \n \n Pan top\n \n ⌘T\n \n \n \n \n \n \n \n \n \n \n \n \n Pan left\n \n ⌘L\n \n \n \n \n
\n \n
\n \n \n \n \n \n \n Pan right\n \n ⌘R\n \n \n \n \n \n \n \n \n \n \n \n \n Pan bottom\n \n ⌘B\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "button", "kbd", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-361.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-361", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-361.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n
    \n
  • \n Status\n Completed\n
  • \n
  • \n Code Coverage\n 94.3%\n
  • \n
  • \n Last Deploy\n Today at 15:42\n
  • \n
  • \n Performance Score\n 98/100\n
  • \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-362.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-362", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-362.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n
\n
Tuesday, Aug 13
\n
\n \n \n \n \n Sales $40\n \n
\n
\n \n \n \n \n Revenue $74\n \n
\n
\n \n \n \n \n Costs $410\n \n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "chart", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-363.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-363", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/hover-card.json" ], "files": [ { "path": "registry/default/components/comp-363.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n HoverCard,\n HoverCardContent,\n HoverCardTrigger,\n} from \"@/registry/default/ui/hover-card\";\n\nexport default function HoverCardDemo() {\n return (\n \n \n \n \n \n \n \n \n \n
\n \n
\n

@Origin_UI

\n

\n Beautiful UI components built with Tailwind CSS and Next.js.\n

\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "hover card", "user", "avatar", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-364.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-364", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/hover-card.json" ], "files": [ { "path": "registry/default/components/comp-364.tsx", "content": "import {\n HoverCard,\n HoverCardContent,\n HoverCardTrigger,\n} from \"@/registry/default/ui/hover-card\";\n\nexport default function HoverCardDemo() {\n return (\n \n
\n \n
\n \n

\n \n Keith Kennedy\n \n

\n
\n

@k.kennedy

\n
\n
\n \n
\n
\n \n
\n

Keith Kennedy

\n

@k.kennedy

\n
\n
\n

\n Designer at{\" \"}\n @coss.com.\n Crafting web experiences with Tailwind CSS.\n

\n
\n
\n \n \n \n
\n
\n 3 mutual friends\n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "hover card", "user", "avatar", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-365.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-365", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/hover-card.json" ], "files": [ { "path": "registry/default/components/comp-365.tsx", "content": "import {\n HoverCard,\n HoverCardContent,\n HoverCardTrigger,\n} from \"@/registry/default/ui/hover-card\";\n\nexport default function HoverCardDemo() {\n return (\n
\n \n \n \n \n \n \n \n
\n
\n

\n Building a Design System with Next.js and Tailwind CSS\n

\n

\n Learn how to build a comprehensive design system using Tailwind\n CSS, including component architecture, and theme customization.\n

\n
\n
\n 8 min read\n ·\n Updated 2 days ago\n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "tooltip", "hover card", "image", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-366.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-366", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-366.tsx", "content": "import { EllipsisIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n Option 1\n Option 2\n Option 3\n Option 4\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-367.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-367", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-367.tsx", "content": "import { ChevronDownIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Option 1\n Option 2\n Option 3\n Option 4\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-368.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-368", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-368.tsx", "content": "import {\n BoltIcon,\n ChevronDownIcon,\n CopyPlusIcon,\n FilesIcon,\n Layers2Icon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n Copy\n \n \n \n Edit\n \n \n \n Group\n \n \n \n Clone\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-369.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-369", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-369.tsx", "content": "import {\n BoltIcon,\n ChevronDownIcon,\n CopyPlusIcon,\n FilesIcon,\n Layers2Icon,\n TrashIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n \n Copy\n \n \n \n Edit\n \n \n \n \n \n \n Group\n \n \n \n Clone\n \n \n \n Delete\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-37.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-37", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-37.tsx", "content": "\"use client\";\n\nimport { Label } from \"react-aria-components\";\n\nimport { DateInput, TimeField } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n \n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-370.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-370", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-370.tsx", "content": "import {\n BoltIcon,\n ChevronDownIcon,\n CopyPlusIcon,\n FilesIcon,\n Layers2Icon,\n TrashIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Label\n \n \n \n Copy\n \n \n \n Edit\n \n \n \n Label\n \n \n \n Group\n \n \n \n Clone\n \n \n \n Delete\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-371.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-371", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-371.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\ntype Checked = boolean;\n\nexport default function Component() {\n const [nextjs, setNextjs] = useState(false);\n const [sveltekit, setSveltekit] = useState(true);\n const [astro, setAstro] = useState(false);\n const [remix, setRemix] = useState(false);\n\n return (\n \n \n \n \n \n \n Next.js\n \n \n SvelteKit\n \n \n Remix\n \n \n Astro\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "checkbox", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-372.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-372", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-372.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n const [framework, setFramework] = useState(\"nextjs\");\n\n return (\n \n \n \n \n \n \n Next.js\n \n SvelteKit\n \n Remix\n Astro\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "radio", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-373.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-373", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-373.tsx", "content": "import { ChevronDownIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n Edit\n ⌘E\n \n \n Duplicate\n ⌘D\n \n \n \n \n \n Archive\n ⌘A\n \n \n More\n \n \n Move to project\n Move to folder\n \n Advanced options\n \n \n \n \n \n \n Share\n Add to favorites\n \n \n \n Delete\n ⌘⌫\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "kbd", "delete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-374.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-374", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-374.tsx", "content": "\"use client\";\n\nimport {\n ArchiveRestoreIcon,\n ChevronDownIcon,\n PlusIcon,\n Share2Icon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuPortal,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n const [framework, setFramework] = useState(\"nextjs\");\n const [emailNotifications, setEmailNotifications] = useState(false);\n const [pushNotifications, setPushNotifications] = useState(true);\n\n return (\n \n \n \n \n \n \n \n \n New\n ⌘N\n \n \n \n \n \n Framework\n \n \n \n \n Next.js\n \n \n SvelteKit\n \n \n Remix\n \n \n Astro\n \n \n \n \n \n \n Notifications\n \n \n \n Email\n \n \n Push\n \n \n \n \n \n \n \n \n \n Share\n \n \n \n Archive\n \n \n \n \n \n Delete\n ⌘⌫\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "checkbox", "radio", "delete", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-375.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-375", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-375.tsx", "content": "import { CircleUserRoundIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n Signed in as\n \n k.kennedy@coss.com\n \n \n \n \n Option 1\n Option 2\n Option 3\n \n \n Logout\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "user", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-376.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-376", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-376.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n CircleUserRoundIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n
\n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n
\n
\n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "user", "profile", "avatar", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-377.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-377", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-377.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n ChevronDownIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "user", "avatar", "profile", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-378.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-378", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-378.tsx", "content": "import {\n BookIcon,\n InfoIcon,\n LifeBuoyIcon,\n MessageCircleMoreIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n Need help?\n \n \n \n Documentation\n \n \n \n \n \n Support\n \n \n \n \n \n Contact us\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "info", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-379.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-379", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-379.tsx", "content": "import {\n Heading1Icon,\n Heading2Icon,\n MinusIcon,\n PlusIcon,\n TextQuoteIcon,\n TypeIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n Add block\n \n \n \n \n
\n
Text
\n
\n Start writing with plain text\n
\n
\n
\n \n \n \n \n
\n
Quote
\n
Capture a quote
\n
\n
\n \n \n \n \n
\n
Divider
\n
\n Visually divide blocks\n
\n
\n
\n \n \n \n \n
\n
Heading 1
\n
\n Big section heading\n
\n
\n
\n \n \n \n \n
\n
Heading 2
\n
\n Medium section subheading\n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "text editor", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-38.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-38", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-38.tsx", "content": "\"use client\";\n\nimport { ClockIcon } from \"lucide-react\";\nimport { Label } from \"react-aria-components\";\n\nimport { DateInput, TimeField } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n
\n
\n \n
\n \n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-380.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-380", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-380.tsx", "content": "\"use client\";\n\nimport { MonitorIcon, MoonIcon, SunIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\ntype Theme = \"light\" | \"dark\" | \"system\";\n\nexport default function Component() {\n const [theme, setTheme] = useState(\"system\");\n\n // For demo purposes, we'll simulate system preference as \"light\"\n const systemPreference = \"light\";\n const displayTheme = theme === \"system\" ? systemPreference : theme;\n\n return (\n
\n \n \n \n \n \n setTheme(\"light\")}>\n \n Light\n \n setTheme(\"dark\")}>\n \n Dark\n \n setTheme(\"system\")}>\n \n System\n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "dropdown", "darkmode", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-381.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-381", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-381.tsx", "content": "import { ListFilterIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n
\n
\n Filters\n
\n
\n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n \n
\n
\n \n
\n \n \n
\n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "filter", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-382.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-382", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-382.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst initialNotifications = [\n {\n action: \"requested review on\",\n id: 1,\n target: \"PR #42: Feature implementation\",\n timestamp: \"15 minutes ago\",\n unread: true,\n user: \"Chris Tompson\",\n },\n {\n action: \"shared\",\n id: 2,\n target: \"New component library\",\n timestamp: \"45 minutes ago\",\n unread: true,\n user: \"Emma Davis\",\n },\n {\n action: \"assigned you to\",\n id: 3,\n target: \"API integration task\",\n timestamp: \"4 hours ago\",\n unread: false,\n user: \"James Wilson\",\n },\n {\n action: \"replied to your comment in\",\n id: 4,\n target: \"Authentication flow\",\n timestamp: \"12 hours ago\",\n unread: false,\n user: \"Alex Morgan\",\n },\n {\n action: \"commented on\",\n id: 5,\n target: \"Dashboard redesign\",\n timestamp: \"2 days ago\",\n unread: false,\n user: \"Sarah Chen\",\n },\n {\n action: \"mentioned you in\",\n id: 6,\n target: \"coss.com open graph image\",\n timestamp: \"2 weeks ago\",\n unread: false,\n user: \"Miky Derya\",\n },\n];\n\nfunction Dot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function Component() {\n const [notifications, setNotifications] = useState(initialNotifications);\n const unreadCount = notifications.filter((n) => n.unread).length;\n\n const handleMarkAllAsRead = () => {\n setNotifications(\n notifications.map((notification) => ({\n ...notification,\n unread: false,\n })),\n );\n };\n\n const handleNotificationClick = (id: number) => {\n setNotifications(\n notifications.map((notification) =>\n notification.id === id\n ? { ...notification, unread: false }\n : notification,\n ),\n );\n };\n\n return (\n \n \n \n \n {unreadCount > 0 && (\n \n {unreadCount > 99 ? \"99+\" : unreadCount}\n \n )}\n \n \n \n
\n
Notifications
\n {unreadCount > 0 && (\n \n Mark all as read\n \n )}\n
\n \n {notifications.map((notification) => (\n \n
\n
\n handleNotificationClick(notification.id)}\n type=\"button\"\n >\n \n {notification.user}\n {\" \"}\n {notification.action}{\" \"}\n \n {notification.target}\n \n .\n \n
\n {notification.timestamp}\n
\n
\n {notification.unread && (\n
\n Unread\n \n
\n )}\n
\n \n ))}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "notification", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-383.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-383", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-383.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst initialNotifications = [\n {\n action: \"requested review on\",\n id: 1,\n image: \"/origin/avatar-80-01.jpg\",\n target: \"PR #42: Feature implementation\",\n timestamp: \"15 minutes ago\",\n unread: true,\n user: \"Chris Tompson\",\n },\n {\n action: \"shared\",\n id: 2,\n image: \"/origin/avatar-80-02.jpg\",\n target: \"New component library\",\n timestamp: \"45 minutes ago\",\n unread: true,\n user: \"Emma Davis\",\n },\n {\n action: \"assigned you to\",\n id: 3,\n image: \"/origin/avatar-80-03.jpg\",\n target: \"API integration task\",\n timestamp: \"4 hours ago\",\n unread: false,\n user: \"James Wilson\",\n },\n {\n action: \"replied to your comment in\",\n id: 4,\n image: \"/origin/avatar-80-04.jpg\",\n target: \"Authentication flow\",\n timestamp: \"12 hours ago\",\n unread: false,\n user: \"Alex Morgan\",\n },\n {\n action: \"commented on\",\n id: 5,\n image: \"/origin/avatar-80-05.jpg\",\n target: \"Dashboard redesign\",\n timestamp: \"2 days ago\",\n unread: false,\n user: \"Sarah Chen\",\n },\n {\n action: \"mentioned you in\",\n id: 6,\n image: \"/origin/avatar-80-06.jpg\",\n target: \"coss.com open graph image\",\n timestamp: \"2 weeks ago\",\n unread: false,\n user: \"Miky Derya\",\n },\n];\n\nfunction Dot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function Component() {\n const [notifications, setNotifications] = useState(initialNotifications);\n const unreadCount = notifications.filter((n) => n.unread).length;\n\n const handleMarkAllAsRead = () => {\n setNotifications(\n notifications.map((notification) => ({\n ...notification,\n unread: false,\n })),\n );\n };\n\n const handleNotificationClick = (id: number) => {\n setNotifications(\n notifications.map((notification) =>\n notification.id === id\n ? { ...notification, unread: false }\n : notification,\n ),\n );\n };\n\n return (\n \n \n \n \n {unreadCount > 0 && (\n \n {unreadCount > 99 ? \"99+\" : unreadCount}\n \n )}\n \n \n \n
\n
Notifications
\n {unreadCount > 0 && (\n \n Mark all as read\n \n )}\n
\n \n {notifications.map((notification) => (\n \n
\n \n
\n handleNotificationClick(notification.id)}\n type=\"button\"\n >\n \n {notification.user}\n {\" \"}\n {notification.action}{\" \"}\n \n {notification.target}\n \n .\n \n
\n {notification.timestamp}\n
\n
\n {notification.unread && (\n
\n \n
\n )}\n
\n \n ))}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "notification", "user", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-384.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-384", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-384.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n
\n
\n

Popover with button

\n

\n I am a popover that would like to look like a tooltip. I\n can‘t be a tooltip because of the interactive element inside\n me.\n

\n
\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-385.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-385", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-385.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst tips = [\n {\n description:\n \"This is your new workspace. Here you'll find all your projects, recent activities, settings, and more.\",\n title: \"Welcome to Dashboard\",\n },\n {\n description:\n \"Use the toolbar above to create new projects, invite team members, or access settings.\",\n title: \"Quick Actions\",\n },\n {\n description:\n \"Click the support icon in the top right corner to access our help center and documentation.\",\n title: \"Need Help?\",\n },\n];\n\nexport default function Component() {\n const [currentTip, setCurrentTip] = useState(0);\n\n const handleNavigation = () => {\n if (currentTip === tips.length - 1) {\n setCurrentTip(0);\n } else {\n setCurrentTip(currentTip + 1);\n }\n };\n\n return (\n \n \n \n \n \n
\n
\n

{tips[currentTip].title}

\n

\n {tips[currentTip].description}\n

\n
\n
\n \n {currentTip + 1}/{tips.length}\n \n \n {currentTip === tips.length - 1 ? \"Start over\" : \"Next\"}\n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-386.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-386", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-386.tsx", "content": "\"use client\";\n\nimport { ArrowLeftIcon, ArrowRightIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst tips = [\n {\n description:\n \"This is your new workspace. Here you'll find all your projects, recent activities, settings, and more.\",\n title: \"Welcome to Dashboard\",\n },\n {\n description:\n \"Use the toolbar above to create new projects, invite team members, or access settings.\",\n title: \"Quick Actions\",\n },\n {\n description:\n \"Click the support icon in the top right corner to access our help center and documentation.\",\n title: \"Need Help?\",\n },\n {\n description:\n \"Press ⌘K to open the command palette. Use arrow keys to navigate and Enter to select an action.\",\n title: \"Keyboard Shortcuts\",\n },\n {\n description:\n \"Enable notifications to receive updates about your projects, team activity, and important deadlines.\",\n title: \"Stay Updated\",\n },\n];\n\nexport default function Component() {\n const [currentTip, setCurrentTip] = useState(0);\n\n const handleNext = () => {\n if (currentTip < tips.length - 1) {\n setCurrentTip(currentTip + 1);\n }\n };\n\n const handlePrev = () => {\n if (currentTip > 0) {\n setCurrentTip(currentTip - 1);\n }\n };\n\n const isFirstTip = currentTip === 0;\n const isLastTip = currentTip === tips.length - 1;\n\n return (\n \n \n \n \n \n
\n
\n

{tips[currentTip].title}

\n

\n {tips[currentTip].description}\n

\n
\n
\n \n {currentTip + 1}/{tips.length}\n \n
\n \n \n \n \n \n \n
\n
\n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "tooltip", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-387.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-387", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-387.tsx", "content": "\"use client\";\n\nimport {\n RiCodeFill,\n RiFacebookFill,\n RiMailLine,\n RiTwitterXFill,\n} from \"@remixicon/react\";\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n const id = useId();\n const [copied, setCopied] = useState(false);\n const inputRef = useRef(null);\n\n const handleCopy = () => {\n if (inputRef.current) {\n navigator.clipboard.writeText(inputRef.current.value);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n }\n };\n\n return (\n
\n \n \n \n \n \n
\n
Share code
\n
\n \n \n \n \n \n \n \n \n \n \n
\n
\n
\n \n \n \n \n \n \n \n
\n \n \n
\n \n \n \n Copy to clipboard\n \n \n \n
\n
\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "share", "social", "copy", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-388.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-388", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/textarea.json" ], "files": [ { "path": "registry/default/components/comp-388.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n

Send us feedback

\n
\n \n
\n \n
\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "feedback", "form", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-389.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-389", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-389.tsx", "content": "\"use client\";\n\nimport {\n ClubIcon,\n DiamondIcon,\n HeartIcon,\n type LucideIcon,\n SpadeIcon,\n} from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverAnchor,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\ninterface TourStep {\n icon: LucideIcon;\n title: string;\n description: string;\n}\n\nconst tourSteps: TourStep[] = [\n {\n description:\n \"This is your new workspace. Here you'll find all your projects, recent activities, settings, and more.\",\n icon: HeartIcon,\n title: \"Heart\",\n },\n {\n description:\n \"Use the toolbar above to create new projects, invite team members, or access settings.\",\n icon: DiamondIcon,\n title: \"Diamond\",\n },\n {\n description:\n \"Click the support icon in the top right corner to access our help center and documentation.\",\n icon: ClubIcon,\n title: \"Club\",\n },\n {\n description:\n \"Press ⌘K to open the command palette. Use arrow keys to navigate and Enter to select an action.\",\n icon: SpadeIcon,\n title: \"Spade\",\n },\n];\n\ninterface CardProps {\n number: number;\n isActive: boolean;\n}\n\nfunction Card({ number, isActive }: CardProps) {\n const content = (\n
\n {number + 1}\n
\n );\n\n return isActive ? {content} : content;\n}\n\nexport default function Component() {\n const [currentTip, setCurrentTip] = useState(0);\n\n const handleNavigation = () => {\n if (currentTip === tourSteps.length - 1) {\n setCurrentTip(0);\n } else {\n setCurrentTip(currentTip + 1);\n }\n };\n\n return (\n
\n {\n if (open) setCurrentTip(0);\n }}\n >\n
\n {tourSteps.map((step, index) => (\n \n ))}\n
\n\n \n \n \n\n \n
\n
\n

\n {tourSteps[currentTip].title}\n

\n

\n {tourSteps[currentTip].description}\n

\n
\n
\n \n {currentTip + 1}/{tourSteps.length}\n \n \n {currentTip === tourSteps.length - 1 ? \"Start over\" : \"Next\"}\n \n
\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "popover", "tour", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-39.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-39", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-39.tsx", "content": "\"use client\";\n\nimport { ClockIcon } from \"lucide-react\";\nimport { Label } from \"react-aria-components\";\n\nimport { DateInput, TimeField } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n
\n \n
\n \n
\n
\n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-390.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-390", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-390.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n \n \n KK\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile" ] } } ================================================ FILE: apps/origin/public/r/comp-391.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-391", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-391.tsx", "content": "import { Avatar, AvatarFallback } from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n \n KK\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile" ] } } ================================================ FILE: apps/origin/public/r/comp-392.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-392", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-392.tsx", "content": "import { UserRoundIcon } from \"lucide-react\";\n\nimport { Avatar, AvatarFallback } from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile" ] } } ================================================ FILE: apps/origin/public/r/comp-393.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-393", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-393.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n \n \n KK\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile" ] } } ================================================ FILE: apps/origin/public/r/comp-394.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-394", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-394.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n
\n \n \n KK\n \n \n Online\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-395.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-395", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-395.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n
\n \n \n KK\n \n \n Offline\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-396.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-396", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-396.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n
\n \n \n KK\n \n \n Online\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-397.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-397", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json" ], "files": [ { "path": "registry/default/components/comp-397.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\n\nexport default function Component() {\n return (\n
\n \n \n KK\n \n \n Verified\n \n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile", "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-398.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-398", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-398.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n
\n \n \n KK\n \n \n 6\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile", "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-399.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-399", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-399.tsx", "content": "import {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n
\n \n \n KK\n \n \n 6\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile", "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-40.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-40", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-40.tsx", "content": "\"use client\";\n\nimport { Label } from \"react-aria-components\";\n\nimport { DateField, DateInput } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n \n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-400.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-400", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-400.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "user", "profile" ] } } ================================================ FILE: apps/origin/public/r/comp-401.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-401", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-401.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-402.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-402", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-402.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-403.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-403", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-403.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-404.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-404", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-404.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-405.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-405", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-405.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-406.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-406", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-406.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-407.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-407", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-407.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-408.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-408", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-408.tsx", "content": "export default function Component() {\n return (\n
\n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-409.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-409", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-409.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n +3\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-41.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-41", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/calendar-rac.json", "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-41.tsx", "content": "\"use client\";\n\nimport { CalendarIcon } from \"lucide-react\";\nimport {\n Button,\n DatePicker,\n Dialog,\n Group,\n Label,\n Popover,\n} from \"react-aria-components\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar-rac\";\nimport { DateInput } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n
\n \n \n \n \n
\n \n \n \n \n \n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "calendar", "picker", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-410.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-410", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-410.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n
\n \n \n \n \n
\n \n +3\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-411.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-411", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-411.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n return (\n
\n
\n \n \n \n \n
\n \n +3\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-412.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-412", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-412.tsx", "content": "export default function Component() {\n return (\n
\n
\n \n \n \n \n
\n

\n Trusted by 60K+{\" \"}\n developers.\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "avatar", "avatar group" ] } } ================================================ FILE: apps/origin/public/r/comp-413.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-413", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-413.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return Badge;\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-414.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-414", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-414.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return Badge;\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-415.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-415", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-415.tsx", "content": "import { ZapIcon } from \"lucide-react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n \n Badge\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-416.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-416", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-416.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return 6;\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "counter" ] } } ================================================ FILE: apps/origin/public/r/comp-417.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-417", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-417.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n Link\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-418.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-418", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-418.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n Badge\n \n 73\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "counter" ] } } ================================================ FILE: apps/origin/public/r/comp-419.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-419", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-419.tsx", "content": "import { CheckIcon } from \"lucide-react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n \n Badge\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-42.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-42", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/calendar-rac.json", "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-42.tsx", "content": "\"use client\";\n\nimport { CalendarIcon } from \"lucide-react\";\nimport {\n Button,\n DateRangePicker,\n Dialog,\n Group,\n Label,\n Popover,\n} from \"react-aria-components\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { RangeCalendar } from \"@/registry/default/ui/calendar-rac\";\nimport { DateInput, dateInputStyle } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n return (\n \n \n
\n \n \n \n -\n \n \n \n \n
\n \n \n \n \n \n \n Built with{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "calendar", "range calendar", "picker", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-420.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-420", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-420.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n \n Badge\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-421.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-421", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-421.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n \n Badge\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-422.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-422", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-422.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n return (\n \n \n Badge\n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "status" ] } } ================================================ FILE: apps/origin/public/r/comp-423.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-423", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/checkbox.json" ], "files": [ { "path": "registry/default/components/comp-423.tsx", "content": "import { CheckIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\n\nexport default function Component() {\n const id = useId();\n return (\n \n \n \n \n Selectable\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "checkbox" ] } } ================================================ FILE: apps/origin/public/r/comp-424.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-424", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-424.tsx", "content": "\"use client\";\n\nimport { XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n const [isActive, setIsActive] = useState(true);\n\n if (!isActive) return null;\n\n return (\n \n Removable\n setIsActive(false)}\n type=\"button\"\n >\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-425.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-425", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json" ], "files": [ { "path": "registry/default/components/comp-425.tsx", "content": "\"use client\";\n\nimport { XIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\n\nexport default function Component() {\n const [isActive, setIsActive] = useState(true);\n\n if (!isActive) return null;\n\n return (\n \n Tag\n setIsActive(false)}\n type=\"button\"\n >\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "badge", "chip", "tag" ] } } ================================================ FILE: apps/origin/public/r/comp-426.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-426", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-426.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n Tab 1\n Tab 2\n Tab 3\n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-427.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-427", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-427.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Tab 1\n \n \n Tab 2\n \n \n Tab 3\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-428.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-428", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-428.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Tab 1\n \n \n Tab 2\n \n \n Tab 3\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-429.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-429", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-429.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Tab 1\n \n \n Tab 2\n \n \n Tab 3\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-43.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-43", "type": "registry:component", "dependencies": [ "react-aria-components", "react-aria", "@internationalized/date" ], "registryDependencies": [ "https://coss.com/origin/r/calendar-rac.json", "https://coss.com/origin/r/datefield-rac.json" ], "files": [ { "path": "registry/default/components/comp-43.tsx", "content": "\"use client\";\n\nimport { getLocalTimeZone, isWeekend, today } from \"@internationalized/date\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { useLocale } from \"react-aria\";\nimport type { DateValue } from \"react-aria-components\";\nimport {\n Button,\n DateRangePicker,\n Dialog,\n Group,\n Label,\n Popover,\n} from \"react-aria-components\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { RangeCalendar } from \"@/registry/default/ui/calendar-rac\";\nimport { DateInput, dateInputStyle } from \"@/registry/default/ui/datefield-rac\";\n\nexport default function Component() {\n const now = today(getLocalTimeZone());\n const disabledRanges = [\n [now, now.add({ days: 5 })],\n [now.add({ days: 14 }), now.add({ days: 16 })],\n [now.add({ days: 23 }), now.add({ days: 24 })],\n ];\n\n const { locale } = useLocale();\n const isDateUnavailable = (date: DateValue) =>\n isWeekend(date, locale) ||\n disabledRanges.some(\n (interval) =>\n date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0,\n );\n const validate = (value: { start: DateValue; end: DateValue } | null) =>\n disabledRanges.some(\n (interval) =>\n value &&\n value.end.compare(interval[0]) >= 0 &&\n value.start.compare(interval[1]) <= 0,\n )\n ? \"Selected date range may not include unavailable dates.\"\n : null;\n\n return (\n \n \n
\n \n \n \n -\n \n \n \n \n
\n \n \n \n \n \n \n Built with{\" \"}\n \n React Aria\n \n

\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "date", "calendar", "range calendar", "picker", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-430.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-430", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-430.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Tab 1\n \n \n Tab 2\n \n \n Tab 3\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-431.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-431", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-431.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Tab 1\n \n \n Tab 2\n \n \n Tab 3\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-432.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-432", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-432.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Tab 1\n \n \n Tab 2\n \n \n Tab 3\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-433.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-433", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/scroll-area.json", "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-433.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { ScrollArea, ScrollBar } from \"@/registry/default/ui/scroll-area\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Overview\n \n \n \n Projects\n \n 3\n \n \n \n \n Packages\n \n New\n \n \n \n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-434.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-434", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/scroll-area.json", "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-434.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport { ScrollArea, ScrollBar } from \"@/registry/default/ui/scroll-area\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Overview\n \n \n \n Projects\n \n \n \n Packages\n \n \n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-435.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-435", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/scroll-area.json", "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-435.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport { ScrollArea, ScrollBar } from \"@/registry/default/ui/scroll-area\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Overview\n \n \n \n Projects\n \n \n \n Packages\n \n \n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-436.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-436", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/scroll-area.json", "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-436.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport { ScrollArea, ScrollBar } from \"@/registry/default/ui/scroll-area\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Overview\n \n \n \n Projects\n \n \n \n Packages\n \n \n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-437.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-437", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/scroll-area.json", "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-437.tsx", "content": "import {\n BoxIcon,\n ChartLine,\n HouseIcon,\n PanelsTopLeftIcon,\n SettingsIcon,\n UsersRoundIcon,\n} from \"lucide-react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { ScrollArea, ScrollBar } from \"@/registry/default/ui/scroll-area\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Overview\n \n \n \n Projects\n \n 3\n \n \n \n \n Packages\n New\n \n \n \n Team\n \n \n \n Insights\n \n \n \n Settings\n \n \n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n \n

\n Content for Tab 4\n

\n
\n \n

\n Content for Tab 5\n

\n
\n \n

\n Content for Tab 6\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-438.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-438", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-438.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n Overview\n \n \n \n Projects\n \n \n \n Packages\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-439.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-439", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-439.tsx", "content": "import { Badge } from \"@/registry/default/ui/badge\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n 3\n \n Overview\n \n \n \n 0\n \n Projects\n \n \n \n 7\n \n Packages\n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-44.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-44", "type": "registry:component", "dependencies": [ "input-otp" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-44.tsx", "content": "\"use client\";\n\nimport { OTPInput, type SlotProps } from \"input-otp\";\nimport { useId } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n (\n
\n {slots.map((slot, idx) => (\n \n ))}\n
\n )}\n />\n \n Built with{\" \"}\n \n Input OTP\n \n

\n
\n );\n}\n\nfunction Slot(props: SlotProps) {\n return (\n \n {props.char !== null &&
{props.char}
}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "otp" ] } } ================================================ FILE: apps/origin/public/r/comp-440.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-440", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/tabs.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-440.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n Overview\n \n \n \n \n \n \n \n \n \n \n \n 3\n \n \n \n \n \n \n Projects\n \n \n \n \n \n \n \n \n \n \n \n \n \n Packages\n \n \n \n \n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-441.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-441", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/tabs.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-441.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n \n \n \n \n \n \n \n Overview\n \n \n \n \n \n \n \n \n \n \n \n 3\n \n \n \n \n \n \n Projects\n \n \n \n \n \n \n \n \n \n \n \n \n \n Packages\n \n \n \n \n
\n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-442.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-442", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-442.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Overview\n \n \n Projects\n \n \n Packages\n \n \n
\n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "vertical tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-443.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-443", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-443.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Overview\n \n \n Projects\n \n \n Packages\n \n \n
\n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "vertical tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-444.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-444", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-444.tsx", "content": "import { BoxIcon, HouseIcon, PanelsTopLeftIcon } from \"lucide-react\";\n\nimport {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n \n Overview\n \n \n \n Projects\n \n \n \n Packages\n \n \n
\n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "vertical tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-445.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-445", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tabs.json" ], "files": [ { "path": "registry/default/components/comp-445.tsx", "content": "import {\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from \"@/registry/default/ui/tabs\";\n\nexport default function Component() {\n return (\n \n \n \n Overview\n \n \n Projects\n \n \n Packages\n \n \n
\n \n

\n Content for Tab 1\n

\n
\n \n

\n Content for Tab 2\n

\n
\n \n

\n Content for Tab 3\n

\n
\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 2, "tags": [ "tabs", "vertical tabs", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-446.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-446", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-446.tsx", "content": "import {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n Home\n \n \n \n \n \n \n Toggle menu\n \n \n \n Documentation\n \n \n Themes\n \n \n GitHub\n \n \n \n \n \n \n Components\n \n \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-447.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-447", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json", "https://coss.com/origin/r/dropdown-menu.json" ], "files": [ { "path": "registry/default/components/comp-447.tsx", "content": "import { FoldersIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function Component() {\n return (\n \n \n \n Home\n \n \n \n \n \n \n \n \n Toggle menu\n \n \n \n Documentation\n \n \n Themes\n \n \n GitHub\n \n \n \n \n \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "dropdown", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-448.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-448", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json" ], "files": [ { "path": "registry/default/components/comp-448.tsx", "content": "import { HomeIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Home\n \n \n \n \n Components\n \n \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-449.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-449", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json" ], "files": [ { "path": "registry/default/components/comp-449.tsx", "content": "import { ComponentIcon, HomeIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Home\n \n \n \n \n \n \n Components\n \n \n \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-45.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-45", "type": "registry:component", "dependencies": [ "input-otp" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-45.tsx", "content": "\"use client\";\n\nimport { OTPInput, type SlotProps } from \"input-otp\";\nimport { MinusIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n (\n <>\n
\n {slots.slice(0, 3).map((slot, idx) => (\n \n ))}\n
\n\n
\n \n
\n\n
\n {slots.slice(3).map((slot, idx) => (\n \n ))}\n
\n \n )}\n />\n \n Built with{\" \"}\n \n Input OTP\n \n

\n
\n );\n}\n\nfunction Slot(props: SlotProps) {\n return (\n \n {props.char !== null &&
{props.char}
}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "otp" ] } } ================================================ FILE: apps/origin/public/r/comp-450.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-450", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json" ], "files": [ { "path": "registry/default/components/comp-450.tsx", "content": "import { HomeIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Home\n \n \n / \n \n Components\n \n / \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-451.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-451", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json" ], "files": [ { "path": "registry/default/components/comp-451.tsx", "content": "import { HomeIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Home\n \n \n · \n \n Components\n \n · \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-452.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-452", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json" ], "files": [ { "path": "registry/default/components/comp-452.tsx", "content": "import { HomeIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\n\nexport default function Component() {\n return (\n \n \n \n \n \n Home\n \n \n \n \n Components\n \n \n \n Breadcrumb\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-453.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-453", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/breadcrumb.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-453.tsx", "content": "import { DatabaseIcon } from \"lucide-react\";\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n return (\n \n \n \n Databases\n \n \n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "style": 1, "tags": [ "breadcrumb", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-454.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-454", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-454.tsx", "content": "import { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n return (\n \n \n \n \n \n \n Previous\n \n \n \n \n \n \n Next\n \n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-455.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-455", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-455.tsx", "content": "import { ArrowLeftIcon, ArrowRightIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n return (\n \n \n \n \n \n Previous\n \n \n \n \n Next\n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-456.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-456", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-456.tsx", "content": "import { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { buttonVariants } from \"@/registry/default/ui/button\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n return (\n \n \n \n \n \n \n \n \n

\n Page {currentPage} of{\" \"}\n {totalPages}\n

\n
\n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-457.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-457", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-457.tsx", "content": "import { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\n\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n return (\n \n \n \n \n \n \n \n \n

\n Page {currentPage} of{\" \"}\n {totalPages}\n

\n
\n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-458.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-458", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-458.tsx", "content": "import { Button } from \"@/registry/default/ui/button\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n return (\n
\n

\n Page {currentPage} of{\" \"}\n {totalPages}\n

\n \n \n \n \n \n Previous\n \n \n \n \n \n \n Next\n \n \n \n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-459.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-459", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-459.tsx", "content": "import { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n PaginationNext,\n PaginationPrevious,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay?: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n paginationItemsToDisplay = 5,\n}: PaginationProps) {\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage,\n paginationItemsToDisplay,\n totalPages,\n });\n\n return (\n \n \n {/* Previous page button */}\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number links */}\n {pages.map((page) => (\n \n \n {page}\n \n \n ))}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-46.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-46", "type": "registry:component", "dependencies": [ "react-phone-number-input" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-46.tsx", "content": "\"use client\";\n\nimport { ChevronDownIcon, PhoneIcon } from \"lucide-react\";\nimport type React from \"react\";\nimport { useId, useState } from \"react\";\nimport * as RPNInput from \"react-phone-number-input\";\nimport flags from \"react-phone-number-input/flags\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [value, setValue] = useState(\"\");\n\n return (\n
\n \n setValue(newValue ?? \"\")}\n placeholder=\"Enter phone number\"\n value={value}\n />\n \n Built with{\" \"}\n \n react-phone-number-input\n \n

\n
\n );\n}\n\nconst PhoneInput = ({ className, ...props }: React.ComponentProps<\"input\">) => {\n return (\n \n );\n};\n\nPhoneInput.displayName = \"PhoneInput\";\n\ntype CountrySelectProps = {\n disabled?: boolean;\n value: RPNInput.Country;\n onChange: (value: RPNInput.Country) => void;\n options: { label: string; value: RPNInput.Country | undefined }[];\n};\n\nconst CountrySelect = ({\n disabled,\n value,\n onChange,\n options,\n}: CountrySelectProps) => {\n const handleSelect = (event: React.ChangeEvent) => {\n onChange(event.target.value as RPNInput.Country);\n };\n\n return (\n
\n
\n \n \n \n \n
\n \n \n {options\n .filter((x) => x.value)\n .map((option, i) => (\n \n ))}\n \n
\n );\n};\n\nconst FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {\n const Flag = flags[country];\n\n return (\n \n {Flag ? (\n \n ) : (\n \n )}\n \n );\n};\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "phone" ] } } ================================================ FILE: apps/origin/public/r/comp-460.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-460", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-460.tsx", "content": "import {\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\";\n\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay?: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n paginationItemsToDisplay = 5,\n}: PaginationProps) {\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage,\n paginationItemsToDisplay,\n totalPages,\n });\n\n return (\n \n \n {/* First page button */}\n \n \n \n \n \n\n {/* Previous page button */}\n \n \n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number links */}\n {pages.map((page) => (\n \n \n {page}\n \n \n ))}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n \n \n \n \n\n {/* Last page button */}\n \n \n \n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-461.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-461", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-461.tsx", "content": "import { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\n\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { buttonVariants } from \"@/registry/default/ui/button\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay?: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n paginationItemsToDisplay = 5,\n}: PaginationProps) {\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage,\n paginationItemsToDisplay,\n totalPages,\n });\n\n return (\n \n \n {/* Previous page button */}\n a]:rounded-s-md [&:last-child>a]:rounded-e-md\">\n svg]:opacity-50\",\n )}\n href={currentPage === 1 ? undefined : `#/page/${currentPage - 1}`}\n role={currentPage === 1 ? \"link\" : undefined}\n >\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n a]:rounded-s-md [&:last-child>a]:rounded-e-md\">\n \n \n )}\n\n {/* Page number links */}\n {pages.map((page) => (\n \n \n {page}\n \n \n ))}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n a]:rounded-s-md [&:last-child>a]:rounded-e-md\">\n \n \n )}\n\n {/* Next page button */}\n a]:rounded-s-md [&:last-child>a]:rounded-e-md\">\n svg]:opacity-50\",\n )}\n href={\n currentPage === totalPages\n ? undefined\n : `#/page/${currentPage + 1}`\n }\n role={currentPage === totalPages ? \"link\" : undefined}\n >\n \n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-462.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-462", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/pagination.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-462.tsx", "content": "import { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\n\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay?: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n paginationItemsToDisplay = 5,\n}: PaginationProps) {\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage,\n paginationItemsToDisplay,\n totalPages,\n });\n\n return (\n
\n {/* Page number information */}\n \n Page {currentPage} of{\" \"}\n {totalPages}\n

\n\n {/* Pagination */}\n
\n \n \n {/* Previous page button */}\n \n \n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number links */}\n {pages.map((page) => (\n \n \n {page}\n \n \n ))}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n \n \n \n \n \n \n
\n\n {/* Results per page */}\n
\n \n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-463.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-463", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/pagination.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-463.tsx", "content": "import {\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n const id = useId();\n return (\n
\n {/* Results per page */}\n
\n \n \n
\n\n {/* Page number information */}\n
\n \n 1-25 of{\" \"}\n 100\n

\n
\n\n {/* Pagination */}\n
\n \n \n {/* First page button */}\n \n \n \n \n \n\n {/* Previous page button */}\n \n \n \n \n \n\n {/* Next page button */}\n \n \n \n \n \n\n {/* Last page button */}\n \n \n \n \n \n \n \n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-464.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-464", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/pagination.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-464.tsx", "content": "import {\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n} from \"lucide-react\";\n\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay?: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n}: PaginationProps) {\n return (\n \n \n {/* First page button */}\n \n \n \n \n \n\n {/* Previous page button */}\n \n \n \n \n \n\n {/* Page number select */}\n \n \n \n\n {/* Next page button */}\n \n \n \n \n \n\n {/* Last page button */}\n \n \n \n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination", "select", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-465.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-465", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/pagination.json" ], "files": [ { "path": "registry/default/components/comp-465.tsx", "content": "import { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n PaginationLink,\n} from \"@/registry/default/ui/pagination\";\n\ntype PaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay?: number;\n};\n\nexport default function Component({\n currentPage,\n totalPages,\n paginationItemsToDisplay = 5,\n}: PaginationProps) {\n const id = useId();\n\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage,\n paginationItemsToDisplay,\n totalPages,\n });\n\n return (\n
\n {/* Pagination */}\n
\n \n \n {/* Previous page button */}\n \n \n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number links */}\n {pages.map((page) => (\n \n \n {page}\n \n \n ))}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n \n \n \n \n \n \n
\n\n {/* Go to page input */}\n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "pagination", "input" ] } } ================================================ FILE: apps/origin/public/r/comp-466.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-466", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-466.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n {items.map((item) => (\n \n {item.name}\n {item.email}\n {item.location}\n {item.status}\n {item.balance}\n \n ))}\n \n \n \n Total\n $2,500.00\n \n \n
\n

\n Basic table\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table" ] } } ================================================ FILE: apps/origin/public/r/comp-467.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-467", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-467.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n image:\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/exp1/avatar-40-02_upqrxi.jpg\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n username: \"@alexthompson\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n image:\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/exp1/avatar-40-01_ij9v7j.jpg\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n username: \"@sarahchen\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n image:\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/exp1/avatar-40-03_dkeufx.jpg\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n username: \"@mariagarcia\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n image:\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/exp1/avatar-40-05_cmz0mg.jpg\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n username: \"@davidkim\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n {items.map((item) => (\n \n \n
\n \n
\n
{item.name}
\n \n {item.username}\n \n
\n
\n
\n {item.email}\n {item.location}\n {item.status}\n {item.balance}\n
\n ))}\n
\n
\n

\n Table with images\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "user", "avatar" ] } } ================================================ FILE: apps/origin/public/r/comp-468.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-468", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-468.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n \n {items.map((item) => (\n \n {item.name}\n {item.email}\n {item.location}\n {item.status}\n \n {item.balance}\n \n \n ))}\n \n \n \n \n Total\n $2,500.00\n \n \n
\n

\n Table without horizontal dividers\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table" ] } } ================================================ FILE: apps/origin/public/r/comp-469.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-469", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-469.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n \n {items.map((item) => (\n \n {item.name}\n {item.email}\n {item.location}\n {item.status}\n \n {item.balance}\n \n \n ))}\n \n \n \n \n Total\n $2,500.00\n \n \n
\n

\n Striped table\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table" ] } } ================================================ FILE: apps/origin/public/r/comp-47.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-47", "type": "registry:component", "dependencies": [ "react-payment-inputs" ], "devDependencies": [ "@types/react-payment-inputs" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-47.tsx", "content": "\"use client\";\n\nimport { CreditCardIcon } from \"lucide-react\";\nimport { useId } from \"react\";\nimport { usePaymentInputs } from \"react-payment-inputs\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const { getCardNumberProps } = usePaymentInputs();\n\n return (\n
\n \n
\n \n
\n \n
\n
\n \n Built with{\" \"}\n \n React Payment Inputs\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "checkout", "payment", "credit card", "form" ] } } ================================================ FILE: apps/origin/public/r/comp-470.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-470", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-470.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n \n :not(:last-child)]:border-r\">\n Name\n Email\n Location\n Status\n Balance\n \n \n \n {items.map((item) => (\n :not(:last-child)]:border-r\"\n key={item.id}\n >\n {item.name}\n {item.email}\n {item.location}\n {item.status}\n {item.balance}\n \n ))}\n \n
\n

\n Table with vertical lines\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table" ] } } ================================================ FILE: apps/origin/public/r/comp-471.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-471", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-471.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst programmingLanguages = [\n {\n developer: \"Brendan Eich\",\n extension: \".js\",\n id: \"1\",\n latestVersion: \"ES2021\",\n name: \"JavaScript\",\n paradigm: \"Multi-paradigm\",\n popularity: \"High\",\n releaseYear: \"1995\",\n typing: \"Dynamic\",\n },\n {\n developer: \"Guido van Rossum\",\n extension: \".py\",\n id: \"2\",\n latestVersion: \"3.10\",\n name: \"Python\",\n paradigm: \"Multi-paradigm\",\n popularity: \"High\",\n releaseYear: \"1991\",\n typing: \"Dynamic\",\n },\n {\n developer: \"James Gosling\",\n extension: \".java\",\n id: \"3\",\n latestVersion: \"17\",\n name: \"Java\",\n paradigm: \"Object-oriented\",\n popularity: \"High\",\n releaseYear: \"1995\",\n typing: \"Static\",\n },\n {\n developer: \"Bjarne Stroustrup\",\n extension: \".cpp\",\n id: \"4\",\n latestVersion: \"C++20\",\n name: \"C++\",\n paradigm: \"Multi-paradigm\",\n popularity: \"High\",\n releaseYear: \"1985\",\n typing: \"Static\",\n },\n {\n developer: \"Yukihiro Matsumoto\",\n extension: \".rb\",\n id: \"5\",\n latestVersion: \"3.0\",\n name: \"Ruby\",\n paradigm: \"Multi-paradigm\",\n popularity: \"Low\",\n releaseYear: \"1995\",\n typing: \"Dynamic\",\n },\n];\n\nexport default function Component() {\n return (\n
\n
\n \n \n \n Name\n Release Year\n Developer\n Typing\n Paradigm\n Extension\n Latest Version\n Popularity\n \n \n \n {programmingLanguages.map((language) => (\n \n \n {language.name}\n \n {language.releaseYear}\n {language.developer}\n {language.typing}\n {language.paradigm}\n {language.extension}\n {language.latestVersion}\n {language.popularity}\n \n ))}\n \n
\n
\n

\n Dense table\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table" ] } } ================================================ FILE: apps/origin/public/r/comp-472.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-472", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-472.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n \n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n {items.map((item) => (\n \n \n \n \n {item.name}\n {item.email}\n {item.location}\n {item.status}\n {item.balance}\n \n ))}\n \n \n \n Total\n $2,500.00\n \n \n
\n

\n Table with row selection\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "checkbox" ] } } ================================================ FILE: apps/origin/public/r/comp-473.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-473", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-473.tsx", "content": "import { useId } from \"react\";\n\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n return (\n
\n
\n \n \n \n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n {items.map((item) => (\n \n \n \n \n {item.name}\n {item.email}\n {item.location}\n {item.status}\n {item.balance}\n \n ))}\n \n \n \n Total\n $2,500.00\n \n \n
\n
\n

\n Card Table\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "checkbox", "card" ] } } ================================================ FILE: apps/origin/public/r/comp-474.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-474", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-474.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nexport default function Component() {\n return (\n
\n
\n \n \n :not(:last-child)]:border-r\">\n \n Name\n \n David Kim\n \n :not(:last-child)]:border-r\">\n \n Email\n \n d.kim@company.com\n \n :not(:last-child)]:border-r\">\n \n Location\n \n Seoul, KR\n \n :not(:last-child)]:border-r\">\n \n Status\n \n Active\n \n :not(:last-child)]:border-r\">\n \n Balance\n \n $1,000.00\n \n \n
\n
\n

\n Vertical table\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "vertical table" ] } } ================================================ FILE: apps/origin/public/r/comp-475.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-475", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-475.tsx", "content": "import {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n balance: \"$1,250.00\",\n email: \"alex.t@company.com\",\n id: \"1\",\n location: \"San Francisco, US\",\n name: \"Alex Thompson\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"sarah.c@company.com\",\n id: \"2\",\n location: \"Singapore\",\n name: \"Sarah Chen\",\n status: \"Active\",\n },\n {\n balance: \"$650.00\",\n email: \"j.wilson@company.com\",\n id: \"3\",\n location: \"London, UK\",\n name: \"James Wilson\",\n status: \"Inactive\",\n },\n {\n balance: \"$0.00\",\n email: \"m.garcia@company.com\",\n id: \"4\",\n location: \"Madrid, Spain\",\n name: \"Maria Garcia\",\n status: \"Active\",\n },\n {\n balance: \"-$1,000.00\",\n email: \"d.kim@company.com\",\n id: \"5\",\n location: \"Seoul, KR\",\n name: \"David Kim\",\n status: \"Active\",\n },\n {\n balance: \"$1,500.00\",\n email: \"john.brown@company.com\",\n id: \"6\",\n location: \"New York, US\",\n name: \"John Brown\",\n status: \"Active\",\n },\n {\n balance: \"$200.00\",\n email: \"jane.doe@company.com\",\n id: \"7\",\n location: \"Paris, FR\",\n name: \"Jane Doe\",\n status: \"Inactive\",\n },\n {\n balance: \"$1,000.00\",\n email: \"peter.smith@company.com\",\n id: \"8\",\n location: \"Berlin, DE\",\n name: \"Peter Smith\",\n status: \"Active\",\n },\n {\n balance: \"$500.00\",\n email: \"olivia.lee@company.com\",\n id: \"9\",\n location: \"Tokyo, JP\",\n name: \"Olivia Lee\",\n status: \"Active\",\n },\n {\n balance: \"$300.00\",\n email: \"liam.chen@company.com\",\n id: \"10\",\n location: \"Shanghai, CN\",\n name: \"Liam Chen\",\n status: \"Inactive\",\n },\n {\n balance: \"$800.00\",\n email: \"ethan.kim@company.com\",\n id: \"11\",\n location: \"Busan, KR\",\n name: \"Ethan Kim\",\n status: \"Active\",\n },\n {\n balance: \"$1,200.00\",\n email: \"ava.brown@company.com\",\n id: \"12\",\n location: \"London, UK\",\n name: \"Ava Brown\",\n status: \"Active\",\n },\n {\n balance: \"$400.00\",\n email: \"lily.lee@company.com\",\n id: \"13\",\n location: \"Seoul, KR\",\n name: \"Lily Lee\",\n status: \"Active\",\n },\n {\n balance: \"$600.00\",\n email: \"noah.smith@company.com\",\n id: \"14\",\n location: \"New York, US\",\n name: \"Noah Smith\",\n status: \"Inactive\",\n },\n {\n balance: \"$1,800.00\",\n email: \"eve.chen@company.com\",\n id: \"15\",\n location: \"Taipei, TW\",\n name: \"Eve Chen\",\n status: \"Active\",\n },\n];\n\nexport default function Component() {\n return (\n
\n
div]:max-h-96\">\n \n \n \n Name\n Email\n Location\n Status\n Balance\n \n \n \n {items.map((item) => (\n \n {item.name}\n {item.email}\n {item.location}\n {item.status}\n {item.balance}\n \n ))}\n \n \n \n Total\n $2,500.00\n \n \n
\n
\n

\n Table with sticky header\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "sticky" ] } } ================================================ FILE: apps/origin/public/r/comp-476.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-476", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-476.tsx", "content": "import { CheckIcon, MonitorIcon, SmartphoneIcon, XIcon } from \"lucide-react\";\n\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\nconst items = [\n {\n desktop: [\n { name: \"Chrome\", supported: true, version: \"115\" },\n { name: \"Edge\", supported: true, version: \"115\" },\n { name: \"Firefox\", supported: false, version: \"111\" },\n { name: \"Opera\", supported: true, version: \"101\" },\n { name: \"Safari\", supported: false, version: \"No\" },\n ],\n feature: \"scroll-timeline\",\n mobile: [\n { name: \"Chrome Android\", supported: true, version: \"115\" },\n { name: \"Firefox Android\", supported: false, version: \"No\" },\n { name: \"Opera Android\", supported: true, version: \"77\" },\n { name: \"Safari iOS\", supported: false, version: \"No\" },\n { name: \"Samsung Internet\", supported: true, version: \"23\" },\n ],\n },\n {\n desktop: [\n { name: \"Chrome\", supported: true, version: \"115\" },\n { name: \"Edge\", supported: true, version: \"115\" },\n { name: \"Firefox\", supported: false, version: \"114\" },\n { name: \"Opera\", supported: true, version: \"101\" },\n { name: \"Safari\", supported: false, version: \"No\" },\n ],\n feature: \"view-timeline\",\n mobile: [\n { name: \"Chrome Android\", supported: true, version: \"115\" },\n { name: \"Firefox Android\", supported: false, version: \"No\" },\n { name: \"Opera Android\", supported: true, version: \"77\" },\n { name: \"Safari iOS\", supported: false, version: \"No\" },\n { name: \"Samsung Internet\", supported: true, version: \"23\" },\n ],\n },\n {\n desktop: [\n { name: \"Chrome\", supported: true, version: \"127\" },\n { name: \"Edge\", supported: true, version: \"127\" },\n { name: \"Firefox\", supported: false, version: \"3\" },\n { name: \"Opera\", supported: true, version: \"113\" },\n { name: \"Safari\", supported: true, version: \"16.4\" },\n ],\n feature: \"font-size-adjust\",\n mobile: [\n { name: \"Chrome Android\", supported: true, version: \"127\" },\n { name: \"Firefox Android\", supported: true, version: \"4\" },\n { name: \"Opera Android\", supported: true, version: \"84\" },\n { name: \"Safari iOS\", supported: true, version: \"16.4\" },\n { name: \"Samsung Internet\", supported: false, version: \"No\" },\n ],\n },\n];\n\nexport default function Component() {\n return (\n \n \n :not(:last-child)]:border-r\">\n \n \n \n Desktop browsers\n \n \n \n Mobile browsers\n \n \n \n \n :not(:last-child)]:border-r\">\n \n {items[0].desktop.map((browser) => (\n \n \n {browser.name}\n \n \n ))}\n {items[0].mobile.map((browser) => (\n \n \n {browser.name}\n \n \n ))}\n \n \n \n {items.map((item) => (\n :not(:last-child)]:border-r\"\n key={item.feature}\n >\n \n {item.feature}\n \n {[...item.desktop, ...item.mobile].map((browser, index) => (\n \n {browser.supported ? (\n \n ) : (\n \n )}\n \n {browser.supported ? \"Supported\" : \"Not supported\"}\n \n
\n {browser.version}\n
\n \n ))}\n \n ))}\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table" ] } } ================================================ FILE: apps/origin/public/r/comp-477.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-477", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-477.tsx", "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useEffect, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableFooter,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return
{formatted}
;\n },\n header: () =>
Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n getCoreRowModel: getCoreRowModel(),\n });\n\n return (\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n \n Total\n \n {new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(data.reduce((total, item) => total + item.balance, 0))}\n \n \n \n
\n

\n Basic data table made with{\" \"}\n \n TanStack Table\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "checkbox", "badge", "chip", "flag" ] } } ================================================ FILE: apps/origin/public/r/comp-478.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-478", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-478.tsx", "content": "\"use client\";\n\nimport {\n type Column,\n type ColumnDef,\n type ColumnFiltersState,\n flexRender,\n getCoreRowModel,\n getFacetedMinMaxValues,\n getFacetedRowModel,\n getFacetedUniqueValues,\n getFilteredRowModel,\n getSortedRowModel,\n type RowData,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronUpIcon,\n ExternalLinkIcon,\n SearchIcon,\n} from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ndeclare module \"@tanstack/react-table\" {\n //allows us to define custom properties for our columns\n // Type parameters TData and TValue must match TanStack Table's declaration exactly\n // biome-ignore lint: Type parameters required for module augmentation compatibility\n interface ColumnMeta {\n filterVariant?: \"text\" | \"range\" | \"select\";\n }\n}\n\ntype Item = {\n id: string;\n keyword: string;\n intents: Array<\n \"Informational\" | \"Navigational\" | \"Commercial\" | \"Transactional\"\n >;\n volume: number;\n cpc: number;\n traffic: number;\n link: string;\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"keyword\",\n cell: ({ row }) => (\n
{row.getValue(\"keyword\")}
\n ),\n header: \"Keyword\",\n },\n {\n accessorKey: \"intents\",\n cell: ({ row }) => {\n const intents = row.getValue(\"intents\") as string[];\n return (\n
\n {intents.map((intent) => {\n const styles = {\n Commercial: \"bg-amber-400/20 text-amber-500\",\n Informational: \"bg-indigo-400/20 text-indigo-500\",\n Navigational: \"bg-emerald-400/20 text-emerald-500\",\n Transactional: \"bg-rose-400/20 text-rose-500\",\n }[intent];\n\n return (\n \n {intent.charAt(0)}\n
\n );\n })}\n \n );\n },\n enableSorting: false,\n filterFn: (row, id, filterValue) => {\n const rowValue = row.getValue(id);\n return Array.isArray(rowValue) && rowValue.includes(filterValue);\n },\n header: \"Intents\",\n meta: {\n filterVariant: \"select\",\n },\n },\n {\n accessorKey: \"volume\",\n cell: ({ row }) => {\n const volume = Number.parseInt(row.getValue(\"volume\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(volume);\n },\n header: \"Volume\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"cpc\",\n cell: ({ row }) =>
${row.getValue(\"cpc\")}
,\n header: \"CPC\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"traffic\",\n cell: ({ row }) => {\n const traffic = Number.parseInt(row.getValue(\"traffic\"), 10);\n return new Intl.NumberFormat(\"en-US\", {\n maximumFractionDigits: 1,\n notation: \"compact\",\n }).format(traffic);\n },\n header: \"Traffic\",\n meta: {\n filterVariant: \"range\",\n },\n },\n {\n accessorKey: \"link\",\n cell: ({ row }) => (\n \n {row.getValue(\"link\")} \n \n ),\n enableSorting: false,\n header: \"Link\",\n },\n];\n\nconst items: Item[] = [\n {\n cpc: 2.5,\n id: \"1\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react components\",\n link: \"https://coss.com/origin\",\n traffic: 88,\n volume: 2507,\n },\n {\n cpc: 4.75,\n id: \"2\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"buy react templates\",\n link: \"https://coss.com/origin/input\",\n traffic: 65,\n volume: 1850,\n },\n {\n cpc: 3.25,\n id: \"3\",\n intents: [\"Informational\", \"Commercial\"],\n keyword: \"react ui library\",\n link: \"https://coss.com/origin/badge\",\n traffic: 112,\n volume: 3200,\n },\n {\n cpc: 1.95,\n id: \"4\",\n intents: [\"Transactional\"],\n keyword: \"tailwind components download\",\n link: \"https://coss.com/origin/alert\",\n traffic: 45,\n volume: 890,\n },\n {\n cpc: 5.5,\n id: \"5\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react dashboard template free\",\n link: \"https://coss.com/origin/tabs\",\n traffic: 156,\n volume: 4100,\n },\n {\n cpc: 1.25,\n id: \"6\",\n intents: [\"Informational\"],\n keyword: \"how to use react components\",\n link: \"https://coss.com/origin/table\",\n traffic: 42,\n volume: 1200,\n },\n {\n cpc: 6.8,\n id: \"7\",\n intents: [\"Commercial\", \"Transactional\"],\n keyword: \"react ui kit premium\",\n link: \"https://coss.com/origin/avatar\",\n traffic: 28,\n volume: 760,\n },\n {\n cpc: 1.8,\n id: \"8\",\n intents: [\"Informational\", \"Navigational\"],\n keyword: \"react component documentation\",\n link: \"https://coss.com/origin\",\n traffic: 35,\n volume: 950,\n },\n];\n\nexport default function Component() {\n const [columnFilters, setColumnFilters] = useState([]);\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"traffic\",\n },\n ]);\n\n const table = useReactTable({\n columns,\n data: items,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getFacetedMinMaxValues: getFacetedMinMaxValues(), // generate min/max values for range filter\n getFacetedRowModel: getFacetedRowModel(), // client-side faceting\n getFacetedUniqueValues: getFacetedUniqueValues(), // generate unique values for select filter/autocomplete\n getFilteredRowModel: getFilteredRowModel(), //client-side filtering\n getSortedRowModel: getSortedRowModel(),\n onColumnFiltersChange: setColumnFilters,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n sorting,\n },\n });\n\n const keywordColumn = table.getColumn(\"keyword\");\n const intentsColumn = table.getColumn(\"intents\");\n const volumeColumn = table.getColumn(\"volume\");\n const cpcColumn = table.getColumn(\"cpc\");\n const trafficColumn = table.getColumn(\"traffic\");\n\n return (\n
\n {/* Filters */}\n
\n {/* Search input */}\n {keywordColumn && (\n
\n \n
\n )}\n {/* Intents select */}\n {intentsColumn && (\n
\n \n
\n )}\n {/* Volume inputs */}\n {volumeColumn && (\n
\n \n
\n )}\n {/* CPC inputs */}\n {cpcColumn && (\n
\n \n
\n )}\n {/* Traffic inputs */}\n {trafficColumn && (\n
\n \n
\n )}\n
\n\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n \n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n

\n Data table with filters made with{\" \"}\n \n TanStack Table\n \n

\n
\n );\n}\n\nfunction Filter({ column }: { column: Column }) {\n const id = useId();\n const columnFilterValue = column.getFilterValue();\n const { filterVariant } = column.columnDef.meta ?? {};\n const columnHeader =\n typeof column.columnDef.header === \"string\" ? column.columnDef.header : \"\";\n const sortedUniqueValues = useMemo(() => {\n if (filterVariant === \"range\") return [];\n\n // Get all unique values from the column\n const values = Array.from(column.getFacetedUniqueValues().keys());\n\n // If the values are arrays, flatten them and get unique items\n const flattenedValues = values.reduce((acc: string[], curr) => {\n if (Array.isArray(curr)) {\n acc.push(...curr);\n } else {\n acc.push(curr);\n }\n return acc;\n }, []);\n\n // Get unique values and sort them\n return Array.from(new Set(flattenedValues)).sort();\n }, [column, filterVariant]);\n\n if (filterVariant === \"range\") {\n return (\n
\n \n
\n \n column.setFilterValue((old: [number, number]) => [\n e.target.value ? Number(e.target.value) : undefined,\n old?.[1],\n ])\n }\n placeholder=\"Min\"\n type=\"number\"\n value={(columnFilterValue as [number, number])?.[0] ?? \"\"}\n />\n \n column.setFilterValue((old: [number, number]) => [\n old?.[0],\n e.target.value ? Number(e.target.value) : undefined,\n ])\n }\n placeholder=\"Max\"\n type=\"number\"\n value={(columnFilterValue as [number, number])?.[1] ?? \"\"}\n />\n
\n
\n );\n }\n\n if (filterVariant === \"select\") {\n return (\n
\n \n {\n column.setFilterValue(value === \"all\" ? undefined : value);\n }}\n value={columnFilterValue?.toString() ?? \"all\"}\n >\n \n \n \n \n All\n {sortedUniqueValues.map((value) => (\n \n {String(value)}\n \n ))}\n \n \n
\n );\n }\n\n return (\n
\n \n
\n column.setFilterValue(e.target.value)}\n placeholder={`Search ${columnHeader.toLowerCase()}`}\n type=\"text\"\n value={(columnFilterValue ?? \"\") as string}\n />\n
\n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "checkbox", "search", "select", "range", "input", "filter", "sort" ] } } ================================================ FILE: apps/origin/public/r/comp-479.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-479", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-479.tsx", "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon } from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Excellent\" | \"Good\" | \"Average\" | \"Poor\";\n};\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState([]);\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n .cursor-col-resize]:opacity-0\"\n key={header.id}\n {...{\n colSpan: header.colSpan,\n style: {\n width: header.getSize(),\n },\n }}\n >\n {header.isPlaceholder ? null : (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n
\n )}\n {header.column.getCanResize() && (\n header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n

\n Resizable and sortable columns made with{\" \"}\n \n TanStack Table\n \n

\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "flag", "sort", "resize" ] } } ================================================ FILE: apps/origin/public/r/comp-48.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-48", "type": "registry:component", "dependencies": [ "react-payment-inputs" ], "devDependencies": [ "@types/react-payment-inputs" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-48.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\nimport { usePaymentInputs } from \"react-payment-inputs\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const { getExpiryDateProps } = usePaymentInputs();\n\n return (\n
\n \n \n \n Built with{\" \"}\n \n React Payment Inputs\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "checkout", "payment", "credit card", "form" ] } } ================================================ FILE: apps/origin/public/r/comp-480.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-480", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-480.tsx", "content": "\"use client\";\n\nimport {\n type Column,\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ArrowLeftToLineIcon,\n ArrowRightToLineIcon,\n EllipsisIcon,\n PinOffIcon,\n} from \"lucide-react\";\nimport { type CSSProperties, useEffect, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n department: string;\n role: string;\n joinDate: string;\n lastActive: string;\n performance: \"Good\" | \"Very Good\" | \"Excellent\" | \"Outstanding\";\n};\n\n// Helper function to compute pinning styles for columns\nconst getPinningStyles = (column: Column): CSSProperties => {\n const isPinned = column.getIsPinned();\n return {\n left: isPinned === \"left\" ? `${column.getStart(\"left\")}px` : undefined,\n position: isPinned ? \"sticky\" : \"relative\",\n right: isPinned === \"right\" ? `${column.getAfter(\"right\")}px` : undefined,\n width: column.getSize(),\n zIndex: isPinned ? 1 : 0,\n };\n};\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n },\n {\n accessorKey: \"department\",\n header: \"Department\",\n },\n {\n accessorKey: \"role\",\n header: \"Role\",\n },\n {\n accessorKey: \"joinDate\",\n header: \"Join Date\",\n },\n {\n accessorKey: \"lastActive\",\n header: \"Last Active\",\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState([]);\n const [sorting, setSorting] = useState([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: setSorting,\n state: {\n sorting,\n },\n });\n\n return (\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n const { column } = header;\n const isPinned = column.getIsPinned();\n const isLastLeftPinned =\n isPinned === \"left\" && column.getIsLastColumn(\"left\");\n const isFirstRightPinned =\n isPinned === \"right\" && column.getIsFirstColumn(\"right\");\n\n return (\n \n
\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n {/* Pin/Unpin column controls with enhanced accessibility */}\n {!header.isPlaceholder &&\n header.column.getCanPin() &&\n (header.column.getIsPinned() ? (\n header.column.pin(false)}\n size=\"icon\"\n title={`Unpin ${header.column.columnDef.header as string} column`}\n variant=\"ghost\"\n >\n \n \n ) : (\n \n \n \n \n \n \n \n header.column.pin(\"left\")}\n >\n \n Stick to left\n \n header.column.pin(\"right\")}\n >\n \n Stick to right\n \n \n \n ))}\n {header.column.getCanResize() && (\n header.column.resetSize(),\n onMouseDown: header.getResizeHandler(),\n onTouchStart: header.getResizeHandler(),\n }}\n />\n )}\n
\n \n );\n })}\n
\n ))}\n
\n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => {\n const { column } = cell;\n const isPinned = column.getIsPinned();\n const isLastLeftPinned =\n isPinned === \"left\" && column.getIsLastColumn(\"left\");\n const isFirstRightPinned =\n isPinned === \"right\" && column.getIsFirstColumn(\"right\");\n\n return (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n );\n })}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n \n

\n Pinnable columns made with{\" \"}\n \n TanStack Table\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "flag", "sticky", "resize" ] } } ================================================ FILE: apps/origin/public/r/comp-481.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-481", "type": "registry:component", "dependencies": [ "@dnd-kit/core", "@dnd-kit/modifiers", "@dnd-kit/sortable", "@dnd-kit/utilities", "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-481.tsx", "content": "\"use client\";\n\nimport {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n MouseSensor,\n TouchSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { restrictToHorizontalAxis } from \"@dnd-kit/modifiers\";\nimport {\n arrayMove,\n horizontalListSortingStrategy,\n SortableContext,\n useSortable,\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport {\n type Cell,\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n type Header,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, GripVerticalIcon } from \"lucide-react\";\nimport { type CSSProperties, useEffect, useId, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef[] = [\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n id: \"name\",\n sortDescFirst: false,\n sortUndefined: \"last\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n id: \"email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n id: \"location\",\n },\n {\n accessorKey: \"status\",\n header: \"Status\",\n id: \"status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n id: \"balance\",\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState([]);\n const [sorting, setSorting] = useState([]);\n const [columnOrder, setColumnOrder] = useState(\n columns.map((column) => column.id as string),\n );\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columnResizeMode: \"onChange\",\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onColumnOrderChange: setColumnOrder,\n onSortingChange: setSorting,\n state: {\n columnOrder,\n sorting,\n },\n });\n\n // reorder columns after drag & drop\n function handleDragEnd(event: DragEndEvent) {\n const { active, over } = event;\n if (active && over && active.id !== over.id) {\n setColumnOrder((columnOrder) => {\n const oldIndex = columnOrder.indexOf(active.id as string);\n const newIndex = columnOrder.indexOf(over.id as string);\n return arrayMove(columnOrder, oldIndex, newIndex); //this is just a splice util\n });\n }\n }\n\n const sensors = useSensors(\n useSensor(MouseSensor, {}),\n useSensor(TouchSensor, {}),\n useSensor(KeyboardSensor, {}),\n );\n\n return (\n \n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n \n {headerGroup.headers.map((header) => (\n \n ))}\n \n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n \n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n

\n Draggable columns made with{\" \"}\n \n TanStack Table\n {\" \"}\n and{\" \"}\n \n dnd kit\n \n

\n \n );\n}\n\nconst DraggableTableHeader = ({\n header,\n}: {\n header: Header;\n}) => {\n const {\n attributes,\n isDragging,\n listeners,\n setNodeRef,\n transform,\n transition,\n } = useSortable({\n id: header.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n whiteSpace: \"nowrap\",\n width: header.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n
\n \n \n \n \n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n \n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n size=\"icon\"\n variant=\"ghost\"\n >\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? (\n \n )}\n \n
\n \n );\n};\n\nconst DragAlongCell = ({ cell }: { cell: Cell }) => {\n const { isDragging, setNodeRef, transform, transition } = useSortable({\n id: cell.column.id,\n });\n\n const style: CSSProperties = {\n opacity: isDragging ? 0.8 : 1,\n position: \"relative\",\n transform: CSS.Translate.toString(transform),\n transition,\n width: cell.column.getSize(),\n zIndex: isDragging ? 1 : 0,\n };\n\n return (\n \n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n \n );\n};\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "flag", "sort", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-482.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-482", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-482.tsx", "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { ChevronDownIcon, ChevronUpIcon, InfoIcon } from \"lucide-react\";\nimport { Fragment, useEffect, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n note?: string;\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => {\n return row.getCanExpand() ? (\n \n {row.getIsExpanded() ? (\n \n ) : (\n \n )}\n \n ) : undefined;\n },\n header: () => null,\n id: \"expander\",\n },\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return
{formatted}
;\n },\n header: () =>
Balance
,\n },\n];\n\nexport default function Component() {\n const [data, setData] = useState([]);\n\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data.slice(0, 5)); // Limit to 5 items\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n getCoreRowModel: getCoreRowModel(),\n getExpandedRowModel: getExpandedRowModel(),\n getRowCanExpand: (row) => Boolean(row.original.note),\n });\n\n return (\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder\n ? null\n : flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n {row.getIsExpanded() && (\n \n \n
\n \n \n \n

{row.original.note}

\n
\n
\n
\n )}\n
\n ))\n ) : (\n \n \n No results.\n \n \n )}\n
\n
\n

\n Expanding sub-row made with{\" \"}\n \n TanStack Table\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "checkbox", "collapsible", "flag", "badge", "chip" ] } } ================================================ FILE: apps/origin/public/r/comp-483.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-483", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/pagination.json", "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-483.tsx", "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 5,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData([...data, ...data]);\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n return (\n
\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n \n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.getState().pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n \n \n {table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n table.getState().pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n

\n
\n {/* Pagination buttons */}\n
\n \n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n

\n Paginated table made with{\" \"}\n \n TanStack Table\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "checkbox", "sort", "flag", "badge", "chip", "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-484.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-484", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/pagination.json", "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-484.tsx", "content": "\"use client\";\n\nimport {\n type ColumnDef,\n flexRender,\n getCoreRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type SortingState,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n} from \"lucide-react\";\nimport { useEffect, useState } from \"react\";\n\nimport { usePagination } from \"@/registry/default/hooks/use-pagination\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Pagination,\n PaginationContent,\n PaginationEllipsis,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 200,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n header: \"Status\",\n size: 120,\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n];\n\nexport default function Component() {\n const pageSize = 5;\n\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: pageSize,\n });\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const table = useReactTable({\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n pagination,\n sorting,\n },\n });\n\n const { pages, showLeftEllipsis, showRightEllipsis } = usePagination({\n currentPage: table.getState().pagination.pageIndex + 1,\n paginationItemsToDisplay: 5,\n totalPages: table.getPageCount(),\n });\n\n return (\n
\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n \n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Page number information */}\n \n Page{\" \"}\n \n {table.getState().pagination.pageIndex + 1}\n {\" \"}\n of {table.getPageCount()}\n

\n\n {/* Pagination buttons */}\n
\n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n\n {/* Left ellipsis (...) */}\n {showLeftEllipsis && (\n \n \n \n )}\n\n {/* Page number buttons */}\n {pages.map((page) => {\n const isActive =\n page === table.getState().pagination.pageIndex + 1;\n return (\n \n table.setPageIndex(page - 1)}\n size=\"icon\"\n variant={`${isActive ? \"outline\" : \"ghost\"}`}\n >\n {page}\n \n \n );\n })}\n\n {/* Right ellipsis (...) */}\n {showRightEllipsis && (\n \n \n \n )}\n\n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n\n {/* Results per page */}\n
\n {\n table.setPageSize(Number(value));\n }}\n value={table.getState().pagination.pageSize.toString()}\n >\n \n \n \n \n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize} / page\n \n ))}\n \n \n
\n
\n

\n Numeric pagination made with{\" \"}\n \n TanStack Table\n \n

\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-pagination.ts", "content": "type UsePaginationProps = {\n currentPage: number;\n totalPages: number;\n paginationItemsToDisplay: number;\n};\n\ntype UsePaginationReturn = {\n pages: number[];\n showLeftEllipsis: boolean;\n showRightEllipsis: boolean;\n};\n\nexport function usePagination({\n currentPage,\n totalPages,\n paginationItemsToDisplay,\n}: UsePaginationProps): UsePaginationReturn {\n const showLeftEllipsis = currentPage - 1 > paginationItemsToDisplay / 2;\n const showRightEllipsis =\n totalPages - currentPage + 1 > paginationItemsToDisplay / 2;\n\n function calculatePaginationRange(): number[] {\n if (totalPages <= paginationItemsToDisplay) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const halfDisplay = Math.floor(paginationItemsToDisplay / 2);\n const initialRange = {\n end: currentPage + halfDisplay,\n start: currentPage - halfDisplay,\n };\n\n const adjustedRange = {\n end: Math.min(totalPages, initialRange.end),\n start: Math.max(1, initialRange.start),\n };\n\n if (adjustedRange.start === 1) {\n adjustedRange.end = paginationItemsToDisplay;\n }\n if (adjustedRange.end === totalPages) {\n adjustedRange.start = totalPages - paginationItemsToDisplay + 1;\n }\n\n if (showLeftEllipsis) adjustedRange.start++;\n if (showRightEllipsis) adjustedRange.end--;\n\n return Array.from(\n { length: adjustedRange.end - adjustedRange.start + 1 },\n (_, i) => adjustedRange.start + i,\n );\n }\n\n const pages = calculatePaginationRange();\n\n return {\n pages,\n showLeftEllipsis,\n showRightEllipsis,\n };\n}\n", "type": "registry:hook" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "checkbox", "sort", "flag", "badge", "chip", "pagination" ] } } ================================================ FILE: apps/origin/public/r/comp-485.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-485", "type": "registry:component", "dependencies": [ "@tanstack/react-table" ], "registryDependencies": [ "https://coss.com/origin/r/alert-dialog.json", "https://coss.com/origin/r/badge.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/pagination.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-485.tsx", "content": "\"use client\";\n\nimport {\n type ColumnDef,\n type ColumnFiltersState,\n type FilterFn,\n flexRender,\n getCoreRowModel,\n getFacetedUniqueValues,\n getFilteredRowModel,\n getPaginationRowModel,\n getSortedRowModel,\n type PaginationState,\n type Row,\n type SortingState,\n useReactTable,\n type VisibilityState,\n} from \"@tanstack/react-table\";\nimport {\n ChevronDownIcon,\n ChevronFirstIcon,\n ChevronLastIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n ChevronUpIcon,\n CircleAlertIcon,\n CircleXIcon,\n Columns3Icon,\n EllipsisIcon,\n FilterIcon,\n ListFilterIcon,\n PlusIcon,\n TrashIcon,\n} from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport {\n AlertDialog,\n AlertDialogAction,\n AlertDialogCancel,\n AlertDialogContent,\n AlertDialogDescription,\n AlertDialogFooter,\n AlertDialogHeader,\n AlertDialogTitle,\n AlertDialogTrigger,\n} from \"@/registry/default/ui/alert-dialog\";\nimport { Badge } from \"@/registry/default/ui/badge\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n DropdownMenu,\n DropdownMenuCheckboxItem,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuPortal,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubContent,\n DropdownMenuSubTrigger,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Pagination,\n PaginationContent,\n PaginationItem,\n} from \"@/registry/default/ui/pagination\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\ntype Item = {\n id: string;\n name: string;\n email: string;\n location: string;\n flag: string;\n status: \"Active\" | \"Inactive\" | \"Pending\";\n balance: number;\n};\n\n// Custom filter function for multi-column searching\nconst multiColumnFilterFn: FilterFn = (row, _columnId, filterValue) => {\n const searchableRowContent =\n `${row.original.name} ${row.original.email}`.toLowerCase();\n const searchTerm = (filterValue ?? \"\").toLowerCase();\n return searchableRowContent.includes(searchTerm);\n};\n\nconst statusFilterFn: FilterFn = (\n row,\n columnId,\n filterValue: string[],\n) => {\n if (!filterValue?.length) return true;\n const status = row.getValue(columnId) as string;\n return filterValue.includes(status);\n};\n\nconst columns: ColumnDef[] = [\n {\n cell: ({ row }) => (\n row.toggleSelected(!!value)}\n />\n ),\n enableHiding: false,\n enableSorting: false,\n header: ({ table }) => (\n table.toggleAllPageRowsSelected(!!value)}\n />\n ),\n id: \"select\",\n size: 28,\n },\n {\n accessorKey: \"name\",\n cell: ({ row }) => (\n
{row.getValue(\"name\")}
\n ),\n enableHiding: false,\n filterFn: multiColumnFilterFn,\n header: \"Name\",\n size: 180,\n },\n {\n accessorKey: \"email\",\n header: \"Email\",\n size: 220,\n },\n {\n accessorKey: \"location\",\n cell: ({ row }) => (\n
\n {row.original.flag}{\" \"}\n {row.getValue(\"location\")}\n
\n ),\n header: \"Location\",\n size: 180,\n },\n {\n accessorKey: \"status\",\n cell: ({ row }) => (\n \n {row.getValue(\"status\")}\n \n ),\n filterFn: statusFilterFn,\n header: \"Status\",\n size: 100,\n },\n {\n accessorKey: \"performance\",\n header: \"Performance\",\n },\n {\n accessorKey: \"balance\",\n cell: ({ row }) => {\n const amount = Number.parseFloat(row.getValue(\"balance\"));\n const formatted = new Intl.NumberFormat(\"en-US\", {\n currency: \"USD\",\n style: \"currency\",\n }).format(amount);\n return formatted;\n },\n header: \"Balance\",\n size: 120,\n },\n {\n cell: ({ row }) => ,\n enableHiding: false,\n header: () => Actions,\n id: \"actions\",\n size: 60,\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [columnFilters, setColumnFilters] = useState([]);\n const [columnVisibility, setColumnVisibility] = useState({});\n const [pagination, setPagination] = useState({\n pageIndex: 0,\n pageSize: 10,\n });\n const inputRef = useRef(null);\n\n const [sorting, setSorting] = useState([\n {\n desc: false,\n id: \"name\",\n },\n ]);\n\n const [data, setData] = useState([]);\n useEffect(() => {\n async function fetchPosts() {\n const res = await fetch(\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/users-01_fertyx.json\",\n );\n const data = await res.json();\n setData(data);\n }\n fetchPosts();\n }, []);\n\n const handleDeleteRows = () => {\n const selectedRows = table.getSelectedRowModel().rows;\n const updatedData = data.filter(\n (item) => !selectedRows.some((row) => row.original.id === item.id),\n );\n setData(updatedData);\n table.resetRowSelection();\n };\n\n const table = useReactTable({\n columns,\n data,\n enableSortingRemoval: false,\n getCoreRowModel: getCoreRowModel(),\n getFacetedUniqueValues: getFacetedUniqueValues(),\n getFilteredRowModel: getFilteredRowModel(),\n getPaginationRowModel: getPaginationRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onColumnFiltersChange: setColumnFilters,\n onColumnVisibilityChange: setColumnVisibility,\n onPaginationChange: setPagination,\n onSortingChange: setSorting,\n state: {\n columnFilters,\n columnVisibility,\n pagination,\n sorting,\n },\n });\n\n // Get unique status values\n const uniqueStatusValues = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n\n if (!statusColumn) return [];\n\n const values = Array.from(statusColumn.getFacetedUniqueValues().keys());\n\n return values.sort();\n }, [table.getColumn]);\n\n // Get counts for each status\n const statusCounts = useMemo(() => {\n const statusColumn = table.getColumn(\"status\");\n if (!statusColumn) return new Map();\n return statusColumn.getFacetedUniqueValues();\n }, [table]);\n\n const selectedStatuses = useMemo(() => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n return filterValue ?? [];\n }, [table]);\n\n const handleStatusChange = (checked: boolean, value: string) => {\n const filterValue = table.getColumn(\"status\")?.getFilterValue() as string[];\n const newFilterValue = filterValue ? [...filterValue] : [];\n\n if (checked) {\n newFilterValue.push(value);\n } else {\n const index = newFilterValue.indexOf(value);\n if (index > -1) {\n newFilterValue.splice(index, 1);\n }\n }\n\n table\n .getColumn(\"status\")\n ?.setFilterValue(newFilterValue.length ? newFilterValue : undefined);\n };\n\n return (\n
\n {/* Filters */}\n
\n
\n {/* Filter by name or email */}\n
\n \n table.getColumn(\"name\")?.setFilterValue(e.target.value)\n }\n placeholder=\"Filter by name or email...\"\n ref={inputRef}\n type=\"text\"\n value={\n (table.getColumn(\"name\")?.getFilterValue() ?? \"\") as string\n }\n />\n
\n \n
\n {Boolean(table.getColumn(\"name\")?.getFilterValue()) && (\n {\n table.getColumn(\"name\")?.setFilterValue(\"\");\n if (inputRef.current) {\n inputRef.current.focus();\n }\n }}\n type=\"button\"\n >\n \n \n )}\n
\n {/* Filter by status */}\n \n \n \n \n \n
\n
\n Filters\n
\n
\n {uniqueStatusValues.map((value, i) => (\n
\n \n handleStatusChange(checked, value)\n }\n />\n \n {value}{\" \"}\n \n {statusCounts.get(value)}\n \n \n
\n ))}\n
\n
\n
\n
\n {/* Toggle columns visibility */}\n \n \n \n \n \n Toggle columns\n {table\n .getAllColumns()\n .filter((column) => column.getCanHide())\n .map((column) => {\n return (\n \n column.toggleVisibility(!!value)\n }\n onSelect={(event) => event.preventDefault()}\n >\n {column.id}\n \n );\n })}\n \n \n
\n
\n {/* Delete button */}\n {table.getSelectedRowModel().rows.length > 0 && (\n \n \n \n \n \n
\n \n \n
\n \n \n Are you absolutely sure?\n \n \n This action cannot be undone. This will permanently delete{\" \"}\n {table.getSelectedRowModel().rows.length} selected{\" \"}\n {table.getSelectedRowModel().rows.length === 1\n ? \"row\"\n : \"rows\"}\n .\n \n \n
\n \n Cancel\n \n Delete\n \n \n \n \n )}\n {/* Add user button */}\n \n
\n
\n\n {/* Table */}\n
\n \n \n {table.getHeaderGroups().map((headerGroup) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : header.column.getCanSort() ? (\n {\n // Enhanced keyboard handling for sorting\n if (\n header.column.getCanSort() &&\n (e.key === \"Enter\" || e.key === \" \")\n ) {\n e.preventDefault();\n header.column.getToggleSortingHandler()?.(e);\n }\n }}\n tabIndex={header.column.getCanSort() ? 0 : undefined}\n >\n {flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )}\n {{\n asc: (\n \n ),\n desc: (\n \n ),\n }[header.column.getIsSorted() as string] ?? null}\n \n ) : (\n flexRender(\n header.column.columnDef.header,\n header.getContext(),\n )\n )}\n \n );\n })}\n \n ))}\n \n \n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n \n {row.getVisibleCells().map((cell) => (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n )}\n \n ))}\n \n ))\n ) : (\n \n \n No results.\n \n \n )}\n \n
\n
\n\n {/* Pagination */}\n
\n {/* Results per page */}\n
\n \n {\n table.setPageSize(Number(value));\n }}\n value={table.getState().pagination.pageSize.toString()}\n >\n \n \n \n span]:start-auto [&_*[role=option]>span]:end-2 [&_*[role=option]]:ps-2 [&_*[role=option]]:pe-8\">\n {[5, 10, 25, 50].map((pageSize) => (\n \n {pageSize}\n \n ))}\n \n \n
\n {/* Page number information */}\n
\n \n \n {table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n 1}\n -\n {Math.min(\n Math.max(\n table.getState().pagination.pageIndex *\n table.getState().pagination.pageSize +\n table.getState().pagination.pageSize,\n 0,\n ),\n table.getRowCount(),\n )}\n {\" \"}\n of{\" \"}\n \n {table.getRowCount().toString()}\n \n

\n
\n\n {/* Pagination buttons */}\n
\n \n \n {/* First page button */}\n \n table.firstPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Previous page button */}\n \n table.previousPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Next page button */}\n \n table.nextPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n {/* Last page button */}\n \n table.lastPage()}\n size=\"icon\"\n variant=\"outline\"\n >\n \n \n \n \n \n
\n
\n

\n Example of a more complex table made with{\" \"}\n \n TanStack Table\n \n

\n \n );\n}\n\nfunction RowActions({ row: _row }: { row: Row }) {\n return (\n \n \n
\n \n \n \n
\n
\n \n \n \n Edit\n ⌘E\n \n \n Duplicate\n ⌘D\n \n \n \n \n \n Archive\n ⌘A\n \n \n More\n \n \n Move to project\n Move to folder\n \n Advanced options\n \n \n \n \n \n \n Share\n Add to favorites\n \n \n \n Delete\n ⌘⌫\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "table", "tanstack", "checkbox", "sort", "flag", "badge", "chip", "pagination", "filter", "select" ] } } ================================================ FILE: apps/origin/public/r/comp-486.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-486", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-486.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n
\n \n \n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "range" ] } } ================================================ FILE: apps/origin/public/r/comp-487.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-487", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/calendar-rac.json" ], "files": [ { "path": "registry/default/components/comp-487.tsx", "content": "\"use client\";\n\nimport { getLocalTimeZone, today } from \"@internationalized/date\";\nimport { useState } from \"react\";\nimport type { DateValue } from \"react-aria-components\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar-rac\";\n\nexport default function Component() {\n const [date, setDate] = useState(today(getLocalTimeZone()));\n\n return (\n
\n \n \n Calendar -{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-488.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-488", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/calendar-rac.json" ], "files": [ { "path": "registry/default/components/comp-488.tsx", "content": "\"use client\";\n\nimport { getLocalTimeZone, today } from \"@internationalized/date\";\nimport { useState } from \"react\";\nimport type { DateRange } from \"react-aria-components\";\n\nimport { RangeCalendar } from \"@/registry/default/ui/calendar-rac\";\n\nexport default function Component() {\n const now = today(getLocalTimeZone());\n const [date, setDate] = useState({\n end: now.add({ days: 3 }),\n start: now,\n });\n\n return (\n
\n \n \n Range calendar -{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "range calendar", "date", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-489.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-489", "type": "registry:component", "dependencies": [ "react-aria-components" ], "registryDependencies": [ "https://coss.com/origin/r/calendar-rac.json" ], "files": [ { "path": "registry/default/components/comp-489.tsx", "content": "\"use client\";\n\nimport { getLocalTimeZone, isWeekend, today } from \"@internationalized/date\";\nimport { useLocale } from \"react-aria\";\nimport type { DateValue } from \"react-aria-components\";\n\nimport { RangeCalendar } from \"@/registry/default/ui/calendar-rac\";\n\nexport default function Component() {\n const now = today(getLocalTimeZone());\n const disabledRanges = [\n [now, now], // Disables today\n [now.add({ days: 14 }), now.add({ days: 14 })], // Disables only the 14th day from now\n [now.add({ days: 23 }), now.add({ days: 23 })], // Disables only the 23rd day from now\n ];\n\n const { locale } = useLocale();\n const isDateUnavailable = (date: DateValue) =>\n isWeekend(date, locale) ||\n disabledRanges.some(\n (interval) =>\n date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0,\n );\n\n return (\n
\n \n \n Disabled dates -{\" \"}\n \n React Aria\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "range calendar", "date", "disabled", "react aria" ] } } ================================================ FILE: apps/origin/public/r/comp-49.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-49", "type": "registry:component", "dependencies": [ "react-payment-inputs" ], "devDependencies": [ "@types/react-payment-inputs" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-49.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\nimport { usePaymentInputs } from \"react-payment-inputs\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const { getCVCProps } = usePaymentInputs();\n\n return (\n
\n \n \n \n Built with{\" \"}\n \n React Payment Inputs\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "checkout", "payment", "credit card", "form" ] } } ================================================ FILE: apps/origin/public/r/comp-490.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-490", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-490.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const [date, setDate] = useState(new Date());\n\n return (\n
\n \n \n Calendar -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-491.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-491", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-491.tsx", "content": "\"use client\";\n\nimport { addDays } from \"date-fns\";\nimport { useState } from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState({\n from: today,\n to: addDays(today, 3),\n });\n\n return (\n
\n \n \n Range calendar -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "range calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-492.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-492", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-492.tsx", "content": "import { addDays } from \"date-fns\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n\n return (\n
\n \n \n Disabled dates -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "range calendar", "date", "disabled", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-493.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-493", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-493.tsx", "content": "\"use client\";\n\nimport { addDays, subDays } from \"date-fns\";\nimport { useState } from \"react\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState([\n subDays(today, 17),\n addDays(today, 2),\n addDays(today, 6),\n addDays(today, 8),\n ]);\n\n return (\n
\n \n \n Multiple day selection -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-494.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-494", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-494.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const [date, setDate] = useState(new Date());\n\n return (\n
\n \n \n Custom select day style -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-495.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-495", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-495.tsx", "content": "\"use client\";\n\nimport { addDays } from \"date-fns\";\nimport { useState } from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState({\n from: today,\n to: addDays(today, 3),\n });\n\n return (\n
\n \n \n Custom select range style -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "range calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-496.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-496", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-496.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const [date, setDate] = useState(new Date());\n\n return (\n
\n \n \n Right navigation -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-497.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-497", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-497.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport type { DropdownNavProps, DropdownProps } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const [date, setDate] = useState(new Date());\n\n const handleCalendarChange = (\n _value: string | number,\n _e: React.ChangeEventHandler,\n ) => {\n const _event = {\n target: {\n value: String(_value),\n },\n } as React.ChangeEvent;\n _e(_event);\n };\n\n return (\n
\n {\n return (\n {\n if (props.onChange) {\n handleCalendarChange(value, props.onChange);\n }\n }}\n value={String(props.value)}\n >\n \n \n \n \n {props.options?.map((option) => (\n \n {option.label}\n \n ))}\n \n \n );\n },\n DropdownNav: (props: DropdownNavProps) => {\n return (\n
\n {props.children}\n
\n );\n },\n }}\n defaultMonth={new Date()}\n hideNavigation\n mode=\"single\"\n onSelect={setDate}\n selected={date}\n startMonth={new Date(1980, 6)}\n />\n \n Monthly / yearly selects -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-498.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-498", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-498.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport type { DropdownNavProps, DropdownProps } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n const [date, setDate] = useState(new Date());\n\n const handleCalendarChange = (\n _value: string | number,\n _e: React.ChangeEventHandler,\n ) => {\n const _event = {\n target: {\n value: String(_value),\n },\n } as React.ChangeEvent;\n _e(_event);\n };\n\n return (\n
\n {\n return (\n
span]:font-medium [&>span]:text-sm\">\n {props.children}\n
\n );\n },\n YearsDropdown: (props: DropdownProps) => {\n return (\n {\n if (props.onChange) {\n handleCalendarChange(value, props.onChange);\n }\n }}\n value={String(props.value)}\n >\n \n \n \n \n {props.options?.map((option) => (\n \n {option.label}\n \n ))}\n \n \n );\n },\n }}\n defaultMonth={new Date()}\n mode=\"single\"\n onSelect={setDate}\n selected={date}\n startMonth={new Date(1980, 6)}\n />\n \n Yearly select + nav -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-499.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-499", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-499.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\nimport type { WeekNumberProps } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const [date, setDate] = useState(new Date());\n\n return (\n
\n {\n return (\n \n \n {week.weekNumber}\n \n \n );\n },\n }}\n fixedWeeks\n mode=\"single\"\n onSelect={setDate}\n selected={date}\n showWeekNumber\n />\n \n Weekly numbers -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "week", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-50.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-50", "type": "registry:component", "dependencies": [ "react-payment-inputs" ], "devDependencies": [ "@types/react-payment-inputs" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-50.tsx", "content": "\"use client\";\n\nimport { CreditCardIcon } from \"lucide-react\";\nimport { useId } from \"react\";\nimport { usePaymentInputs } from \"react-payment-inputs\";\nimport images, { type CardImages } from \"react-payment-inputs/images\";\n\nimport { Input } from \"@/registry/default/ui/input\";\n\nexport default function Component() {\n const id = useId();\n const {\n meta,\n getCardNumberProps,\n getExpiryDateProps,\n getCVCProps,\n getCardImageProps,\n } = usePaymentInputs();\n\n return (\n
\n \n Card Details\n \n
\n
\n \n
\n {meta.cardType ? (\n \n ) : (\n \n )}\n
\n
\n
\n
\n \n
\n
\n \n
\n
\n
\n \n Built with{\" \"}\n \n React Payment Inputs\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "checkout", "payment", "credit card", "form" ] } } ================================================ FILE: apps/origin/public/r/comp-500.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-500", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-500.tsx", "content": "\"use client\";\n\nimport { addDays } from \"date-fns\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const selectedDay = addDays(today, -28);\n const [month, setMonth] = useState(selectedDay);\n const [date, setDate] = useState(selectedDay);\n\n return (\n
\n
\n \n setMonth(today)}\n size=\"sm\"\n variant=\"outline\"\n >\n Current month\n \n
\n \n With button -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "button", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-501.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-501", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-501.tsx", "content": "\"use client\";\n\nimport { addDays } from \"date-fns\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const selectedDay = addDays(today, -28);\n const [month, setMonth] = useState(selectedDay);\n const [date, setDate] = useState(selectedDay);\n\n return (\n
\n
\n \n {\n setDate(today);\n setMonth(today);\n }}\n size=\"sm\"\n variant=\"outline\"\n >\n Today\n \n
\n \n With button -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "button", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-502.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-502", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-502.tsx", "content": "\"use client\";\n\nimport { format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { useEffect, useId, useState } from \"react\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const today = new Date();\n const [month, setMonth] = useState(today);\n const [date, setDate] = useState(today);\n const [inputValue, setInputValue] = useState(\"\");\n\n const handleDayPickerSelect = (date: Date | undefined) => {\n if (!date) {\n setInputValue(\"\");\n setDate(undefined);\n } else {\n setDate(date);\n setMonth(date);\n setInputValue(format(date, \"yyyy-MM-dd\"));\n }\n };\n\n const handleInputChange = (e: React.ChangeEvent) => {\n const value = e.target.value;\n setInputValue(value);\n\n if (value) {\n const parsedDate = new Date(value);\n setDate(parsedDate);\n setMonth(parsedDate);\n } else {\n setDate(undefined);\n }\n };\n\n useEffect(() => {\n setInputValue(format(today, \"yyyy-MM-dd\"));\n }, [today]);\n\n return (\n
\n
\n \n
\n
\n \n
\n \n
\n \n
\n
\n
\n
\n
\n \n Date input -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "input", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-503.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-503", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-503.tsx", "content": "\"use client\";\n\nimport { ClockIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [date, setDate] = useState(new Date());\n\n return (\n
\n
\n \n
\n
\n \n
\n \n
\n \n
\n
\n
\n
\n
\n \n Time input -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "input", "time", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-504.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-504", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/collapsible.json", "https://coss.com/origin/r/scroll-area.json" ], "files": [ { "path": "registry/default/components/comp-504.tsx", "content": "\"use client\";\n\nimport {\n eachMonthOfInterval,\n eachYearOfInterval,\n endOfYear,\n format,\n isAfter,\n isBefore,\n startOfYear,\n} from \"date-fns\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport { useEffect, useRef, useState } from \"react\";\nimport type { CaptionLabelProps, MonthGridProps } from \"react-day-picker\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n} from \"@/registry/default/ui/collapsible\";\nimport { ScrollArea } from \"@/registry/default/ui/scroll-area\";\n\nexport default function Component() {\n const today = new Date();\n const [month, setMonth] = useState(today);\n const [date, setDate] = useState(today);\n const [isYearView, setIsYearView] = useState(false);\n const startDate = new Date(1980, 6);\n const endDate = new Date(2030, 6);\n\n const years = eachYearOfInterval({\n end: endOfYear(endDate),\n start: startOfYear(startDate),\n });\n\n return (\n
\n (\n \n ),\n MonthGrid: (props: MonthGridProps) => {\n return (\n {\n setMonth(selectedMonth);\n setIsYearView(false);\n }}\n setIsYearView={setIsYearView}\n startDate={startDate}\n years={years}\n >\n {props.children}\n \n );\n },\n }}\n defaultMonth={new Date()}\n endMonth={endDate}\n mode=\"single\"\n month={month}\n onMonthChange={setMonth}\n onSelect={setDate}\n selected={date}\n startMonth={startDate}\n />\n \n Advanced selection -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n\nfunction MonthGrid({\n className,\n children,\n isYearView,\n startDate,\n endDate,\n years,\n currentYear,\n currentMonth,\n onMonthSelect,\n}: {\n className?: string;\n children: React.ReactNode;\n isYearView: boolean;\n setIsYearView: React.Dispatch>;\n startDate: Date;\n endDate: Date;\n years: Date[];\n currentYear: number;\n currentMonth: number;\n onMonthSelect: (date: Date) => void;\n}) {\n const currentYearRef = useRef(null);\n const currentMonthButtonRef = useRef(null);\n const scrollAreaRef = useRef(null);\n\n useEffect(() => {\n if (isYearView && currentYearRef.current && scrollAreaRef.current) {\n const viewport = scrollAreaRef.current.querySelector(\n \"[data-radix-scroll-area-viewport]\",\n ) as HTMLElement;\n if (viewport) {\n const yearTop = currentYearRef.current.offsetTop;\n viewport.scrollTop = yearTop;\n }\n setTimeout(() => {\n currentMonthButtonRef.current?.focus();\n }, 100);\n }\n }, [isYearView]);\n\n return (\n
\n {children}
\n {isYearView && (\n
\n \n {years.map((year) => {\n const months = eachMonthOfInterval({\n end: endOfYear(year),\n start: startOfYear(year),\n });\n const isCurrentYear = year.getFullYear() === currentYear;\n\n return (\n \n \n
\n {months.map((month) => {\n const isDisabled =\n isBefore(month, startDate) || isAfter(month, endDate);\n const isCurrentMonth =\n month.getMonth() === currentMonth &&\n year.getFullYear() === currentYear;\n\n return (\n onMonthSelect(month)}\n ref={\n isCurrentMonth ? currentMonthButtonRef : undefined\n }\n size=\"sm\"\n variant={isCurrentMonth ? \"default\" : \"outline\"}\n >\n {format(month, \"MMM\")}\n \n );\n })}\n
\n \n
\n );\n })}\n \n
\n )}\n \n );\n}\n\nfunction CaptionLabel({\n children,\n isYearView,\n setIsYearView,\n}: {\n isYearView: boolean;\n setIsYearView: React.Dispatch>;\n} & React.HTMLAttributes) {\n return (\n svg]:rotate-180\"\n data-state={isYearView ? \"open\" : \"closed\"}\n onClick={() => setIsYearView((prev) => !prev)}\n size=\"sm\"\n variant=\"ghost\"\n >\n {children}\n \n \n );\n}\n\nfunction CollapsibleYear({\n title,\n children,\n open,\n}: {\n title: string;\n children: React.ReactNode;\n open?: boolean;\n}) {\n return (\n \n \n svg]:rotate-180\"\n size=\"sm\"\n variant=\"ghost\"\n >\n \n {title}\n \n \n \n {children}\n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "style": 1, "tags": [ "calendar", "date", "collapsible", "react daypicker", "radix" ] } } ================================================ FILE: apps/origin/public/r/comp-505.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-505", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/scroll-area.json" ], "files": [ { "path": "registry/default/components/comp-505.tsx", "content": "\"use client\";\n\nimport { format } from \"date-fns\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport { ScrollArea } from \"@/registry/default/ui/scroll-area\";\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState(today);\n const [time, setTime] = useState(null);\n\n // Mock time slots data\n const timeSlots = [\n { available: false, time: \"09:00\" },\n { available: false, time: \"09:30\" },\n { available: true, time: \"10:00\" },\n { available: true, time: \"10:30\" },\n { available: true, time: \"11:00\" },\n { available: true, time: \"11:30\" },\n { available: false, time: \"12:00\" },\n { available: true, time: \"12:30\" },\n { available: true, time: \"13:00\" },\n { available: true, time: \"13:30\" },\n { available: true, time: \"14:00\" },\n { available: false, time: \"14:30\" },\n { available: false, time: \"15:00\" },\n { available: true, time: \"15:30\" },\n { available: true, time: \"16:00\" },\n { available: true, time: \"16:30\" },\n { available: true, time: \"17:00\" },\n { available: true, time: \"17:30\" },\n ];\n\n return (\n
\n
\n
\n {\n if (newDate) {\n setDate(newDate);\n setTime(null);\n }\n }}\n selected={date}\n />\n
\n
\n \n
\n
\n

\n {format(date, \"EEEE, d\")}\n

\n
\n
\n {timeSlots.map(({ time: timeSlot, available }) => (\n setTime(timeSlot)}\n size=\"sm\"\n variant={time === timeSlot ? \"default\" : \"outline\"}\n >\n {timeSlot}\n \n ))}\n
\n
\n
\n
\n
\n
\n
\n \n Appointment picker -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "style": 1, "tags": [ "calendar", "date", "time", "button", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-506.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-506", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-506.tsx", "content": "\"use client\";\n\nimport { subDays, subMonths, subYears } from \"date-fns\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const yesterday = subDays(today, 1);\n const lastWeek = subDays(today, 7);\n const lastMonth = subMonths(today, 1);\n const lastYear = subYears(today, 1);\n const [month, setMonth] = useState(today);\n const [date, setDate] = useState(today);\n\n return (\n
\n
\n
\n
\n
\n
\n {\n setDate(today);\n setMonth(today);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Today\n \n {\n setDate(yesterday);\n setMonth(yesterday);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Yesterday\n \n {\n setDate(lastWeek);\n setMonth(lastWeek);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last week\n \n {\n setDate(lastMonth);\n setMonth(lastMonth);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last month\n \n {\n setDate(lastYear);\n setMonth(lastYear);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last year\n \n
\n
\n
\n {\n if (newDate) {\n setDate(newDate);\n }\n }}\n selected={date}\n />\n
\n
\n \n Calendar with presets -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "style": 1, "tags": [ "calendar", "date", "button", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-507.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-507", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-507.tsx", "content": "\"use client\";\n\nimport {\n endOfMonth,\n endOfYear,\n startOfMonth,\n startOfYear,\n subDays,\n subMonths,\n subYears,\n} from \"date-fns\";\nimport { useState } from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const yesterday = {\n from: subDays(today, 1),\n to: subDays(today, 1),\n };\n const last7Days = {\n from: subDays(today, 6),\n to: today,\n };\n const last30Days = {\n from: subDays(today, 29),\n to: today,\n };\n const monthToDate = {\n from: startOfMonth(today),\n to: today,\n };\n const lastMonth = {\n from: startOfMonth(subMonths(today, 1)),\n to: endOfMonth(subMonths(today, 1)),\n };\n const yearToDate = {\n from: startOfYear(today),\n to: today,\n };\n const lastYear = {\n from: startOfYear(subYears(today, 1)),\n to: endOfYear(subYears(today, 1)),\n };\n const [month, setMonth] = useState(today);\n const [date, setDate] = useState(last7Days);\n\n return (\n
\n
\n
\n
\n
\n
\n {\n setDate({\n from: today,\n to: today,\n });\n setMonth(today);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Today\n \n {\n setDate(yesterday);\n setMonth(yesterday.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Yesterday\n \n {\n setDate(last7Days);\n setMonth(last7Days.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last 7 days\n \n {\n setDate(last30Days);\n setMonth(last30Days.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last 30 days\n \n {\n setDate(monthToDate);\n setMonth(monthToDate.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Month to date\n \n {\n setDate(lastMonth);\n setMonth(lastMonth.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last month\n \n {\n setDate(yearToDate);\n setMonth(yearToDate.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Year to date\n \n {\n setDate(lastYear);\n setMonth(lastYear.to);\n }}\n size=\"sm\"\n variant=\"ghost\"\n >\n Last year\n \n
\n
\n
\n {\n if (newDate) {\n setDate(newDate);\n }\n }}\n selected={date}\n />\n
\n
\n \n Range calendar with presets -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "style": 1, "tags": [ "calendar", "range calendar", "date", "button", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-508.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-508", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-508.tsx", "content": "\"use client\";\n\nimport { addDays } from \"date-fns\";\nimport { useState } from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState({\n from: today,\n to: addDays(today, 25),\n });\n\n return (\n
\n \n \n Two months calendar -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "style": 1, "tags": [ "calendar", "range calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-509.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-509", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-509.tsx", "content": "\"use client\";\n\nimport { addDays } from \"date-fns\";\nimport { useState } from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState({\n from: today,\n to: addDays(today, 48),\n });\n\n return (\n
\n \n \n Three months calendar -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "style": 1, "tags": [ "calendar", "range calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-51.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-51", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-51.tsx", "content": "\"use client\";\n\nimport { CheckIcon, EyeIcon, EyeOffIcon, XIcon } from \"lucide-react\";\nimport { useId, useMemo, useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n const [password, setPassword] = useState(\"\");\n const [isVisible, setIsVisible] = useState(false);\n\n const toggleVisibility = () => setIsVisible((prevState) => !prevState);\n\n const checkStrength = (pass: string) => {\n const requirements = [\n { regex: /.{8,}/, text: \"At least 8 characters\" },\n { regex: /[0-9]/, text: \"At least 1 number\" },\n { regex: /[a-z]/, text: \"At least 1 lowercase letter\" },\n { regex: /[A-Z]/, text: \"At least 1 uppercase letter\" },\n ];\n\n return requirements.map((req) => ({\n met: req.regex.test(pass),\n text: req.text,\n }));\n };\n\n const strength = checkStrength(password);\n\n const strengthScore = useMemo(() => {\n return strength.filter((req) => req.met).length;\n }, [strength]);\n\n const getStrengthColor = (score: number) => {\n if (score === 0) return \"bg-border\";\n if (score <= 1) return \"bg-red-500\";\n if (score <= 2) return \"bg-orange-500\";\n if (score === 3) return \"bg-amber-500\";\n return \"bg-emerald-500\";\n };\n\n const getStrengthText = (score: number) => {\n if (score === 0) return \"Enter a password\";\n if (score <= 2) return \"Weak password\";\n if (score === 3) return \"Medium password\";\n return \"Strong password\";\n };\n\n return (\n
\n {/* Password input field with toggle visibility button */}\n
\n \n
\n setPassword(e.target.value)}\n placeholder=\"Password\"\n type={isVisible ? \"text\" : \"password\"}\n value={password}\n />\n \n {isVisible ? (\n \n ) : (\n \n )}\n \n
\n
\n\n {/* Password strength indicator */}\n \n \n
\n\n {/* Password strength description */}\n \n {getStrengthText(strengthScore)}. Must contain:\n

\n\n {/* Password requirements list */}\n
    \n {strength.map((req, _index) => (\n
  • \n {req.met ? (\n \n ) : (\n \n )}\n \n {req.text}\n \n {req.met ? \" - Requirement met\" : \" - Requirement not met\"}\n \n \n
  • \n ))}\n
\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "password" ] } } ================================================ FILE: apps/origin/public/r/comp-510.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-510", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/calendar.json" ], "files": [ { "path": "registry/default/components/comp-510.tsx", "content": "\"use client\";\n\nimport { format } from \"date-fns\";\nimport { useEffect, useState } from \"react\";\nimport type { DayButtonProps } from \"react-day-picker\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\n\nconst GOOD_PRICE_THRESHOLD = 100;\n\nexport default function Component() {\n const today = new Date();\n const [date, setDate] = useState(today);\n\n // Mock price data\n const [mockPriceData, setMockPriceData] = useState>(\n {},\n );\n useEffect(() => {\n const generateMockPriceData = () => {\n const data: Record = {};\n const todayDate = new Date();\n\n for (let i = 0; i < 180; i++) {\n const date = new Date(todayDate);\n date.setDate(todayDate.getDate() + i);\n const dateKey = format(date, \"yyyy-MM-dd\");\n const randomPrice = Math.floor(Math.random() * (200 - 80 + 1)) + 80;\n data[dateKey] = randomPrice;\n }\n return data;\n };\n setMockPriceData(generateMockPriceData());\n }, []);\n\n const isDateDisabled = (date: Date) => {\n return !mockPriceData[format(date, \"yyyy-MM-dd\")];\n };\n\n return (\n
\n (\n \n ),\n }}\n disabled={isDateDisabled}\n mode=\"single\"\n numberOfMonths={2}\n onSelect={setDate}\n pagedNavigation\n selected={date}\n showOutsideDays={false}\n />\n \n Pricing calendar -{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n\nfunction DayButton(props: DayButtonProps & { prices: Record }) {\n const { day, prices, ...buttonProps } = props;\n const price = prices[format(day.date, \"yyyy-MM-dd\")];\n const isGoodPrice = price < GOOD_PRICE_THRESHOLD;\n\n return (\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "style": 1, "tags": [ "calendar", "date", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-511.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-511", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-511.tsx", "content": "\"use client\";\n\nimport { format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nexport default function Component() {\n const id = useId();\n const [date, setDate] = useState();\n\n return (\n
\n
\n \n \n \n \n \n {date ? format(date, \"PPP\") : \"Pick a date\"}\n \n \n \n \n \n \n \n \n
\n \n Built with{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "calendar", "date", "button", "picker", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-512.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-512", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-512.tsx", "content": "\"use client\";\n\nimport { format } from \"date-fns\";\nimport { CalendarIcon } from \"lucide-react\";\nimport { useId, useState } from \"react\";\nimport type { DateRange } from \"react-day-picker\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nexport default function Component() {\n const id = useId();\n const [date, setDate] = useState();\n\n return (\n
\n
\n \n \n \n \n \n {date?.from ? (\n date.to ? (\n <>\n {format(date.from, \"LLL dd, y\")} -{\" \"}\n {format(date.to, \"LLL dd, y\")}\n \n ) : (\n format(date.from, \"LLL dd, y\")\n )\n ) : (\n \"Pick a date range\"\n )}\n \n \n \n \n \n \n \n \n
\n \n Built with{\" \"}\n \n React DayPicker\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "calendar", "date", "button", "picker", "react daypicker" ] } } ================================================ FILE: apps/origin/public/r/comp-513.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-513", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-513.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n return (\n
\n \n {steps.map((step) => (\n \n \n {step}\n \n {step < steps.length && }\n \n ))}\n \n \n Stepper with numbers only\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-514.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-514", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-514.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n return (\n
\n \n {steps.map((step) => (\n \n \n \n \n {step < steps.length && }\n \n ))}\n \n \n Stepper with numbers and checkmarks\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-515.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-515", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-515.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n return (\n
\n \n {steps.map((step) => (\n \n \n \n \n {step < steps.length && }\n \n ))}\n \n \n Stepper with tiny buttons and checkmarks\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-516.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-516", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-516.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n const [currentStep, setCurrentStep] = useState(2);\n\n return (\n
\n \n {steps.map((step) => (\n \n \n \n \n {step < steps.length && }\n \n ))}\n \n
\n setCurrentStep((prev) => prev - 1)}\n variant=\"outline\"\n >\n Prev step\n \n steps.length}\n onClick={() => setCurrentStep((prev) => prev + 1)}\n variant=\"outline\"\n >\n Next step\n \n
\n \n Controlled stepper with checkmarks\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-517.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-517", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-517.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n const [currentStep, setCurrentStep] = useState(2);\n const [isLoading, setIsLoading] = useState(false);\n\n const handleNextStep = () => {\n setIsLoading(true);\n setTimeout(() => {\n setCurrentStep((prev) => prev + 1);\n setIsLoading(false);\n }, 1000);\n };\n\n return (\n
\n \n {steps.map((step) => (\n \n \n \n \n {step < steps.length && }\n \n ))}\n \n
\n setCurrentStep((prev) => prev - 1)}\n variant=\"outline\"\n >\n Prev step\n \n steps.length}\n onClick={handleNextStep}\n variant=\"outline\"\n >\n Next step\n \n
\n \n Controlled stepper with checkmarks and loading state\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-518.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-518", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-518.tsx", "content": "import { Shuffle } from \"lucide-react\";\n\nimport {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n Shuffle\n \n \n \n \n \n Stepper with mixed elements\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-519.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-519", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-519.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n step: 1,\n title: \"Step One\",\n },\n {\n step: 2,\n title: \"Step Two\",\n },\n {\n step: 3,\n title: \"Step Three\",\n },\n {\n step: 4,\n title: \"Step Four\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title }) => (\n \n \n \n {step}\n \n
\n {title}\n
\n
\n
\n ))}\n
\n \n Stepper with labels\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-52.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-52", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-52.tsx", "content": "import { useId } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "read-only" ] } } ================================================ FILE: apps/origin/public/r/comp-520.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-520", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-520.tsx", "content": "\"use client\";\n\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n const [currentStep, setCurrentStep] = useState(2);\n\n return (\n
\n
\n setCurrentStep((prev) => prev - 1)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n \n {steps.map((step) => (\n \n \n \n {step}\n \n \n \n ))}\n \n setCurrentStep((prev) => prev + 1)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n
\n \n Paginated stepper\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-521.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-521", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-521.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n const [currentStep, setCurrentStep] = useState(1);\n\n return (\n
\n
\n \n {steps.map((step) => (\n \n \n \n {step}\n \n \n \n ))}\n \n
\n Step {currentStep} of {steps.length}\n
\n
\n
\n setCurrentStep((prev) => prev - 1)}\n variant=\"outline\"\n >\n Prev step\n \n = steps.length}\n onClick={() => setCurrentStep((prev) => prev + 1)}\n variant=\"outline\"\n >\n Next step\n \n
\n \n Progress stepper\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-522.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-522", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-522.tsx", "content": "import {\n Stepper,\n StepperDescription,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n description: \"Desc for step one\",\n step: 1,\n title: \"Step One\",\n },\n {\n description: \"Desc for step two\",\n step: 2,\n title: \"Step Two\",\n },\n {\n description: \"Desc for step three\",\n step: 3,\n title: \"Step Three\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title, description }) => (\n \n \n \n
\n {title}\n \n {description}\n \n
\n
\n {step < steps.length && (\n \n )}\n \n ))}\n
\n \n Stepper with titles and descriptions\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-523.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-523", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-523.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n step: 1,\n title: \"Step One\",\n },\n {\n step: 2,\n title: \"Step Two\",\n },\n {\n step: 3,\n title: \"Step Three\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title }) => (\n \n \n \n
\n {title}\n
\n
\n {step < steps.length && (\n \n )}\n \n ))}\n
\n \n Stepper with inline titles\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-524.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-524", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-524.tsx", "content": "import {\n Stepper,\n StepperDescription,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n description: \"Desc for step one\",\n step: 1,\n title: \"Step One\",\n },\n {\n description: \"Desc for step two\",\n step: 2,\n title: \"Step Two\",\n },\n {\n description: \"Desc for step three\",\n step: 3,\n title: \"Step Three\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title, description }) => (\n \n \n \n
\n {title}\n \n {description}\n \n
\n
\n {step < steps.length && (\n \n )}\n \n ))}\n
\n \n Stepper with inline titles and descriptions\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-525.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-525", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-525.tsx", "content": "import {\n Stepper,\n StepperDescription,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n description: \"Desc for step one\",\n step: 1,\n title: \"Step One\",\n },\n {\n description: \"Desc for step two\",\n step: 2,\n title: \"Step Two\",\n },\n {\n description: \"Desc for step three\",\n step: 3,\n title: \"Step Three\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title, description }) => (\n \n \n \n
\n {title}\n \n {description}\n \n
\n
\n {step < steps.length && (\n \n )}\n \n ))}\n
\n \n Stepper with inline titles and descriptions\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-526.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-526", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-526.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n return (\n
\n \n {steps.map((step) => (\n \n \n \n \n {step < steps.length && }\n \n ))}\n \n \n Vertical stepper with numbers and checkmarks\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "stepper", "vertical stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-527.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-527", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-527.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [1, 2, 3, 4];\n\nexport default function Component() {\n const [currentStep, setCurrentStep] = useState(1);\n return (\n
\n \n {steps.map((step) => (\n \n \n \n \n {step < steps.length && }\n \n ))}\n \n
\n setCurrentStep((prev) => prev - 1)}\n variant=\"outline\"\n >\n Prev step\n \n steps.length}\n onClick={() => setCurrentStep((prev) => prev + 1)}\n variant=\"outline\"\n >\n Next step\n \n
\n \n Controlled vertical stepper with checkmarks\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "stepper", "vertical stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-528.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-528", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-528.tsx", "content": "import {\n Stepper,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n step: 1,\n title: \"Step One\",\n },\n {\n step: 2,\n title: \"Step Two\",\n },\n {\n step: 3,\n title: \"Step Three\",\n },\n {\n step: 4,\n title: \"Step Four\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title }) => (\n \n \n \n
\n {title}\n
\n
\n {step < steps.length && (\n \n )}\n \n ))}\n
\n \n Vertical stepper with inline titles\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "stepper", "vertical stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-529.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-529", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/stepper.json" ], "files": [ { "path": "registry/default/components/comp-529.tsx", "content": "import {\n Stepper,\n StepperDescription,\n StepperIndicator,\n StepperItem,\n StepperSeparator,\n StepperTitle,\n StepperTrigger,\n} from \"@/registry/default/ui/stepper\";\n\nconst steps = [\n {\n description: \"Desc for step one\",\n step: 1,\n title: \"Step One\",\n },\n {\n description: \"Desc for step two\",\n step: 2,\n title: \"Step Two\",\n },\n {\n description: \"Desc for step three\",\n step: 3,\n title: \"Step Three\",\n },\n];\n\nexport default function Component() {\n return (\n
\n \n {steps.map(({ step, title, description }) => (\n \n \n \n
\n {title}\n {description}\n
\n
\n {step < steps.length && (\n \n )}\n \n ))}\n
\n \n Vertical stepper with inline titles and descriptions\n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "stepper", "vertical stepper" ] } } ================================================ FILE: apps/origin/public/r/comp-53.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-53", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-53.tsx", "content": "\"use client\";\n\nimport { CheckIcon, CopyIcon } from \"lucide-react\";\nimport { useId, useRef, useState } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\nexport default function Component() {\n const id = useId();\n const [copied, setCopied] = useState(false);\n const inputRef = useRef(null);\n\n const handleCopy = () => {\n if (inputRef.current) {\n navigator.clipboard.writeText(inputRef.current.value);\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n }\n };\n\n return (\n
\n \n
\n \n \n \n \n \n \n \n
\n \n \n
\n \n \n \n Copy to clipboard\n \n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "copy" ] } } ================================================ FILE: apps/origin/public/r/comp-530.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-530", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-530.tsx", "content": "import {\n Timeline,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n description:\n \"Initial team meeting and project scope definition. Established key milestones and resource allocation.\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n description:\n \"Completed wireframes and user interface mockups. Stakeholder review and feedback incorporated.\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n description:\n \"Backend API implementation and frontend component development in progress.\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n description:\n \"Quality assurance testing, performance optimization, and production deployment preparation.\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.title}\n \n \n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-531.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-531", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-531.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n description:\n \"Initial team meeting and project scope definition. Established key milestones and resource allocation.\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n description:\n \"Completed wireframes and user interface mockups. Stakeholder review and feedback incorporated.\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n description:\n \"Backend API implementation and frontend component development in progress.\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n description:\n \"Quality assurance testing, performance optimization, and production deployment preparation.\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n \n {item.date}\n \n {item.title}\n \n \n {item.description}\n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-532.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-532", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-532.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n description:\n \"Initial team meeting and project scope definition. Established key milestones and resource allocation.\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n description:\n \"Completed wireframes and user interface mockups. Stakeholder review and feedback incorporated.\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n description:\n \"Backend API implementation and frontend component development in progress.\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n description:\n \"Quality assurance testing, performance optimization, and production deployment preparation.\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.date}\n {item.title}\n \n \n {item.description}\n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-533.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-533", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-533.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"15 minutes ago\",\n description:\n \"Submitted PR #342 with new feature implementation. Waiting for code review from team leads.\",\n id: 1,\n title: \"Pull Request Submitted\",\n },\n {\n date: \"10 minutes ago\",\n description:\n \"Automated tests and build process initiated. Running unit tests and code quality checks.\",\n id: 2,\n title: \"CI Pipeline Started\",\n },\n {\n date: \"5 minutes ago\",\n description:\n \"Received comments on PR. Minor adjustments needed in error handling and documentation.\",\n id: 3,\n title: \"Code Review Feedback\",\n },\n {\n description:\n \"Implemented requested changes and pushed updates to feature branch. Awaiting final approval.\",\n id: 4,\n title: \"Changes Pushed\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.title}\n \n \n \n {item.description}\n {item.date}\n \n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-534.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-534", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-534.tsx", "content": "import { CheckIcon } from \"lucide-react\";\n\nimport {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n description:\n \"Initial team meeting and project scope definition. Established key milestones and resource allocation.\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n description:\n \"Completed wireframes and user interface mockups. Stakeholder review and feedback incorporated.\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n description:\n \"Backend API implementation and frontend component development in progress.\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n description:\n \"Quality assurance testing, performance optimization, and production deployment preparation.\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.date}\n {item.title}\n \n \n \n \n {item.description}\n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-535.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-535", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-535.tsx", "content": "import { GitCompare, GitFork, GitMerge, GitPullRequest } from \"lucide-react\";\n\nimport {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"15 minutes ago\",\n description:\n \"Forked the repository to create a new branch for development.\",\n icon: GitFork,\n id: 1,\n title: \"Forked Repository\",\n },\n {\n date: \"10 minutes ago\",\n description:\n \"Submitted PR #342 with new feature implementation. Waiting for code review from team leads.\",\n icon: GitPullRequest,\n id: 2,\n title: \"Pull Request Submitted\",\n },\n {\n date: \"5 minutes ago\",\n description:\n \"Received comments on PR. Minor adjustments needed in error handling and documentation.\",\n icon: GitCompare,\n id: 3,\n title: \"Comparing Branches\",\n },\n {\n description:\n \"Merged the feature branch into the main branch. Ready for deployment.\",\n icon: GitMerge,\n id: 4,\n title: \"Merged Branch\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.title}\n \n \n \n \n \n {item.description}\n {item.date}\n \n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-536.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-536", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-536.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n action: \"opened a new issue\",\n date: \"15 minutes ago\",\n description:\n \"I'm having trouble with the new component library. It's not rendering properly.\",\n id: 1,\n image: \"/origin/avatar-40-01.jpg\",\n title: \"Hannah Kandell\",\n },\n {\n action: \"commented on\",\n date: \"10 minutes ago\",\n description:\n \"Hey Hannah, I'm having trouble with the new component library. It's not rendering properly.\",\n id: 2,\n image: \"/origin/avatar-40-02.jpg\",\n title: \"Chris Tompson\",\n },\n {\n action: \"assigned you to\",\n date: \"5 minutes ago\",\n description:\n \"The new component library is not rendering properly. Can you take a look?\",\n id: 3,\n image: \"/origin/avatar-40-03.jpg\",\n title: \"Emma Davis\",\n },\n {\n action: \"closed the issue\",\n date: \"2 minutes ago\",\n description: \"The issue has been fixed. Please review the changes.\",\n id: 4,\n image: \"/origin/avatar-40-05.jpg\",\n title: \"Alex Morgan\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n \n {item.title}{\" \"}\n \n {item.action}\n \n \n \n \n \n \n \n {item.description}\n {item.date}\n \n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-537.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-537", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-537.tsx", "content": "import {\n Timeline,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n {\n date: \"May 3, 2024\",\n id: 5,\n title: \"User Training\",\n },\n {\n date: \"May 17, 2024\",\n id: 6,\n title: \"Project Handover\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.date}\n {item.title}\n \n \n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-538.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-538", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-538.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineItem,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: new Date(\"2024-01-09T10:55:00\"),\n description: \"System backup completed successfully.\",\n id: 1,\n },\n {\n date: new Date(\"2024-01-09T10:50:00\"),\n description:\n \"User authentication service restarted due to configuration update.\",\n id: 2,\n },\n {\n date: new Date(\"2024-01-09T10:45:00\"),\n description: \"Warning: High CPU usage detected on worker node-03.\",\n id: 3,\n },\n {\n date: new Date(\"2024-01-09T10:40:00\"),\n description: \"New deployment initiated for api-service v2.1.0.\",\n id: 4,\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n {item.description}\n \n {item.date.toLocaleDateString(\"en-US\", {\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n })}{\" \"}\n at{\" \"}\n {item.date.toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n hour12: true,\n minute: \"2-digit\",\n })}\n \n \n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-539.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-539", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-539.tsx", "content": "import {\n BookOpenIcon,\n type LucideIcon,\n MessageCircleIcon,\n PencilIcon,\n PlusIcon,\n} from \"lucide-react\";\n\nimport {\n Timeline,\n TimelineContent,\n TimelineItem,\n} from \"@/registry/default/ui/timeline\";\n\nconst items: {\n id: number;\n user: string;\n image: string;\n action: ActionType;\n date: Date;\n}[] = [\n {\n action: \"post\",\n date: new Date(Date.now() - 59000), // 59 seconds ago\n id: 1,\n image: \"/origin/avatar-40-02.jpg\",\n user: \"Matt\",\n },\n {\n action: \"reply\",\n date: new Date(Date.now() - 180000), // 3 minutes ago\n id: 2,\n image: \"/origin/avatar-40-02.jpg\",\n user: \"Matt\",\n },\n {\n action: \"edit\",\n date: new Date(Date.now() - 300000), // 5 minutes ago\n id: 3,\n image: \"/origin/avatar-40-02.jpg\",\n user: \"Matt\",\n },\n {\n action: \"create\",\n date: new Date(Date.now() - 600000), // 10 minutes ago\n id: 4,\n image: \"/origin/avatar-40-02.jpg\",\n user: \"Matt\",\n },\n];\n\ntype ActionType = \"post\" | \"reply\" | \"edit\" | \"create\";\n\nfunction getActionIcon(action: ActionType): LucideIcon {\n const icons: Record = {\n create: PlusIcon,\n edit: PencilIcon,\n post: BookOpenIcon,\n reply: MessageCircleIcon,\n };\n return icons[action];\n}\n\nfunction getActionText(action: ActionType): string {\n const texts: Record = {\n create: \"created a new project\",\n edit: \"edited a post\",\n post: \"wrote a new post\",\n reply: \"replied to a comment\",\n };\n return texts[action];\n}\n\nfunction getRelativeTimeString(date: Date): string {\n const now = new Date();\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);\n\n if (diffInSeconds < 60) {\n return `${diffInSeconds} seconds ago`;\n }\n if (diffInSeconds < 3600) {\n const minutes = Math.floor(diffInSeconds / 60);\n return `${minutes} ${minutes === 1 ? \"minute\" : \"minutes\"} ago`;\n }\n if (diffInSeconds < 86400) {\n const hours = Math.floor(diffInSeconds / 3600);\n return `${hours} ${hours === 1 ? \"hour\" : \"hours\"} ago`;\n }\n const days = Math.floor(diffInSeconds / 86400);\n return `${days} ${days === 1 ? \"day\" : \"days\"} ago`;\n}\n\nexport default function Component() {\n return (\n
\n
Activity
\n \n {items.map((item) => {\n const ActionIcon = getActionIcon(item.action);\n return (\n \n \n \n \n \n {item.user}\n \n \n {\" \"}\n {getActionText(item.action)}{\" \"}\n \n {getRelativeTimeString(item.date)}\n \n \n \n \n );\n })}\n \n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "timeline", "vertical timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-54.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-54", "type": "registry:component", "dependencies": [ "use-mask-input" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-54.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\nimport { withMask } from \"use-mask-input\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n {\n if (input) {\n withMask(\"AA99 AAA\", {\n placeholder: \"\",\n showMaskOnHover: false,\n })(input);\n }\n }}\n type=\"text\"\n />\n \n Built with{\" \"}\n \n use-mask-input\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "mask" ] } } ================================================ FILE: apps/origin/public/r/comp-540.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-540", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-540.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n description: \"Initial team meeting.\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n description: \"Completed wireframes.\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n description: \"Backend development.\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n description: \"Performance optimization.\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.date}\n {item.title}\n \n \n {item.description}\n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-541.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-541", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/timeline.json" ], "files": [ { "path": "registry/default/components/comp-541.tsx", "content": "import {\n Timeline,\n TimelineContent,\n TimelineDate,\n TimelineHeader,\n TimelineIndicator,\n TimelineItem,\n TimelineSeparator,\n TimelineTitle,\n} from \"@/registry/default/ui/timeline\";\n\nconst items = [\n {\n date: \"Mar 15, 2024\",\n description: \"Initial team meeting.\",\n id: 1,\n title: \"Project Kickoff\",\n },\n {\n date: \"Mar 22, 2024\",\n description: \"Completed wireframes.\",\n id: 2,\n title: \"Design Phase\",\n },\n {\n date: \"Apr 5, 2024\",\n description: \"Backend development.\",\n id: 3,\n title: \"Development Sprint\",\n },\n {\n date: \"Apr 19, 2024\",\n description: \"Performance optimization.\",\n id: 4,\n title: \"Testing & Deployment\",\n },\n];\n\nexport default function Component() {\n return (\n \n {items.map((item) => (\n \n \n \n {item.date}\n {item.title}\n \n \n {item.description}\n \n ))}\n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "timeline" ] } } ================================================ FILE: apps/origin/public/r/comp-542.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-542", "type": "registry:component", "dependencies": [ "date-fns", "@dnd-kit/core", "@dnd-kit/modifiers", "@dnd-kit/utilities", "@remixicon/react" ], "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/calendar.json", "https://coss.com/origin/r/checkbox.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/textarea.json", "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/radio-group.json", "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/sonner.json" ], "files": [ { "path": "registry/default/components/comp-542.tsx", "content": "\"use client\";\n\nimport { addDays, setHours, setMinutes, subDays } from \"date-fns\";\nimport { useState } from \"react\";\n\nimport {\n type CalendarEvent,\n EventCalendar,\n} from \"@/registry/default/components/event-calendar\";\n\n// Sample events data with hardcoded times\nconst sampleEvents: CalendarEvent[] = [\n {\n allDay: true,\n color: \"sky\",\n description: \"Strategic planning for next year\",\n end: subDays(new Date(), 23), // 23 days before today\n id: \"1\",\n location: \"Main Conference Hall\",\n start: subDays(new Date(), 24), // 24 days before today\n title: \"Annual Planning\",\n },\n {\n color: \"amber\",\n description: \"Submit final deliverables\",\n end: setMinutes(setHours(subDays(new Date(), 9), 15), 30), // 3:30 PM, 9 days before\n id: \"2\",\n location: \"Office\",\n start: setMinutes(setHours(subDays(new Date(), 9), 13), 0), // 1:00 PM, 9 days before\n title: \"Project Deadline\",\n },\n {\n allDay: true,\n color: \"orange\",\n description: \"Strategic planning for next year\",\n end: subDays(new Date(), 13), // 13 days before today\n id: \"3\",\n location: \"Main Conference Hall\",\n start: subDays(new Date(), 13), // 13 days before today\n title: \"Quarterly Budget Review\",\n },\n {\n color: \"sky\",\n description: \"Weekly team sync\",\n end: setMinutes(setHours(new Date(), 11), 0), // 11:00 AM today\n id: \"4\",\n location: \"Conference Room A\",\n start: setMinutes(setHours(new Date(), 10), 0), // 10:00 AM today\n title: \"Team Meeting\",\n },\n {\n color: \"emerald\",\n description: \"Discuss new project requirements\",\n end: setMinutes(setHours(addDays(new Date(), 1), 13), 15), // 1:15 PM, 1 day from now\n id: \"5\",\n location: \"Downtown Cafe\",\n start: setMinutes(setHours(addDays(new Date(), 1), 12), 0), // 12:00 PM, 1 day from now\n title: \"Lunch with Client\",\n },\n {\n allDay: true,\n color: \"violet\",\n description: \"New product release\",\n end: addDays(new Date(), 6), // 6 days from now\n id: \"6\",\n start: addDays(new Date(), 3), // 3 days from now\n title: \"Product Launch\",\n },\n {\n color: \"rose\",\n description: \"Discuss about new clients\",\n end: setMinutes(setHours(addDays(new Date(), 5), 14), 45), // 2:45 PM, 5 days from now\n id: \"7\",\n location: \"Downtown Cafe\",\n start: setMinutes(setHours(addDays(new Date(), 4), 14), 30), // 2:30 PM, 4 days from now\n title: \"Sales Conference\",\n },\n {\n color: \"orange\",\n description: \"Weekly team sync\",\n end: setMinutes(setHours(addDays(new Date(), 5), 10), 30), // 10:30 AM, 5 days from now\n id: \"8\",\n location: \"Conference Room A\",\n start: setMinutes(setHours(addDays(new Date(), 5), 9), 0), // 9:00 AM, 5 days from now\n title: \"Team Meeting\",\n },\n {\n color: \"sky\",\n description: \"Weekly team sync\",\n end: setMinutes(setHours(addDays(new Date(), 5), 15), 30), // 3:30 PM, 5 days from now\n id: \"9\",\n location: \"Conference Room A\",\n start: setMinutes(setHours(addDays(new Date(), 5), 14), 0), // 2:00 PM, 5 days from now\n title: \"Review contracts\",\n },\n {\n color: \"amber\",\n description: \"Weekly team sync\",\n end: setMinutes(setHours(addDays(new Date(), 5), 11), 0), // 11:00 AM, 5 days from now\n id: \"10\",\n location: \"Conference Room A\",\n start: setMinutes(setHours(addDays(new Date(), 5), 9), 45), // 9:45 AM, 5 days from now\n title: \"Team Meeting\",\n },\n {\n color: \"emerald\",\n description: \"Quarterly marketing planning\",\n end: setMinutes(setHours(addDays(new Date(), 9), 15), 30), // 3:30 PM, 9 days from now\n id: \"11\",\n location: \"Marketing Department\",\n start: setMinutes(setHours(addDays(new Date(), 9), 10), 0), // 10:00 AM, 9 days from now\n title: \"Marketing Strategy Session\",\n },\n {\n allDay: true,\n color: \"sky\",\n description: \"Presentation of yearly results\",\n end: addDays(new Date(), 17), // 17 days from now\n id: \"12\",\n location: \"Grand Conference Center\",\n start: addDays(new Date(), 17), // 17 days from now\n title: \"Annual Shareholders Meeting\",\n },\n {\n color: \"rose\",\n description: \"Brainstorming for new features\",\n end: setMinutes(setHours(addDays(new Date(), 27), 17), 0), // 5:00 PM, 27 days from now\n id: \"13\",\n location: \"Innovation Lab\",\n start: setMinutes(setHours(addDays(new Date(), 26), 9), 0), // 9:00 AM, 26 days from now\n title: \"Product Development Workshop\",\n },\n];\n\nexport default function Component() {\n const [events, setEvents] = useState(sampleEvents);\n\n const handleEventAdd = (event: CalendarEvent) => {\n setEvents([...events, event]);\n };\n\n const handleEventUpdate = (updatedEvent: CalendarEvent) => {\n setEvents(\n events.map((event) =>\n event.id === updatedEvent.id ? updatedEvent : event,\n ),\n );\n };\n\n const handleEventDelete = (eventId: string) => {\n setEvents(events.filter((event) => event.id !== eventId));\n };\n\n return (\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/agenda-view.tsx", "content": "\"use client\";\n\nimport { RiCalendarEventLine } from \"@remixicon/react\";\nimport { addDays, format, isToday } from \"date-fns\";\nimport { useMemo } from \"react\";\n\nimport {\n AgendaDaysToShow,\n type CalendarEvent,\n EventItem,\n getAgendaEventsForDay,\n} from \"@/registry/default/components/event-calendar\";\n\ninterface AgendaViewProps {\n currentDate: Date;\n events: CalendarEvent[];\n onEventSelect: (event: CalendarEvent) => void;\n}\n\nexport function AgendaView({\n currentDate,\n events,\n onEventSelect,\n}: AgendaViewProps) {\n // Show events for the next days based on constant\n const days = useMemo(() => {\n console.log(\"Agenda view updating with date:\", currentDate.toISOString());\n return Array.from({ length: AgendaDaysToShow }, (_, i) =>\n addDays(new Date(currentDate), i),\n );\n }, [currentDate]);\n\n const handleEventClick = (event: CalendarEvent, e: React.MouseEvent) => {\n e.stopPropagation();\n console.log(\"Agenda view event clicked:\", event);\n onEventSelect(event);\n };\n\n // Check if there are any days with events\n const hasEvents = days.some(\n (day) => getAgendaEventsForDay(events, day).length > 0,\n );\n\n return (\n
\n {!hasEvents ? (\n
\n \n

No events found

\n

\n There are no events scheduled for this time period.\n

\n
\n ) : (\n days.map((day) => {\n const dayEvents = getAgendaEventsForDay(events, day);\n\n if (dayEvents.length === 0) return null;\n\n return (\n \n \n {format(day, \"d MMM, EEEE\")}\n \n
\n {dayEvents.map((event) => (\n handleEventClick(event, e)}\n view=\"agenda\"\n />\n ))}\n
\n
\n );\n })\n )}\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/calendar-dnd-context.tsx", "content": "\"use client\";\n\nimport {\n DndContext,\n type DragEndEvent,\n type DragOverEvent,\n DragOverlay,\n type DragStartEvent,\n MouseSensor,\n PointerSensor,\n TouchSensor,\n type UniqueIdentifier,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { addMinutes, differenceInMinutes } from \"date-fns\";\nimport {\n createContext,\n type ReactNode,\n useContext,\n useId,\n useRef,\n useState,\n} from \"react\";\n\nimport {\n type CalendarEvent,\n EventItem,\n} from \"@/registry/default/components/event-calendar\";\n\n// Define the context type\ntype CalendarDndContextType = {\n activeEvent: CalendarEvent | null;\n activeId: UniqueIdentifier | null;\n activeView: \"month\" | \"week\" | \"day\" | null;\n currentTime: Date | null;\n eventHeight: number | null;\n isMultiDay: boolean;\n multiDayWidth: number | null;\n dragHandlePosition: {\n x?: number;\n y?: number;\n data?: {\n isFirstDay?: boolean;\n isLastDay?: boolean;\n };\n } | null;\n};\n\n// Create the context\nconst CalendarDndContext = createContext({\n activeEvent: null,\n activeId: null,\n activeView: null,\n currentTime: null,\n dragHandlePosition: null,\n eventHeight: null,\n isMultiDay: false,\n multiDayWidth: null,\n});\n\n// Hook to use the context\nexport const useCalendarDnd = () => useContext(CalendarDndContext);\n\n// Props for the provider\ninterface CalendarDndProviderProps {\n children: ReactNode;\n onEventUpdate: (event: CalendarEvent) => void;\n}\n\nexport function CalendarDndProvider({\n children,\n onEventUpdate,\n}: CalendarDndProviderProps) {\n const [activeEvent, setActiveEvent] = useState(null);\n const [activeId, setActiveId] = useState(null);\n const [activeView, setActiveView] = useState<\"month\" | \"week\" | \"day\" | null>(\n null,\n );\n const [currentTime, setCurrentTime] = useState(null);\n const [eventHeight, setEventHeight] = useState(null);\n const [isMultiDay, setIsMultiDay] = useState(false);\n const [multiDayWidth, setMultiDayWidth] = useState(null);\n const [dragHandlePosition, setDragHandlePosition] = useState<{\n x?: number;\n y?: number;\n data?: {\n isFirstDay?: boolean;\n isLastDay?: boolean;\n };\n } | null>(null);\n\n // Store original event dimensions\n const eventDimensions = useRef<{ height: number }>({ height: 0 });\n\n // Configure sensors for better drag detection\n const sensors = useSensors(\n useSensor(MouseSensor, {\n // Require the mouse to move by 5px before activating\n activationConstraint: {\n distance: 5,\n },\n }),\n useSensor(TouchSensor, {\n // Press delay of 250ms, with tolerance of 5px of movement\n activationConstraint: {\n delay: 250,\n tolerance: 5,\n },\n }),\n useSensor(PointerSensor, {\n // Require the pointer to move by 5px before activating\n activationConstraint: {\n distance: 5,\n },\n }),\n );\n\n // Generate a stable ID for the DndContext\n const dndContextId = useId();\n\n const handleDragStart = (event: DragStartEvent) => {\n const { active } = event;\n\n // Add safety check for data.current\n if (!active.data.current) {\n console.error(\"Missing data in drag start event\", event);\n return;\n }\n\n const {\n event: calendarEvent,\n view,\n height,\n isMultiDay: eventIsMultiDay,\n multiDayWidth: eventMultiDayWidth,\n dragHandlePosition: eventDragHandlePosition,\n } = active.data.current as {\n event: CalendarEvent;\n view: \"month\" | \"week\" | \"day\";\n height?: number;\n isMultiDay?: boolean;\n multiDayWidth?: number;\n dragHandlePosition?: {\n x?: number;\n y?: number;\n data?: {\n isFirstDay?: boolean;\n isLastDay?: boolean;\n };\n };\n };\n\n setActiveEvent(calendarEvent);\n setActiveId(active.id);\n setActiveView(view);\n setCurrentTime(new Date(calendarEvent.start));\n setIsMultiDay(eventIsMultiDay || false);\n setMultiDayWidth(eventMultiDayWidth || null);\n setDragHandlePosition(eventDragHandlePosition || null);\n\n // Store event height if provided\n if (height) {\n eventDimensions.current.height = height;\n setEventHeight(height);\n }\n };\n\n const handleDragOver = (event: DragOverEvent) => {\n const { over } = event;\n\n if (over && activeEvent && over.data.current) {\n const { date, time } = over.data.current as { date: Date; time?: number };\n\n // Update time for week/day views\n if (time !== undefined && activeView !== \"month\") {\n const newTime = new Date(date);\n\n // Calculate hours and minutes with 15-minute precision\n const hours = Math.floor(time);\n const fractionalHour = time - hours;\n\n // Map to nearest 15 minute interval (0, 0.25, 0.5, 0.75)\n let minutes = 0;\n if (fractionalHour < 0.125) minutes = 0;\n else if (fractionalHour < 0.375) minutes = 15;\n else if (fractionalHour < 0.625) minutes = 30;\n else minutes = 45;\n\n newTime.setHours(hours, minutes, 0, 0);\n\n // Only update if time has changed\n if (\n !currentTime ||\n newTime.getHours() !== currentTime.getHours() ||\n newTime.getMinutes() !== currentTime.getMinutes() ||\n newTime.getDate() !== currentTime.getDate() ||\n newTime.getMonth() !== currentTime.getMonth() ||\n newTime.getFullYear() !== currentTime.getFullYear()\n ) {\n setCurrentTime(newTime);\n }\n } else if (activeView === \"month\") {\n // For month view, just update the date but preserve time\n const newTime = new Date(date);\n if (currentTime) {\n newTime.setHours(\n currentTime.getHours(),\n currentTime.getMinutes(),\n currentTime.getSeconds(),\n currentTime.getMilliseconds(),\n );\n }\n\n // Only update if date has changed\n if (\n !currentTime ||\n newTime.getDate() !== currentTime.getDate() ||\n newTime.getMonth() !== currentTime.getMonth() ||\n newTime.getFullYear() !== currentTime.getFullYear()\n ) {\n setCurrentTime(newTime);\n }\n }\n }\n };\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n\n // Add robust error checking\n if (!over || !activeEvent || !currentTime) {\n // Reset state and exit early\n setActiveEvent(null);\n setActiveId(null);\n setActiveView(null);\n setCurrentTime(null);\n setEventHeight(null);\n setIsMultiDay(false);\n setMultiDayWidth(null);\n setDragHandlePosition(null);\n return;\n }\n\n try {\n // Safely access data with checks\n if (!active.data.current || !over.data.current) {\n throw new Error(\"Missing data in drag event\");\n }\n\n const activeData = active.data.current as {\n event?: CalendarEvent;\n view?: string;\n };\n const overData = over.data.current as { date?: Date; time?: number };\n\n // Verify we have all required data\n if (!activeData.event || !overData.date) {\n throw new Error(\"Missing required event data\");\n }\n\n const calendarEvent = activeData.event;\n const date = overData.date;\n const time = overData.time;\n\n // Calculate new start time\n const newStart = new Date(date);\n\n // If time is provided (for week/day views), set the hours and minutes\n if (time !== undefined) {\n const hours = Math.floor(time);\n const fractionalHour = time - hours;\n\n // Map to nearest 15 minute interval (0, 0.25, 0.5, 0.75)\n let minutes = 0;\n if (fractionalHour < 0.125) minutes = 0;\n else if (fractionalHour < 0.375) minutes = 15;\n else if (fractionalHour < 0.625) minutes = 30;\n else minutes = 45;\n\n newStart.setHours(hours, minutes, 0, 0);\n } else {\n // For month view, preserve the original time from currentTime\n newStart.setHours(\n currentTime.getHours(),\n currentTime.getMinutes(),\n currentTime.getSeconds(),\n currentTime.getMilliseconds(),\n );\n }\n\n // Calculate new end time based on the original duration\n const originalStart = new Date(calendarEvent.start);\n const originalEnd = new Date(calendarEvent.end);\n const durationMinutes = differenceInMinutes(originalEnd, originalStart);\n const newEnd = addMinutes(newStart, durationMinutes);\n\n // Only update if the start time has actually changed\n const hasStartTimeChanged =\n originalStart.getFullYear() !== newStart.getFullYear() ||\n originalStart.getMonth() !== newStart.getMonth() ||\n originalStart.getDate() !== newStart.getDate() ||\n originalStart.getHours() !== newStart.getHours() ||\n originalStart.getMinutes() !== newStart.getMinutes();\n\n if (hasStartTimeChanged) {\n // Update the event only if the time has changed\n onEventUpdate({\n ...calendarEvent,\n end: newEnd,\n start: newStart,\n });\n }\n } catch (error) {\n console.error(\"Error in drag end handler:\", error);\n } finally {\n // Always reset state\n setActiveEvent(null);\n setActiveId(null);\n setActiveView(null);\n setCurrentTime(null);\n setEventHeight(null);\n setIsMultiDay(false);\n setMultiDayWidth(null);\n setDragHandlePosition(null);\n }\n };\n\n return (\n \n \n {children}\n\n \n {activeEvent && activeView && (\n \n \n \n )}\n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/constants.ts", "content": "// Height of calendar events in pixels - used in month, week and day views\nexport const EventHeight = 24;\n\n// Vertical gap between events in pixels - controls spacing in month view\nexport const EventGap = 4;\n\n// Height of hour cells in week and day views - controls the scale of time display\nexport const WeekCellsHeight = 64;\n\n// Number of days to show in the agenda view\nexport const AgendaDaysToShow = 30;\n\n// Start and end hours for the week and day views\nexport const StartHour = 0;\nexport const EndHour = 24;\n\n// Default start and end times\nexport const DefaultStartHour = 9; // 9 AM\nexport const DefaultEndHour = 10; // 10 AM\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/day-view.tsx", "content": "\"use client\";\n\nimport {\n addHours,\n areIntervalsOverlapping,\n differenceInMinutes,\n eachHourOfInterval,\n format,\n getHours,\n getMinutes,\n isSameDay,\n startOfDay,\n} from \"date-fns\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\n\nimport {\n type CalendarEvent,\n DraggableEvent,\n DroppableCell,\n EventItem,\n isMultiDayEvent,\n useCurrentTimeIndicator,\n WeekCellsHeight,\n} from \"@/registry/default/components/event-calendar\";\nimport {\n EndHour,\n StartHour,\n} from \"@/registry/default/components/event-calendar/constants\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\ninterface DayViewProps {\n currentDate: Date;\n events: CalendarEvent[];\n onEventSelect: (event: CalendarEvent) => void;\n onEventCreate: (startTime: Date) => void;\n}\n\ninterface PositionedEvent {\n event: CalendarEvent;\n top: number;\n height: number;\n left: number;\n width: number;\n zIndex: number;\n}\n\nexport function DayView({\n currentDate,\n events,\n onEventSelect,\n onEventCreate,\n}: DayViewProps) {\n const hours = useMemo(() => {\n const dayStart = startOfDay(currentDate);\n return eachHourOfInterval({\n end: addHours(dayStart, EndHour - 1),\n start: addHours(dayStart, StartHour),\n });\n }, [currentDate]);\n\n const dayEvents = useMemo(() => {\n return events\n .filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return (\n isSameDay(currentDate, eventStart) ||\n isSameDay(currentDate, eventEnd) ||\n (currentDate > eventStart && currentDate < eventEnd)\n );\n })\n .sort(\n (a, b) => new Date(a.start).getTime() - new Date(b.start).getTime(),\n );\n }, [currentDate, events]);\n\n // Filter all-day events\n const allDayEvents = useMemo(() => {\n return dayEvents.filter((event) => {\n // Include explicitly marked all-day events or multi-day events\n return event.allDay || isMultiDayEvent(event);\n });\n }, [dayEvents]);\n\n // Get only single-day time-based events\n const timeEvents = useMemo(() => {\n return dayEvents.filter((event) => {\n // Exclude all-day events and multi-day events\n return !event.allDay && !isMultiDayEvent(event);\n });\n }, [dayEvents]);\n\n // Process events to calculate positions\n const positionedEvents = useMemo(() => {\n const result: PositionedEvent[] = [];\n const dayStart = startOfDay(currentDate);\n\n // Sort events by start time and duration\n const sortedEvents = [...timeEvents].sort((a, b) => {\n const aStart = new Date(a.start);\n const bStart = new Date(b.start);\n const aEnd = new Date(a.end);\n const bEnd = new Date(b.end);\n\n // First sort by start time\n if (aStart < bStart) return -1;\n if (aStart > bStart) return 1;\n\n // If start times are equal, sort by duration (longer events first)\n const aDuration = differenceInMinutes(aEnd, aStart);\n const bDuration = differenceInMinutes(bEnd, bStart);\n return bDuration - aDuration;\n });\n\n // Track columns for overlapping events\n const columns: { event: CalendarEvent; end: Date }[][] = [];\n\n for (const event of sortedEvents) {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n\n // Adjust start and end times if they're outside this day\n const adjustedStart = isSameDay(currentDate, eventStart)\n ? eventStart\n : dayStart;\n const adjustedEnd = isSameDay(currentDate, eventEnd)\n ? eventEnd\n : addHours(dayStart, 24);\n\n // Calculate top position and height\n const startHour =\n getHours(adjustedStart) + getMinutes(adjustedStart) / 60;\n const endHour = getHours(adjustedEnd) + getMinutes(adjustedEnd) / 60;\n\n const top = (startHour - StartHour) * WeekCellsHeight;\n const height = (endHour - startHour) * WeekCellsHeight;\n\n // Find a column for this event\n let columnIndex = 0;\n let placed = false;\n\n while (!placed) {\n const col = columns[columnIndex] || [];\n if (col.length === 0) {\n columns[columnIndex] = col;\n placed = true;\n } else {\n const overlaps = col.some((c) =>\n areIntervalsOverlapping(\n { end: adjustedEnd, start: adjustedStart },\n { end: new Date(c.event.end), start: new Date(c.event.start) },\n ),\n );\n\n if (!overlaps) {\n placed = true;\n } else {\n columnIndex++;\n }\n }\n }\n\n // Ensure column is initialized before pushing\n const currentColumn = columns[columnIndex] || [];\n columns[columnIndex] = currentColumn;\n currentColumn.push({ end: adjustedEnd, event });\n\n // First column takes full width, others are indented by 10% and take 90% width\n const width = columnIndex === 0 ? 1 : 0.9;\n const left = columnIndex === 0 ? 0 : columnIndex * 0.1;\n\n result.push({\n event,\n height,\n left,\n top,\n width,\n zIndex: 10 + columnIndex,\n });\n }\n\n return result;\n }, [currentDate, timeEvents]);\n\n const handleEventClick = (event: CalendarEvent, e: React.MouseEvent) => {\n e.stopPropagation();\n onEventSelect(event);\n };\n\n const showAllDaySection = allDayEvents.length > 0;\n const { currentTimePosition, currentTimeVisible } = useCurrentTimeIndicator(\n currentDate,\n \"day\",\n );\n\n return (\n
\n {showAllDaySection && (\n
\n
\n
\n \n All day\n \n
\n
\n {allDayEvents.map((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n const isFirstDay = isSameDay(currentDate, eventStart);\n const isLastDay = isSameDay(currentDate, eventEnd);\n\n return (\n handleEventClick(event, e)}\n view=\"month\"\n >\n {/* Always show the title in day view for better usability */}\n
{event.title}
\n \n );\n })}\n
\n
\n
\n )}\n\n
\n
\n {hours.map((hour, index) => (\n \n {index > 0 && (\n \n {format(hour, \"h a\")}\n \n )}\n
\n ))}\n
\n\n
\n {/* Positioned events */}\n {positionedEvents.map((positionedEvent) => (\n \n
\n handleEventClick(positionedEvent.event, e)}\n showTime\n view=\"day\"\n />\n
\n
\n ))}\n\n {/* Current time indicator */}\n {currentTimeVisible && (\n \n
\n
\n
\n
\n
\n )}\n\n {/* Time grid */}\n {hours.map((hour) => {\n const hourValue = getHours(hour);\n return (\n \n {/* Quarter-hour intervals */}\n {[0, 1, 2, 3].map((quarter) => {\n const quarterHourTime = hourValue + quarter * 0.25;\n return (\n {\n const startTime = new Date(currentDate);\n startTime.setHours(hourValue);\n startTime.setMinutes(quarter * 15);\n onEventCreate(startTime);\n }}\n time={quarterHourTime}\n />\n );\n })}\n
\n );\n })}\n
\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/draggable-event.tsx", "content": "\"use client\";\n\nimport { useDraggable } from \"@dnd-kit/core\";\nimport { CSS } from \"@dnd-kit/utilities\";\nimport { differenceInDays } from \"date-fns\";\nimport { useRef, useState } from \"react\";\n\nimport {\n type CalendarEvent,\n EventItem,\n useCalendarDnd,\n} from \"@/registry/default/components/event-calendar\";\n\ninterface DraggableEventProps {\n event: CalendarEvent;\n view: \"month\" | \"week\" | \"day\";\n showTime?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n height?: number;\n isMultiDay?: boolean;\n multiDayWidth?: number;\n isFirstDay?: boolean;\n isLastDay?: boolean;\n \"aria-hidden\"?: boolean | \"true\" | \"false\";\n}\n\nexport function DraggableEvent({\n event,\n view,\n showTime,\n onClick,\n height,\n isMultiDay,\n multiDayWidth,\n isFirstDay = true,\n isLastDay = true,\n \"aria-hidden\": ariaHidden,\n}: DraggableEventProps) {\n const { activeId } = useCalendarDnd();\n const elementRef = useRef(null);\n const [dragHandlePosition, setDragHandlePosition] = useState<{\n x: number;\n y: number;\n } | null>(null);\n\n // Check if this is a multi-day event\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n const isMultiDayEvent =\n isMultiDay || event.allDay || differenceInDays(eventEnd, eventStart) >= 1;\n\n const { attributes, listeners, setNodeRef, transform, isDragging } =\n useDraggable({\n data: {\n dragHandlePosition,\n event,\n height: height || elementRef.current?.offsetHeight || null,\n isFirstDay,\n isLastDay,\n isMultiDay: isMultiDayEvent,\n multiDayWidth: multiDayWidth,\n view,\n },\n id: `${event.id}-${view}`,\n });\n\n // Handle mouse down to track where on the event the user clicked\n const handleMouseDown = (e: React.MouseEvent) => {\n if (elementRef.current) {\n const rect = elementRef.current.getBoundingClientRect();\n setDragHandlePosition({\n x: e.clientX - rect.left,\n y: e.clientY - rect.top,\n });\n }\n };\n\n // Don't render if this event is being dragged\n if (isDragging || activeId === `${event.id}-${view}`) {\n return (\n \n );\n }\n\n const style = transform\n ? {\n height: height || \"auto\",\n transform: CSS.Translate.toString(transform),\n width:\n isMultiDayEvent && multiDayWidth ? `${multiDayWidth}%` : undefined,\n }\n : {\n height: height || \"auto\",\n width:\n isMultiDayEvent && multiDayWidth ? `${multiDayWidth}%` : undefined,\n };\n\n // Handle touch start to track where on the event the user touched\n const handleTouchStart = (e: React.TouchEvent) => {\n if (elementRef.current) {\n const rect = elementRef.current.getBoundingClientRect();\n const touch = e.touches[0];\n if (touch) {\n setDragHandlePosition({\n x: touch.clientX - rect.left,\n y: touch.clientY - rect.top,\n });\n }\n }\n };\n\n return (\n {\n setNodeRef(node);\n if (elementRef) elementRef.current = node;\n }}\n style={style}\n >\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/droppable-cell.tsx", "content": "\"use client\";\n\nimport { useDroppable } from \"@dnd-kit/core\";\n\nimport { useCalendarDnd } from \"@/registry/default/components/event-calendar\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\ninterface DroppableCellProps {\n id: string;\n date: Date;\n time?: number; // For week/day views, represents hours (e.g., 9.25 for 9:15)\n children?: React.ReactNode;\n className?: string;\n onClick?: () => void;\n}\n\nexport function DroppableCell({\n id,\n date,\n time,\n children,\n className,\n onClick,\n}: DroppableCellProps) {\n const { activeEvent } = useCalendarDnd();\n\n const { setNodeRef, isOver } = useDroppable({\n data: {\n date,\n time,\n },\n id,\n });\n\n // Format time for display in tooltip (only for debugging)\n const formattedTime =\n time !== undefined\n ? `${Math.floor(time)}:${Math.round((time - Math.floor(time)) * 60)\n .toString()\n .padStart(2, \"0\")}`\n : null;\n\n return (\n \n {children}\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/event-dialog.tsx", "content": "\"use client\";\n\nimport { RiCalendarLine, RiDeleteBinLine } from \"@remixicon/react\";\nimport { format, isBefore } from \"date-fns\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\n\nimport type {\n CalendarEvent,\n EventColor,\n} from \"@/registry/default/components/event-calendar\";\nimport {\n DefaultEndHour,\n DefaultStartHour,\n EndHour,\n StartHour,\n} from \"@/registry/default/components/event-calendar/constants\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Calendar } from \"@/registry/default/ui/calendar\";\nimport { Checkbox } from \"@/registry/default/ui/checkbox\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@/registry/default/ui/dialog\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport { RadioGroup, RadioGroupItem } from \"@/registry/default/ui/radio-group\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\ninterface EventDialogProps {\n event: CalendarEvent | null;\n isOpen: boolean;\n onClose: () => void;\n onSave: (event: CalendarEvent) => void;\n onDelete: (eventId: string) => void;\n}\n\nexport function EventDialog({\n event,\n isOpen,\n onClose,\n onSave,\n onDelete,\n}: EventDialogProps) {\n const [title, setTitle] = useState(\"\");\n const [description, setDescription] = useState(\"\");\n const [startDate, setStartDate] = useState(new Date());\n const [endDate, setEndDate] = useState(new Date());\n const [startTime, setStartTime] = useState(`${DefaultStartHour}:00`);\n const [endTime, setEndTime] = useState(`${DefaultEndHour}:00`);\n const [allDay, setAllDay] = useState(false);\n const [location, setLocation] = useState(\"\");\n const [color, setColor] = useState(\"sky\");\n const [error, setError] = useState(null);\n const [startDateOpen, setStartDateOpen] = useState(false);\n const [endDateOpen, setEndDateOpen] = useState(false);\n\n // Debug log to check what event is being passed\n useEffect(() => {\n console.log(\"EventDialog received event:\", event);\n }, [event]);\n\n const resetForm = useCallback(() => {\n setTitle(\"\");\n setDescription(\"\");\n setStartDate(new Date());\n setEndDate(new Date());\n setStartTime(`${DefaultStartHour}:00`);\n setEndTime(`${DefaultEndHour}:00`);\n setAllDay(false);\n setLocation(\"\");\n setColor(\"sky\");\n setError(null);\n }, []);\n\n const formatTimeForInput = useCallback((date: Date) => {\n const hours = date.getHours().toString().padStart(2, \"0\");\n const minutes = Math.floor(date.getMinutes() / 15) * 15;\n return `${hours}:${minutes.toString().padStart(2, \"0\")}`;\n }, []);\n\n useEffect(() => {\n if (event) {\n setTitle(event.title || \"\");\n setDescription(event.description || \"\");\n\n const start = new Date(event.start);\n const end = new Date(event.end);\n\n setStartDate(start);\n setEndDate(end);\n setStartTime(formatTimeForInput(start));\n setEndTime(formatTimeForInput(end));\n setAllDay(event.allDay || false);\n setLocation(event.location || \"\");\n setColor((event.color as EventColor) || \"sky\");\n setError(null); // Reset error when opening dialog\n } else {\n resetForm();\n }\n }, [event, formatTimeForInput, resetForm]);\n\n // Memoize time options so they're only calculated once\n const timeOptions = useMemo(() => {\n const options = [];\n for (let hour = StartHour; hour <= EndHour; hour++) {\n for (let minute = 0; minute < 60; minute += 15) {\n const formattedHour = hour.toString().padStart(2, \"0\");\n const formattedMinute = minute.toString().padStart(2, \"0\");\n const value = `${formattedHour}:${formattedMinute}`;\n // Use a fixed date to avoid unnecessary date object creations\n const date = new Date(2000, 0, 1, hour, minute);\n const label = format(date, \"h:mm a\");\n options.push({ label, value });\n }\n }\n return options;\n }, []); // Empty dependency array ensures this only runs once\n\n const handleSave = () => {\n const start = new Date(startDate);\n const end = new Date(endDate);\n\n if (!allDay) {\n const [startHours = 0, startMinutes = 0] = startTime\n .split(\":\")\n .map(Number);\n const [endHours = 0, endMinutes = 0] = endTime.split(\":\").map(Number);\n\n if (\n startHours < StartHour ||\n startHours > EndHour ||\n endHours < StartHour ||\n endHours > EndHour\n ) {\n setError(\n `Selected time must be between ${StartHour}:00 and ${EndHour}:00`,\n );\n return;\n }\n\n start.setHours(startHours, startMinutes, 0);\n end.setHours(endHours, endMinutes, 0);\n } else {\n start.setHours(0, 0, 0, 0);\n end.setHours(23, 59, 59, 999);\n }\n\n // Validate that end date is not before start date\n if (isBefore(end, start)) {\n setError(\"End date cannot be before start date\");\n return;\n }\n\n // Use generic title if empty\n const eventTitle = title.trim() ? title : \"(no title)\";\n\n onSave({\n allDay,\n color,\n description,\n end,\n id: event?.id || \"\",\n location,\n start,\n title: eventTitle,\n });\n };\n\n const handleDelete = () => {\n if (event?.id) {\n onDelete(event.id);\n }\n };\n\n // Updated color options to match types.ts\n const colorOptions: Array<{\n value: EventColor;\n label: string;\n bgClass: string;\n borderClass: string;\n }> = [\n {\n bgClass: \"bg-sky-400 data-[state=checked]:bg-sky-400\",\n borderClass: \"border-sky-400 data-[state=checked]:border-sky-400\",\n label: \"Sky\",\n value: \"sky\",\n },\n {\n bgClass: \"bg-amber-400 data-[state=checked]:bg-amber-400\",\n borderClass: \"border-amber-400 data-[state=checked]:border-amber-400\",\n label: \"Amber\",\n value: \"amber\",\n },\n {\n bgClass: \"bg-violet-400 data-[state=checked]:bg-violet-400\",\n borderClass: \"border-violet-400 data-[state=checked]:border-violet-400\",\n label: \"Violet\",\n value: \"violet\",\n },\n {\n bgClass: \"bg-rose-400 data-[state=checked]:bg-rose-400\",\n borderClass: \"border-rose-400 data-[state=checked]:border-rose-400\",\n label: \"Rose\",\n value: \"rose\",\n },\n {\n bgClass: \"bg-emerald-400 data-[state=checked]:bg-emerald-400\",\n borderClass: \"border-emerald-400 data-[state=checked]:border-emerald-400\",\n label: \"Emerald\",\n value: \"emerald\",\n },\n {\n bgClass: \"bg-orange-400 data-[state=checked]:bg-orange-400\",\n borderClass: \"border-orange-400 data-[state=checked]:border-orange-400\",\n label: \"Orange\",\n value: \"orange\",\n },\n ];\n\n return (\n !open && onClose()} open={isOpen}>\n \n \n {event?.id ? \"Edit Event\" : \"Create Event\"}\n \n {event?.id\n ? \"Edit the details of this event\"\n : \"Add a new event to your calendar\"}\n \n \n {error && (\n
\n {error}\n
\n )}\n
\n
\n \n setTitle(e.target.value)}\n value={title}\n />\n
\n\n
\n \n setDescription(e.target.value)}\n rows={3}\n value={description}\n />\n
\n\n
\n
\n \n \n \n \n \n {startDate ? format(startDate, \"PPP\") : \"Pick a date\"}\n \n \n \n \n \n {\n if (date) {\n setStartDate(date);\n // If end date is before the new start date, update it to match the start date\n if (isBefore(endDate, date)) {\n setEndDate(date);\n }\n setError(null);\n setStartDateOpen(false);\n }\n }}\n selected={startDate}\n />\n \n \n
\n\n {!allDay && (\n
\n \n \n
\n )}\n
\n\n
\n
\n \n \n \n \n \n {endDate ? format(endDate, \"PPP\") : \"Pick a date\"}\n \n \n \n \n \n {\n if (date) {\n setEndDate(date);\n setError(null);\n setEndDateOpen(false);\n }\n }}\n selected={endDate}\n />\n \n \n
\n\n {!allDay && (\n
\n \n \n
\n )}\n
\n\n
\n setAllDay(checked === true)}\n />\n \n
\n\n
\n \n setLocation(e.target.value)}\n value={location}\n />\n
\n
\n \n Etiquette\n \n setColor(value)}\n value={color}\n >\n {colorOptions.map((colorOption) => (\n \n ))}\n \n
\n
\n \n {event?.id && (\n \n \n \n )}\n
\n \n \n
\n
\n
\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/event-item.tsx", "content": "\"use client\";\n\nimport type { DraggableAttributes } from \"@dnd-kit/core\";\nimport type { SyntheticListenerMap } from \"@dnd-kit/core/dist/hooks/utilities\";\nimport { differenceInMinutes, format, getMinutes, isPast } from \"date-fns\";\nimport { useMemo } from \"react\";\n\nimport {\n type CalendarEvent,\n getBorderRadiusClasses,\n getEventColorClasses,\n} from \"@/registry/default/components/event-calendar\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\n// Using date-fns format with custom formatting:\n// 'h' - hours (1-12)\n// 'a' - am/pm\n// ':mm' - minutes with leading zero (only if the token 'mm' is present)\nconst formatTimeWithOptionalMinutes = (date: Date) => {\n return format(date, getMinutes(date) === 0 ? \"ha\" : \"h:mma\").toLowerCase();\n};\n\ninterface EventWrapperProps {\n event: CalendarEvent;\n isFirstDay?: boolean;\n isLastDay?: boolean;\n isDragging?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n className?: string;\n children: React.ReactNode;\n currentTime?: Date;\n dndListeners?: SyntheticListenerMap;\n dndAttributes?: DraggableAttributes;\n onMouseDown?: (e: React.MouseEvent) => void;\n onTouchStart?: (e: React.TouchEvent) => void;\n}\n\n// Shared wrapper component for event styling\nfunction EventWrapper({\n event,\n isFirstDay = true,\n isLastDay = true,\n isDragging,\n onClick,\n className,\n children,\n currentTime,\n dndListeners,\n dndAttributes,\n onMouseDown,\n onTouchStart,\n}: EventWrapperProps) {\n // Always use the currentTime (if provided) to determine if the event is in the past\n const displayEnd = currentTime\n ? new Date(\n new Date(currentTime).getTime() +\n (new Date(event.end).getTime() - new Date(event.start).getTime()),\n )\n : new Date(event.end);\n\n const isEventInPast = isPast(displayEnd);\n\n return (\n \n {children}\n \n );\n}\n\ninterface EventItemProps {\n event: CalendarEvent;\n view: \"month\" | \"week\" | \"day\" | \"agenda\";\n isDragging?: boolean;\n onClick?: (e: React.MouseEvent) => void;\n showTime?: boolean;\n currentTime?: Date; // For updating time during drag\n isFirstDay?: boolean;\n isLastDay?: boolean;\n children?: React.ReactNode;\n className?: string;\n dndListeners?: SyntheticListenerMap;\n dndAttributes?: DraggableAttributes;\n onMouseDown?: (e: React.MouseEvent) => void;\n onTouchStart?: (e: React.TouchEvent) => void;\n}\n\nexport function EventItem({\n event,\n view,\n isDragging,\n onClick,\n showTime,\n currentTime,\n isFirstDay = true,\n isLastDay = true,\n children,\n className,\n dndListeners,\n dndAttributes,\n onMouseDown,\n onTouchStart,\n}: EventItemProps) {\n const eventColor = event.color;\n\n // Use the provided currentTime (for dragging) or the event's actual time\n const displayStart = useMemo(() => {\n return currentTime || new Date(event.start);\n }, [currentTime, event.start]);\n\n const displayEnd = useMemo(() => {\n return currentTime\n ? new Date(\n new Date(currentTime).getTime() +\n (new Date(event.end).getTime() - new Date(event.start).getTime()),\n )\n : new Date(event.end);\n }, [currentTime, event.start, event.end]);\n\n // Calculate event duration in minutes\n const durationMinutes = useMemo(() => {\n return differenceInMinutes(displayEnd, displayStart);\n }, [displayStart, displayEnd]);\n\n const getEventTime = () => {\n if (event.allDay) return \"All day\";\n\n // For short events (less than 45 minutes), only show start time\n if (durationMinutes < 45) {\n return formatTimeWithOptionalMinutes(displayStart);\n }\n\n // For longer events, show both start and end time\n return `${formatTimeWithOptionalMinutes(displayStart)} - ${formatTimeWithOptionalMinutes(displayEnd)}`;\n };\n\n if (view === \"month\") {\n return (\n \n {children || (\n \n {!event.allDay && (\n \n {formatTimeWithOptionalMinutes(displayStart)}{\" \"}\n \n )}\n {event.title}\n \n )}\n \n );\n }\n\n if (view === \"week\" || view === \"day\") {\n return (\n \n {durationMinutes < 45 ? (\n
\n {event.title}{\" \"}\n {showTime && (\n \n {formatTimeWithOptionalMinutes(displayStart)}\n \n )}\n
\n ) : (\n <>\n
{event.title}
\n {showTime && (\n
\n {getEventTime()}\n
\n )}\n \n )}\n \n );\n }\n\n // Agenda view - kept separate since it's significantly different\n return (\n \n
{event.title}
\n
\n {event.allDay ? (\n All day\n ) : (\n \n {formatTimeWithOptionalMinutes(displayStart)} -{\" \"}\n {formatTimeWithOptionalMinutes(displayEnd)}\n \n )}\n {event.location && (\n <>\n · \n {event.location}\n \n )}\n
\n {event.description && (\n
{event.description}
\n )}\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/events-popup.tsx", "content": "\"use client\";\n\nimport { format, isSameDay } from \"date-fns\";\nimport { XIcon } from \"lucide-react\";\nimport { useEffect, useMemo, useRef } from \"react\";\n\nimport {\n type CalendarEvent,\n EventItem,\n} from \"@/registry/default/components/event-calendar\";\n\ninterface EventsPopupProps {\n date: Date;\n events: CalendarEvent[];\n position: { top: number; left: number };\n onClose: () => void;\n onEventSelect: (event: CalendarEvent) => void;\n}\n\nexport function EventsPopup({\n date,\n events,\n position,\n onClose,\n onEventSelect,\n}: EventsPopupProps) {\n const popupRef = useRef(null);\n\n // Handle click outside to close popup\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (\n popupRef.current &&\n !popupRef.current.contains(event.target as Node)\n ) {\n onClose();\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }, [onClose]);\n\n // Handle escape key to close popup\n useEffect(() => {\n const handleEscKey = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscKey);\n return () => {\n document.removeEventListener(\"keydown\", handleEscKey);\n };\n }, [onClose]);\n\n const handleEventClick = (event: CalendarEvent) => {\n onEventSelect(event);\n onClose();\n };\n\n // Adjust position to ensure popup stays within viewport\n const adjustedPosition = useMemo(() => {\n const positionCopy = { ...position };\n\n // Check if we need to adjust the position to fit in the viewport\n if (popupRef.current) {\n const rect = popupRef.current.getBoundingClientRect();\n const viewportWidth = window.innerWidth;\n const viewportHeight = window.innerHeight;\n\n // Adjust horizontally if needed\n if (positionCopy.left + rect.width > viewportWidth) {\n positionCopy.left = Math.max(0, viewportWidth - rect.width);\n }\n\n // Adjust vertically if needed\n if (positionCopy.top + rect.height > viewportHeight) {\n positionCopy.top = Math.max(0, viewportHeight - rect.height);\n }\n }\n\n return positionCopy;\n }, [position]);\n\n return (\n \n
\n

{format(date, \"d MMMM yyyy\")}

\n \n \n \n
\n\n
\n {events.length === 0 ? (\n
No events
\n ) : (\n events.map((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n const isFirstDay = isSameDay(date, eventStart);\n const isLastDay = isSameDay(date, eventEnd);\n\n return (\n handleEventClick(event)}\n >\n \n
\n );\n })\n )}\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/event-calendar.tsx", "content": "\"use client\";\n\nimport { RiCalendarCheckLine } from \"@remixicon/react\";\nimport {\n addDays,\n addMonths,\n addWeeks,\n endOfWeek,\n format,\n isSameMonth,\n startOfWeek,\n subMonths,\n subWeeks,\n} from \"date-fns\";\nimport {\n ChevronDownIcon,\n ChevronLeftIcon,\n ChevronRightIcon,\n PlusIcon,\n} from \"lucide-react\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { toast } from \"sonner\";\n\nimport {\n AgendaDaysToShow,\n AgendaView,\n addHoursToDate,\n CalendarDndProvider,\n type CalendarEvent,\n type CalendarView,\n DayView,\n EventDialog,\n EventGap,\n EventHeight,\n MonthView,\n WeekCellsHeight,\n WeekView,\n} from \"@/registry/default/components/event-calendar\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuShortcut,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport interface EventCalendarProps {\n events?: CalendarEvent[];\n onEventAdd?: (event: CalendarEvent) => void;\n onEventUpdate?: (event: CalendarEvent) => void;\n onEventDelete?: (eventId: string) => void;\n className?: string;\n initialView?: CalendarView;\n}\n\nexport function EventCalendar({\n events = [],\n onEventAdd,\n onEventUpdate,\n onEventDelete,\n className,\n initialView = \"month\",\n}: EventCalendarProps) {\n const [currentDate, setCurrentDate] = useState(new Date());\n const [view, setView] = useState(initialView);\n const [isEventDialogOpen, setIsEventDialogOpen] = useState(false);\n const [selectedEvent, setSelectedEvent] = useState(\n null,\n );\n\n // Add keyboard shortcuts for view switching\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n // Skip if user is typing in an input, textarea or contentEditable element\n // or if the event dialog is open\n if (\n isEventDialogOpen ||\n e.target instanceof HTMLInputElement ||\n e.target instanceof HTMLTextAreaElement ||\n (e.target instanceof HTMLElement && e.target.isContentEditable)\n ) {\n return;\n }\n\n switch (e.key.toLowerCase()) {\n case \"m\":\n setView(\"month\");\n break;\n case \"w\":\n setView(\"week\");\n break;\n case \"d\":\n setView(\"day\");\n break;\n case \"a\":\n setView(\"agenda\");\n break;\n }\n };\n\n window.addEventListener(\"keydown\", handleKeyDown);\n\n return () => {\n window.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [isEventDialogOpen]);\n\n const handlePrevious = () => {\n if (view === \"month\") {\n setCurrentDate(subMonths(currentDate, 1));\n } else if (view === \"week\") {\n setCurrentDate(subWeeks(currentDate, 1));\n } else if (view === \"day\") {\n setCurrentDate(addDays(currentDate, -1));\n } else if (view === \"agenda\") {\n // For agenda view, go back 30 days (a full month)\n setCurrentDate(addDays(currentDate, -AgendaDaysToShow));\n }\n };\n\n const handleNext = () => {\n if (view === \"month\") {\n setCurrentDate(addMonths(currentDate, 1));\n } else if (view === \"week\") {\n setCurrentDate(addWeeks(currentDate, 1));\n } else if (view === \"day\") {\n setCurrentDate(addDays(currentDate, 1));\n } else if (view === \"agenda\") {\n // For agenda view, go forward 30 days (a full month)\n setCurrentDate(addDays(currentDate, AgendaDaysToShow));\n }\n };\n\n const handleToday = () => {\n setCurrentDate(new Date());\n };\n\n const handleEventSelect = (event: CalendarEvent) => {\n console.log(\"Event selected:\", event); // Debug log\n setSelectedEvent(event);\n setIsEventDialogOpen(true);\n };\n\n const handleEventCreate = (startTime: Date) => {\n console.log(\"Creating new event at:\", startTime); // Debug log\n\n // Snap to 15-minute intervals\n const minutes = startTime.getMinutes();\n const remainder = minutes % 15;\n if (remainder !== 0) {\n if (remainder < 7.5) {\n // Round down to nearest 15 min\n startTime.setMinutes(minutes - remainder);\n } else {\n // Round up to nearest 15 min\n startTime.setMinutes(minutes + (15 - remainder));\n }\n startTime.setSeconds(0);\n startTime.setMilliseconds(0);\n }\n\n const newEvent: CalendarEvent = {\n allDay: false,\n end: addHoursToDate(startTime, 1),\n id: \"\",\n start: startTime,\n title: \"\",\n };\n setSelectedEvent(newEvent);\n setIsEventDialogOpen(true);\n };\n\n const handleEventSave = (event: CalendarEvent) => {\n if (event.id) {\n onEventUpdate?.(event);\n // Show toast notification when an event is updated\n toast(`Event \"${event.title}\" updated`, {\n description: format(new Date(event.start), \"MMM d, yyyy\"),\n position: \"bottom-left\",\n });\n } else {\n onEventAdd?.({\n ...event,\n id: Math.random().toString(36).substring(2, 11),\n });\n // Show toast notification when an event is added\n toast(`Event \"${event.title}\" added`, {\n description: format(new Date(event.start), \"MMM d, yyyy\"),\n position: \"bottom-left\",\n });\n }\n setIsEventDialogOpen(false);\n setSelectedEvent(null);\n };\n\n const handleEventDelete = (eventId: string) => {\n const deletedEvent = events.find((e) => e.id === eventId);\n onEventDelete?.(eventId);\n setIsEventDialogOpen(false);\n setSelectedEvent(null);\n\n // Show toast notification when an event is deleted\n if (deletedEvent) {\n toast(`Event \"${deletedEvent.title}\" deleted`, {\n description: format(new Date(deletedEvent.start), \"MMM d, yyyy\"),\n position: \"bottom-left\",\n });\n }\n };\n\n const handleEventUpdate = (updatedEvent: CalendarEvent) => {\n onEventUpdate?.(updatedEvent);\n\n // Show toast notification when an event is updated via drag and drop\n toast(`Event \"${updatedEvent.title}\" moved`, {\n description: format(new Date(updatedEvent.start), \"MMM d, yyyy\"),\n position: \"bottom-left\",\n });\n };\n\n const viewTitle = useMemo(() => {\n if (view === \"month\") {\n return format(currentDate, \"MMMM yyyy\");\n }\n if (view === \"week\") {\n const start = startOfWeek(currentDate, { weekStartsOn: 0 });\n const end = endOfWeek(currentDate, { weekStartsOn: 0 });\n if (isSameMonth(start, end)) {\n return format(start, \"MMMM yyyy\");\n }\n return `${format(start, \"MMM\")} - ${format(end, \"MMM yyyy\")}`;\n }\n if (view === \"day\") {\n return (\n <>\n \n {format(currentDate, \"MMM d, yyyy\")}\n \n \n {format(currentDate, \"MMMM d, yyyy\")}\n \n \n {format(currentDate, \"EEE MMMM d, yyyy\")}\n \n \n );\n }\n if (view === \"agenda\") {\n // Show the month range for agenda view\n const start = currentDate;\n const end = addDays(currentDate, AgendaDaysToShow - 1);\n\n if (isSameMonth(start, end)) {\n return format(start, \"MMMM yyyy\");\n }\n return `${format(start, \"MMM\")} - ${format(end, \"MMM yyyy\")}`;\n }\n return format(currentDate, \"MMMM yyyy\");\n }, [currentDate, view]);\n\n return (\n \n \n \n
\n \n \n Today\n \n
\n \n \n \n \n \n \n
\n

\n {viewTitle}\n

\n
\n
\n \n \n \n \n \n setView(\"month\")}>\n Month M\n \n setView(\"week\")}>\n Week W\n \n setView(\"day\")}>\n Day D\n \n setView(\"agenda\")}>\n Agenda A\n \n \n \n {\n setSelectedEvent(null); // Ensure we're creating a new event\n setIsEventDialogOpen(true);\n }}\n size=\"sm\"\n >\n \n New event\n \n
\n \n\n
\n {view === \"month\" && (\n \n )}\n {view === \"week\" && (\n \n )}\n {view === \"day\" && (\n \n )}\n {view === \"agenda\" && (\n \n )}\n
\n\n {\n setIsEventDialogOpen(false);\n setSelectedEvent(null);\n }}\n onDelete={handleEventDelete}\n onSave={handleEventSave}\n />\n
\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/index.ts", "content": "\"use client\";\n\n// Component exports\n\nexport { AgendaView } from \"./agenda-view\";\nexport { CalendarDndProvider, useCalendarDnd } from \"./calendar-dnd-context\";\n// Constants and utility exports\nexport * from \"./constants\";\nexport { DayView } from \"./day-view\";\nexport { DraggableEvent } from \"./draggable-event\";\nexport { DroppableCell } from \"./droppable-cell\";\nexport { EventCalendar } from \"./event-calendar\";\nexport { EventDialog } from \"./event-dialog\";\nexport { EventItem } from \"./event-item\";\nexport { EventsPopup } from \"./events-popup\";\n// Hook exports\nexport * from \"./hooks/use-current-time-indicator\";\nexport * from \"./hooks/use-event-visibility\";\nexport { MonthView } from \"./month-view\";\n// Type exports\nexport type { CalendarEvent, CalendarView, EventColor } from \"./types\";\nexport * from \"./utils\";\nexport { WeekView } from \"./week-view\";\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/month-view.tsx", "content": "\"use client\";\n\nimport {\n addDays,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n format,\n isSameDay,\n isSameMonth,\n isToday,\n startOfMonth,\n startOfWeek,\n} from \"date-fns\";\nimport type React from \"react\";\nimport { useEffect, useMemo, useState } from \"react\";\n\nimport {\n type CalendarEvent,\n DraggableEvent,\n DroppableCell,\n EventGap,\n EventHeight,\n EventItem,\n getAllEventsForDay,\n getEventsForDay,\n getSpanningEventsForDay,\n sortEvents,\n useEventVisibility,\n} from \"@/registry/default/components/event-calendar\";\nimport { DefaultStartHour } from \"@/registry/default/components/event-calendar/constants\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\ninterface MonthViewProps {\n currentDate: Date;\n events: CalendarEvent[];\n onEventSelect: (event: CalendarEvent) => void;\n onEventCreate: (startTime: Date) => void;\n}\n\nexport function MonthView({\n currentDate,\n events,\n onEventSelect,\n onEventCreate,\n}: MonthViewProps) {\n const days = useMemo(() => {\n const monthStart = startOfMonth(currentDate);\n const monthEnd = endOfMonth(monthStart);\n const calendarStart = startOfWeek(monthStart, { weekStartsOn: 0 });\n const calendarEnd = endOfWeek(monthEnd, { weekStartsOn: 0 });\n\n return eachDayOfInterval({ end: calendarEnd, start: calendarStart });\n }, [currentDate]);\n\n const weekdays = useMemo(() => {\n return Array.from({ length: 7 }).map((_, i) => {\n const date = addDays(startOfWeek(new Date()), i);\n return format(date, \"EEE\");\n });\n }, []);\n\n const weeks = useMemo(() => {\n const result = [];\n let week = [];\n\n for (let i = 0; i < days.length; i++) {\n week.push(days[i]);\n if (week.length === 7 || i === days.length - 1) {\n result.push(week);\n week = [];\n }\n }\n\n return result;\n }, [days]);\n\n const handleEventClick = (event: CalendarEvent, e: React.MouseEvent) => {\n e.stopPropagation();\n onEventSelect(event);\n };\n\n const [isMounted, setIsMounted] = useState(false);\n const { contentRef, getVisibleEventCount } = useEventVisibility({\n eventGap: EventGap,\n eventHeight: EventHeight,\n });\n\n useEffect(() => {\n setIsMounted(true);\n }, []);\n\n return (\n
\n
\n {weekdays.map((day) => (\n \n {day}\n
\n ))}\n
\n
\n {weeks.map((week, weekIndex) => (\n *]:border-b-0\"\n key={`week-${week}`}\n >\n {week.map((day, dayIndex) => {\n if (!day) return null; // Skip if day is undefined\n\n const dayEvents = getEventsForDay(events, day);\n const spanningEvents = getSpanningEventsForDay(events, day);\n const isCurrentMonth = isSameMonth(day, currentDate);\n const cellId = `month-cell-${day.toISOString()}`;\n const allDayEvents = [...spanningEvents, ...dayEvents];\n const allEvents = getAllEventsForDay(events, day);\n\n const isReferenceCell = weekIndex === 0 && dayIndex === 0;\n const visibleCount = isMounted\n ? getVisibleEventCount(allDayEvents.length)\n : undefined;\n const hasMore =\n visibleCount !== undefined &&\n allDayEvents.length > visibleCount;\n const remainingCount = hasMore\n ? allDayEvents.length - visibleCount\n : 0;\n\n return (\n \n {\n const startTime = new Date(day);\n startTime.setHours(DefaultStartHour, 0, 0);\n onEventCreate(startTime);\n }}\n >\n
\n {format(day, \"d\")}\n
\n \n {sortEvents(allDayEvents).map((event, index) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n const isFirstDay = isSameDay(day, eventStart);\n const isLastDay = isSameDay(day, eventEnd);\n\n const isHidden =\n isMounted && visibleCount && index >= visibleCount;\n\n if (!visibleCount) return null;\n\n if (!isFirstDay) {\n return (\n \n handleEventClick(event, e)}\n view=\"month\"\n >\n
\n {!event.allDay && (\n \n {format(\n new Date(event.start),\n \"h:mm\",\n )}{\" \"}\n \n )}\n {event.title}\n
\n \n
\n );\n }\n\n return (\n \n handleEventClick(event, e)}\n view=\"month\"\n />\n \n );\n })}\n\n {hasMore && (\n \n \n e.stopPropagation()}\n type=\"button\"\n >\n \n + {remainingCount}{\" \"}\n more\n \n \n \n \n }\n >\n
\n
\n {format(day, \"EEE d\")}\n
\n
\n {sortEvents(allEvents).map((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n const isFirstDay = isSameDay(day, eventStart);\n const isLastDay = isSameDay(day, eventEnd);\n\n return (\n \n handleEventClick(event, e)\n }\n view=\"month\"\n />\n );\n })}\n
\n
\n \n
\n )}\n \n \n \n );\n })}\n \n ))}\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/types.ts", "content": "export type CalendarView = \"month\" | \"week\" | \"day\" | \"agenda\";\n\nexport interface CalendarEvent {\n id: string;\n title: string;\n description?: string;\n start: Date;\n end: Date;\n allDay?: boolean;\n color?: EventColor;\n location?: string;\n}\n\nexport type EventColor =\n | \"sky\"\n | \"amber\"\n | \"violet\"\n | \"rose\"\n | \"emerald\"\n | \"orange\";\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/utils.ts", "content": "import { isSameDay } from \"date-fns\";\n\nimport type {\n CalendarEvent,\n EventColor,\n} from \"@/registry/default/components/event-calendar\";\n\n/**\n * Get CSS classes for event colors\n */\nexport function getEventColorClasses(color?: EventColor | string): string {\n const eventColor = color || \"sky\";\n\n switch (eventColor) {\n case \"sky\":\n return \"bg-sky-200/50 hover:bg-sky-200/40 text-sky-950/80 dark:bg-sky-400/25 dark:hover:bg-sky-400/20 dark:text-sky-200 shadow-sky-700/8\";\n case \"amber\":\n return \"bg-amber-200/50 hover:bg-amber-200/40 text-amber-950/80 dark:bg-amber-400/25 dark:hover:bg-amber-400/20 dark:text-amber-200 shadow-amber-700/8\";\n case \"violet\":\n return \"bg-violet-200/50 hover:bg-violet-200/40 text-violet-950/80 dark:bg-violet-400/25 dark:hover:bg-violet-400/20 dark:text-violet-200 shadow-violet-700/8\";\n case \"rose\":\n return \"bg-rose-200/50 hover:bg-rose-200/40 text-rose-950/80 dark:bg-rose-400/25 dark:hover:bg-rose-400/20 dark:text-rose-200 shadow-rose-700/8\";\n case \"emerald\":\n return \"bg-emerald-200/50 hover:bg-emerald-200/40 text-emerald-950/80 dark:bg-emerald-400/25 dark:hover:bg-emerald-400/20 dark:text-emerald-200 shadow-emerald-700/8\";\n case \"orange\":\n return \"bg-orange-200/50 hover:bg-orange-200/40 text-orange-950/80 dark:bg-orange-400/25 dark:hover:bg-orange-400/20 dark:text-orange-200 shadow-orange-700/8\";\n default:\n return \"bg-sky-200/50 hover:bg-sky-200/40 text-sky-950/80 dark:bg-sky-400/25 dark:hover:bg-sky-400/20 dark:text-sky-200 shadow-sky-700/8\";\n }\n}\n\n/**\n * Get CSS classes for border radius based on event position in multi-day events\n */\nexport function getBorderRadiusClasses(\n isFirstDay: boolean,\n isLastDay: boolean,\n): string {\n if (isFirstDay && isLastDay) {\n return \"rounded\"; // Both ends rounded\n }\n if (isFirstDay) {\n return \"rounded-l rounded-r-none\"; // Only left end rounded\n }\n if (isLastDay) {\n return \"rounded-r rounded-l-none\"; // Only right end rounded\n }\n return \"rounded-none\"; // No rounded corners\n}\n\n/**\n * Check if an event is a multi-day event\n */\nexport function isMultiDayEvent(event: CalendarEvent): boolean {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return event.allDay || eventStart.getDate() !== eventEnd.getDate();\n}\n\n/**\n * Filter events for a specific day\n */\nexport function getEventsForDay(\n events: CalendarEvent[],\n day: Date,\n): CalendarEvent[] {\n return events\n .filter((event) => {\n const eventStart = new Date(event.start);\n return isSameDay(day, eventStart);\n })\n .sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());\n}\n\n/**\n * Sort events with multi-day events first, then by start time\n */\nexport function sortEvents(events: CalendarEvent[]): CalendarEvent[] {\n return [...events].sort((a, b) => {\n const aIsMultiDay = isMultiDayEvent(a);\n const bIsMultiDay = isMultiDayEvent(b);\n\n if (aIsMultiDay && !bIsMultiDay) return -1;\n if (!aIsMultiDay && bIsMultiDay) return 1;\n\n return new Date(a.start).getTime() - new Date(b.start).getTime();\n });\n}\n\n/**\n * Get multi-day events that span across a specific day (but don't start on that day)\n */\nexport function getSpanningEventsForDay(\n events: CalendarEvent[],\n day: Date,\n): CalendarEvent[] {\n return events.filter((event) => {\n if (!isMultiDayEvent(event)) return false;\n\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n\n // Only include if it's not the start day but is either the end day or a middle day\n return (\n !isSameDay(day, eventStart) &&\n (isSameDay(day, eventEnd) || (day > eventStart && day < eventEnd))\n );\n });\n}\n\n/**\n * Get all events visible on a specific day (starting, ending, or spanning)\n */\nexport function getAllEventsForDay(\n events: CalendarEvent[],\n day: Date,\n): CalendarEvent[] {\n return events.filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return (\n isSameDay(day, eventStart) ||\n isSameDay(day, eventEnd) ||\n (day > eventStart && day < eventEnd)\n );\n });\n}\n\n/**\n * Get all events for a day (for agenda view)\n */\nexport function getAgendaEventsForDay(\n events: CalendarEvent[],\n day: Date,\n): CalendarEvent[] {\n return events\n .filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return (\n isSameDay(day, eventStart) ||\n isSameDay(day, eventEnd) ||\n (day > eventStart && day < eventEnd)\n );\n })\n .sort((a, b) => new Date(a.start).getTime() - new Date(b.start).getTime());\n}\n\n/**\n * Add hours to a date\n */\nexport function addHoursToDate(date: Date, hours: number): Date {\n const result = new Date(date);\n result.setHours(result.getHours() + hours);\n return result;\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/week-view.tsx", "content": "\"use client\";\n\nimport {\n addHours,\n areIntervalsOverlapping,\n differenceInMinutes,\n eachDayOfInterval,\n eachHourOfInterval,\n endOfWeek,\n format,\n getHours,\n getMinutes,\n isBefore,\n isSameDay,\n isToday,\n startOfDay,\n startOfWeek,\n} from \"date-fns\";\nimport type React from \"react\";\nimport { useMemo } from \"react\";\n\nimport {\n type CalendarEvent,\n DraggableEvent,\n DroppableCell,\n EventItem,\n isMultiDayEvent,\n useCurrentTimeIndicator,\n WeekCellsHeight,\n} from \"@/registry/default/components/event-calendar\";\nimport {\n EndHour,\n StartHour,\n} from \"@/registry/default/components/event-calendar/constants\";\nimport { cn } from \"@/registry/default/lib/utils\";\n\ninterface WeekViewProps {\n currentDate: Date;\n events: CalendarEvent[];\n onEventSelect: (event: CalendarEvent) => void;\n onEventCreate: (startTime: Date) => void;\n}\n\ninterface PositionedEvent {\n event: CalendarEvent;\n top: number;\n height: number;\n left: number;\n width: number;\n zIndex: number;\n}\n\nexport function WeekView({\n currentDate,\n events,\n onEventSelect,\n onEventCreate,\n}: WeekViewProps) {\n const days = useMemo(() => {\n const weekStart = startOfWeek(currentDate, { weekStartsOn: 0 });\n const weekEnd = endOfWeek(currentDate, { weekStartsOn: 0 });\n return eachDayOfInterval({ end: weekEnd, start: weekStart });\n }, [currentDate]);\n\n const weekStart = useMemo(\n () => startOfWeek(currentDate, { weekStartsOn: 0 }),\n [currentDate],\n );\n\n const hours = useMemo(() => {\n const dayStart = startOfDay(currentDate);\n return eachHourOfInterval({\n end: addHours(dayStart, EndHour - 1),\n start: addHours(dayStart, StartHour),\n });\n }, [currentDate]);\n\n // Get all-day events and multi-day events for the week\n const allDayEvents = useMemo(() => {\n return events\n .filter((event) => {\n // Include explicitly marked all-day events or multi-day events\n return event.allDay || isMultiDayEvent(event);\n })\n .filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return days.some(\n (day) =>\n isSameDay(day, eventStart) ||\n isSameDay(day, eventEnd) ||\n (day > eventStart && day < eventEnd),\n );\n });\n }, [events, days]);\n\n // Process events for each day to calculate positions\n const processedDayEvents = useMemo(() => {\n const result = days.map((day) => {\n // Get events for this day that are not all-day events or multi-day events\n const dayEvents = events.filter((event) => {\n // Skip all-day events and multi-day events\n if (event.allDay || isMultiDayEvent(event)) return false;\n\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n\n // Check if event is on this day\n return (\n isSameDay(day, eventStart) ||\n isSameDay(day, eventEnd) ||\n (eventStart < day && eventEnd > day)\n );\n });\n\n // Sort events by start time and duration\n const sortedEvents = [...dayEvents].sort((a, b) => {\n const aStart = new Date(a.start);\n const bStart = new Date(b.start);\n const aEnd = new Date(a.end);\n const bEnd = new Date(b.end);\n\n // First sort by start time\n if (aStart < bStart) return -1;\n if (aStart > bStart) return 1;\n\n // If start times are equal, sort by duration (longer events first)\n const aDuration = differenceInMinutes(aEnd, aStart);\n const bDuration = differenceInMinutes(bEnd, bStart);\n return bDuration - aDuration;\n });\n\n // Calculate positions for each event\n const positionedEvents: PositionedEvent[] = [];\n const dayStart = startOfDay(day);\n\n // Track columns for overlapping events\n const columns: { event: CalendarEvent; end: Date }[][] = [];\n\n for (const event of sortedEvents) {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n\n // Adjust start and end times if they're outside this day\n const adjustedStart = isSameDay(day, eventStart)\n ? eventStart\n : dayStart;\n const adjustedEnd = isSameDay(day, eventEnd)\n ? eventEnd\n : addHours(dayStart, 24);\n\n // Calculate top position and height\n const startHour =\n getHours(adjustedStart) + getMinutes(adjustedStart) / 60;\n const endHour = getHours(adjustedEnd) + getMinutes(adjustedEnd) / 60;\n\n // Adjust the top calculation to account for the new start time\n const top = (startHour - StartHour) * WeekCellsHeight;\n const height = (endHour - startHour) * WeekCellsHeight;\n\n // Find a column for this event\n let columnIndex = 0;\n let placed = false;\n\n while (!placed) {\n const col = columns[columnIndex] || [];\n if (col.length === 0) {\n columns[columnIndex] = col;\n placed = true;\n } else {\n const overlaps = col.some((c) =>\n areIntervalsOverlapping(\n { end: adjustedEnd, start: adjustedStart },\n {\n end: new Date(c.event.end),\n start: new Date(c.event.start),\n },\n ),\n );\n\n if (!overlaps) {\n placed = true;\n } else {\n columnIndex++;\n }\n }\n }\n\n // Ensure column is initialized before pushing\n const currentColumn = columns[columnIndex] || [];\n columns[columnIndex] = currentColumn;\n currentColumn.push({ end: adjustedEnd, event });\n\n // Calculate width and left position based on number of columns\n const width = columnIndex === 0 ? 1 : 0.9;\n const left = columnIndex === 0 ? 0 : columnIndex * 0.1;\n\n positionedEvents.push({\n event,\n height,\n left,\n top,\n width,\n zIndex: 10 + columnIndex, // Higher columns get higher z-index\n });\n }\n\n return positionedEvents;\n });\n\n return result;\n }, [days, events]);\n\n const handleEventClick = (event: CalendarEvent, e: React.MouseEvent) => {\n e.stopPropagation();\n onEventSelect(event);\n };\n\n const showAllDaySection = allDayEvents.length > 0;\n const { currentTimePosition, currentTimeVisible } = useCurrentTimeIndicator(\n currentDate,\n \"week\",\n );\n\n return (\n
\n
\n
\n {format(new Date(), \"O\")}\n
\n {days.map((day) => (\n \n \n {format(day, \"E\")[0]} {format(day, \"d\")}\n \n {format(day, \"EEE dd\")}\n
\n ))}\n
\n\n {showAllDaySection && (\n
\n
\n
\n \n All day\n \n
\n {days.map((day, dayIndex) => {\n const dayAllDayEvents = allDayEvents.filter((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n return (\n isSameDay(day, eventStart) ||\n (day > eventStart && day < eventEnd) ||\n isSameDay(day, eventEnd)\n );\n });\n\n return (\n \n {dayAllDayEvents.map((event) => {\n const eventStart = new Date(event.start);\n const eventEnd = new Date(event.end);\n const isFirstDay = isSameDay(day, eventStart);\n const isLastDay = isSameDay(day, eventEnd);\n\n // Check if this is the first day in the current week view\n const isFirstVisibleDay =\n dayIndex === 0 && isBefore(eventStart, weekStart);\n const shouldShowTitle = isFirstDay || isFirstVisibleDay;\n\n return (\n handleEventClick(event, e)}\n view=\"month\"\n >\n {/* Show title if it's the first day of the event or the first visible day in the week */}\n \n {event.title}\n
\n \n );\n })}\n
\n );\n })}\n \n \n )}\n\n
\n
\n {hours.map((hour, index) => (\n \n {index > 0 && (\n \n {format(hour, \"h a\")}\n \n )}\n
\n ))}\n
\n\n {days.map((day, dayIndex) => (\n \n {/* Positioned events */}\n {(processedDayEvents[dayIndex] ?? []).map((positionedEvent) => (\n e.stopPropagation()}\n style={{\n height: `${positionedEvent.height}px`,\n left: `${positionedEvent.left * 100}%`,\n top: `${positionedEvent.top}px`,\n width: `${positionedEvent.width * 100}%`,\n zIndex: positionedEvent.zIndex,\n }}\n >\n
\n handleEventClick(positionedEvent.event, e)}\n showTime\n view=\"week\"\n />\n
\n \n ))}\n\n {/* Current time indicator - only show for today's column */}\n {currentTimeVisible && isToday(day) && (\n \n
\n
\n
\n
\n
\n )}\n {hours.map((hour) => {\n const hourValue = getHours(hour);\n return (\n \n {/* Quarter-hour intervals */}\n {[0, 1, 2, 3].map((quarter) => {\n const quarterHourTime = hourValue + quarter * 0.25;\n return (\n {\n const startTime = new Date(day);\n startTime.setHours(hourValue);\n startTime.setMinutes(quarter * 15);\n onEventCreate(startTime);\n }}\n time={quarterHourTime}\n />\n );\n })}\n
\n );\n })}\n \n ))}\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/hooks/use-current-time-indicator.ts", "content": "\"use client\";\n\nimport { endOfWeek, isSameDay, isWithinInterval, startOfWeek } from \"date-fns\";\nimport { useEffect, useState } from \"react\";\n\nimport {\n EndHour,\n StartHour,\n} from \"@/registry/default/components/event-calendar/constants\";\n\nexport function useCurrentTimeIndicator(\n currentDate: Date,\n view: \"day\" | \"week\",\n) {\n const [currentTimePosition, setCurrentTimePosition] = useState(0);\n const [currentTimeVisible, setCurrentTimeVisible] = useState(false);\n\n useEffect(() => {\n const calculateTimePosition = () => {\n const now = new Date();\n const hours = now.getHours();\n const minutes = now.getMinutes();\n const totalMinutes = (hours - StartHour) * 60 + minutes;\n const dayStartMinutes = 0; // 12am\n const dayEndMinutes = (EndHour - StartHour) * 60; // 12am next day\n\n // Calculate position as percentage of day\n const position =\n ((totalMinutes - dayStartMinutes) / (dayEndMinutes - dayStartMinutes)) *\n 100;\n\n // Check if current day is in view based on the calendar view\n let isCurrentTimeVisible = false;\n\n if (view === \"day\") {\n isCurrentTimeVisible = isSameDay(now, currentDate);\n } else if (view === \"week\") {\n const startOfWeekDate = startOfWeek(currentDate, { weekStartsOn: 0 });\n const endOfWeekDate = endOfWeek(currentDate, { weekStartsOn: 0 });\n isCurrentTimeVisible = isWithinInterval(now, {\n end: endOfWeekDate,\n start: startOfWeekDate,\n });\n }\n\n setCurrentTimePosition(position);\n setCurrentTimeVisible(isCurrentTimeVisible);\n };\n\n // Calculate immediately\n calculateTimePosition();\n\n // Update every minute\n const interval = setInterval(calculateTimePosition, 60000);\n\n return () => clearInterval(interval);\n }, [currentDate, view]);\n\n return { currentTimePosition, currentTimeVisible };\n}\n", "type": "registry:component" }, { "path": "registry/default/components/event-calendar/hooks/use-event-visibility.ts", "content": "\"use client\";\n\nimport { useLayoutEffect, useMemo, useRef, useState } from \"react\";\n\ninterface EventVisibilityOptions {\n eventHeight: number;\n eventGap: number;\n}\n\ninterface EventVisibilityResult {\n contentRef: React.RefObject;\n contentHeight: number | null;\n getVisibleEventCount: (totalEvents: number) => number;\n}\n\n/**\n * Hook for calculating event visibility based on container height\n * Uses ResizeObserver for efficient updates\n */\nexport function useEventVisibility({\n eventHeight,\n eventGap,\n}: EventVisibilityOptions): EventVisibilityResult {\n // Use the standard pattern for React refs\n const contentRef = useRef(null);\n const observerRef = useRef(null);\n const [contentHeight, setContentHeight] = useState(null);\n\n // Use layout effect for synchronous measurement before paint\n useLayoutEffect(() => {\n if (!contentRef.current) return;\n\n // Function to update the content height\n const updateHeight = () => {\n if (contentRef.current) {\n setContentHeight(contentRef.current.clientHeight);\n }\n };\n\n // Initial measurement (synchronous)\n updateHeight();\n\n // Create observer only once and reuse it\n if (!observerRef.current) {\n observerRef.current = new ResizeObserver(() => {\n // Just call updateHeight when resize is detected\n updateHeight();\n });\n }\n\n // Start observing the content container\n observerRef.current.observe(contentRef.current);\n\n // Clean up function\n return () => {\n if (observerRef.current) {\n observerRef.current.disconnect();\n }\n };\n }, []);\n\n // Function to calculate visible events for a cell\n const getVisibleEventCount = useMemo(() => {\n return (totalEvents: number): number => {\n if (!contentHeight) return totalEvents;\n\n // Calculate how many events can fit in the container\n const maxEvents = Math.floor(contentHeight / (eventHeight + eventGap));\n\n // If all events fit, show them all\n if (totalEvents <= maxEvents) {\n return totalEvents;\n }\n // Otherwise, reserve space for \"more\" button by showing one less\n return maxEvents > 0 ? maxEvents - 1 : 0;\n };\n }, [contentHeight, eventHeight, eventGap]);\n\n // Use type assertion to satisfy TypeScript\n return {\n contentHeight,\n contentRef,\n getVisibleEventCount,\n } as EventVisibilityResult;\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "calendar" ] } } ================================================ FILE: apps/origin/public/r/comp-543.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-543", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-543.tsx", "content": "\"use client\";\n\nimport { CircleUserRoundIcon, XIcon } from \"lucide-react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const [\n { files, isDragging },\n {\n removeFile,\n openFileDialog,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n },\n ] = useFileUpload({\n accept: \"image/*\",\n });\n\n const previewUrl = files[0]?.preview || null;\n\n return (\n
\n
\n {/* Drop area */}\n \n {previewUrl ? (\n \n ) : (\n
\n \n
\n )}\n \n {previewUrl && (\n removeFile(files[0]?.id)}\n size=\"icon\"\n >\n \n \n )}\n \n
\n \n Avatar uploader with droppable area ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "tags": [ "upload", "file", "image", "drag and drop", "avatar" ] } } ================================================ FILE: apps/origin/public/r/comp-544.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-544", "type": "registry:component", "files": [ { "path": "registry/default/components/comp-544.tsx", "content": "\"use client\";\n\nimport { AlertCircleIcon, ImageUpIcon, XIcon } from \"lucide-react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\n\nexport default function Component() {\n const maxSizeMB = 5;\n const maxSize = maxSizeMB * 1024 * 1024; // 5MB default\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n getInputProps,\n },\n ] = useFileUpload({\n accept: \"image/*\",\n maxSize,\n });\n\n const previewUrl = files[0]?.preview || null;\n\n return (\n
\n
\n {/* Drop area */}\n \n \n {previewUrl ? (\n
\n \n
\n ) : (\n
\n \n \n
\n

\n Drop your image here or click to browse\n

\n

\n Max size: {maxSizeMB}MB\n

\n
\n )}\n
\n {previewUrl && (\n
\n removeFile(files[0]?.id)}\n type=\"button\"\n >\n \n \n
\n )}\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n \n Single image uploader w/ max size ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-545.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-545", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-545.tsx", "content": "\"use client\";\n\nimport { AlertCircleIcon, ImageIcon, UploadIcon, XIcon } from \"lucide-react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nexport default function Component() {\n const maxSizeMB = 2;\n const maxSize = maxSizeMB * 1024 * 1024; // 2MB default\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n getInputProps,\n },\n ] = useFileUpload({\n accept: \"image/svg+xml,image/png,image/jpeg,image/jpg,image/gif\",\n maxSize,\n });\n const previewUrl = files[0]?.preview || null;\n const _fileName = files[0]?.file.name || null;\n\n return (\n
\n
\n {/* Drop area */}\n \n \n {previewUrl ? (\n
\n \n
\n ) : (\n
\n \n \n
\n

Drop your image here

\n

\n SVG, PNG, JPG or GIF (max. {maxSizeMB}MB)\n

\n \n \n Select image\n \n
\n )}\n
\n\n {previewUrl && (\n
\n removeFile(files[0]?.id)}\n type=\"button\"\n >\n \n \n
\n )}\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n \n Single image uploader w/ max size (drop area + button) ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-546.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-546", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-546.tsx", "content": "\"use client\";\n\nimport { AlertCircleIcon, ImageIcon, UploadIcon, XIcon } from \"lucide-react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"image-01-123456789\",\n name: \"image-01.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=1\",\n },\n {\n id: \"image-02-123456789\",\n name: \"image-02.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=2\",\n },\n {\n id: \"image-03-123456789\",\n name: \"image-03.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=3\",\n },\n {\n id: \"image-04-123456789\",\n name: \"image-04.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=4\",\n },\n];\n\nexport default function Component() {\n const maxSizeMB = 5;\n const maxSize = maxSizeMB * 1024 * 1024; // 5MB default\n const maxFiles = 6;\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n getInputProps,\n },\n ] = useFileUpload({\n accept: \"image/svg+xml,image/png,image/jpeg,image/jpg,image/gif\",\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n });\n\n return (\n
\n {/* Drop area */}\n 0 || undefined}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n \n {files.length > 0 ? (\n
\n
\n

\n Uploaded Files ({files.length})\n

\n = maxFiles}\n onClick={openFileDialog}\n size=\"sm\"\n variant=\"outline\"\n >\n \n Add more\n \n
\n\n
\n {files.map((file) => (\n \n \n removeFile(file.id)}\n size=\"icon\"\n >\n \n \n
\n ))}\n
\n
\n ) : (\n
\n \n \n
\n

Drop your images here

\n

\n SVG, PNG, JPG or GIF (max. {maxSizeMB}MB)\n

\n \n \n )}\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n \n Multiple image uploader w/ image grid ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-547.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-547", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-547.tsx", "content": "\"use client\";\n\nimport { AlertCircleIcon, ImageIcon, UploadIcon, XIcon } from \"lucide-react\";\n\nimport {\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"image-01-123456789\",\n name: \"image-01.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=1\",\n },\n {\n id: \"image-02-123456789\",\n name: \"image-02.jpg\",\n size: 2345678,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=2\",\n },\n {\n id: \"image-03-123456789\",\n name: \"image-03.jpg\",\n size: 3456789,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=3\",\n },\n];\n\nexport default function Component() {\n const maxSizeMB = 5;\n const maxSize = maxSizeMB * 1024 * 1024; // 5MB default\n const maxFiles = 6;\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n clearFiles,\n getInputProps,\n },\n ] = useFileUpload({\n accept: \"image/svg+xml,image/png,image/jpeg,image/jpg,image/gif\",\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n });\n\n return (\n
\n {/* Drop area */}\n 0 || undefined}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n \n
\n \n \n
\n

Drop your images here

\n

\n SVG, PNG, JPG or GIF (max. {maxSizeMB}MB)\n

\n \n
\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n {/* File list */}\n {files.length > 0 && (\n
\n {files.map((file) => (\n \n
\n
\n \n
\n
\n

\n {file.file.name}\n

\n

\n {formatBytes(file.file.size)}\n

\n
\n
\n\n removeFile(file.id)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n
\n ))}\n\n {/* Remove all files button */}\n {files.length > 1 && (\n
\n \n
\n )}\n \n )}\n\n \n Multiple image uploader w/ image list ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-548.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-548", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-548.tsx", "content": "\"use client\";\n\nimport {\n AlertCircleIcon,\n PaperclipIcon,\n UploadIcon,\n XIcon,\n} from \"lucide-react\";\n\nimport {\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"document.pdf-1744638436563-8u5xuls\",\n name: \"document.pdf\",\n size: 1528737,\n type: \"application/pdf\",\n url: \"https://picsum.photos/1000/800?grayscale&random=1\",\n },\n];\n\nexport default function Component() {\n const maxSize = 10 * 1024 * 1024; // 10MB default\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n getInputProps,\n },\n ] = useFileUpload({\n initialFiles,\n maxSize,\n });\n\n const file = files[0];\n\n return (\n
\n {/* Drop area */}\n \n \n\n
\n \n \n
\n

Upload file

\n

\n Drag & drop or click to browse (max. {formatBytes(maxSize)})\n

\n
\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n {/* File list */}\n {file && (\n
\n \n
\n \n
\n

\n {file.file.name}\n

\n
\n
\n\n removeFile(files[0]?.id)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n
\n \n )}\n\n \n Single file uploader w/ max size ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-549.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-549", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-549.tsx", "content": "\"use client\";\n\nimport {\n AlertCircleIcon,\n FileArchiveIcon,\n FileIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n FileUpIcon,\n HeadphonesIcon,\n ImageIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\n\nimport {\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"document.pdf-1744638436563-8u5xuls\",\n name: \"document.pdf\",\n size: 528737,\n type: \"application/pdf\",\n url: \"https://example.com/document.pdf\",\n },\n {\n id: \"intro.zip-1744638436563-8u5xuls\",\n name: \"intro.zip\",\n size: 252873,\n type: \"application/zip\",\n url: \"https://example.com/intro.zip\",\n },\n {\n id: \"conclusion.xlsx-1744638436563-8u5xuls\",\n name: \"conclusion.xlsx\",\n size: 352873,\n type: \"application/xlsx\",\n url: \"https://example.com/conclusion.xlsx\",\n },\n];\n\nconst getFileIcon = (file: { file: File | { type: string; name: string } }) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n if (\n fileType.includes(\"pdf\") ||\n fileName.endsWith(\".pdf\") ||\n fileType.includes(\"word\") ||\n fileName.endsWith(\".doc\") ||\n fileName.endsWith(\".docx\")\n ) {\n return ;\n }\n if (\n fileType.includes(\"zip\") ||\n fileType.includes(\"archive\") ||\n fileName.endsWith(\".zip\") ||\n fileName.endsWith(\".rar\")\n ) {\n return ;\n }\n if (\n fileType.includes(\"excel\") ||\n fileName.endsWith(\".xls\") ||\n fileName.endsWith(\".xlsx\")\n ) {\n return ;\n }\n if (fileType.includes(\"video/\")) {\n return ;\n }\n if (fileType.includes(\"audio/\")) {\n return ;\n }\n if (fileType.startsWith(\"image/\")) {\n return ;\n }\n return ;\n};\n\nexport default function Component() {\n const maxSize = 100 * 1024 * 1024; // 10MB default\n const maxFiles = 10;\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n clearFiles,\n getInputProps,\n },\n ] = useFileUpload({\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n });\n\n return (\n
\n {/* Drop area */}\n \n \n\n
\n \n \n
\n

Upload files

\n

\n Drag & drop or click to browse\n

\n
\n All files\n \n Max {maxFiles} files\n \n Up to {formatBytes(maxSize)}\n
\n
\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n {/* File list */}\n {files.length > 0 && (\n
\n {files.map((file) => (\n \n
\n
\n {getFileIcon(file)}\n
\n
\n

\n {file.file instanceof File\n ? file.file.name\n : file.file.name}\n

\n

\n {formatBytes(\n file.file instanceof File\n ? file.file.size\n : file.file.size,\n )}\n

\n
\n
\n\n removeFile(file.id)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n
\n ))}\n\n {/* Remove all files button */}\n {files.length > 1 && (\n
\n \n
\n )}\n \n )}\n\n \n Multiple files uploader w/ list ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-55.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-55", "type": "registry:component", "dependencies": [ "use-mask-input" ], "registryDependencies": [ "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-55.tsx", "content": "\"use client\";\n\nimport { useId } from \"react\";\nimport { withMask } from \"use-mask-input\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
\n \n {\n if (input) {\n withMask(\"99:99:99\", {\n placeholder: \"-\",\n showMaskOnHover: false,\n })(input);\n }\n }}\n type=\"text\"\n />\n \n Built with{\" \"}\n \n use-mask-input\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "mask", "time" ] } } ================================================ FILE: apps/origin/public/r/comp-550.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-550", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-550.tsx", "content": "\"use client\";\n\nimport {\n AlertCircleIcon,\n FileArchiveIcon,\n FileIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n HeadphonesIcon,\n ImageIcon,\n Trash2Icon,\n UploadIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\n\nimport {\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\nconst getFileIcon = (file: { file: File | { type: string; name: string } }) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n if (\n fileType.includes(\"pdf\") ||\n fileName.endsWith(\".pdf\") ||\n fileType.includes(\"word\") ||\n fileName.endsWith(\".doc\") ||\n fileName.endsWith(\".docx\")\n ) {\n return ;\n }\n if (\n fileType.includes(\"zip\") ||\n fileType.includes(\"archive\") ||\n fileName.endsWith(\".zip\") ||\n fileName.endsWith(\".rar\")\n ) {\n return ;\n }\n if (\n fileType.includes(\"excel\") ||\n fileName.endsWith(\".xls\") ||\n fileName.endsWith(\".xlsx\")\n ) {\n return ;\n }\n if (fileType.includes(\"video/\")) {\n return ;\n }\n if (fileType.includes(\"audio/\")) {\n return ;\n }\n if (fileType.startsWith(\"image/\")) {\n return ;\n }\n return ;\n};\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"document.pdf-1744638436563-8u5xuls\",\n name: \"document.pdf\",\n size: 528737,\n type: \"application/pdf\",\n url: \"https://example.com/document.pdf\",\n },\n {\n id: \"intro.zip-1744638436563-8u5xuls\",\n name: \"intro.zip\",\n size: 252873,\n type: \"application/zip\",\n url: \"https://example.com/intro.zip\",\n },\n {\n id: \"conclusion.xlsx-1744638436563-8u5xuls\",\n name: \"conclusion.xlsx\",\n size: 352873,\n type: \"application/xlsx\",\n url: \"https://example.com/conclusion.xlsx\",\n },\n];\n\nexport default function Component() {\n const maxSize = 10 * 1024 * 1024; // 10MB default\n const maxFiles = 10;\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n clearFiles,\n getInputProps,\n },\n ] = useFileUpload({\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n });\n\n return (\n
\n {/* Drop area */}\n 0 || undefined}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n \n\n {files.length > 0 ? (\n
\n
\n

\n Uploaded Files ({files.length})\n

\n \n
\n
\n {files.map((file) => (\n \n
\n
\n {getFileIcon(file)}\n
\n
\n

\n {file.file instanceof File\n ? file.file.name\n : file.file.name}\n

\n

\n {formatBytes(\n file.file instanceof File\n ? file.file.size\n : file.file.size,\n )}\n

\n
\n
\n\n removeFile(file.id)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n
\n ))}\n\n {files.length < maxFiles && (\n \n \n Add more\n \n )}\n
\n
\n ) : (\n
\n \n \n
\n

Upload files

\n

\n Max {maxFiles} files ∙ Up to {maxSize}MB\n

\n \n \n )}\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n \n Multiple files uploader w/ list inside ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-551.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-551", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/table.json" ], "files": [ { "path": "registry/default/components/comp-551.tsx", "content": "\"use client\";\n\nimport {\n AlertCircleIcon,\n DownloadIcon,\n FileArchiveIcon,\n FileIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n HeadphonesIcon,\n ImageIcon,\n Trash2Icon,\n UploadCloudIcon,\n UploadIcon,\n VideoIcon,\n} from \"lucide-react\";\n\nimport {\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Table,\n TableBody,\n TableCell,\n TableHead,\n TableHeader,\n TableRow,\n} from \"@/registry/default/ui/table\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"document.pdf-1744638436563-8u5xuls\",\n name: \"document.pdf\",\n size: 528737,\n type: \"application/pdf\",\n url: \"https://coss.com/origin\",\n },\n {\n id: \"intro.zip-1744638436563-8u5xuls\",\n name: \"intro.zip\",\n size: 252873,\n type: \"application/zip\",\n url: \"https://coss.com/origin\",\n },\n {\n id: \"conclusion.xlsx-1744638436563-8u5xuls\",\n name: \"conclusion.xlsx\",\n size: 352873,\n type: \"application/xlsx\",\n url: \"https://coss.com/origin\",\n },\n];\n\nconst getFileIcon = (file: { file: File | { type: string; name: string } }) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n if (\n fileType.includes(\"pdf\") ||\n fileName.endsWith(\".pdf\") ||\n fileType.includes(\"word\") ||\n fileName.endsWith(\".doc\") ||\n fileName.endsWith(\".docx\")\n ) {\n return ;\n }\n if (\n fileType.includes(\"zip\") ||\n fileType.includes(\"archive\") ||\n fileName.endsWith(\".zip\") ||\n fileName.endsWith(\".rar\")\n ) {\n return ;\n }\n if (\n fileType.includes(\"excel\") ||\n fileName.endsWith(\".xls\") ||\n fileName.endsWith(\".xlsx\")\n ) {\n return ;\n }\n if (fileType.includes(\"video/\")) {\n return ;\n }\n if (fileType.includes(\"audio/\")) {\n return ;\n }\n if (fileType.startsWith(\"image/\")) {\n return ;\n }\n return ;\n};\n\nexport default function Component() {\n const maxSize = 10 * 1024 * 1024; // 10MB default\n const maxFiles = 10;\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n clearFiles,\n getInputProps,\n },\n ] = useFileUpload({\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n });\n\n return (\n
\n {/* Drop area */}\n 0 || undefined}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n \n
\n \n \n
\n

Upload files

\n

\n Max {maxFiles} files ∙ Up to {formatBytes(maxSize)}\n

\n \n
\n \n {files.length > 0 && (\n <>\n {/* Table with files */}\n
\n

Files ({files.length})

\n
\n \n \n
\n
\n
\n \n \n \n Name\n Type\n Size\n \n Actions\n \n \n \n \n {files.map((file) => (\n \n \n \n {getFileIcon(file)}{\" \"}\n {file.file.name}\n \n \n \n {file.file.type.split(\"/\")[1]?.toUpperCase() || \"UNKNOWN\"}\n \n \n {formatBytes(file.file.size)}\n \n \n window.open(file.preview, \"_blank\")}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n removeFile(file.id)}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n \n \n ))}\n \n
\n
\n \n )}\n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n \n Multiple files uploader w/ table ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-552.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-552", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-552.tsx", "content": "\"use client\";\n\nimport {\n AlertCircleIcon,\n FileArchiveIcon,\n FileIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n HeadphonesIcon,\n ImageIcon,\n Trash2Icon,\n UploadIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\n\nimport {\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"intro.zip-1744638436563-8u5xuls\",\n name: \"intro.zip\",\n size: 252873,\n type: \"application/zip\",\n url: \"https://example.com/intro.zip\",\n },\n {\n id: \"image-01-123456789\",\n name: \"image-01.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=1\",\n },\n {\n id: \"audio-123456789\",\n name: \"audio.mp3\",\n size: 1528737,\n type: \"audio/mpeg\",\n url: \"https://example.com/audio.mp3\",\n },\n];\n\nconst getFileIcon = (file: { file: File | { type: string; name: string } }) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n const iconMap = {\n archive: {\n conditions: (type: string, name: string) =>\n type.includes(\"zip\") ||\n type.includes(\"archive\") ||\n name.endsWith(\".zip\") ||\n name.endsWith(\".rar\"),\n icon: FileArchiveIcon,\n },\n audio: {\n conditions: (type: string) => type.includes(\"audio/\"),\n icon: HeadphonesIcon,\n },\n excel: {\n conditions: (type: string, name: string) =>\n type.includes(\"excel\") ||\n name.endsWith(\".xls\") ||\n name.endsWith(\".xlsx\"),\n icon: FileSpreadsheetIcon,\n },\n image: {\n conditions: (type: string) => type.startsWith(\"image/\"),\n icon: ImageIcon,\n },\n pdf: {\n conditions: (type: string, name: string) =>\n type.includes(\"pdf\") ||\n name.endsWith(\".pdf\") ||\n type.includes(\"word\") ||\n name.endsWith(\".doc\") ||\n name.endsWith(\".docx\"),\n icon: FileTextIcon,\n },\n video: {\n conditions: (type: string) => type.includes(\"video/\"),\n icon: VideoIcon,\n },\n };\n\n for (const { icon: Icon, conditions } of Object.values(iconMap)) {\n if (conditions(fileType, fileName)) {\n return ;\n }\n }\n\n return ;\n};\n\nconst getFilePreview = (file: {\n file: File | { type: string; name: string; url?: string };\n}) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n const renderImage = (src: string) => (\n \n );\n\n return (\n
\n {fileType.startsWith(\"image/\") ? (\n file.file instanceof File ? (\n (() => {\n const previewUrl = URL.createObjectURL(file.file);\n return renderImage(previewUrl);\n })()\n ) : file.file.url ? (\n renderImage(file.file.url)\n ) : (\n \n )\n ) : (\n getFileIcon(file)\n )}\n
\n );\n};\n\nexport default function Component() {\n const maxSizeMB = 5;\n const maxSize = maxSizeMB * 1024 * 1024; // 5MB default\n const maxFiles = 6;\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n clearFiles,\n getInputProps,\n },\n ] = useFileUpload({\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n });\n\n return (\n
\n {/* Drop area */}\n 0 || undefined}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n \n {files.length > 0 ? (\n
\n
\n

\n Files ({files.length})\n

\n
\n \n \n
\n
\n\n
\n {files.map((file) => (\n \n {getFilePreview(file)}\n removeFile(file.id)}\n size=\"icon\"\n >\n \n \n
\n

\n {file.file.name}\n

\n

\n {formatBytes(file.file.size)}\n

\n
\n
\n ))}\n
\n
\n ) : (\n
\n \n \n
\n

Drop your files here

\n

\n Max {maxFiles} files ∙ Up to {maxSizeMB}MB\n

\n \n \n )}\n \n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n \n Mixed content w/ card ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-553.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-553", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-553.tsx", "content": "\"use client\";\n\nimport {\n AlertCircleIcon,\n FileArchiveIcon,\n FileIcon,\n FileSpreadsheetIcon,\n FileTextIcon,\n HeadphonesIcon,\n ImageIcon,\n Trash2Icon,\n UploadIcon,\n VideoIcon,\n XIcon,\n} from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport {\n type FileWithPreview,\n formatBytes,\n useFileUpload,\n} from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\n\n// Create some dummy initial files\nconst initialFiles = [\n {\n id: \"intro.zip-1744638436563-8u5xuls\",\n name: \"intro.zip\",\n size: 252873,\n type: \"application/zip\",\n url: \"https://example.com/intro.zip\",\n },\n {\n id: \"image-01-123456789\",\n name: \"image-01.jpg\",\n size: 1528737,\n type: \"image/jpeg\",\n url: \"https://picsum.photos/1000/800?grayscale&random=1\",\n },\n {\n id: \"audio-123456789\",\n name: \"audio.mp3\",\n size: 1528737,\n type: \"audio/mpeg\",\n url: \"https://example.com/audio.mp3\",\n },\n];\n\nconst getFileIcon = (file: { file: File | { type: string; name: string } }) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n const iconMap = {\n archive: {\n conditions: (type: string, name: string) =>\n type.includes(\"zip\") ||\n type.includes(\"archive\") ||\n name.endsWith(\".zip\") ||\n name.endsWith(\".rar\"),\n icon: FileArchiveIcon,\n },\n audio: {\n conditions: (type: string) => type.includes(\"audio/\"),\n icon: HeadphonesIcon,\n },\n excel: {\n conditions: (type: string, name: string) =>\n type.includes(\"excel\") ||\n name.endsWith(\".xls\") ||\n name.endsWith(\".xlsx\"),\n icon: FileSpreadsheetIcon,\n },\n image: {\n conditions: (type: string) => type.startsWith(\"image/\"),\n icon: ImageIcon,\n },\n pdf: {\n conditions: (type: string, name: string) =>\n type.includes(\"pdf\") ||\n name.endsWith(\".pdf\") ||\n type.includes(\"word\") ||\n name.endsWith(\".doc\") ||\n name.endsWith(\".docx\"),\n icon: FileTextIcon,\n },\n video: {\n conditions: (type: string) => type.includes(\"video/\"),\n icon: VideoIcon,\n },\n };\n\n for (const { icon: Icon, conditions } of Object.values(iconMap)) {\n if (conditions(fileType, fileName)) {\n return ;\n }\n }\n\n return ;\n};\n\nconst _getFilePreview = (file: {\n file: File | { type: string; name: string; url?: string };\n}) => {\n const fileType = file.file instanceof File ? file.file.type : file.file.type;\n const fileName = file.file instanceof File ? file.file.name : file.file.name;\n\n const renderImage = (src: string) => (\n \n );\n\n return (\n
\n {fileType.startsWith(\"image/\") ? (\n file.file instanceof File ? (\n (() => {\n const previewUrl = URL.createObjectURL(file.file);\n return renderImage(previewUrl);\n })()\n ) : file.file.url ? (\n renderImage(file.file.url)\n ) : (\n \n )\n ) : (\n getFileIcon(file)\n )}\n
\n );\n};\n\n// Type for tracking upload progress\ntype UploadProgress = {\n fileId: string;\n progress: number;\n completed: boolean;\n};\n\n// Function to simulate file upload with more realistic timing and progress\nconst simulateUpload = (\n totalBytes: number,\n onProgress: (progress: number) => void,\n onComplete: () => void,\n) => {\n let timeoutId: NodeJS.Timeout;\n let uploadedBytes = 0;\n let lastProgressReport = 0;\n\n const simulateChunk = () => {\n // Simulate variable network conditions with random chunk sizes\n const chunkSize = Math.floor(Math.random() * 300000) + 2000;\n uploadedBytes = Math.min(totalBytes, uploadedBytes + chunkSize);\n\n // Calculate progress percentage (0-100)\n const progressPercent = Math.floor((uploadedBytes / totalBytes) * 100);\n\n // Only report progress if it's changed by at least 1%\n if (progressPercent > lastProgressReport) {\n lastProgressReport = progressPercent;\n onProgress(progressPercent);\n }\n\n // Continue simulation if not complete\n if (uploadedBytes < totalBytes) {\n // Variable delay between 50ms and 500ms to simulate network fluctuations (reduced for faster uploads)\n const delay = Math.floor(Math.random() * 450) + 50;\n\n // Occasionally add a longer pause to simulate network congestion (5% chance, shorter duration)\n const extraDelay = Math.random() < 0.05 ? 500 : 0;\n\n timeoutId = setTimeout(simulateChunk, delay + extraDelay);\n } else {\n // Upload complete\n onComplete();\n }\n };\n\n // Start the simulation\n timeoutId = setTimeout(simulateChunk, 100);\n\n // Return a cleanup function to cancel the simulation\n return () => {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n };\n};\n\nexport default function Component() {\n const maxSizeMB = 5;\n const maxSize = maxSizeMB * 1024 * 1024; // 5MB default\n const maxFiles = 6;\n\n // State to track upload progress for each file\n const [uploadProgress, setUploadProgress] = useState([]);\n\n // Function to handle newly added files\n const handleFilesAdded = (addedFiles: FileWithPreview[]) => {\n const newProgressItems = addedFiles.map((file) => ({\n completed: false,\n fileId: file.id,\n progress: 0,\n }));\n\n setUploadProgress((prev) => [...prev, ...newProgressItems]);\n\n const cleanupFunctions: Array<() => void> = [];\n\n for (const file of addedFiles) {\n const fileSize =\n file.file instanceof File ? file.file.size : file.file.size;\n\n const cleanup = simulateUpload(\n fileSize,\n (progress) => {\n setUploadProgress((prev) =>\n prev.map((item) =>\n item.fileId === file.id ? { ...item, progress } : item,\n ),\n );\n },\n () => {\n setUploadProgress((prev) =>\n prev.map((item) =>\n item.fileId === file.id ? { ...item, completed: true } : item,\n ),\n );\n },\n );\n\n cleanupFunctions.push(cleanup);\n }\n\n return () => {\n for (const cleanup of cleanupFunctions) {\n cleanup();\n }\n };\n };\n\n // Remove the progress tracking for the file\n const handleFileRemoved = (fileId: string) => {\n setUploadProgress((prev) => prev.filter((item) => item.fileId !== fileId));\n };\n\n const [\n { files, isDragging, errors },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n clearFiles,\n getInputProps,\n },\n ] = useFileUpload({\n initialFiles,\n maxFiles,\n maxSize,\n multiple: true,\n onFilesAdded: handleFilesAdded,\n });\n\n return (\n
\n {/* Drop area */}\n 0 || undefined}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDragOver={handleDragOver}\n onDrop={handleDrop}\n >\n \n {files.length > 0 ? (\n
\n
\n

\n Files ({files.length})\n

\n
\n \n {\n // Clear all progress tracking\n setUploadProgress([]);\n clearFiles();\n }}\n size=\"sm\"\n variant=\"outline\"\n >\n \n Remove all\n \n
\n
\n\n
\n {files.map((file) => {\n // Find the upload progress for this file once to avoid repeated lookups\n const fileProgress = uploadProgress.find(\n (p) => p.fileId === file.id,\n );\n const isUploading = fileProgress && !fileProgress.completed;\n\n return (\n \n
\n
\n
\n {getFileIcon(file)}\n
\n
\n

\n {file.file instanceof File\n ? file.file.name\n : file.file.name}\n

\n

\n {formatBytes(\n file.file instanceof File\n ? file.file.size\n : file.file.size,\n )}\n

\n
\n
\n {\n handleFileRemoved(file.id);\n removeFile(file.id);\n }}\n size=\"icon\"\n variant=\"ghost\"\n >\n \n \n
\n\n {/* Upload progress bar */}\n {fileProgress &&\n (() => {\n const progress = fileProgress.progress || 0;\n const completed = fileProgress.completed || false;\n\n if (completed) return null;\n\n return (\n
\n
\n \n
\n \n {progress}%\n \n
\n );\n })()}\n
\n );\n })}\n
\n
\n ) : (\n
\n \n \n
\n

Drop your files here

\n

\n Max {maxFiles} files ∙ Up to {maxSizeMB}MB\n

\n \n \n )}\n \n\n {errors.length > 0 && (\n \n \n {errors[0]}\n \n )}\n\n \n With simulated progress track ∙{\" \"}\n \n API\n \n

\n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 2, "tags": [ "upload", "file", "image", "drag and drop" ] } } ================================================ FILE: apps/origin/public/r/comp-554.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-554", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/cropper.json", "https://coss.com/origin/r/dialog.json", "https://coss.com/origin/r/slider.json" ], "files": [ { "path": "registry/default/components/comp-554.tsx", "content": "\"use client\";\n\nimport {\n ArrowLeftIcon,\n CircleUserRoundIcon,\n XIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from \"lucide-react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport { useFileUpload } from \"@/registry/default/hooks/use-file-upload\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n} from \"@/registry/default/ui/dialog\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\n// Define type for pixel crop area\ntype Area = { x: number; y: number; width: number; height: number };\n\n// Helper function to create a cropped image blob\nconst createImage = (url: string): Promise =>\n new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener(\"load\", () => resolve(image));\n image.addEventListener(\"error\", (error) => reject(error));\n image.setAttribute(\"crossOrigin\", \"anonymous\"); // Needed for canvas Tainted check\n image.src = url;\n });\n\nasync function getCroppedImg(\n imageSrc: string,\n pixelCrop: Area,\n outputWidth: number = pixelCrop.width, // Optional: specify output size\n outputHeight: number = pixelCrop.height,\n): Promise {\n try {\n const image = await createImage(imageSrc);\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n\n if (!ctx) {\n return null;\n }\n\n // Set canvas size to desired output size\n canvas.width = outputWidth;\n canvas.height = outputHeight;\n\n // Draw the cropped image onto the canvas\n ctx.drawImage(\n image,\n pixelCrop.x,\n pixelCrop.y,\n pixelCrop.width,\n pixelCrop.height,\n 0,\n 0,\n outputWidth, // Draw onto the output size\n outputHeight,\n );\n\n // Convert canvas to blob\n return new Promise((resolve) => {\n canvas.toBlob((blob) => {\n resolve(blob);\n }, \"image/jpeg\"); // Specify format and quality if needed\n });\n } catch (error) {\n console.error(\"Error in getCroppedImg:\", error);\n return null;\n }\n}\n\nexport default function Component() {\n const [\n { files, isDragging },\n {\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n openFileDialog,\n removeFile,\n getInputProps,\n },\n ] = useFileUpload({\n accept: \"image/*\",\n });\n\n const previewUrl = files[0]?.preview || null;\n const fileId = files[0]?.id;\n\n const [finalImageUrl, setFinalImageUrl] = useState(null);\n const [isDialogOpen, setIsDialogOpen] = useState(false);\n\n // Ref to track the previous file ID to detect new uploads\n const previousFileIdRef = useRef(null);\n\n // State to store the desired crop area in pixels\n const [croppedAreaPixels, setCroppedAreaPixels] = useState(null);\n\n // State for zoom level\n const [zoom, setZoom] = useState(1);\n\n // Callback for Cropper to provide crop data - Wrap with useCallback\n const handleCropChange = useCallback((pixels: Area | null) => {\n setCroppedAreaPixels(pixels);\n }, []);\n\n const handleApply = async () => {\n // Check if we have the necessary data\n if (!previewUrl || !fileId || !croppedAreaPixels) {\n console.error(\"Missing data for apply:\", {\n croppedAreaPixels,\n fileId,\n previewUrl,\n });\n // Remove file if apply is clicked without crop data?\n if (fileId) {\n removeFile(fileId);\n setCroppedAreaPixels(null);\n }\n return;\n }\n\n try {\n // 1. Get the cropped image blob using the helper\n const croppedBlob = await getCroppedImg(previewUrl, croppedAreaPixels);\n\n if (!croppedBlob) {\n throw new Error(\"Failed to generate cropped image blob.\");\n }\n\n // 2. Create a NEW object URL from the cropped blob\n const newFinalUrl = URL.createObjectURL(croppedBlob);\n\n // 3. Revoke the OLD finalImageUrl if it exists\n if (finalImageUrl) {\n URL.revokeObjectURL(finalImageUrl);\n }\n\n // 4. Set the final avatar state to the NEW URL\n setFinalImageUrl(newFinalUrl);\n\n // 5. Close the dialog (don't remove the file yet)\n setIsDialogOpen(false);\n } catch (error) {\n console.error(\"Error during apply:\", error);\n // Close the dialog even if cropping fails\n setIsDialogOpen(false);\n }\n };\n\n const handleRemoveFinalImage = () => {\n if (finalImageUrl) {\n URL.revokeObjectURL(finalImageUrl);\n }\n setFinalImageUrl(null);\n };\n\n useEffect(() => {\n const currentFinalUrl = finalImageUrl;\n // Cleanup function\n return () => {\n if (currentFinalUrl?.startsWith(\"blob:\")) {\n URL.revokeObjectURL(currentFinalUrl);\n }\n };\n }, [finalImageUrl]);\n\n // Effect to open dialog when a *new* file is ready\n useEffect(() => {\n // Check if fileId exists and is different from the previous one\n if (fileId && fileId !== previousFileIdRef.current) {\n setIsDialogOpen(true); // Open dialog for the new file\n setCroppedAreaPixels(null); // Reset crop area for the new file\n setZoom(1); // Reset zoom for the new file\n }\n // Update the ref to the current fileId for the next render\n previousFileIdRef.current = fileId;\n }, [fileId]); // Depend only on fileId\n\n return (\n
\n
\n {/* Drop area - uses finalImageUrl */}\n \n {finalImageUrl ? (\n \n ) : (\n
\n \n
\n )}\n \n {/* Remove button - depends on finalImageUrl */}\n {finalImageUrl && (\n \n \n \n )}\n \n
\n\n {/* Cropper Dialog - Use isDialogOpen for open prop */}\n \n \n \n Crop image dialog\n \n \n \n
\n setIsDialogOpen(false)}\n size=\"icon\"\n type=\"button\"\n variant=\"ghost\"\n >\n \n \n Crop image\n
\n \n Apply\n \n
\n
\n {previewUrl && (\n \n \n \n \n \n )}\n \n
\n \n setZoom(value[0])}\n step={0.1}\n value={[zoom]}\n />\n \n
\n
\n
\n
\n\n \n Avatar{\" \"}\n \n uploader\n {\" \"}\n with{\" \"}\n \n cropper\n \n

\n
\n );\n}\n", "type": "registry:component" }, { "path": "registry/default/hooks/use-file-upload.ts", "content": "\"use client\";\n\nimport {\n type ChangeEvent,\n type DragEvent,\n type InputHTMLAttributes,\n useCallback,\n useRef,\n useState,\n} from \"react\";\n\nexport type FileMetadata = {\n name: string;\n size: number;\n type: string;\n url: string;\n id: string;\n};\n\nexport type FileWithPreview = {\n file: File | FileMetadata;\n id: string;\n preview?: string;\n};\n\nexport type FileUploadOptions = {\n maxFiles?: number; // Only used when multiple is true, defaults to Infinity\n maxSize?: number; // in bytes\n accept?: string;\n multiple?: boolean; // Defaults to false\n initialFiles?: FileMetadata[];\n onFilesChange?: (files: FileWithPreview[]) => void; // Callback when files change\n onFilesAdded?: (addedFiles: FileWithPreview[]) => void; // Callback when new files are added\n};\n\nexport type FileUploadState = {\n files: FileWithPreview[];\n isDragging: boolean;\n errors: string[];\n};\n\nexport type FileUploadActions = {\n addFiles: (files: FileList | File[]) => void;\n removeFile: (id: string) => void;\n clearFiles: () => void;\n clearErrors: () => void;\n handleDragEnter: (e: DragEvent) => void;\n handleDragLeave: (e: DragEvent) => void;\n handleDragOver: (e: DragEvent) => void;\n handleDrop: (e: DragEvent) => void;\n handleFileChange: (e: ChangeEvent) => void;\n openFileDialog: () => void;\n getInputProps: (\n props?: InputHTMLAttributes,\n ) => InputHTMLAttributes & {\n // Use `any` here to avoid cross-React ref type conflicts across packages\n // biome-ignore lint/suspicious/noExplicitAny: intentional\n ref: any;\n };\n};\n\nexport const useFileUpload = (\n options: FileUploadOptions = {},\n): [FileUploadState, FileUploadActions] => {\n const {\n maxFiles = Number.POSITIVE_INFINITY,\n maxSize = Number.POSITIVE_INFINITY,\n accept = \"*\",\n multiple = false,\n initialFiles = [],\n onFilesChange,\n onFilesAdded,\n } = options;\n\n const [state, setState] = useState({\n errors: [],\n files: initialFiles.map((file) => ({\n file,\n id: file.id,\n preview: file.url,\n })),\n isDragging: false,\n });\n\n const inputRef = useRef(null);\n\n const validateFile = useCallback(\n (file: File | FileMetadata): string | null => {\n if (file instanceof File) {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n } else {\n if (file.size > maxSize) {\n return `File \"${file.name}\" exceeds the maximum size of ${formatBytes(maxSize)}.`;\n }\n }\n\n if (accept !== \"*\") {\n const acceptedTypes = accept.split(\",\").map((type) => type.trim());\n const fileType = file instanceof File ? file.type || \"\" : file.type;\n const fileExtension = `.${file instanceof File ? file.name.split(\".\").pop() : file.name.split(\".\").pop()}`;\n\n const isAccepted = acceptedTypes.some((type) => {\n if (type.startsWith(\".\")) {\n return fileExtension.toLowerCase() === type.toLowerCase();\n }\n if (type.endsWith(\"/*\")) {\n const baseType = type.split(\"/\")[0];\n return fileType.startsWith(`${baseType}/`);\n }\n return fileType === type;\n });\n\n if (!isAccepted) {\n return `File \"${file instanceof File ? file.name : file.name}\" is not an accepted file type.`;\n }\n }\n\n return null;\n },\n [accept, maxSize],\n );\n\n const createPreview = useCallback(\n (file: File | FileMetadata): string | undefined => {\n if (file instanceof File) {\n return URL.createObjectURL(file);\n }\n return file.url;\n },\n [],\n );\n\n const generateUniqueId = useCallback((file: File | FileMetadata): string => {\n if (file instanceof File) {\n return `${file.name}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n return file.id;\n }, []);\n\n const clearFiles = useCallback(() => {\n setState((prev) => {\n // Clean up object URLs\n for (const file of prev.files ?? []) {\n if (\n file.preview &&\n file.file instanceof File &&\n file.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(file.preview);\n }\n }\n\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n\n const newState = {\n ...prev,\n errors: [],\n files: [],\n };\n\n onFilesChange?.(newState.files);\n return newState;\n });\n }, [onFilesChange]);\n\n const addFiles = useCallback(\n (newFiles: FileList | File[]) => {\n if (!newFiles || newFiles.length === 0) return;\n\n const newFilesArray = Array.from(newFiles);\n const errors: string[] = [];\n\n // Clear existing errors when new files are uploaded\n setState((prev) => ({ ...prev, errors: [] }));\n\n // In single file mode, clear existing files first\n if (!multiple) {\n clearFiles();\n }\n\n // Check if adding these files would exceed maxFiles (only in multiple mode)\n if (\n multiple &&\n maxFiles !== Number.POSITIVE_INFINITY &&\n state.files.length + newFilesArray.length > maxFiles\n ) {\n errors.push(`You can only upload a maximum of ${maxFiles} files.`);\n setState((prev) => ({ ...prev, errors }));\n return;\n }\n\n const validFiles: FileWithPreview[] = [];\n\n for (const file of newFilesArray) {\n if (multiple) {\n const isDuplicate = state.files.some(\n (existingFile) =>\n existingFile.file.name === file.name &&\n existingFile.file.size === file.size,\n );\n\n if (isDuplicate) {\n continue;\n }\n }\n\n if (file.size > maxSize) {\n errors.push(\n multiple\n ? `Some files exceed the maximum size of ${formatBytes(maxSize)}.`\n : `File exceeds the maximum size of ${formatBytes(maxSize)}.`,\n );\n continue;\n }\n\n const error = validateFile(file);\n\n if (error) {\n errors.push(error);\n continue;\n }\n\n validFiles.push({\n file,\n id: generateUniqueId(file),\n preview: createPreview(file),\n });\n }\n\n // Only update state if we have valid files to add\n if (validFiles.length > 0) {\n // Call the onFilesAdded callback with the newly added valid files\n onFilesAdded?.(validFiles);\n\n setState((prev) => {\n const newFiles = !multiple\n ? validFiles\n : [...prev.files, ...validFiles];\n onFilesChange?.(newFiles);\n return {\n ...prev,\n errors,\n files: newFiles,\n };\n });\n } else if (errors.length > 0) {\n setState((prev) => ({\n ...prev,\n errors,\n }));\n }\n\n // Reset input value after handling files\n if (inputRef.current) {\n inputRef.current.value = \"\";\n }\n },\n [\n state.files,\n maxFiles,\n multiple,\n maxSize,\n validateFile,\n createPreview,\n generateUniqueId,\n clearFiles,\n onFilesChange,\n onFilesAdded,\n ],\n );\n\n const removeFile = useCallback(\n (id: string) => {\n setState((prev) => {\n const fileToRemove = prev.files.find((file) => file.id === id);\n if (\n fileToRemove?.preview &&\n fileToRemove.file instanceof File &&\n fileToRemove.file.type.startsWith(\"image/\")\n ) {\n URL.revokeObjectURL(fileToRemove.preview);\n }\n\n const newFiles = prev.files.filter((file) => file.id !== id);\n onFilesChange?.(newFiles);\n\n return {\n ...prev,\n errors: [],\n files: newFiles,\n };\n });\n },\n [onFilesChange],\n );\n\n const clearErrors = useCallback(() => {\n setState((prev) => ({\n ...prev,\n errors: [],\n }));\n }, []);\n\n const handleDragEnter = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: true }));\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n if (e.currentTarget.contains(e.relatedTarget as Node)) {\n return;\n }\n\n setState((prev) => ({ ...prev, isDragging: false }));\n }, []);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n }, []);\n\n const handleDrop = useCallback(\n (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setState((prev) => ({ ...prev, isDragging: false }));\n\n // Don't process files if the input is disabled\n if (inputRef.current?.disabled) {\n return;\n }\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n // In single file mode, only use the first file\n if (!multiple) {\n const file = e.dataTransfer.files[0];\n addFiles([file]);\n } else {\n addFiles(e.dataTransfer.files);\n }\n }\n },\n [addFiles, multiple],\n );\n\n const handleFileChange = useCallback(\n (e: ChangeEvent) => {\n if (e.target.files && e.target.files.length > 0) {\n addFiles(e.target.files);\n }\n },\n [addFiles],\n );\n\n const openFileDialog = useCallback(() => {\n if (inputRef.current) {\n inputRef.current.click();\n }\n }, []);\n\n const getInputProps = useCallback(\n (props: InputHTMLAttributes = {}) => {\n return {\n ...props,\n accept: props.accept || accept,\n multiple: props.multiple !== undefined ? props.multiple : multiple,\n onChange: handleFileChange,\n // Cast to `any` to prevent mismatched React ref type errors across workspaces\n // biome-ignore lint/suspicious/noExplicitAny: Intentional\n ref: inputRef as any,\n type: \"file\" as const,\n };\n },\n [accept, multiple, handleFileChange],\n );\n\n return [\n state,\n {\n addFiles,\n clearErrors,\n clearFiles,\n getInputProps,\n handleDragEnter,\n handleDragLeave,\n handleDragOver,\n handleDrop,\n handleFileChange,\n openFileDialog,\n removeFile,\n },\n ];\n};\n\n// Helper function to format bytes to human-readable format\nexport const formatBytes = (bytes: number, decimals = 2): string => {\n if (bytes === 0) return \"0 Bytes\";\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\", \"EB\", \"ZB\", \"YB\"];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return Number.parseFloat((bytes / k ** i).toFixed(dm)) + sizes[i];\n};\n", "type": "registry:hook" } ], "meta": { "colSpan": 3, "tags": [ "upload", "file", "image", "drag and drop", "crop", "dialog", "slider", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-555.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-555", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-555.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Basic cropper ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-556.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-556", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-556.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Cropper with aspect ratio 16:9 ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-557.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-557", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-557.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Cropper with custom crop area color ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-558.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-558", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-558.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Cropper with custom mask overlay ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-559.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-559", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-559.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Cropper with full size crop area ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-56.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-56", "type": "registry:component", "dependencies": [ "emblor" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-56.tsx", "content": "\"use client\";\n\nimport { type Tag, TagInput } from \"emblor\";\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\n\nconst tags = [\n {\n id: \"1\",\n text: \"Sport\",\n },\n {\n id: \"2\",\n text: \"Coding\",\n },\n {\n id: \"3\",\n text: \"Travel\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [exampleTags, setExampleTags] = useState(tags);\n const [activeTagIndex, setActiveTagIndex] = useState(null);\n\n return (\n
\n \n {\n setExampleTags(newTags);\n }}\n styleClasses={{\n input:\n \"rounded-md transition-[color,box-shadow] placeholder:text-muted-foreground/70 focus-visible:border-ring outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n tag: {\n body: \"relative h-7 bg-background border border-input hover:bg-background rounded-md font-medium text-xs ps-2 pe-7\",\n closeButton:\n \"absolute -inset-y-px -end-px p-0 rounded-s-none rounded-e-md flex size-7 transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] text-muted-foreground/80 hover:text-foreground\",\n },\n tagList: {\n container: \"gap-1\",\n },\n }}\n tags={exampleTags}\n />\n \n Built with{\" \"}\n \n emblor\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "tag", "emblor" ] } } ================================================ FILE: apps/origin/public/r/comp-560.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-560", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-560.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Cropper with full-rounded mask ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-561.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-561", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-561.tsx", "content": "\"use client\";\n\nimport { useState } from \"react\";\n\nimport {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\nimport { Slider } from \"@/registry/default/ui/slider\";\n\nexport default function Component() {\n const [zoom, setZoom] = useState(1);\n\n return (\n
\n
\n \n \n \n \n \n
\n setZoom(value[0])}\n step={0.1}\n value={[zoom]}\n />\n \n {Number.parseFloat(zoom.toFixed(1))}x\n \n
\n
\n\n \n Cropper with zoom slider ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom", "slider" ] } } ================================================ FILE: apps/origin/public/r/comp-562.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-562", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-562.tsx", "content": "import {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\nexport default function Component() {\n return (\n
\n \n \n \n \n \n\n \n Cropper with custom zoom limits ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-563.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-563", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-563.tsx", "content": "\"use client\";\n\nimport React from \"react\";\n\nimport {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\ntype Area = { x: number; y: number; width: number; height: number };\n\nexport default function Component() {\n const [cropData, setCropData] = React.useState(null);\n\n return (\n
\n
\n \n \n \n \n \n\n {cropData && (\n
\n            {JSON.stringify(cropData, null, 2)}\n          
\n )}\n
\n\n \n Cropper with crop data output ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-564.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-564", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/cropper.json" ], "files": [ { "path": "registry/default/components/comp-564.tsx", "content": "\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Cropper,\n CropperCropArea,\n CropperDescription,\n CropperImage,\n} from \"@/registry/default/ui/cropper\";\n\n// Define type for pixel crop area\ntype Area = { x: number; y: number; width: number; height: number };\n\n// --- Start: Copied Helper Functions ---\nconst createImage = (url: string): Promise =>\n new Promise((resolve, reject) => {\n const image = new Image();\n image.addEventListener(\"load\", () => resolve(image));\n image.addEventListener(\"error\", (error) => reject(error));\n image.setAttribute(\"crossOrigin\", \"anonymous\"); // Needed for canvas Tainted check\n image.src = url;\n });\n\nasync function getCroppedImg(\n imageSrc: string,\n pixelCrop: Area,\n outputWidth: number = pixelCrop.width, // Optional: specify output size\n outputHeight: number = pixelCrop.height,\n): Promise {\n try {\n const image = await createImage(imageSrc);\n const canvas = document.createElement(\"canvas\");\n const ctx = canvas.getContext(\"2d\");\n\n if (!ctx) {\n return null;\n }\n\n // Set canvas size to desired output size\n canvas.width = outputWidth;\n canvas.height = outputHeight;\n\n // Draw the cropped image onto the canvas\n ctx.drawImage(\n image,\n pixelCrop.x,\n pixelCrop.y,\n pixelCrop.width,\n pixelCrop.height,\n 0,\n 0,\n outputWidth, // Draw onto the output size\n outputHeight,\n );\n\n // Convert canvas to blob\n return new Promise((resolve) => {\n canvas.toBlob((blob) => {\n resolve(blob);\n }, \"image/jpeg\"); // Specify format and quality if needed\n });\n } catch (error) {\n console.error(\"Error in getCroppedImg:\", error);\n return null;\n }\n}\n// --- End: Copied Helper Functions ---\n\nconst ORIGINAL_IMAGE_URL =\n \"https://raw.githubusercontent.com/origin-space/origin-images/refs/heads/main/cropper-10_k24zxk.jpg\";\n\nexport default function Component() {\n const [croppedAreaPixels, setCroppedAreaPixels] = useState(null);\n const [croppedImageUrl, setCroppedImageUrl] = useState(null);\n\n // Callback to update crop area state\n const handleCropChange = useCallback((pixels: Area | null) => {\n setCroppedAreaPixels(pixels);\n }, []);\n\n // Function to handle the crop button click\n const handleCrop = async () => {\n if (!croppedAreaPixels) {\n console.error(\"No crop area selected.\");\n return;\n }\n\n try {\n const croppedBlob = await getCroppedImg(\n ORIGINAL_IMAGE_URL,\n croppedAreaPixels,\n );\n if (!croppedBlob) {\n throw new Error(\"Failed to generate cropped image blob.\");\n }\n\n // Create a new object URL\n const newCroppedUrl = URL.createObjectURL(croppedBlob);\n\n // Revoke the old URL if it exists\n if (croppedImageUrl) {\n URL.revokeObjectURL(croppedImageUrl);\n }\n\n // Set the new URL\n setCroppedImageUrl(newCroppedUrl);\n } catch (error) {\n console.error(\"Error during cropping:\", error);\n // Optionally: Clear the old image URL on error\n if (croppedImageUrl) {\n URL.revokeObjectURL(croppedImageUrl);\n }\n setCroppedImageUrl(null);\n }\n };\n\n // Effect for cleaning up the object URL\n useEffect(() => {\n // This is the cleanup function that runs when the component unmounts\n // or when croppedImageUrl changes before the next effect runs.\n const currentUrl = croppedImageUrl;\n return () => {\n if (currentUrl?.startsWith(\"blob:\")) {\n URL.revokeObjectURL(currentUrl);\n console.log(\"Revoked URL:\", currentUrl); // Optional: for debugging\n }\n };\n }, [croppedImageUrl]); // Dependency array ensures cleanup runs when URL changes\n\n return (\n
\n
\n \n \n \n \n \n
\n \n {/* Display Area */}\n
\n {croppedImageUrl ? (\n \n ) : (\n
\n Image preview\n
\n )}\n
\n
\n
\n\n \n Cropper with image preview ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 2, "tags": [ "image", "crop", "zoom" ] } } ================================================ FILE: apps/origin/public/r/comp-565.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-565", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-565.tsx", "content": "\"use client\";\n\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [syncDataLoaderFeature, hotkeysCoreFeature],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n });\n\n return (\n
\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n );\n })}\n \n\n \n Basic tree with no extra features ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-566.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-566", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-566.tsx", "content": "\"use client\";\n\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [syncDataLoaderFeature, hotkeysCoreFeature],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n });\n\n return (\n
\n
\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n );\n })}\n \n
\n\n \n Basic tree with vertical lines ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-567.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-567", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-567.tsx", "content": "\"use client\";\n\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { FileIcon, FolderIcon, FolderOpenIcon } from \"lucide-react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [syncDataLoaderFeature, hotkeysCoreFeature],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n });\n\n return (\n
\n
\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() ? (\n item.isExpanded() ? (\n \n ) : (\n \n )\n ) : (\n \n )}\n {item.getItemName()}\n \n \n \n );\n })}\n \n
\n\n \n Basic tree with icons ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-568.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-568", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-568.tsx", "content": "\"use client\";\n\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { FileIcon, FolderIcon, FolderOpenIcon } from \"lucide-react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [syncDataLoaderFeature, hotkeysCoreFeature],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n });\n\n return (\n
\n
\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() ? (\n item.isExpanded() ? (\n \n ) : (\n \n )\n ) : (\n \n )}\n {item.getItemName()}\n \n \n \n );\n })}\n \n
\n\n \n Basic tree with caret icon on the right ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-569.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-569", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-569.tsx", "content": "\"use client\";\n\nimport {\n createOnDropHandler,\n dragAndDropFeature,\n hotkeysCoreFeature,\n keyboardDragAndDropFeature,\n selectionFeature,\n syncDataLoaderFeature,\n} from \"@headless-tree/core\";\nimport { AssistiveTreeDescription, useTree } from \"@headless-tree/react\";\nimport { FolderIcon, FolderOpenIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport {\n Tree,\n TreeDragLine,\n TreeItem,\n TreeItemLabel,\n} from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst initialItems: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const [items, setItems] = useState(initialItems);\n\n const tree = useTree({\n canReorder: true,\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n selectionFeature,\n hotkeysCoreFeature,\n dragAndDropFeature,\n keyboardDragAndDropFeature,\n ],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n selectedItems: [\"components\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n onDrop: createOnDropHandler((parentItem, newChildrenIds) => {\n setItems((prevItems) => ({\n ...prevItems,\n [parentItem.getId()]: {\n ...prevItems[parentItem.getId()],\n children: newChildrenIds,\n },\n }));\n }),\n rootItemId: \"company\",\n });\n\n return (\n
\n \n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() &&\n (item.isExpanded() ? (\n \n ) : (\n \n ))}\n {item.getItemName()}\n \n \n \n );\n })}\n \n \n\n \n Tree with multi-select and drag and drop ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-57.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-57", "type": "registry:component", "dependencies": [ "emblor" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-57.tsx", "content": "\"use client\";\n\nimport { type Tag, TagInput } from \"emblor\";\nimport { useId, useState } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\n\nconst tags = [\n {\n id: \"1\",\n text: \"Red\",\n },\n];\n\nexport default function Component() {\n const id = useId();\n const [exampleTags, setExampleTags] = useState(tags);\n const [activeTagIndex, setActiveTagIndex] = useState(null);\n\n return (\n
\n \n {\n setExampleTags(newTags);\n }}\n styleClasses={{\n inlineTagsContainer:\n \"border-input rounded-md bg-background shadow-xs transition-[color,box-shadow] focus-within:border-ring outline-none focus-within:ring-[3px] focus-within:ring-ring/50 p-1 gap-1\",\n input: \"w-full min-w-[80px] shadow-none px-2 h-7\",\n tag: {\n body: \"h-7 relative bg-background border border-input hover:bg-background rounded-md font-medium text-xs ps-2 pe-7\",\n closeButton:\n \"absolute -inset-y-px -end-px p-0 rounded-e-md flex size-7 transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] text-muted-foreground/80 hover:text-foreground\",\n },\n }}\n tags={exampleTags}\n />\n \n Built with{\" \"}\n \n emblor\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "tag", "emblor" ] } } ================================================ FILE: apps/origin/public/r/comp-570.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-570", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-570.tsx", "content": "\"use client\";\n\nimport {\n hotkeysCoreFeature,\n renamingFeature,\n selectionFeature,\n syncDataLoaderFeature,\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { FileIcon, FolderIcon, FolderOpenIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\n// Initial data\nconst initialItems: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const [items, setItems] = useState(initialItems);\n\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n hotkeysCoreFeature,\n renamingFeature,\n selectionFeature,\n ],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n onRename: (item, newName) => {\n // Update the item name in our state\n const itemId = item.getId();\n setItems((prevItems) => ({\n ...prevItems,\n [itemId]: {\n ...prevItems[itemId],\n name: newName,\n },\n }));\n },\n rootItemId: \"company\",\n });\n\n return (\n
\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() ? (\n item.isExpanded() ? (\n \n ) : (\n \n )\n ) : (\n \n )}\n {item.isRenaming() ? (\n \n ) : (\n item.getItemName()\n )}\n \n \n \n );\n })}\n \n\n \n Tree with renaming (press F2 to rename) ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-571.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-571", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-571.tsx", "content": "\"use client\";\n\nimport {\n expandAllFeature,\n hotkeysCoreFeature,\n searchFeature,\n selectionFeature,\n syncDataLoaderFeature,\n type TreeState,\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { FolderIcon, FolderOpenIcon, SearchIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n // Store the initial expanded items to reset when search is cleared\n const initialExpandedItems = [\"engineering\", \"frontend\", \"design-system\"];\n const [state, setState] = useState>>({});\n\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n hotkeysCoreFeature,\n selectionFeature,\n searchFeature,\n expandAllFeature,\n ],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: initialExpandedItems,\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n setState,\n state,\n });\n\n return (\n
\n
\n {\n // First call the original onChange handler from getSearchInputElementProps\n const originalProps = tree.getSearchInputElementProps();\n if (originalProps.onChange) {\n originalProps.onChange(e);\n }\n\n // Then handle our custom logic\n const value = e.target.value;\n\n if (value.length > 0) {\n // If input has at least one character, expand all items\n tree.expandAll();\n } else {\n // If input is cleared, reset to initial expanded state\n setState((prevState) => {\n return {\n ...prevState,\n expandedItems: initialExpandedItems,\n };\n });\n }\n },\n }}\n placeholder=\"Quick search...\"\n type=\"search\"\n />\n
\n \n
\n
\n\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() &&\n (item.isExpanded() ? (\n \n ) : (\n \n ))}\n {item.getItemName()}\n \n \n \n );\n })}\n \n\n \n Tree with search highlight ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree", "filter", "search" ] } } ================================================ FILE: apps/origin/public/r/comp-572.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-572", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-572.tsx", "content": "\"use client\";\n\nimport {\n expandAllFeature,\n hotkeysCoreFeature,\n searchFeature,\n selectionFeature,\n syncDataLoaderFeature,\n type TreeState,\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport {\n CircleXIcon,\n FilterIcon,\n FolderIcon,\n FolderOpenIcon,\n} from \"lucide-react\";\nimport type React from \"react\";\nimport { useEffect, useRef, useState } from \"react\";\n\nimport { Input } from \"@/registry/default/ui/input\";\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n // Store the initial expanded items to reset when search is cleared\n const initialExpandedItems = [\"engineering\", \"frontend\", \"design-system\"];\n const [state, setState] = useState>>({});\n const [searchValue, setSearchValue] = useState(\"\");\n const inputRef = useRef(null);\n\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n hotkeysCoreFeature,\n selectionFeature,\n searchFeature,\n expandAllFeature,\n ],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: initialExpandedItems,\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n setState,\n state,\n });\n\n // Handle clearing the search\n const handleClearSearch = () => {\n setSearchValue(\"\");\n\n // Manually trigger the tree's search onChange with an empty value\n // to ensure item.isMatchingSearch() is correctly updated.\n const searchProps = tree.getSearchInputElementProps();\n if (searchProps.onChange) {\n const syntheticEvent = {\n target: { value: \"\" },\n } as React.ChangeEvent; // Cast to the expected event type\n searchProps.onChange(syntheticEvent);\n }\n\n // Reset tree state to initial expanded items\n setState((prevState) => ({\n ...prevState,\n expandedItems: initialExpandedItems,\n }));\n\n // Clear custom filtered items\n setFilteredItems([]);\n\n if (inputRef.current) {\n inputRef.current.focus();\n // Also clear the internal search input\n inputRef.current.value = \"\";\n }\n };\n\n // Keep track of filtered items separately from the tree's internal search state\n const [filteredItems, setFilteredItems] = useState([]);\n\n // This function determines if an item should be visible based on our custom filtering\n const shouldShowItem = (itemId: string) => {\n if (!searchValue || searchValue.length === 0) return true;\n return filteredItems.includes(itemId);\n };\n\n // Update filtered items when search value changes\n useEffect(() => {\n if (!searchValue || searchValue.length === 0) {\n setFilteredItems([]);\n return;\n }\n\n // Get all items\n const allItems = tree.getItems();\n\n // First, find direct matches\n const directMatches = allItems\n .filter((item) => {\n const name = item.getItemName().toLowerCase();\n return name.includes(searchValue.toLowerCase());\n })\n .map((item) => item.getId());\n\n // Then, find all parent IDs of matching items\n const parentIds = new Set();\n for (const matchId of directMatches) {\n let item = tree.getItems().find((i) => i.getId() === matchId);\n\n while (item?.getParent?.()) {\n const parent = item.getParent();\n if (parent) {\n parentIds.add(parent.getId());\n item = parent;\n } else {\n break;\n }\n }\n }\n\n // Find all children of matching items\n const childrenIds = new Set();\n for (const matchId of directMatches) {\n const item = tree.getItems().find((i) => i.getId() === matchId);\n\n if (item?.isFolder()) {\n const getDescendants = (itemId: string) => {\n const children = items[itemId]?.children || [];\n\n for (const childId of children) {\n childrenIds.add(childId);\n\n if (items[childId]?.children?.length) {\n getDescendants(childId);\n }\n }\n };\n\n getDescendants(item.getId());\n }\n }\n\n // Combine direct matches, parents, and children\n setFilteredItems([\n ...directMatches,\n ...Array.from(parentIds),\n ...Array.from(childrenIds),\n ]);\n\n // Keep all folders expanded during search to ensure all matches are visible\n // Store current expanded state first\n const currentExpandedItems = tree.getState().expandedItems || [];\n\n // Get all folder IDs that need to be expanded to show matches\n const folderIdsToExpand = allItems\n .filter((item) => item.isFolder())\n .map((item) => item.getId());\n\n // Update expanded items in the tree state\n setState((prevState) => ({\n ...prevState,\n expandedItems: [\n ...new Set([...currentExpandedItems, ...folderIdsToExpand]),\n ],\n }));\n }, [searchValue, tree]);\n\n return (\n
\n
\n {\n // Prevent default blur behavior\n e.preventDefault();\n\n // Re-apply the search to ensure it stays active\n if (searchValue && searchValue.length > 0) {\n const searchProps = tree.getSearchInputElementProps();\n if (searchProps.onChange) {\n const syntheticEvent = {\n target: { value: searchValue },\n } as React.ChangeEvent;\n searchProps.onChange(syntheticEvent);\n }\n }\n }}\n onChange={(e) => {\n const value = e.target.value;\n setSearchValue(value);\n\n // Apply the search to the tree's internal state as well\n const searchProps = tree.getSearchInputElementProps();\n if (searchProps.onChange) {\n searchProps.onChange(e);\n }\n\n if (value.length > 0) {\n // If input has at least one character, expand all items\n tree.expandAll();\n } else {\n // If input is cleared, reset to initial expanded state\n setState((prevState) => ({\n ...prevState,\n expandedItems: initialExpandedItems,\n }));\n setFilteredItems([]);\n }\n }}\n placeholder=\"Filter items...\"\n // Prevent the internal search from being cleared on blur\n ref={inputRef}\n type=\"search\"\n value={searchValue}\n />\n
\n \n
\n {searchValue && (\n \n \n \n )}\n
\n\n \n {searchValue && filteredItems.length === 0 ? (\n

\n No items found for \"{searchValue}\"\n

\n ) : (\n tree.getItems().map((item) => {\n const isVisible = shouldShowItem(item.getId());\n\n return (\n \n \n \n {item.isFolder() &&\n (item.isExpanded() ? (\n \n ) : (\n \n ))}\n {item.getItemName()}\n \n \n \n );\n })\n )}\n
\n\n \n Tree with filtering ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree", "filter", "search" ] } } ================================================ FILE: apps/origin/public/r/comp-573.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-573", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-573.tsx", "content": "\"use client\";\n\nimport {\n type FeatureImplementation,\n hotkeysCoreFeature,\n selectionFeature,\n syncDataLoaderFeature,\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport { FolderIcon, FolderOpenIcon } from \"lucide-react\";\nimport type React from \"react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nconst doubleClickExpandFeature: FeatureImplementation = {\n itemInstance: {\n getProps: ({ tree, item, prev }) => ({\n ...prev?.(),\n onClick: (e: React.MouseEvent) => {\n if (e.shiftKey) {\n item.selectUpTo(e.ctrlKey || e.metaKey);\n } else if (e.ctrlKey || e.metaKey) {\n item.toggleSelect();\n } else {\n tree.setSelectedItems([item.getItemMeta().itemId]);\n }\n\n item.setFocused();\n },\n onDoubleClick: (_e: React.MouseEvent) => {\n item.primaryAction();\n\n if (!item.isFolder()) {\n return;\n }\n\n if (item.isExpanded()) {\n item.collapse();\n } else {\n item.expand();\n }\n },\n }),\n },\n};\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n selectionFeature,\n hotkeysCoreFeature,\n doubleClickExpandFeature,\n ],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n selectedItems: [\"components\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n });\n\n return (\n
\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() &&\n (item.isExpanded() ? (\n \n ) : (\n \n ))}\n {item.getItemName()}\n \n \n \n );\n })}\n \n\n \n Tree with items expandable on double click ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-574.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-574", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json", "https://coss.com/origin/r/button.json" ], "files": [ { "path": "registry/default/components/comp-574.tsx", "content": "\"use client\";\n\nimport {\n expandAllFeature,\n hotkeysCoreFeature,\n selectionFeature,\n syncDataLoaderFeature,\n} from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\nimport {\n FolderIcon,\n FolderOpenIcon,\n ListCollapseIcon,\n ListTreeIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n}\n\nconst items: Record = {\n apis: { name: \"APIs\" },\n backend: { children: [\"apis\", \"infrastructure\"], name: \"Backend\" },\n company: {\n children: [\"engineering\", \"marketing\", \"operations\"],\n name: \"Company\",\n },\n components: { name: \"Components\" },\n content: { name: \"Content\" },\n \"design-system\": {\n children: [\"components\", \"tokens\", \"guidelines\"],\n name: \"Design System\",\n },\n engineering: {\n children: [\"frontend\", \"backend\", \"platform-team\"],\n name: \"Engineering\",\n },\n finance: { name: \"Finance\" },\n frontend: { children: [\"design-system\", \"web-platform\"], name: \"Frontend\" },\n guidelines: { name: \"Guidelines\" },\n hr: { name: \"HR\" },\n infrastructure: { name: \"Infrastructure\" },\n marketing: { children: [\"content\", \"seo\"], name: \"Marketing\" },\n operations: { children: [\"hr\", \"finance\"], name: \"Operations\" },\n \"platform-team\": { name: \"Platform Team\" },\n seo: { name: \"SEO\" },\n tokens: { name: \"Tokens\" },\n \"web-platform\": { name: \"Web Platform\" },\n};\n\nconst indent = 20;\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n selectionFeature,\n hotkeysCoreFeature,\n expandAllFeature,\n ],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems: [\"engineering\", \"frontend\", \"design-system\"],\n selectedItems: [\"components\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"company\",\n });\n\n return (\n
\n
\n \n \n
\n\n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {item.isFolder() &&\n (item.isExpanded() ? (\n \n ) : (\n \n ))}\n {item.getItemName()}\n {item.isFolder() && (\n \n {`(${item.getChildren().length})`}\n \n )}\n \n \n \n );\n })}\n \n\n \n Tree with expand/collapse all buttons ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree", "button" ] } } ================================================ FILE: apps/origin/public/r/comp-575.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-575", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-575.tsx", "content": "\"use client\";\n\nimport {\n createOnDropHandler,\n dragAndDropFeature,\n hotkeysCoreFeature,\n keyboardDragAndDropFeature,\n selectionFeature,\n syncDataLoaderFeature,\n} from \"@headless-tree/core\";\nimport { AssistiveTreeDescription, useTree } from \"@headless-tree/react\";\nimport {\n RiBracesLine,\n RiCodeSSlashLine,\n RiFileLine,\n RiFileTextLine,\n RiImageLine,\n RiReactjsLine,\n} from \"@remixicon/react\";\nimport { useState } from \"react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n children?: string[];\n fileExtension?: string;\n}\n\nconst initialItems: Record = {\n app: {\n children: [\"app/layout.tsx\", \"app/page.tsx\", \"app/(dashboard)\", \"app/api\"],\n name: \"app\",\n },\n \"app/(dashboard)\": {\n children: [\"app/(dashboard)/dashboard\"],\n name: \"(dashboard)\",\n },\n \"app/(dashboard)/dashboard\": {\n children: [\"app/(dashboard)/dashboard/page.tsx\"],\n name: \"dashboard\",\n },\n \"app/(dashboard)/dashboard/page.tsx\": {\n fileExtension: \"tsx\",\n name: \"page.tsx\",\n },\n \"app/api\": { children: [\"app/api/hello\"], name: \"api\" },\n \"app/api/hello\": { children: [\"app/api/hello/route.ts\"], name: \"hello\" },\n \"app/api/hello/route.ts\": { fileExtension: \"ts\", name: \"route.ts\" },\n \"app/layout.tsx\": { fileExtension: \"tsx\", name: \"layout.tsx\" },\n \"app/page.tsx\": { fileExtension: \"tsx\", name: \"page.tsx\" },\n components: {\n children: [\"components/button.tsx\", \"components/card.tsx\"],\n name: \"components\",\n },\n \"components/button.tsx\": { fileExtension: \"tsx\", name: \"button.tsx\" },\n \"components/card.tsx\": { fileExtension: \"tsx\", name: \"card.tsx\" },\n lib: { children: [\"lib/utils.ts\"], name: \"lib\" },\n \"lib/utils.ts\": { fileExtension: \"ts\", name: \"utils.ts\" },\n \"next.config.mjs\": { fileExtension: \"mjs\", name: \"next.config.mjs\" },\n \"package.json\": { fileExtension: \"json\", name: \"package.json\" },\n public: {\n children: [\"public/favicon.ico\", \"public/vercel.svg\"],\n name: \"public\",\n },\n \"public/favicon.ico\": { fileExtension: \"ico\", name: \"favicon.ico\" },\n \"public/vercel.svg\": { fileExtension: \"svg\", name: \"vercel.svg\" },\n \"README.md\": { fileExtension: \"md\", name: \"README.md\" },\n root: {\n children: [\n \"app\",\n \"components\",\n \"lib\",\n \"public\",\n \"package.json\",\n \"tailwind.config.ts\",\n \"tsconfig.json\",\n \"next.config.mjs\",\n \"README.md\",\n ],\n name: \"Project Root\",\n },\n \"tailwind.config.ts\": { fileExtension: \"ts\", name: \"tailwind.config.ts\" },\n \"tsconfig.json\": { fileExtension: \"json\", name: \"tsconfig.json\" },\n};\n\n// Helper function to get icon based on file extension\nfunction getFileIcon(extension: string | undefined, className: string) {\n switch (extension) {\n case \"tsx\":\n case \"jsx\":\n return ;\n case \"ts\":\n case \"js\":\n case \"mjs\":\n return ;\n case \"json\":\n return ;\n case \"svg\":\n case \"ico\":\n case \"png\":\n case \"jpg\":\n return ;\n case \"md\":\n return ;\n default:\n return ;\n }\n}\n\nconst indent = 20;\n\nexport default function Component() {\n const [items, setItems] = useState(initialItems);\n\n const tree = useTree({\n canReorder: false,\n dataLoader: {\n getChildren: (itemId) => items[itemId]?.children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [\n syncDataLoaderFeature,\n selectionFeature,\n hotkeysCoreFeature,\n dragAndDropFeature,\n keyboardDragAndDropFeature,\n ],\n getItemName: (item) => item.getItemData()?.name ?? \"Unknown\",\n indent,\n initialState: {\n expandedItems: [\"app\", \"app/(dashboard)\", \"app/(dashboard)/dashboard\"],\n selectedItems: [\"components\"],\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n onDrop: createOnDropHandler((parentItem, newChildrenIds) => {\n setItems((prevItems) => {\n // Sort the children alphabetically\n const sortedChildren = [...newChildrenIds].sort((a, b) => {\n const itemA = prevItems[a];\n const itemB = prevItems[b];\n\n // First sort folders before files\n const isAFolder = (itemA?.children?.length ?? 0) > 0;\n const isBFolder = (itemB?.children?.length ?? 0) > 0;\n\n if (isAFolder && !isBFolder) return -1;\n if (!isAFolder && isBFolder) return 1;\n\n // Then sort alphabetically by name\n return (itemA?.name ?? \"\").localeCompare(itemB?.name ?? \"\");\n });\n\n return {\n ...prevItems,\n [parentItem.getId()]: {\n ...prevItems[parentItem.getId()],\n children: sortedChildren,\n },\n };\n });\n }),\n rootItemId: \"root\",\n });\n\n return (\n
\n
\n \n \n {tree.getItems().map((item) => {\n return (\n \n \n \n {!item.isFolder() &&\n getFileIcon(\n item.getItemData()?.fileExtension,\n \"text-muted-foreground pointer-events-none size-4\",\n )}\n {item.getItemName()}\n \n \n \n );\n })}\n \n
\n\n \n File editor with drag and drop ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree" ] } } ================================================ FILE: apps/origin/public/r/comp-576.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-576", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/tree.json" ], "files": [ { "path": "registry/default/components/comp-576.tsx", "content": "\"use client\";\n\nimport { hotkeysCoreFeature, syncDataLoaderFeature } from \"@headless-tree/core\";\nimport { useTree } from \"@headless-tree/react\";\n\nimport { Tree, TreeItem, TreeItemLabel } from \"@/registry/default/ui/tree\";\n\ninterface Item {\n name: string;\n href?: string;\n children?: string[];\n current?: boolean;\n}\n\nconst items: Record = {\n advanced: { href: \"#\", name: \"Advanced Usage\" },\n api: { children: [\"endpoints\", \"models\"], name: \"API Reference\" },\n endpoints: { href: \"#\", name: \"Endpoints\" },\n examples: { href: \"#\", name: \"Code Examples\" },\n faq: { href: \"#\", name: \"FAQ\" },\n \"getting-started\": {\n children: [\"installation\", \"setup\"],\n name: \"Getting Started\",\n },\n guides: { children: [\"getting-started\", \"advanced\"], name: \"User Guides\" },\n installation: { current: true, href: \"#\", name: \"Installation\" },\n main: { children: [\"guides\", \"api\", \"resources\"], name: \"Documentation\" },\n models: { href: \"#\", name: \"Data Models\" },\n resources: { children: [\"examples\", \"faq\"], name: \"Resources\" },\n setup: { href: \"#\", name: \"Configuration\" },\n};\n\nconst indent = 20;\n\n// Find the path from root to the current item\nfunction findPathToCurrent(\n items: Record,\n rootId: string,\n): string[] {\n const path: string[] = [];\n\n function findPath(itemId: string): boolean {\n const item = items[itemId];\n if (!item) return false;\n\n // If this is the current item, we found the path\n if (item.current) {\n path.unshift(itemId);\n return true;\n }\n\n // If this item has children, search them\n if (item.children?.length) {\n for (const childId of item.children) {\n if (findPath(childId)) {\n // If we found the path in this branch, add this item to the path\n path.unshift(itemId);\n return true;\n }\n }\n }\n\n return false;\n }\n\n findPath(rootId);\n return path;\n}\n\n// Get all parent IDs that need to be expanded\nconst pathToCurrent = findPathToCurrent(items, \"main\");\n// Remove the current item from the path if it's a leaf node\nconst expandedItems = pathToCurrent.filter((id) => items[id].children?.length);\n\nexport default function Component() {\n const tree = useTree({\n dataLoader: {\n getChildren: (itemId) => items[itemId].children ?? [],\n getItem: (itemId) => items[itemId],\n },\n features: [syncDataLoaderFeature, hotkeysCoreFeature],\n getItemName: (item) => item.getItemData().name,\n indent,\n initialState: {\n expandedItems,\n },\n isItemFolder: (item) => (item.getItemData()?.children?.length ?? 0) > 0,\n rootItemId: \"main\",\n });\n\n return (\n
\n \n {tree.getItems().map((item) => {\n return (\n \n {item.getItemData()?.href ? (\n \n \n \n ) : (\n \n )}\n \n );\n })}\n \n\n \n Menu navigation tree ∙{\" \"}\n \n API\n \n

\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "tree", "menu" ] } } ================================================ FILE: apps/origin/public/r/comp-577.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-577", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-577.tsx", "content": "import Logo from \"@/registry/default/components/navbar-components/logo\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { active: true, href: \"#\", label: \"Home\" },\n { href: \"#\", label: \"Features\" },\n { href: \"#\", label: \"Pricing\" },\n { href: \"#\", label: \"About\" },\n];\n\nexport default function Component() {\n return (\n
\n
\n {/* Left side */}\n
\n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, _index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n \n \n {/* Main nav */}\n
\n \n \n \n {/* Navigation menu */}\n \n \n {navigationLinks.map((link, _index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n
\n
\n {/* Right side */}\n
\n \n \n
\n
\n
\n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-578.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-578", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-578.tsx", "content": "import { BookOpenIcon, InfoIcon, LifeBuoyIcon } from \"lucide-react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuContent,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n NavigationMenuTrigger,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { href: \"#\", label: \"Home\" },\n {\n items: [\n {\n description: \"Browse all components in the library.\",\n href: \"#\",\n label: \"Components\",\n },\n {\n description: \"Learn how to use the library.\",\n href: \"#\",\n label: \"Documentation\",\n },\n {\n description: \"Pre-built layouts for common use cases.\",\n href: \"#\",\n label: \"Templates\",\n },\n ],\n label: \"Features\",\n submenu: true,\n type: \"description\",\n },\n {\n items: [\n { href: \"#\", label: \"Product A\" },\n { href: \"#\", label: \"Product B\" },\n { href: \"#\", label: \"Product C\" },\n { href: \"#\", label: \"Product D\" },\n ],\n label: \"Pricing\",\n submenu: true,\n type: \"simple\",\n },\n {\n items: [\n { href: \"#\", icon: \"BookOpenIcon\", label: \"Getting Started\" },\n { href: \"#\", icon: \"LifeBuoyIcon\", label: \"Tutorials\" },\n { href: \"#\", icon: \"InfoIcon\", label: \"About Us\" },\n ],\n label: \"About\",\n submenu: true,\n type: \"icon\",\n },\n];\n\nexport default function Component() {\n return (\n
\n
\n {/* Left side */}\n
\n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, index) => (\n \n {link.submenu ? (\n <>\n
\n {link.label}\n
\n
    \n {link.items.map((item, _itemIndex) => (\n
  • \n \n {item.label}\n \n
  • \n ))}\n
\n \n ) : (\n \n {link.label}\n \n )}\n {/* Add separator between different types of items */}\n {index < navigationLinks.length - 1 &&\n // Show separator if:\n // 1. One is submenu and one is simple link OR\n // 2. Both are submenus but with different types\n ((!link.submenu &&\n navigationLinks[index + 1].submenu) ||\n (link.submenu &&\n !navigationLinks[index + 1].submenu) ||\n (link.submenu &&\n navigationLinks[index + 1].submenu &&\n link.type !== navigationLinks[index + 1].type)) && (\n \n )}\n
\n ))}\n
\n
\n
\n
\n {/* Main nav */}\n
\n \n \n \n {/* Navigation menu */}\n \n \n {navigationLinks.map((link) => (\n \n {link.submenu ? (\n <>\n \n {link.label}\n \n \n \n {link.items.map((item) => (\n
  • \n \n {/* Display icon if present */}\n {link.type === \"icon\" && \"icon\" in item && (\n
    \n {item.icon === \"BookOpenIcon\" && (\n \n )}\n {item.icon === \"LifeBuoyIcon\" && (\n \n )}\n {item.icon === \"InfoIcon\" && (\n \n )}\n {item.label}\n
    \n )}\n\n {/* Display label with description if present */}\n {link.type === \"description\" &&\n \"description\" in item ? (\n
    \n
    \n {item.label}\n
    \n

    \n {item.description}\n

    \n
    \n ) : (\n // Display simple label if not icon or description type\n !link.type ||\n (link.type !== \"icon\" &&\n link.type !== \"description\" && (\n {item.label}\n ))\n )}\n \n
  • \n ))}\n \n
    \n \n ) : (\n \n {link.label}\n \n )}\n
    \n ))}\n
    \n
    \n
    \n
    \n {/* Right side */}\n
    \n \n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-579.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-579", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-579.tsx", "content": "import Logo from \"@/registry/default/components/navbar-components/logo\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { active: true, href: \"#\", label: \"Home\" },\n { href: \"#\", label: \"Features\" },\n { href: \"#\", label: \"Pricing\" },\n { href: \"#\", label: \"About\" },\n];\n\nexport default function Component() {\n return (\n
    \n
    \n {/* Left side */}\n
    \n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n {navigationLinks.map((link, index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n \n \n
    \n {/* Main nav */}\n
    \n \n \n \n {/* Navigation menu */}\n \n \n {navigationLinks.map((link, index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n
    \n
    \n {/* Right side */}\n
    \n \n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-58.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-58", "type": "registry:component", "dependencies": [ "input-otp" ], "registryDependencies": [ "https://coss.com/origin/r/label.json" ], "files": [ { "path": "registry/default/components/comp-58.tsx", "content": "\"use client\";\n\nimport { OTPInput, type SlotProps } from \"input-otp\";\nimport { useId } from \"react\";\n\nimport { cn } from \"@/registry/default/lib/utils\";\nimport { Label } from \"@/registry/default/ui/label\";\n\nexport default function Component() {\n const id = useId();\n return (\n
    \n \n (\n
    \n {slots.map((slot, idx) => (\n \n ))}\n
    \n )}\n />\n \n Built with{\" \"}\n \n Input OTP\n \n

    \n
    \n );\n}\n\nfunction Slot(props: SlotProps) {\n return (\n \n {props.char !== null &&
    {props.char}
    }\n \n );\n}\n", "type": "registry:component" } ], "meta": { "tags": [ "input", "label", "otp" ] } } ================================================ FILE: apps/origin/public/r/comp-580.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-580", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-580.tsx", "content": "import { SearchIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { href: \"#\", label: \"Products\" },\n { href: \"#\", label: \"Categories\" },\n { href: \"#\", label: \"Deals\" },\n];\n\nexport default function Component() {\n const id = useId();\n\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link) => (\n \n \n {link.label}\n \n \n ))}\n \n \n \n \n \n Sign In\n \n \n \n \n \n Cart\n \n 2\n \n \n \n \n \n \n \n \n {/* Main nav */}\n
    \n \n \n \n {/* Navigation menu */}\n \n \n {navigationLinks.map((link) => (\n \n \n {link.label}\n \n \n ))}\n \n \n {/* Search form */}\n
    \n \n
    \n \n
    \n
    \n
    \n
    \n {/* Right side */}\n
    \n \n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-581.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-581", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-581.tsx", "content": "import InfoMenu from \"@/registry/default/components/navbar-components/info-menu\";\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport NotificationMenu from \"@/registry/default/components/navbar-components/notification-menu\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { href: \"#\", label: \"Home\" },\n { href: \"#\", label: \"Features\" },\n { href: \"#\", label: \"Pricing\" },\n { href: \"#\", label: \"About\" },\n];\n\nexport default function Component() {\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n \n \n {/* Main nav */}\n
    \n \n \n \n {/* Navigation menu */}\n \n \n {navigationLinks.map((link, index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n
    \n
    \n {/* Right side */}\n
    \n
    \n {/* Info menu */}\n \n {/* Notification */}\n \n
    \n {/* User menu */}\n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/info-menu.tsx", "content": "import {\n BookIcon,\n InfoIcon,\n LifeBuoyIcon,\n MessageCircleMoreIcon,\n} from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function InfoMenu() {\n return (\n \n \n \n \n \n \n \n Need help?\n \n \n \n Documentation\n \n \n \n \n \n Support\n \n \n \n \n \n Contact us\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/notification-menu.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst initialNotifications = [\n {\n action: \"requested review on\",\n id: 1,\n target: \"PR #42: Feature implementation\",\n timestamp: \"15 minutes ago\",\n unread: true,\n user: \"Chris Tompson\",\n },\n {\n action: \"shared\",\n id: 2,\n target: \"New component library\",\n timestamp: \"45 minutes ago\",\n unread: true,\n user: \"Emma Davis\",\n },\n {\n action: \"assigned you to\",\n id: 3,\n target: \"API integration task\",\n timestamp: \"4 hours ago\",\n unread: false,\n user: \"James Wilson\",\n },\n {\n action: \"replied to your comment in\",\n id: 4,\n target: \"Authentication flow\",\n timestamp: \"12 hours ago\",\n unread: false,\n user: \"Alex Morgan\",\n },\n {\n action: \"commented on\",\n id: 5,\n target: \"Dashboard redesign\",\n timestamp: \"2 days ago\",\n unread: false,\n user: \"Sarah Chen\",\n },\n {\n action: \"mentioned you in\",\n id: 6,\n target: \"coss.com open graph image\",\n timestamp: \"2 weeks ago\",\n unread: false,\n user: \"Miky Derya\",\n },\n];\n\nfunction Dot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function NotificationMenu() {\n const [notifications, setNotifications] = useState(initialNotifications);\n const unreadCount = notifications.filter((n) => n.unread).length;\n\n const handleMarkAllAsRead = () => {\n setNotifications(\n notifications.map((notification) => ({\n ...notification,\n unread: false,\n })),\n );\n };\n\n const handleNotificationClick = (id: number) => {\n setNotifications(\n notifications.map((notification) =>\n notification.id === id\n ? { ...notification, unread: false }\n : notification,\n ),\n );\n };\n\n return (\n \n \n \n \n {unreadCount > 0 && (\n \n )}\n \n \n \n
    \n
    Notifications
    \n {unreadCount > 0 && (\n \n Mark all as read\n \n )}\n
    \n \n {notifications.map((notification) => (\n \n
    \n
    \n handleNotificationClick(notification.id)}\n type=\"button\"\n >\n \n {notification.user}\n {\" \"}\n {notification.action}{\" \"}\n \n {notification.target}\n \n .\n \n
    \n {notification.timestamp}\n
    \n
    \n {notification.unread && (\n
    \n Unread\n \n
    \n )}\n
    \n \n ))}\n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-582.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-582", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/select.json", "https://coss.com/origin/r/tooltip.json" ], "files": [ { "path": "registry/default/components/comp-582.tsx", "content": "import {\n FileTextIcon,\n GlobeIcon,\n HomeIcon,\n LayersIcon,\n UsersIcon,\n} from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport ThemeToggle from \"@/registry/default/components/navbar-components/theme-toggle\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"@/registry/default/ui/select\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipProvider,\n TooltipTrigger,\n} from \"@/registry/default/ui/tooltip\";\n\n// Navigation links with icons for desktop icon-only navigation\nconst navigationLinks = [\n { active: true, href: \"#\", icon: HomeIcon, label: \"Dashboard\" },\n { href: \"#\", icon: LayersIcon, label: \"Projects\" },\n { href: \"#\", icon: FileTextIcon, label: \"Documentation\" },\n { href: \"#\", icon: UsersIcon, label: \"Team\" },\n];\n\n// Language options\nconst languages = [\n { label: \"En\", value: \"en\" },\n { label: \"Es\", value: \"es\" },\n { label: \"Fr\", value: \"fr\" },\n { label: \"De\", value: \"de\" },\n { label: \"Ja\", value: \"ja\" },\n];\n\nexport default function Component() {\n const id = useId();\n\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, _index) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n \n \n
    \n {/* Logo */}\n \n \n \n {/* Desktop navigation - icon only */}\n \n \n \n {navigationLinks.map((link) => (\n \n \n \n \n \n {link.label}\n \n \n \n

    {link.label}

    \n \n
    \n
    \n ))}\n
    \n
    \n
    \n
    \n
    \n {/* Right side */}\n
    \n {/* Theme toggle */}\n \n {/* Language selector */}\n \n {/* User menu */}\n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/theme-toggle.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Toggle } from \"@/registry/default/ui/toggle\";\n\nexport default function ThemeToggle() {\n const [theme, setTheme] = useState(\"light\");\n\n return (\n
    \n \n setTheme((prev) => (prev === \"dark\" ? \"light\" : \"dark\"))\n }\n pressed={theme === \"dark\"}\n variant=\"outline\"\n >\n {/* Note: After dark mode implementation, rely on dark: prefix rather than group-data-[state=on]: */}\n \n \n \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-583.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-583", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/breadcrumb.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-583.tsx", "content": "import { ChevronsUpDown } from \"lucide-react\";\nimport { Select as SelectPrimitive } from \"radix-ui\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport NotificationMenu from \"@/registry/default/components/navbar-components/notification-menu\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\nexport default function Component() {\n return (\n
    \n
    \n {/* Left side */}\n
    \n \n \n \n \n \n \n \n / \n \n \n \n \n Toggle menu\n \n \n \n Personal Account\n \n \n Projects\n \n \n \n \n \n Personal Account\n \n \n {\" \"}\n /{\" \"}\n \n \n Projects\n \n / \n \n \n \n \n \n
    \n {/* Right side */}\n
    \n {/* Notification */}\n \n {/* User menu */}\n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/notification-menu.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst initialNotifications = [\n {\n action: \"requested review on\",\n id: 1,\n target: \"PR #42: Feature implementation\",\n timestamp: \"15 minutes ago\",\n unread: true,\n user: \"Chris Tompson\",\n },\n {\n action: \"shared\",\n id: 2,\n target: \"New component library\",\n timestamp: \"45 minutes ago\",\n unread: true,\n user: \"Emma Davis\",\n },\n {\n action: \"assigned you to\",\n id: 3,\n target: \"API integration task\",\n timestamp: \"4 hours ago\",\n unread: false,\n user: \"James Wilson\",\n },\n {\n action: \"replied to your comment in\",\n id: 4,\n target: \"Authentication flow\",\n timestamp: \"12 hours ago\",\n unread: false,\n user: \"Alex Morgan\",\n },\n {\n action: \"commented on\",\n id: 5,\n target: \"Dashboard redesign\",\n timestamp: \"2 days ago\",\n unread: false,\n user: \"Sarah Chen\",\n },\n {\n action: \"mentioned you in\",\n id: 6,\n target: \"coss.com open graph image\",\n timestamp: \"2 weeks ago\",\n unread: false,\n user: \"Miky Derya\",\n },\n];\n\nfunction Dot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function NotificationMenu() {\n const [notifications, setNotifications] = useState(initialNotifications);\n const unreadCount = notifications.filter((n) => n.unread).length;\n\n const handleMarkAllAsRead = () => {\n setNotifications(\n notifications.map((notification) => ({\n ...notification,\n unread: false,\n })),\n );\n };\n\n const handleNotificationClick = (id: number) => {\n setNotifications(\n notifications.map((notification) =>\n notification.id === id\n ? { ...notification, unread: false }\n : notification,\n ),\n );\n };\n\n return (\n \n \n \n \n {unreadCount > 0 && (\n \n )}\n \n \n \n
    \n
    Notifications
    \n {unreadCount > 0 && (\n \n Mark all as read\n \n )}\n
    \n \n {notifications.map((notification) => (\n \n
    \n
    \n handleNotificationClick(notification.id)}\n type=\"button\"\n >\n \n {notification.user}\n {\" \"}\n {notification.action}{\" \"}\n \n {notification.target}\n \n .\n \n
    \n {notification.timestamp}\n
    \n
    \n {notification.unread && (\n
    \n Unread\n \n
    \n )}\n
    \n \n ))}\n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-584.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-584", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-584.tsx", "content": "import { SearchIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport NotificationMenu from \"@/registry/default/components/navbar-components/notification-menu\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { active: true, href: \"#\", label: \"Home\" },\n { href: \"#\", label: \"Features\" },\n { href: \"#\", label: \"Pricing\" },\n { href: \"#\", label: \"About\" },\n];\n\nexport default function Component() {\n const id = useId();\n\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, _index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n \n \n {/* Logo */}\n
    \n \n \n \n
    \n
    \n {/* Middle area */}\n
    \n {/* Search form */}\n
    \n \n
    \n \n
    \n
    \n \n ⌘K\n \n
    \n
    \n
    \n {/* Right side */}\n
    \n {/* Notification */}\n \n {/* User menu */}\n \n
    \n
    \n {/* Bottom navigation */}\n
    \n {/* Navigation menu */}\n \n \n {navigationLinks.map((link, _index) => (\n \n \n {link.label}\n \n \n ))}\n \n \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/notification-menu.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst initialNotifications = [\n {\n action: \"requested review on\",\n id: 1,\n target: \"PR #42: Feature implementation\",\n timestamp: \"15 minutes ago\",\n unread: true,\n user: \"Chris Tompson\",\n },\n {\n action: \"shared\",\n id: 2,\n target: \"New component library\",\n timestamp: \"45 minutes ago\",\n unread: true,\n user: \"Emma Davis\",\n },\n {\n action: \"assigned you to\",\n id: 3,\n target: \"API integration task\",\n timestamp: \"4 hours ago\",\n unread: false,\n user: \"James Wilson\",\n },\n {\n action: \"replied to your comment in\",\n id: 4,\n target: \"Authentication flow\",\n timestamp: \"12 hours ago\",\n unread: false,\n user: \"Alex Morgan\",\n },\n {\n action: \"commented on\",\n id: 5,\n target: \"Dashboard redesign\",\n timestamp: \"2 days ago\",\n unread: false,\n user: \"Sarah Chen\",\n },\n {\n action: \"mentioned you in\",\n id: 6,\n target: \"coss.com open graph image\",\n timestamp: \"2 weeks ago\",\n unread: false,\n user: \"Miky Derya\",\n },\n];\n\nfunction Dot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function NotificationMenu() {\n const [notifications, setNotifications] = useState(initialNotifications);\n const unreadCount = notifications.filter((n) => n.unread).length;\n\n const handleMarkAllAsRead = () => {\n setNotifications(\n notifications.map((notification) => ({\n ...notification,\n unread: false,\n })),\n );\n };\n\n const handleNotificationClick = (id: number) => {\n setNotifications(\n notifications.map((notification) =>\n notification.id === id\n ? { ...notification, unread: false }\n : notification,\n ),\n );\n };\n\n return (\n \n \n \n \n {unreadCount > 0 && (\n \n )}\n \n \n \n
    \n
    Notifications
    \n {unreadCount > 0 && (\n \n Mark all as read\n \n )}\n
    \n \n {notifications.map((notification) => (\n \n
    \n
    \n handleNotificationClick(notification.id)}\n type=\"button\"\n >\n \n {notification.user}\n {\" \"}\n {notification.action}{\" \"}\n \n {notification.target}\n \n .\n \n
    \n {notification.timestamp}\n
    \n
    \n {notification.unread && (\n
    \n Unread\n \n
    \n )}\n
    \n \n ))}\n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-585.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-585", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-585.tsx", "content": "import {\n HashIcon,\n HouseIcon,\n MailIcon,\n SearchIcon,\n UsersRound,\n} from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport NotificationMenu from \"@/registry/default/components/navbar-components/notification-menu\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst _teams = [\"Acme Inc.\", \"coss.com\", \"Junon\"];\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { href: \"#\", icon: HouseIcon, label: \"Home\" },\n { href: \"#\", icon: HashIcon, label: \"Hash\" },\n { href: \"#\", icon: UsersRound, label: \"Groups\" },\n];\n\nexport default function Component() {\n const id = useId();\n\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, _index) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n \n \n
    \n \n \n \n {/* Search form */}\n
    \n \n
    \n \n
    \n
    \n
    \n
    \n {/* Middle area */}\n \n \n {navigationLinks.map((link, _index) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n {/* Right side */}\n
    \n
    \n {/* Messages */}\n \n \n \n \n {/* Notification menu */}\n \n
    \n {/* User menu */}\n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/notification-menu.tsx", "content": "\"use client\";\n\nimport { BellIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\nconst initialNotifications = [\n {\n action: \"requested review on\",\n id: 1,\n target: \"PR #42: Feature implementation\",\n timestamp: \"15 minutes ago\",\n unread: true,\n user: \"Chris Tompson\",\n },\n {\n action: \"shared\",\n id: 2,\n target: \"New component library\",\n timestamp: \"45 minutes ago\",\n unread: true,\n user: \"Emma Davis\",\n },\n {\n action: \"assigned you to\",\n id: 3,\n target: \"API integration task\",\n timestamp: \"4 hours ago\",\n unread: false,\n user: \"James Wilson\",\n },\n {\n action: \"replied to your comment in\",\n id: 4,\n target: \"Authentication flow\",\n timestamp: \"12 hours ago\",\n unread: false,\n user: \"Alex Morgan\",\n },\n {\n action: \"commented on\",\n id: 5,\n target: \"Dashboard redesign\",\n timestamp: \"2 days ago\",\n unread: false,\n user: \"Sarah Chen\",\n },\n {\n action: \"mentioned you in\",\n id: 6,\n target: \"coss.com open graph image\",\n timestamp: \"2 weeks ago\",\n unread: false,\n user: \"Miky Derya\",\n },\n];\n\nfunction Dot({ className }: { className?: string }) {\n return (\n \n \n \n );\n}\n\nexport default function NotificationMenu() {\n const [notifications, setNotifications] = useState(initialNotifications);\n const unreadCount = notifications.filter((n) => n.unread).length;\n\n const handleMarkAllAsRead = () => {\n setNotifications(\n notifications.map((notification) => ({\n ...notification,\n unread: false,\n })),\n );\n };\n\n const handleNotificationClick = (id: number) => {\n setNotifications(\n notifications.map((notification) =>\n notification.id === id\n ? { ...notification, unread: false }\n : notification,\n ),\n );\n };\n\n return (\n \n \n \n \n {unreadCount > 0 && (\n \n )}\n \n \n \n
    \n
    Notifications
    \n {unreadCount > 0 && (\n \n Mark all as read\n \n )}\n
    \n \n {notifications.map((notification) => (\n \n
    \n
    \n handleNotificationClick(notification.id)}\n type=\"button\"\n >\n \n {notification.user}\n {\" \"}\n {notification.action}{\" \"}\n \n {notification.target}\n \n .\n \n
    \n {notification.timestamp}\n
    \n
    \n {notification.unread && (\n
    \n Unread\n \n
    \n )}\n
    \n \n ))}\n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-586.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-586", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/input.json" ], "files": [ { "path": "registry/default/components/comp-586.tsx", "content": "import { MicIcon, SearchIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport ThemeToggle from \"@/registry/default/components/navbar-components/theme-toggle\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\n\nexport default function Component() {\n const id = useId();\n\n return (\n
    \n
    \n {/* Logo */}\n
    \n \n \n \n
    \n {/* Middle area */}\n
    \n {/* Search form */}\n
    \n \n
    \n \n
    \n \n \n \n
    \n
    \n {/* Right side */}\n
    \n \n \n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/theme-toggle.tsx", "content": "\"use client\";\n\nimport { MoonIcon, SunIcon } from \"lucide-react\";\nimport { useState } from \"react\";\n\nimport { Toggle } from \"@/registry/default/ui/toggle\";\n\nexport default function ThemeToggle() {\n const [theme, setTheme] = useState(\"light\");\n\n return (\n
    \n \n setTheme((prev) => (prev === \"dark\" ? \"light\" : \"dark\"))\n }\n pressed={theme === \"dark\"}\n variant=\"outline\"\n >\n {/* Note: After dark mode implementation, rely on dark: prefix rather than group-data-[state=on]: */}\n \n \n \n
    \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-587.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-587", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/input.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-587.tsx", "content": "import { HouseIcon, InboxIcon, SearchIcon, ZapIcon } from \"lucide-react\";\nimport { useId } from \"react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport { Input } from \"@/registry/default/ui/input\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { active: true, href: \"#\", icon: HouseIcon, label: \"Home\" },\n { href: \"#\", icon: InboxIcon, label: \"Inbox\" },\n { href: \"#\", icon: ZapIcon, label: \"Insights\" },\n];\n\nexport default function Component() {\n const id = useId();\n\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link, _index) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n \n \n {/* Logo */}\n
    \n \n \n \n
    \n
    \n {/* Middle area */}\n \n \n {navigationLinks.map((link, _index) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n {/* Right side */}\n
    \n
    \n \n
    \n \n
    \n
    \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-588.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-588", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json" ], "files": [ { "path": "registry/default/components/comp-588.tsx", "content": "import { HouseIcon, InboxIcon, SparklesIcon, ZapIcon } from \"lucide-react\";\n\nimport Logo from \"@/registry/default/components/navbar-components/logo\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\n\n// Navigation links array\nconst navigationLinks = [\n { active: true, href: \"#\", icon: HouseIcon, label: \"Home\" },\n { href: \"#\", icon: InboxIcon, label: \"Inbox\" },\n { href: \"#\", icon: ZapIcon, label: \"Insights\" },\n];\n\nexport default function Component() {\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n \n \n\n \n \n {navigationLinks.map((link) => {\n const Icon = link.icon;\n return (\n \n \n \n {link.label}\n \n \n );\n })}\n \n \n
    \n\n {/* Middle side: Logo */}\n
    \n \n \n \n
    \n\n {/* Right side: Actions */}\n
    \n {/* User menu */}\n \n {/* Upgrade button */}\n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/logo.tsx", "content": "export default function Logo() {\n return (\n \n \n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-589.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-589", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/avatar.json", "https://coss.com/origin/r/button.json", "https://coss.com/origin/r/breadcrumb.json", "https://coss.com/origin/r/dropdown-menu.json", "https://coss.com/origin/r/navigation-menu.json", "https://coss.com/origin/r/popover.json", "https://coss.com/origin/r/select.json" ], "files": [ { "path": "registry/default/components/comp-589.tsx", "content": "import { ChevronsUpDown } from \"lucide-react\";\nimport { Select as SelectPrimitive } from \"radix-ui\";\n\nimport SettingsMenu from \"@/registry/default/components/navbar-components/settings-menu\";\nimport UserMenu from \"@/registry/default/components/navbar-components/user-menu\";\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbList,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n NavigationMenu,\n NavigationMenuItem,\n NavigationMenuLink,\n NavigationMenuList,\n} from \"@/registry/default/ui/navigation-menu\";\nimport {\n Popover,\n PopoverContent,\n PopoverTrigger,\n} from \"@/registry/default/ui/popover\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectValue,\n} from \"@/registry/default/ui/select\";\n\n// Navigation links array to be used in both desktop and mobile menus\nconst navigationLinks = [\n { href: \"#\", label: \"Dashboard\" },\n { href: \"#\", label: \"Docs\" },\n { href: \"#\", label: \"API reference\" },\n];\n\nexport default function Component() {\n return (\n
    \n
    \n {/* Left side */}\n
    \n {/* Mobile menu trigger */}\n \n \n \n \n \n \n \n \n \n \n \n \n \n {navigationLinks.map((link) => (\n \n \n {link.label}\n \n \n ))}\n \n \n \n \n {/* Breadcrumb */}\n \n \n \n \n \n / \n \n \n \n \n \n
    \n {/* Right side */}\n
    \n
    \n {/* Nav menu */}\n \n \n {navigationLinks.map((link) => (\n \n \n {link.label}\n \n \n ))}\n \n \n {/* Settings */}\n \n
    \n {/* User menu */}\n \n
    \n
    \n
    \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/settings-menu.tsx", "content": "import { SettingsIcon } from \"lucide-react\";\n\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function SettingsMenu() {\n return (\n \n \n \n \n \n \n \n Appearance\n Preferences\n API Settings\n \n \n );\n}\n", "type": "registry:component" }, { "path": "registry/default/components/navbar-components/user-menu.tsx", "content": "import {\n BoltIcon,\n BookOpenIcon,\n Layers2Icon,\n LogOutIcon,\n PinIcon,\n UserPenIcon,\n} from \"lucide-react\";\n\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"@/registry/default/ui/avatar\";\nimport { Button } from \"@/registry/default/ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@/registry/default/ui/dropdown-menu\";\n\nexport default function UserMenu() {\n return (\n \n \n \n \n \n \n \n Keith Kennedy\n \n \n k.kennedy@coss.com\n \n \n \n \n \n \n Option 1\n \n \n \n Option 2\n \n \n \n Option 3\n \n \n \n \n \n \n Option 4\n \n \n \n Option 5\n \n \n \n \n \n Logout\n \n \n \n );\n}\n", "type": "registry:component" } ], "meta": { "colSpan": 3, "tags": [ "navbar, navigation" ] } } ================================================ FILE: apps/origin/public/r/comp-59.json ================================================ { "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "comp-59", "type": "registry:component", "registryDependencies": [ "https://coss.com/origin/r/label.json", "https://coss.com/origin/r/textarea.json" ], "files": [ { "path": "registry/default/components/comp-59.tsx", "content": "import { useId } from \"react\";\n\nimport { Label } from \"@/registry/default/ui/label\";\nimport { Textarea } from \"@/registry/default/ui/textarea\";\n\nexport default function Component() {\n const id = useId();\n return (\n
    \n \n