love-ui 1.2.12 → 1.2.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +8 -7
- package/dist/mcp-server.js +1 -1
- package/package.json +3 -2
- package/packages/loveui-skills/SKILL.md +99 -0
- package/packages/loveui-skills/agents/openai.yaml +11 -0
- package/packages/loveui-skills/references/design-directions.md +60 -0
- package/packages/loveui-skills/references/mcp-catalog-workflow.md +68 -0
- package/packages/loveui-skills/references/page-blueprints.md +76 -0
- package/packages/loveui-skills/references/quality-gates.md +51 -0
- package/public/r/accordion-controlled.json +1 -1
- package/public/r/accordion-demo.json +1 -1
- package/public/r/accordion-multiple.json +1 -1
- package/public/r/accordion-single.json +1 -1
- package/public/r/alert-demo.json +1 -1
- package/public/r/alert-dialog-demo.json +1 -1
- package/public/r/alert-error.json +1 -1
- package/public/r/alert-info.json +1 -1
- package/public/r/alert-success.json +1 -1
- package/public/r/alert-warning.json +1 -1
- package/public/r/alert-with-icon-action.json +1 -1
- package/public/r/alert-with-icon.json +1 -1
- package/public/r/announcement-tagless.json +1 -1
- package/public/r/announcement-themes.json +1 -1
- package/public/r/announcement.json +1 -1
- package/public/r/autocomplete-async.json +1 -1
- package/public/r/autocomplete-autohighlight.json +1 -1
- package/public/r/autocomplete-demo.json +1 -1
- package/public/r/autocomplete-disabled.json +1 -1
- package/public/r/autocomplete-form.json +1 -1
- package/public/r/autocomplete-grouped.json +1 -1
- package/public/r/autocomplete-inline.json +1 -1
- package/public/r/autocomplete-lg.json +1 -1
- package/public/r/autocomplete-limit.json +1 -1
- package/public/r/autocomplete-sm.json +1 -1
- package/public/r/autocomplete-with-clear.json +1 -1
- package/public/r/autocomplete-with-label.json +1 -1
- package/public/r/autocomplete-with-trigger-clear.json +1 -1
- package/public/r/avatar-demo.json +1 -1
- package/public/r/avatar-fallback.json +1 -1
- package/public/r/avatar-group.json +1 -1
- package/public/r/avatar-radius.json +1 -1
- package/public/r/avatar-size.json +1 -1
- package/public/r/avatar-stack-hover.json +1 -1
- package/public/r/avatar-stack.json +1 -1
- package/public/r/badge-demo.json +1 -1
- package/public/r/badge-destructive.json +1 -1
- package/public/r/badge-error.json +1 -1
- package/public/r/badge-info.json +1 -1
- package/public/r/badge-lg.json +1 -1
- package/public/r/badge-outline.json +1 -1
- package/public/r/badge-secondary.json +1 -1
- package/public/r/badge-sm.json +1 -1
- package/public/r/badge-success.json +1 -1
- package/public/r/badge-warning.json +1 -1
- package/public/r/badge-with-icon.json +1 -1
- package/public/r/badge-with-link.json +1 -1
- package/public/r/banner-inset.json +1 -1
- package/public/r/banner-themes.json +1 -1
- package/public/r/banner.json +1 -1
- package/public/r/bookmarks.json +206 -0
- package/public/r/breadcrumb-custom-separator.json +1 -1
- package/public/r/breadcrumb-demo.json +1 -1
- package/public/r/button-demo.json +1 -1
- package/public/r/button-destructive-outline.json +1 -1
- package/public/r/button-destructive.json +1 -1
- package/public/r/button-disabled.json +1 -1
- package/public/r/button-ghost.json +1 -1
- package/public/r/button-lg.json +1 -1
- package/public/r/button-link.json +1 -1
- package/public/r/button-loading.json +1 -1
- package/public/r/button-outline.json +1 -1
- package/public/r/button-secondary.json +1 -1
- package/public/r/button-sm.json +1 -1
- package/public/r/button-with-icon.json +1 -1
- package/public/r/button-with-link.json +1 -1
- package/public/r/button-xl.json +1 -1
- package/public/r/button-xs.json +1 -1
- package/public/r/calendar-headless.json +1 -1
- package/public/r/calendar-rac.json +16 -0
- package/public/r/calendar.json +1 -1
- package/public/r/card-demo.json +1 -1
- package/public/r/chart.json +15 -0
- package/public/r/checkbox-card.json +1 -1
- package/public/r/checkbox-demo.json +1 -1
- package/public/r/checkbox-disabled.json +1 -1
- package/public/r/checkbox-form.json +1 -1
- package/public/r/checkbox-group-demo.json +1 -1
- package/public/r/checkbox-group-disabled.json +1 -1
- package/public/r/checkbox-group-form.json +1 -1
- package/public/r/checkbox-group-nested-parent.json +1 -1
- package/public/r/checkbox-group-parent.json +1 -1
- package/public/r/checkbox-tree.json +12 -0
- package/public/r/checkbox-with-description.json +1 -1
- package/public/r/choicebox-inline.json +1 -1
- package/public/r/choicebox.json +1 -1
- package/public/r/codebase.json +1 -1
- package/public/r/collaborative-canvas.json +1 -1
- package/public/r/collapsible-demo.json +1 -1
- package/public/r/combobox-autohighlight.json +1 -1
- package/public/r/combobox-controlled.json +1 -1
- package/public/r/combobox-create-new.json +1 -1
- package/public/r/combobox-demo.json +1 -1
- package/public/r/combobox-disabled.json +1 -1
- package/public/r/combobox-fixed-width.json +1 -1
- package/public/r/combobox-form.json +1 -1
- package/public/r/combobox-grouped.json +1 -1
- package/public/r/combobox-lg.json +1 -1
- package/public/r/combobox-multiple-form.json +1 -1
- package/public/r/combobox-multiple.json +1 -1
- package/public/r/combobox-sm.json +1 -1
- package/public/r/combobox-with-clear.json +1 -1
- package/public/r/combobox-with-inner-input.json +1 -1
- package/public/r/combobox-with-label.json +1 -1
- package/public/r/command.json +18 -0
- package/public/r/comp-01.json +22 -0
- package/public/r/comp-02.json +23 -0
- package/public/r/comp-03.json +23 -0
- package/public/r/comp-04.json +23 -0
- package/public/r/comp-05.json +22 -0
- package/public/r/comp-06.json +23 -0
- package/public/r/comp-07.json +22 -0
- package/public/r/comp-08.json +23 -0
- package/public/r/comp-09.json +22 -0
- package/public/r/comp-10.json +22 -0
- package/public/r/comp-100.json +23 -0
- package/public/r/comp-101.json +23 -0
- package/public/r/comp-102.json +23 -0
- package/public/r/comp-103.json +23 -0
- package/public/r/comp-104.json +23 -0
- package/public/r/comp-105.json +23 -0
- package/public/r/comp-106.json +22 -0
- package/public/r/comp-107.json +22 -0
- package/public/r/comp-108.json +23 -0
- package/public/r/comp-109.json +22 -0
- package/public/r/comp-11.json +22 -0
- package/public/r/comp-110.json +22 -0
- package/public/r/comp-111.json +21 -0
- package/public/r/comp-112.json +21 -0
- package/public/r/comp-113.json +22 -0
- package/public/r/comp-114.json +23 -0
- package/public/r/comp-115.json +22 -0
- package/public/r/comp-116.json +22 -0
- package/public/r/comp-117.json +23 -0
- package/public/r/comp-118.json +23 -0
- package/public/r/comp-119.json +27 -0
- package/public/r/comp-12.json +22 -0
- package/public/r/comp-120.json +27 -0
- package/public/r/comp-121.json +27 -0
- package/public/r/comp-122.json +27 -0
- package/public/r/comp-123.json +22 -0
- package/public/r/comp-124.json +22 -0
- package/public/r/comp-125.json +31 -0
- package/public/r/comp-126.json +31 -0
- package/public/r/comp-127.json +21 -0
- package/public/r/comp-128.json +21 -0
- package/public/r/comp-129.json +24 -0
- package/public/r/comp-13.json +22 -0
- package/public/r/comp-130.json +23 -0
- package/public/r/comp-131.json +23 -0
- package/public/r/comp-132.json +23 -0
- package/public/r/comp-133.json +23 -0
- package/public/r/comp-134.json +23 -0
- package/public/r/comp-135.json +24 -0
- package/public/r/comp-136.json +23 -0
- package/public/r/comp-137.json +23 -0
- package/public/r/comp-138.json +25 -0
- package/public/r/comp-139.json +23 -0
- package/public/r/comp-14.json +22 -0
- package/public/r/comp-140.json +23 -0
- package/public/r/comp-141.json +23 -0
- package/public/r/comp-142.json +25 -0
- package/public/r/comp-143.json +23 -0
- package/public/r/comp-144.json +24 -0
- package/public/r/comp-145.json +24 -0
- package/public/r/comp-146.json +24 -0
- package/public/r/comp-147.json +24 -0
- package/public/r/comp-148.json +25 -0
- package/public/r/comp-149.json +24 -0
- package/public/r/comp-15.json +22 -0
- package/public/r/comp-150.json +21 -0
- package/public/r/comp-151.json +23 -0
- package/public/r/comp-152.json +23 -0
- package/public/r/comp-153.json +23 -0
- package/public/r/comp-154.json +23 -0
- package/public/r/comp-155.json +23 -0
- package/public/r/comp-156.json +25 -0
- package/public/r/comp-157.json +27 -0
- package/public/r/comp-158.json +24 -0
- package/public/r/comp-159.json +24 -0
- package/public/r/comp-16.json +22 -0
- package/public/r/comp-160.json +24 -0
- package/public/r/comp-161.json +24 -0
- package/public/r/comp-162.json +24 -0
- package/public/r/comp-163.json +28 -0
- package/public/r/comp-164.json +24 -0
- package/public/r/comp-165.json +24 -0
- package/public/r/comp-166.json +25 -0
- package/public/r/comp-167.json +24 -0
- package/public/r/comp-168.json +24 -0
- package/public/r/comp-169.json +23 -0
- package/public/r/comp-17.json +25 -0
- package/public/r/comp-170.json +25 -0
- package/public/r/comp-171.json +28 -0
- package/public/r/comp-172.json +23 -0
- package/public/r/comp-173.json +23 -0
- package/public/r/comp-174.json +23 -0
- package/public/r/comp-175.json +23 -0
- package/public/r/comp-176.json +23 -0
- package/public/r/comp-177.json +23 -0
- package/public/r/comp-178.json +23 -0
- package/public/r/comp-179.json +24 -0
- package/public/r/comp-18.json +25 -0
- package/public/r/comp-180.json +23 -0
- package/public/r/comp-181.json +25 -0
- package/public/r/comp-182.json +24 -0
- package/public/r/comp-183.json +25 -0
- package/public/r/comp-184.json +25 -0
- package/public/r/comp-185.json +24 -0
- package/public/r/comp-186.json +25 -0
- package/public/r/comp-187.json +25 -0
- package/public/r/comp-188.json +25 -0
- package/public/r/comp-189.json +23 -0
- package/public/r/comp-19.json +23 -0
- package/public/r/comp-190.json +23 -0
- package/public/r/comp-191.json +24 -0
- package/public/r/comp-192.json +23 -0
- package/public/r/comp-193.json +23 -0
- package/public/r/comp-194.json +24 -0
- package/public/r/comp-195.json +23 -0
- package/public/r/comp-196.json +24 -0
- package/public/r/comp-197.json +23 -0
- package/public/r/comp-198.json +23 -0
- package/public/r/comp-199.json +23 -0
- package/public/r/comp-20.json +23 -0
- package/public/r/comp-200.json +25 -0
- package/public/r/comp-201.json +22 -0
- package/public/r/comp-202.json +22 -0
- package/public/r/comp-203.json +23 -0
- package/public/r/comp-204.json +23 -0
- package/public/r/comp-205.json +23 -0
- package/public/r/comp-206.json +24 -0
- package/public/r/comp-207.json +23 -0
- package/public/r/comp-208.json +23 -0
- package/public/r/comp-209.json +23 -0
- package/public/r/comp-21.json +23 -0
- package/public/r/comp-210.json +24 -0
- package/public/r/comp-211.json +24 -0
- package/public/r/comp-212.json +23 -0
- package/public/r/comp-213.json +23 -0
- package/public/r/comp-214.json +23 -0
- package/public/r/comp-215.json +24 -0
- package/public/r/comp-216.json +22 -0
- package/public/r/comp-217.json +22 -0
- package/public/r/comp-218.json +25 -0
- package/public/r/comp-219.json +23 -0
- package/public/r/comp-22.json +23 -0
- package/public/r/comp-220.json +24 -0
- package/public/r/comp-221.json +23 -0
- package/public/r/comp-222.json +26 -0
- package/public/r/comp-223.json +26 -0
- package/public/r/comp-224.json +23 -0
- package/public/r/comp-225.json +24 -0
- package/public/r/comp-226.json +26 -0
- package/public/r/comp-227.json +26 -0
- package/public/r/comp-228.json +26 -0
- package/public/r/comp-229.json +30 -0
- package/public/r/comp-23.json +24 -0
- package/public/r/comp-230.json +30 -0
- package/public/r/comp-231.json +32 -0
- package/public/r/comp-232.json +31 -0
- package/public/r/comp-233.json +30 -0
- package/public/r/comp-234.json +28 -0
- package/public/r/comp-235.json +28 -0
- package/public/r/comp-236.json +24 -0
- package/public/r/comp-237.json +26 -0
- package/public/r/comp-238.json +26 -0
- package/public/r/comp-239.json +26 -0
- package/public/r/comp-24.json +23 -0
- package/public/r/comp-240.json +23 -0
- package/public/r/comp-241.json +24 -0
- package/public/r/comp-242.json +23 -0
- package/public/r/comp-243.json +23 -0
- package/public/r/comp-244.json +23 -0
- package/public/r/comp-245.json +23 -0
- package/public/r/comp-246.json +23 -0
- package/public/r/comp-247.json +23 -0
- package/public/r/comp-248.json +23 -0
- package/public/r/comp-249.json +24 -0
- package/public/r/comp-25.json +24 -0
- package/public/r/comp-250.json +25 -0
- package/public/r/comp-251.json +25 -0
- package/public/r/comp-252.json +25 -0
- package/public/r/comp-253.json +25 -0
- package/public/r/comp-254.json +35 -0
- package/public/r/comp-255.json +30 -0
- package/public/r/comp-256.json +25 -0
- package/public/r/comp-257.json +25 -0
- package/public/r/comp-258.json +32 -0
- package/public/r/comp-259.json +26 -0
- package/public/r/comp-26.json +24 -0
- package/public/r/comp-260.json +26 -0
- package/public/r/comp-261.json +24 -0
- package/public/r/comp-262.json +31 -0
- package/public/r/comp-263.json +25 -0
- package/public/r/comp-264.json +33 -0
- package/public/r/comp-265.json +32 -0
- package/public/r/comp-266.json +24 -0
- package/public/r/comp-267.json +19 -0
- package/public/r/comp-268.json +19 -0
- package/public/r/comp-269.json +19 -0
- package/public/r/comp-27.json +24 -0
- package/public/r/comp-270.json +19 -0
- package/public/r/comp-271.json +19 -0
- package/public/r/comp-272.json +19 -0
- package/public/r/comp-273.json +19 -0
- package/public/r/comp-274.json +19 -0
- package/public/r/comp-275.json +19 -0
- package/public/r/comp-276.json +19 -0
- package/public/r/comp-277.json +21 -0
- package/public/r/comp-278.json +21 -0
- package/public/r/comp-279.json +23 -0
- package/public/r/comp-28.json +24 -0
- package/public/r/comp-280.json +23 -0
- package/public/r/comp-281.json +23 -0
- package/public/r/comp-282.json +23 -0
- package/public/r/comp-283.json +23 -0
- package/public/r/comp-284.json +23 -0
- package/public/r/comp-285.json +23 -0
- package/public/r/comp-286.json +23 -0
- package/public/r/comp-287.json +24 -0
- package/public/r/comp-288.json +23 -0
- package/public/r/comp-289.json +24 -0
- package/public/r/comp-29.json +24 -0
- package/public/r/comp-290.json +24 -0
- package/public/r/comp-291.json +24 -0
- package/public/r/comp-292.json +24 -0
- package/public/r/comp-293.json +26 -0
- package/public/r/comp-294.json +24 -0
- package/public/r/comp-295.json +23 -0
- package/public/r/comp-296.json +23 -0
- package/public/r/comp-297.json +30 -0
- package/public/r/comp-298.json +26 -0
- package/public/r/comp-299.json +28 -0
- package/public/r/comp-30.json +23 -0
- package/public/r/comp-300.json +29 -0
- package/public/r/comp-301.json +24 -0
- package/public/r/comp-302.json +18 -0
- package/public/r/comp-303.json +18 -0
- package/public/r/comp-304.json +18 -0
- package/public/r/comp-305.json +21 -0
- package/public/r/comp-306.json +21 -0
- package/public/r/comp-307.json +21 -0
- package/public/r/comp-308.json +21 -0
- package/public/r/comp-309.json +21 -0
- package/public/r/comp-31.json +21 -0
- package/public/r/comp-310.json +23 -0
- package/public/r/comp-311.json +20 -0
- package/public/r/comp-312.json +21 -0
- package/public/r/comp-313.json +26 -0
- package/public/r/comp-314.json +26 -0
- package/public/r/comp-315.json +24 -0
- package/public/r/comp-316.json +25 -0
- package/public/r/comp-317.json +24 -0
- package/public/r/comp-318.json +24 -0
- package/public/r/comp-319.json +24 -0
- package/public/r/comp-32.json +21 -0
- package/public/r/comp-320.json +27 -0
- package/public/r/comp-321.json +28 -0
- package/public/r/comp-322.json +27 -0
- package/public/r/comp-323.json +30 -0
- package/public/r/comp-324.json +28 -0
- package/public/r/comp-325.json +29 -0
- package/public/r/comp-326.json +30 -0
- package/public/r/comp-327.json +30 -0
- package/public/r/comp-328.json +37 -0
- package/public/r/comp-329.json +38 -0
- package/public/r/comp-33.json +18 -0
- package/public/r/comp-330.json +27 -0
- package/public/r/comp-331.json +42 -0
- package/public/r/comp-332.json +25 -0
- package/public/r/comp-333.json +29 -0
- package/public/r/comp-334.json +22 -0
- package/public/r/comp-335.json +22 -0
- package/public/r/comp-336.json +22 -0
- package/public/r/comp-337.json +22 -0
- package/public/r/comp-338.json +22 -0
- package/public/r/comp-339.json +22 -0
- package/public/r/comp-34.json +27 -0
- package/public/r/comp-340.json +22 -0
- package/public/r/comp-341.json +22 -0
- package/public/r/comp-342.json +22 -0
- package/public/r/comp-343.json +22 -0
- package/public/r/comp-344.json +22 -0
- package/public/r/comp-345.json +22 -0
- package/public/r/comp-346.json +22 -0
- package/public/r/comp-347.json +22 -0
- package/public/r/comp-348.json +22 -0
- package/public/r/comp-349.json +22 -0
- package/public/r/comp-35.json +27 -0
- package/public/r/comp-350.json +22 -0
- package/public/r/comp-351.json +22 -0
- package/public/r/comp-352.json +24 -0
- package/public/r/comp-353.json +24 -0
- package/public/r/comp-354.json +23 -0
- package/public/r/comp-355.json +23 -0
- package/public/r/comp-356.json +23 -0
- package/public/r/comp-357.json +23 -0
- package/public/r/comp-358.json +23 -0
- package/public/r/comp-359.json +24 -0
- package/public/r/comp-36.json +26 -0
- package/public/r/comp-360.json +25 -0
- package/public/r/comp-361.json +23 -0
- package/public/r/comp-362.json +24 -0
- package/public/r/comp-363.json +27 -0
- package/public/r/comp-364.json +26 -0
- package/public/r/comp-365.json +24 -0
- package/public/r/comp-366.json +23 -0
- package/public/r/comp-367.json +23 -0
- package/public/r/comp-368.json +23 -0
- package/public/r/comp-369.json +23 -0
- package/public/r/comp-37.json +23 -0
- package/public/r/comp-370.json +23 -0
- package/public/r/comp-371.json +24 -0
- package/public/r/comp-372.json +24 -0
- package/public/r/comp-373.json +25 -0
- package/public/r/comp-374.json +26 -0
- package/public/r/comp-375.json +25 -0
- package/public/r/comp-376.json +26 -0
- package/public/r/comp-377.json +27 -0
- package/public/r/comp-378.json +24 -0
- package/public/r/comp-379.json +24 -0
- package/public/r/comp-38.json +23 -0
- package/public/r/comp-380.json +24 -0
- package/public/r/comp-381.json +26 -0
- package/public/r/comp-382.json +25 -0
- package/public/r/comp-383.json +26 -0
- package/public/r/comp-384.json +24 -0
- package/public/r/comp-385.json +24 -0
- package/public/r/comp-386.json +24 -0
- package/public/r/comp-387.json +28 -0
- package/public/r/comp-388.json +26 -0
- package/public/r/comp-389.json +24 -0
- package/public/r/comp-39.json +23 -0
- package/public/r/comp-390.json +23 -0
- package/public/r/comp-391.json +23 -0
- package/public/r/comp-392.json +23 -0
- package/public/r/comp-393.json +23 -0
- package/public/r/comp-394.json +24 -0
- package/public/r/comp-395.json +24 -0
- package/public/r/comp-396.json +24 -0
- package/public/r/comp-397.json +25 -0
- package/public/r/comp-398.json +26 -0
- package/public/r/comp-399.json +26 -0
- package/public/r/comp-40.json +23 -0
- package/public/r/comp-400.json +20 -0
- package/public/r/comp-401.json +19 -0
- package/public/r/comp-402.json +19 -0
- package/public/r/comp-403.json +19 -0
- package/public/r/comp-404.json +19 -0
- package/public/r/comp-405.json +19 -0
- package/public/r/comp-406.json +19 -0
- package/public/r/comp-407.json +19 -0
- package/public/r/comp-408.json +19 -0
- package/public/r/comp-409.json +22 -0
- package/public/r/comp-41.json +29 -0
- package/public/r/comp-410.json +22 -0
- package/public/r/comp-411.json +22 -0
- package/public/r/comp-412.json +19 -0
- package/public/r/comp-413.json +22 -0
- package/public/r/comp-414.json +22 -0
- package/public/r/comp-415.json +22 -0
- package/public/r/comp-416.json +23 -0
- package/public/r/comp-417.json +22 -0
- package/public/r/comp-418.json +23 -0
- package/public/r/comp-419.json +23 -0
- package/public/r/comp-42.json +30 -0
- package/public/r/comp-420.json +23 -0
- package/public/r/comp-421.json +23 -0
- package/public/r/comp-422.json +23 -0
- package/public/r/comp-423.json +24 -0
- package/public/r/comp-424.json +22 -0
- package/public/r/comp-425.json +23 -0
- package/public/r/comp-426.json +23 -0
- package/public/r/comp-427.json +23 -0
- package/public/r/comp-428.json +23 -0
- package/public/r/comp-429.json +23 -0
- package/public/r/comp-43.json +32 -0
- package/public/r/comp-430.json +23 -0
- package/public/r/comp-431.json +23 -0
- package/public/r/comp-432.json +23 -0
- package/public/r/comp-433.json +24 -0
- package/public/r/comp-434.json +24 -0
- package/public/r/comp-435.json +24 -0
- package/public/r/comp-436.json +24 -0
- package/public/r/comp-437.json +25 -0
- package/public/r/comp-438.json +23 -0
- package/public/r/comp-439.json +24 -0
- package/public/r/comp-44.json +25 -0
- package/public/r/comp-440.json +25 -0
- package/public/r/comp-441.json +25 -0
- package/public/r/comp-442.json +24 -0
- package/public/r/comp-443.json +24 -0
- package/public/r/comp-444.json +24 -0
- package/public/r/comp-445.json +24 -0
- package/public/r/comp-446.json +24 -0
- package/public/r/comp-447.json +25 -0
- package/public/r/comp-448.json +23 -0
- package/public/r/comp-449.json +23 -0
- package/public/r/comp-45.json +25 -0
- package/public/r/comp-450.json +23 -0
- package/public/r/comp-451.json +23 -0
- package/public/r/comp-452.json +23 -0
- package/public/r/comp-453.json +25 -0
- package/public/r/comp-454.json +22 -0
- package/public/r/comp-455.json +22 -0
- package/public/r/comp-456.json +22 -0
- package/public/r/comp-457.json +21 -0
- package/public/r/comp-458.json +22 -0
- package/public/r/comp-459.json +26 -0
- package/public/r/comp-46.json +26 -0
- package/public/r/comp-460.json +26 -0
- package/public/r/comp-461.json +27 -0
- package/public/r/comp-462.json +27 -0
- package/public/r/comp-463.json +30 -0
- package/public/r/comp-464.json +29 -0
- package/public/r/comp-465.json +29 -0
- package/public/r/comp-466.json +21 -0
- package/public/r/comp-467.json +23 -0
- package/public/r/comp-468.json +21 -0
- package/public/r/comp-469.json +21 -0
- package/public/r/comp-47.json +32 -0
- package/public/r/comp-470.json +21 -0
- package/public/r/comp-471.json +21 -0
- package/public/r/comp-472.json +23 -0
- package/public/r/comp-473.json +24 -0
- package/public/r/comp-474.json +22 -0
- package/public/r/comp-475.json +22 -0
- package/public/r/comp-476.json +21 -0
- package/public/r/comp-477.json +31 -0
- package/public/r/comp-478.json +36 -0
- package/public/r/comp-479.json +28 -0
- package/public/r/comp-48.json +32 -0
- package/public/r/comp-480.json +30 -0
- package/public/r/comp-481.json +34 -0
- package/public/r/comp-482.json +33 -0
- package/public/r/comp-483.json +37 -0
- package/public/r/comp-484.json +41 -0
- package/public/r/comp-485.json +43 -0
- package/public/r/comp-486.json +23 -0
- package/public/r/comp-487.json +26 -0
- package/public/r/comp-488.json +27 -0
- package/public/r/comp-489.json +28 -0
- package/public/r/comp-49.json +32 -0
- package/public/r/comp-490.json +23 -0
- package/public/r/comp-491.json +24 -0
- package/public/r/comp-492.json +25 -0
- package/public/r/comp-493.json +23 -0
- package/public/r/comp-494.json +23 -0
- package/public/r/comp-495.json +24 -0
- package/public/r/comp-496.json +23 -0
- package/public/r/comp-497.json +24 -0
- package/public/r/comp-498.json +24 -0
- package/public/r/comp-499.json +24 -0
- package/public/r/comp-50.json +32 -0
- package/public/r/comp-500.json +25 -0
- package/public/r/comp-501.json +25 -0
- package/public/r/comp-502.json +26 -0
- package/public/r/comp-503.json +27 -0
- package/public/r/comp-504.json +28 -0
- package/public/r/comp-505.json +28 -0
- package/public/r/comp-506.json +26 -0
- package/public/r/comp-507.json +27 -0
- package/public/r/comp-508.json +25 -0
- package/public/r/comp-509.json +25 -0
- package/public/r/comp-51.json +23 -0
- package/public/r/comp-510.json +24 -0
- package/public/r/comp-511.json +27 -0
- package/public/r/comp-512.json +27 -0
- package/public/r/comp-513.json +21 -0
- package/public/r/comp-514.json +21 -0
- package/public/r/comp-515.json +21 -0
- package/public/r/comp-516.json +22 -0
- package/public/r/comp-517.json +22 -0
- package/public/r/comp-518.json +21 -0
- package/public/r/comp-519.json +21 -0
- package/public/r/comp-52.json +23 -0
- package/public/r/comp-520.json +22 -0
- package/public/r/comp-521.json +22 -0
- package/public/r/comp-522.json +21 -0
- package/public/r/comp-523.json +21 -0
- package/public/r/comp-524.json +21 -0
- package/public/r/comp-525.json +21 -0
- package/public/r/comp-526.json +22 -0
- package/public/r/comp-527.json +23 -0
- package/public/r/comp-528.json +22 -0
- package/public/r/comp-529.json +22 -0
- package/public/r/comp-53.json +24 -0
- package/public/r/comp-530.json +22 -0
- package/public/r/comp-531.json +22 -0
- package/public/r/comp-532.json +22 -0
- package/public/r/comp-533.json +22 -0
- package/public/r/comp-534.json +22 -0
- package/public/r/comp-535.json +22 -0
- package/public/r/comp-536.json +22 -0
- package/public/r/comp-537.json +22 -0
- package/public/r/comp-538.json +22 -0
- package/public/r/comp-539.json +22 -0
- package/public/r/comp-54.json +26 -0
- package/public/r/comp-540.json +21 -0
- package/public/r/comp-541.json +21 -0
- package/public/r/comp-542.json +124 -0
- package/public/r/comp-543.json +29 -0
- package/public/r/comp-544.json +26 -0
- package/public/r/comp-545.json +29 -0
- package/public/r/comp-546.json +29 -0
- package/public/r/comp-547.json +29 -0
- package/public/r/comp-548.json +29 -0
- package/public/r/comp-549.json +29 -0
- package/public/r/comp-55.json +27 -0
- package/public/r/comp-550.json +29 -0
- package/public/r/comp-551.json +30 -0
- package/public/r/comp-552.json +29 -0
- package/public/r/comp-553.json +29 -0
- package/public/r/comp-554.json +36 -0
- package/public/r/comp-555.json +23 -0
- package/public/r/comp-556.json +23 -0
- package/public/r/comp-557.json +23 -0
- package/public/r/comp-558.json +23 -0
- package/public/r/comp-559.json +23 -0
- package/public/r/comp-56.json +26 -0
- package/public/r/comp-560.json +23 -0
- package/public/r/comp-561.json +25 -0
- package/public/r/comp-562.json +23 -0
- package/public/r/comp-563.json +23 -0
- package/public/r/comp-564.json +24 -0
- package/public/r/comp-565.json +20 -0
- package/public/r/comp-566.json +20 -0
- package/public/r/comp-567.json +20 -0
- package/public/r/comp-568.json +20 -0
- package/public/r/comp-569.json +20 -0
- package/public/r/comp-57.json +26 -0
- package/public/r/comp-570.json +20 -0
- package/public/r/comp-571.json +23 -0
- package/public/r/comp-572.json +23 -0
- package/public/r/comp-573.json +20 -0
- package/public/r/comp-574.json +22 -0
- package/public/r/comp-575.json +20 -0
- package/public/r/comp-576.json +21 -0
- package/public/r/comp-577.json +23 -0
- package/public/r/comp-578.json +28 -0
- package/public/r/comp-579.json +28 -0
- package/public/r/comp-58.json +25 -0
- package/public/r/comp-580.json +29 -0
- package/public/r/comp-581.json +45 -0
- package/public/r/comp-582.json +42 -0
- package/public/r/comp-583.json +41 -0
- package/public/r/comp-584.json +41 -0
- package/public/r/comp-585.json +41 -0
- package/public/r/comp-586.json +34 -0
- package/public/r/comp-587.json +29 -0
- package/public/r/comp-588.json +33 -0
- package/public/r/comp-589.json +37 -0
- package/public/r/comp-59.json +22 -0
- package/public/r/comp-590.json +40 -0
- package/public/r/comp-591.json +29 -0
- package/public/r/comp-592.json +41 -0
- package/public/r/comp-593.json +36 -0
- package/public/r/comp-594.json +33 -0
- package/public/r/comp-595.json +22 -0
- package/public/r/comp-596.json +26 -0
- package/public/r/comp-597.json +22 -0
- package/public/r/comp-598.json +22 -0
- package/public/r/comp-599.json +22 -0
- package/public/r/comp-60.json +23 -0
- package/public/r/comp-600.json +17 -0
- package/public/r/comp-601.json +20 -0
- package/public/r/comp-602.json +17 -0
- package/public/r/comp-603.json +20 -0
- package/public/r/comp-604.json +17 -0
- package/public/r/comp-605.json +17 -0
- package/public/r/comp-606.json +20 -0
- package/public/r/comp-607.json +20 -0
- package/public/r/comp-608.json +20 -0
- package/public/r/comp-609.json +20 -0
- package/public/r/comp-61.json +23 -0
- package/public/r/comp-610.json +23 -0
- package/public/r/comp-611.json +23 -0
- package/public/r/comp-612.json +17 -0
- package/public/r/comp-613.json +20 -0
- package/public/r/comp-614.json +17 -0
- package/public/r/comp-615.json +26 -0
- package/public/r/comp-616.json +26 -0
- package/public/r/comp-617.json +26 -0
- package/public/r/comp-62.json +23 -0
- package/public/r/comp-63.json +22 -0
- package/public/r/comp-64.json +23 -0
- package/public/r/comp-65.json +22 -0
- package/public/r/comp-66.json +22 -0
- package/public/r/comp-67.json +23 -0
- package/public/r/comp-68.json +24 -0
- package/public/r/comp-69.json +24 -0
- package/public/r/comp-70.json +24 -0
- package/public/r/comp-71.json +22 -0
- package/public/r/comp-72.json +21 -0
- package/public/r/comp-73.json +18 -0
- package/public/r/comp-74.json +27 -0
- package/public/r/comp-75.json +22 -0
- package/public/r/comp-76.json +23 -0
- package/public/r/comp-77.json +22 -0
- package/public/r/comp-78.json +21 -0
- package/public/r/comp-79.json +22 -0
- package/public/r/comp-80.json +21 -0
- package/public/r/comp-81.json +21 -0
- package/public/r/comp-82.json +22 -0
- package/public/r/comp-83.json +21 -0
- package/public/r/comp-84.json +21 -0
- package/public/r/comp-85.json +22 -0
- package/public/r/comp-86.json +22 -0
- package/public/r/comp-87.json +21 -0
- package/public/r/comp-88.json +22 -0
- package/public/r/comp-89.json +21 -0
- package/public/r/comp-90.json +22 -0
- package/public/r/comp-91.json +22 -0
- package/public/r/comp-92.json +22 -0
- package/public/r/comp-93.json +22 -0
- package/public/r/comp-94.json +24 -0
- package/public/r/comp-95.json +26 -0
- package/public/r/comp-96.json +21 -0
- package/public/r/comp-97.json +21 -0
- package/public/r/comp-98.json +22 -0
- package/public/r/comp-99.json +23 -0
- package/public/r/comparison-event-handlers.json +1 -1
- package/public/r/comparison-hover.json +1 -1
- package/public/r/comparison.json +1 -1
- package/public/r/context-menu.json +16 -0
- package/public/r/contribution-graph-custom-footer.json +1 -1
- package/public/r/credit-card-apple.json +1 -1
- package/public/r/credit-card-back.json +1 -1
- package/public/r/credit-card.json +1 -1
- package/public/r/cropper.json +15 -0
- package/public/r/cursor-color.json +1 -1
- package/public/r/cursor-message.json +1 -1
- package/public/r/cursor-name-message.json +1 -1
- package/public/r/cursor-name.json +1 -1
- package/public/r/cursor.json +1 -1
- package/public/r/dashboard-1.json +263 -0
- package/public/r/dashboard-2.json +264 -0
- package/public/r/dashboard-3.json +225 -0
- package/public/r/datefield-rac.json +15 -0
- package/public/r/deck-controlled.json +1 -1
- package/public/r/deck-product-cards.json +1 -1
- package/public/r/deck.json +1 -1
- package/public/r/dialog-close-confirmation.json +1 -1
- package/public/r/dialog-demo.json +1 -1
- package/public/r/dialog-from-menu.json +1 -1
- package/public/r/dialog-nested.json +1 -1
- package/public/r/dialog-stack-controlled.json +1 -1
- package/public/r/dialog-stack-navigation.json +1 -1
- package/public/r/dialog-stack-six.json +1 -1
- package/public/r/dialog-stack.json +1 -1
- package/public/r/dropdown-menu.json +15 -0
- package/public/r/dropzone-custom-empty-state.json +1 -1
- package/public/r/dropzone-image-preview.json +1 -1
- package/public/r/editor.json +1 -1
- package/public/r/emails.json +243 -0
- package/public/r/empty-demo.json +1 -1
- package/public/r/example-app-calendar.json +323 -0
- package/public/r/field-2.json +19 -0
- package/public/r/field-autocomplete.json +1 -1
- package/public/r/field-checkbox-group.json +1 -1
- package/public/r/field-checkbox.json +1 -1
- package/public/r/field-combobox-multiple.json +1 -1
- package/public/r/field-combobox.json +1 -1
- package/public/r/field-complete-form.json +1 -1
- package/public/r/field-demo.json +1 -1
- package/public/r/field-disabled.json +1 -1
- package/public/r/field-error.json +1 -1
- package/public/r/field-number-field.json +1 -1
- package/public/r/field-radio.json +1 -1
- package/public/r/field-required.json +1 -1
- package/public/r/field-select.json +1 -1
- package/public/r/field-slider.json +1 -1
- package/public/r/field-switch.json +1 -1
- package/public/r/field-textarea.json +1 -1
- package/public/r/field-validity.json +1 -1
- package/public/r/fieldset-demo.json +1 -1
- package/public/r/files.json +195 -0
- package/public/r/form-demo.json +1 -1
- package/public/r/form-zod.json +1 -1
- package/public/r/form.json +1 -1
- package/public/r/frame-demo.json +1 -1
- package/public/r/gantt-lanes.json +1 -1
- package/public/r/gantt-no-sidebar.json +1 -1
- package/public/r/gantt-read-only.json +1 -1
- package/public/r/gantt.json +1 -1
- package/public/r/glimpse-custom.json +1 -1
- package/public/r/glimpse.json +1 -1
- package/public/r/gooey-toast-demo.json +1 -1
- package/public/r/gooey-toast-promise.json +1 -1
- package/public/r/gooey-toast-states.json +1 -1
- package/public/r/gooey-toast-with-button.json +1 -1
- package/public/r/group-demo.json +1 -1
- package/public/r/group-with-input.json +1 -1
- package/public/r/hero.json +1 -1
- package/public/r/hover-card.json +15 -0
- package/public/r/image-crop-circular.json +1 -1
- package/public/r/image-crop-custom.json +1 -1
- package/public/r/image-crop.json +1 -1
- package/public/r/image-zoom-background.json +1 -1
- package/public/r/image-zoom-margin.json +1 -1
- package/public/r/image-zoom.json +1 -1
- package/public/r/input-demo.json +1 -1
- package/public/r/input-disabled.json +1 -1
- package/public/r/input-file.json +1 -1
- package/public/r/input-group.json +20 -0
- package/public/r/input-lg.json +1 -1
- package/public/r/input-sm.json +1 -1
- package/public/r/input-with-button.json +1 -1
- package/public/r/input-with-label.json +1 -1
- package/public/r/kanban-simple.json +1 -1
- package/public/r/kanban.json +1 -1
- package/public/r/kbd.json +12 -0
- package/public/r/leads.json +271 -0
- package/public/r/list-simple.json +1 -1
- package/public/r/list.json +1 -1
- package/public/r/maps.json +188 -0
- package/public/r/menu-checkbox.json +1 -1
- package/public/r/menu-close-on-click.json +1 -1
- package/public/r/menu-demo.json +1 -1
- package/public/r/menu-group-labels.json +1 -1
- package/public/r/menu-hover.json +1 -1
- package/public/r/menu-link.json +1 -1
- package/public/r/menu-nested.json +1 -1
- package/public/r/menu-radio-group.json +1 -1
- package/public/r/meter-demo.json +1 -1
- package/public/r/meter-with-formatted-value.json +1 -1
- package/public/r/meter-with-range.json +1 -1
- package/public/r/mini-calendar-controlled.json +1 -1
- package/public/r/multiselect.json +15 -0
- package/public/r/navigation-menu.json +12 -0
- package/public/r/number-field-form.json +1 -1
- package/public/r/number-field-with-label.json +1 -1
- package/public/r/number-field-with-scrub.json +1 -1
- package/public/r/number-field-with-step.json +1 -1
- package/public/r/pill-avatar-group.json +1 -1
- package/public/r/pill-delta.json +1 -1
- package/public/r/pill-icon.json +1 -1
- package/public/r/pill-indicator.json +1 -1
- package/public/r/pill-status.json +1 -1
- package/public/r/pill.json +1 -1
- package/public/r/popover-demo.json +1 -1
- package/public/r/popover-with-close.json +1 -1
- package/public/r/preview-card-demo.json +1 -1
- package/public/r/pricing.json +1 -1
- package/public/r/progress-with-formatted-value.json +1 -1
- package/public/r/progress-with-label-value.json +1 -1
- package/public/r/radio-group-card.json +1 -1
- package/public/r/radio-group-demo.json +1 -1
- package/public/r/radio-group-disabled.json +1 -1
- package/public/r/radio-group-form.json +1 -1
- package/public/r/radio-group-with-description.json +1 -1
- package/public/r/reel-custom.json +1 -1
- package/public/r/reel-images.json +1 -1
- package/public/r/reel-minimal.json +1 -1
- package/public/r/reel.json +1 -1
- package/public/r/registry.json +18217 -0
- package/public/r/relative-time-controlled.json +1 -1
- package/public/r/relative-time-format-date.json +1 -1
- package/public/r/relative-time-format-time.json +1 -1
- package/public/r/relative-time.json +1 -1
- package/public/r/rentals.json +187 -0
- package/public/r/roadmap.json +1 -1
- package/public/r/sandbox-no-file-explorer.json +1 -1
- package/public/r/sandbox.json +1 -1
- package/public/r/scroll-area-both.json +1 -1
- package/public/r/scroll-area-demo.json +1 -1
- package/public/r/scroll-area-horizontal.json +1 -1
- package/public/r/select-demo.json +1 -1
- package/public/r/select-disabled.json +1 -1
- package/public/r/select-form.json +1 -1
- package/public/r/select-lg.json +1 -1
- package/public/r/select-native.json +12 -0
- package/public/r/select-sm.json +1 -1
- package/public/r/select-with-groups.json +1 -1
- package/public/r/select-without-alignment.json +1 -1
- package/public/r/select.json +1 -1
- package/public/r/separator-demo.json +1 -1
- package/public/r/sheet-demo.json +1 -1
- package/public/r/sheet-position.json +1 -1
- package/public/r/sidebar-nav.json +22 -0
- package/public/r/skeleton-demo.json +1 -1
- package/public/r/skeleton.json +1 -1
- package/public/r/slider-form.json +1 -1
- package/public/r/slider-with-label-value.json +1 -1
- package/public/r/sonner.json +16 -0
- package/public/r/stats-card.json +22 -0
- package/public/r/status-custom.json +1 -1
- package/public/r/stepper.json +15 -0
- package/public/r/stories-images.json +1 -1
- package/public/r/switch-card.json +1 -1
- package/public/r/switch-demo.json +1 -1
- package/public/r/switch-disabled.json +1 -1
- package/public/r/switch-form.json +1 -1
- package/public/r/switch-with-description.json +1 -1
- package/public/r/table-demo.json +1 -1
- package/public/r/table-framed.json +1 -1
- package/public/r/table-simple.json +1 -1
- package/public/r/table.json +1 -1
- package/public/r/tabs-demo.json +1 -1
- package/public/r/tabs-underline-vertical.json +1 -1
- package/public/r/tabs-underline.json +1 -1
- package/public/r/tabs-vertical.json +1 -1
- package/public/r/tags-create.json +1 -1
- package/public/r/tags-filter.json +1 -1
- package/public/r/tags.json +1 -1
- package/public/r/template-auth-eight.json +28 -0
- package/public/r/template-auth-five.json +28 -0
- package/public/r/template-auth-four.json +29 -0
- package/public/r/template-auth-nine.json +28 -0
- package/public/r/template-auth-one.json +49 -0
- package/public/r/template-auth-seven.json +29 -0
- package/public/r/template-auth-six.json +28 -0
- package/public/r/template-auth-three.json +49 -0
- package/public/r/template-auth-two.json +44 -0
- package/public/r/template-hero-eight.json +83 -0
- package/public/r/template-hero-eleven.json +29 -0
- package/public/r/template-hero-five.json +35 -0
- package/public/r/template-hero-four.json +35 -0
- package/public/r/template-hero-fourteen.json +101 -0
- package/public/r/template-hero-nine.json +74 -0
- package/public/r/template-hero-one.json +90 -0
- package/public/r/template-hero-seven.json +83 -0
- package/public/r/template-hero-six.json +83 -0
- package/public/r/template-hero-ten.json +77 -0
- package/public/r/template-hero-thirteen.json +101 -0
- package/public/r/template-hero-three.json +35 -0
- package/public/r/template-hero-twelve.json +30 -0
- package/public/r/template-hero-two.json +96 -0
- package/public/r/template-logo-cloud-five.json +68 -0
- package/public/r/template-logo-cloud-four.json +71 -0
- package/public/r/template-logo-cloud-one.json +89 -0
- package/public/r/template-logo-cloud-three.json +71 -0
- package/public/r/template-logo-cloud-two.json +74 -0
- package/public/r/textarea-demo.json +1 -1
- package/public/r/textarea-disabled.json +1 -1
- package/public/r/textarea-form.json +1 -1
- package/public/r/textarea-lg.json +1 -1
- package/public/r/textarea-sm.json +1 -1
- package/public/r/textarea-with-label.json +1 -1
- package/public/r/ticker-inline.json +1 -1
- package/public/r/timeline.json +15 -0
- package/public/r/toast-demo.json +1 -1
- package/public/r/toast-heights.json +1 -1
- package/public/r/toast-loading.json +1 -1
- package/public/r/toast-promise.json +1 -1
- package/public/r/toast-with-action.json +1 -1
- package/public/r/toast-with-status.json +1 -1
- package/public/r/toggle-demo.json +1 -1
- package/public/r/toggle-disabled.json +1 -1
- package/public/r/toggle-group-demo.json +1 -1
- package/public/r/toggle-group-disabled.json +1 -1
- package/public/r/toggle-group-lg.json +1 -1
- package/public/r/toggle-group-multiple.json +1 -1
- package/public/r/toggle-group-outline-with-separator.json +1 -1
- package/public/r/toggle-group-outline.json +1 -1
- package/public/r/toggle-group-sm.json +1 -1
- package/public/r/toggle-group-with-disabled-item.json +1 -1
- package/public/r/toggle-icon-group.json +1 -1
- package/public/r/toggle-lg.json +1 -1
- package/public/r/toggle-outline.json +1 -1
- package/public/r/toggle-sm.json +1 -1
- package/public/r/toggle-with-icon.json +1 -1
- package/public/r/toolbar-demo.json +1 -1
- package/public/r/tooltip-demo.json +1 -1
- package/public/r/tooltip-grouped.json +1 -1
- package/public/r/tree-controlled.json +1 -1
- package/public/r/tree-custom-icons.json +1 -1
- package/public/r/tree-no-lines.json +1 -1
- package/public/r/tree-simple.json +1 -1
- package/public/r/tree.json +1 -1
- package/public/r/typography.json +1 -1
- package/public/r/ui.json +5 -0
- package/public/r/use-character-limit.json +12 -0
- package/public/r/use-file-upload.json +12 -0
- package/public/r/use-pagination.json +12 -0
- package/public/r/use-slider-with-input.json +12 -0
- package/public/r/use-toast.json +12 -0
- package/public/r/utils.json +16 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
|
|
3
|
+
"name": "bookmarks",
|
|
4
|
+
"type": "registry:block",
|
|
5
|
+
"title": "Bookmarks Manager",
|
|
6
|
+
"description": "A modern bookmark management app with collections, tags, favorites, and archive/trash views.",
|
|
7
|
+
"files": [
|
|
8
|
+
{
|
|
9
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/archive-content.tsx",
|
|
10
|
+
"type": "registry:component",
|
|
11
|
+
"target": "components/example-apps/bookmarks/components/dashboard/archive-content.tsx",
|
|
12
|
+
"content": "\"use client\"\n\nimport Image from \"next/image\"\nimport {\n Archive,\n ArrowCounterClockwise,\n ArrowSquareOut,\n DotsThree,\n Trash,\n} from \"@phosphor-icons/react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport { cn } from \"../../lib/utils\"\nimport { tags as allTags, type Bookmark } from \"../../mock-data/bookmarks\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\nimport { Button } from \"../ui/button\"\n\nfunction ArchivedBookmarkCard({ bookmark }: { bookmark: Bookmark }) {\n const { restoreFromArchive, trashBookmark } = useBookmarksStore()\n const bookmarkTags = allTags.filter((tag) => bookmark.tags.includes(tag.id))\n\n return (\n <div className=\"group flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-accent/50\">\n <div className=\"flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted\">\n <Image\n src={bookmark.favicon}\n alt={bookmark.title}\n width={24}\n height={24}\n className={cn(\"size-6\", bookmark.hasDarkIcon && \"dark:invert\")}\n />\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"truncate font-medium\">{bookmark.title}</h3>\n {bookmarkTags.length > 0 && (\n <div className=\"hidden items-center gap-1 sm:flex\">\n {bookmarkTags.slice(0, 2).map((tag) => (\n <span\n key={tag.id}\n className={cn(\n \"inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium\",\n tag.color\n )}\n >\n {tag.name}\n </span>\n ))}\n </div>\n )}\n </div>\n <p className=\"truncate text-sm text-muted-foreground\">{bookmark.url}</p>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => restoreFromArchive(bookmark.id)}\n >\n <ArrowCounterClockwise className=\"mr-1 size-4\" />\n Restore\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button variant=\"ghost\" size=\"icon-xs\">\n <DotsThree className=\"size-4\" weight=\"bold\" />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem\n onClick={() => window.open(bookmark.url, \"_blank\")}\n >\n <ArrowSquareOut className=\"mr-2 size-4\" />\n Open URL\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem\n className=\"text-destructive\"\n onClick={() => {\n restoreFromArchive(bookmark.id)\n setTimeout(() => trashBookmark(bookmark.id), 0)\n }}\n >\n <Trash className=\"mr-2 size-4\" />\n Move to Trash\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n )\n}\n\nexport function ArchiveContent() {\n const { getArchivedBookmarks } = useBookmarksStore()\n const archivedBookmarks = getArchivedBookmarks()\n\n return (\n <div className=\"w-full flex-1 overflow-auto\">\n <div className=\"space-y-6 p-4 md:p-6\">\n <div className=\"flex items-center gap-3 rounded-xl border bg-card p-4\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-violet-500/10 text-violet-500\">\n <Archive className=\"size-5\" />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold\">Archived Bookmarks</h2>\n <p className=\"text-sm text-muted-foreground\">\n {archivedBookmarks.length} bookmark\n {archivedBookmarks.length !== 1 ? \"s\" : \"\"} in archive\n </p>\n </div>\n </div>\n\n <div className=\"flex flex-col gap-2\">\n {archivedBookmarks.map((bookmark) => (\n <ArchivedBookmarkCard key={bookmark.id} bookmark={bookmark} />\n ))}\n </div>\n\n {archivedBookmarks.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"mb-4 flex size-12 items-center justify-center rounded-full bg-muted\">\n <Archive className=\"size-6 text-muted-foreground\" />\n </div>\n <h3 className=\"mb-1 text-lg font-medium\">Archive is empty</h3>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n Archived bookmarks will appear here. Archive bookmarks you want to\n keep but don't need right now.\n </p>\n </div>\n )}\n </div>\n </div>\n )\n}\n"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/bookmark-card.tsx",
|
|
16
|
+
"type": "registry:component",
|
|
17
|
+
"target": "components/example-apps/bookmarks/components/dashboard/bookmark-card.tsx",
|
|
18
|
+
"content": "\"use client\"\n\nimport Image from \"next/image\"\nimport {\n Archive,\n ArrowSquareOut,\n Copy,\n DotsThree,\n Heart,\n PencilSimple,\n Tag,\n Trash,\n} from \"@phosphor-icons/react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport { cn } from \"../../lib/utils\"\nimport { tags as allTags, type Bookmark } from \"../../mock-data/bookmarks\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\nimport { Button } from \"../ui/button\"\n\ninterface BookmarkCardProps {\n bookmark: Bookmark\n variant?: \"grid\" | \"list\"\n}\n\nexport function BookmarkCard({\n bookmark,\n variant = \"grid\",\n}: BookmarkCardProps) {\n const { toggleFavorite, archiveBookmark, trashBookmark } = useBookmarksStore()\n const bookmarkTags = allTags.filter((tag) => bookmark.tags.includes(tag.id))\n\n const handleCopyUrl = () => {\n navigator.clipboard.writeText(bookmark.url)\n }\n\n const handleOpenUrl = () => {\n window.open(bookmark.url, \"_blank\")\n }\n\n if (variant === \"list\") {\n return (\n <div className=\"group flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-accent/50\">\n <div className=\"flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted\">\n <Image\n src={bookmark.favicon}\n alt={bookmark.title}\n width={24}\n height={24}\n className={cn(\"size-6\", bookmark.hasDarkIcon && \"dark:invert\")}\n />\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"truncate font-medium\">{bookmark.title}</h3>\n {bookmarkTags.length > 0 && (\n <div className=\"hidden items-center gap-1 sm:flex\">\n {bookmarkTags.slice(0, 2).map((tag) => (\n <span\n key={tag.id}\n className={cn(\n \"inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium\",\n tag.color\n )}\n >\n {tag.name}\n </span>\n ))}\n {bookmarkTags.length > 2 && (\n <span className=\"text-[10px] text-muted-foreground\">\n +{bookmarkTags.length - 2}\n </span>\n )}\n </div>\n )}\n </div>\n <p className=\"truncate text-sm text-muted-foreground\">\n {bookmark.url}\n </p>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={() => toggleFavorite(bookmark.id)}\n >\n <Heart\n className={cn(\n \"size-4\",\n bookmark.isFavorite && \"fill-red-500 text-red-500\"\n )}\n weight={bookmark.isFavorite ? \"fill\" : \"regular\"}\n />\n </Button>\n <Button variant=\"ghost\" size=\"icon-xs\" onClick={handleOpenUrl}>\n <ArrowSquareOut className=\"size-4\" />\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button variant=\"ghost\" size=\"icon-xs\">\n <DotsThree className=\"size-4\" weight=\"bold\" />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem onClick={handleCopyUrl}>\n <Copy className=\"mr-2 size-4\" />\n Copy URL\n </DropdownMenuItem>\n <DropdownMenuItem>\n <PencilSimple className=\"mr-2 size-4\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuItem>\n <Tag className=\"mr-2 size-4\" />\n Add Tags\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem onClick={() => archiveBookmark(bookmark.id)}>\n <Archive className=\"mr-2 size-4\" />\n Archive\n </DropdownMenuItem>\n <DropdownMenuItem\n className=\"text-destructive\"\n onClick={() => trashBookmark(bookmark.id)}\n >\n <Trash className=\"mr-2 size-4\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n )\n }\n\n return (\n <div className=\"group relative flex flex-col overflow-hidden rounded-xl border bg-card transition-colors hover:bg-accent/30\">\n <div className=\"absolute top-3 right-3 z-10 flex items-center gap-1\">\n <Button\n variant=\"secondary\"\n size=\"icon-xs\"\n className=\"bg-background/80 backdrop-blur-sm\"\n onClick={() => toggleFavorite(bookmark.id)}\n >\n <Heart\n className={cn(\n \"size-4\",\n bookmark.isFavorite && \"fill-red-500 text-red-500\"\n )}\n weight={bookmark.isFavorite ? \"fill\" : \"regular\"}\n />\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"secondary\"\n size=\"icon-xs\"\n className=\"bg-background/80 backdrop-blur-sm\"\n >\n <DotsThree className=\"size-4\" weight=\"bold\" />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem onClick={handleCopyUrl}>\n <Copy className=\"mr-2 size-4\" />\n Copy URL\n </DropdownMenuItem>\n <DropdownMenuItem onClick={handleOpenUrl}>\n <ArrowSquareOut className=\"mr-2 size-4\" />\n Open in new tab\n </DropdownMenuItem>\n <DropdownMenuItem>\n <PencilSimple className=\"mr-2 size-4\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuItem>\n <Tag className=\"mr-2 size-4\" />\n Add Tags\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem onClick={() => archiveBookmark(bookmark.id)}>\n <Archive className=\"mr-2 size-4\" />\n Archive\n </DropdownMenuItem>\n <DropdownMenuItem\n className=\"text-destructive\"\n onClick={() => trashBookmark(bookmark.id)}\n >\n <Trash className=\"mr-2 size-4\" />\n Delete\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n\n <button\n className=\"w-full cursor-pointer text-left\"\n onClick={handleOpenUrl}\n >\n <div className=\"flex h-32 items-center justify-center bg-linear-to-br from-muted/50 to-muted\">\n <div className=\"flex size-12 items-center justify-center rounded-xl bg-background shadow-sm\">\n <Image\n src={bookmark.favicon}\n alt={bookmark.title}\n width={32}\n height={32}\n className={cn(\"size-8\", bookmark.hasDarkIcon && \"dark:invert\")}\n />\n </div>\n </div>\n\n <div className=\"space-y-2 p-4\">\n <div className=\"flex items-start justify-between gap-2\">\n <h3 className=\"line-clamp-1 font-medium\">{bookmark.title}</h3>\n </div>\n <p className=\"line-clamp-2 text-sm text-muted-foreground\">\n {bookmark.description}\n </p>\n {bookmarkTags.length > 0 && (\n <div className=\"flex flex-wrap gap-1 pt-1\">\n {bookmarkTags.slice(0, 3).map((tag) => (\n <span\n key={tag.id}\n className={cn(\n \"inline-flex items-center rounded px-1.5 py-0.5 text-[10px] font-medium\",\n tag.color\n )}\n >\n {tag.name}\n </span>\n ))}\n {bookmarkTags.length > 3 && (\n <span className=\"py-0.5 text-[10px] text-muted-foreground\">\n +{bookmarkTags.length - 3} more\n </span>\n )}\n </div>\n )}\n </div>\n </button>\n </div>\n )\n}\n"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/content.tsx",
|
|
22
|
+
"type": "registry:component",
|
|
23
|
+
"target": "components/example-apps/bookmarks/components/dashboard/content.tsx",
|
|
24
|
+
"content": "\"use client\"\n\nimport { X } from \"@phosphor-icons/react\"\n\nimport { collections, tags } from \"../../mock-data/bookmarks\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\nimport { Button } from \"../ui/button\"\nimport { BookmarkCard } from \"./bookmark-card\"\nimport { StatsCards } from \"./stats-cards\"\n\nexport function BookmarksContent() {\n const {\n selectedCollection,\n getFilteredBookmarks,\n viewMode,\n selectedTags,\n toggleTag,\n filterType,\n setFilterType,\n sortBy,\n } = useBookmarksStore()\n const filteredBookmarks = getFilteredBookmarks()\n\n const currentCollection = collections.find((c) => c.id === selectedCollection)\n\n const activeTagsData = tags.filter((t) => selectedTags.includes(t.id))\n const hasActiveFilters =\n selectedTags.length > 0 || filterType !== \"all\" || sortBy !== \"date-newest\"\n\n return (\n <div className=\"w-full flex-1 overflow-auto\">\n <div className=\"space-y-6 p-4 md:p-6\">\n <StatsCards />\n\n <div className=\"space-y-4\">\n <div className=\"flex flex-col justify-between gap-2 sm:flex-row sm:items-center\">\n <div>\n <h2 className=\"text-lg font-semibold\">\n {currentCollection?.name || \"All Bookmarks\"}\n </h2>\n <p className=\"text-sm text-muted-foreground\">\n {filteredBookmarks.length} bookmark\n {filteredBookmarks.length !== 1 ? \"s\" : \"\"}\n {hasActiveFilters && \" (filtered)\"}\n </p>\n </div>\n\n {(activeTagsData.length > 0 || filterType !== \"all\") && (\n <div className=\"flex flex-wrap items-center gap-2\">\n {filterType !== \"all\" && (\n <span className=\"inline-flex items-center gap-1 rounded-md bg-primary/10 px-2 py-1 text-xs font-medium text-primary\">\n {filterType === \"favorites\" && \"Favorites only\"}\n {filterType === \"with-tags\" && \"With tags\"}\n {filterType === \"without-tags\" && \"Without tags\"}\n <button\n onClick={() => setFilterType(\"all\")}\n className=\"rounded-full p-0.5 hover:bg-primary/20\"\n >\n <X className=\"size-3\" />\n </button>\n </span>\n )}\n {activeTagsData.map((tag) => (\n <span\n key={tag.id}\n className=\"inline-flex items-center gap-1 rounded-md bg-primary px-2 py-1 text-xs font-medium text-primary-foreground\"\n >\n {tag.name}\n <button\n onClick={() => toggleTag(tag.id)}\n className=\"rounded-full p-0.5 hover:bg-primary-foreground/20\"\n >\n <X className=\"size-3\" />\n </button>\n </span>\n ))}\n </div>\n )}\n </div>\n\n {viewMode === \"grid\" ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {filteredBookmarks.map((bookmark) => (\n <BookmarkCard key={bookmark.id} bookmark={bookmark} />\n ))}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2\">\n {filteredBookmarks.map((bookmark) => (\n <BookmarkCard\n key={bookmark.id}\n bookmark={bookmark}\n variant=\"list\"\n />\n ))}\n </div>\n )}\n\n {filteredBookmarks.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"mb-4 flex size-12 items-center justify-center rounded-full bg-muted\">\n <svg\n className=\"size-6 text-muted-foreground\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M5 5a2 2 0 012-2h10a2 2 0 012 2v16l-7-3.5L5 21V5z\"\n />\n </svg>\n </div>\n <h3 className=\"mb-1 text-lg font-medium\">No bookmarks found</h3>\n <p className=\"mb-4 max-w-sm text-sm text-muted-foreground\">\n Try adjusting your search or filter to find what you're\n looking for, or add a new bookmark.\n </p>\n {hasActiveFilters && (\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n setFilterType(\"all\")\n }}\n >\n Clear filters\n </Button>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n )\n}\n"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/favorites-content.tsx",
|
|
28
|
+
"type": "registry:component",
|
|
29
|
+
"target": "components/example-apps/bookmarks/components/dashboard/favorites-content.tsx",
|
|
30
|
+
"content": "\"use client\"\n\nimport { Star } from \"@phosphor-icons/react\"\n\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\nimport { BookmarkCard } from \"./bookmark-card\"\n\nexport function FavoritesContent() {\n const { getFavoriteBookmarks, viewMode } = useBookmarksStore()\n const favoriteBookmarks = getFavoriteBookmarks()\n\n return (\n <div className=\"w-full flex-1 overflow-auto\">\n <div className=\"space-y-6 p-4 md:p-6\">\n <div className=\"flex items-center gap-3 rounded-xl border bg-card p-4\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-amber-500/10 text-amber-500\">\n <Star className=\"size-5\" />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold\">Favorite Bookmarks</h2>\n <p className=\"text-sm text-muted-foreground\">\n {favoriteBookmarks.length} bookmark\n {favoriteBookmarks.length !== 1 ? \"s\" : \"\"} marked as favorite\n </p>\n </div>\n </div>\n\n {viewMode === \"grid\" ? (\n <div className=\"grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4\">\n {favoriteBookmarks.map((bookmark) => (\n <BookmarkCard key={bookmark.id} bookmark={bookmark} />\n ))}\n </div>\n ) : (\n <div className=\"flex flex-col gap-2\">\n {favoriteBookmarks.map((bookmark) => (\n <BookmarkCard\n key={bookmark.id}\n bookmark={bookmark}\n variant=\"list\"\n />\n ))}\n </div>\n )}\n\n {favoriteBookmarks.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"mb-4 flex size-12 items-center justify-center rounded-full bg-muted\">\n <Star className=\"size-6 text-muted-foreground\" />\n </div>\n <h3 className=\"mb-1 text-lg font-medium\">No favorites yet</h3>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n Mark bookmarks as favorites by clicking the heart icon to see them\n here.\n </p>\n </div>\n )}\n </div>\n </div>\n )\n}\n"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/header.tsx",
|
|
34
|
+
"type": "registry:component",
|
|
35
|
+
"target": "components/example-apps/bookmarks/components/dashboard/header.tsx",
|
|
36
|
+
"content": "\"use client\"\n\nimport {\n ArrowsDownUp,\n Check,\n List,\n MagnifyingGlass,\n Plus,\n SlidersHorizontal,\n SquaresFour,\n} from \"@phosphor-icons/react\"\n\nimport { Input } from \"@loveui/ui/ui/input\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport { SidebarTrigger } from \"@/components/ui/sidebar\"\n\nimport { cn } from \"../../lib/utils\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\nimport { ThemeToggle } from \"../theme-toggle\"\nimport { Button } from \"../ui/button\"\n\ninterface BookmarksHeaderProps {\n title?: string\n}\n\nconst sortOptions = [\n { value: \"date-newest\", label: \"Date Added (Newest)\" },\n { value: \"date-oldest\", label: \"Date Added (Oldest)\" },\n { value: \"alpha-az\", label: \"Alphabetical (A-Z)\" },\n { value: \"alpha-za\", label: \"Alphabetical (Z-A)\" },\n] as const\n\nconst filterOptions = [\n { value: \"all\", label: \"All Bookmarks\" },\n { value: \"favorites\", label: \"Favorites Only\" },\n { value: \"with-tags\", label: \"With Tags\" },\n { value: \"without-tags\", label: \"Without Tags\" },\n] as const\n\nexport function BookmarksHeader({ title = \"Bookmarks\" }: BookmarksHeaderProps) {\n const {\n viewMode,\n setViewMode,\n searchQuery,\n setSearchQuery,\n sortBy,\n setSortBy,\n filterType,\n setFilterType,\n } = useBookmarksStore()\n\n const currentSort = sortOptions.find((opt) => opt.value === sortBy)\n const currentFilter = filterOptions.find((opt) => opt.value === filterType)\n\n return (\n <header className=\"w-full border-b\">\n <div className=\"flex h-14 items-center justify-between px-4\">\n <div className=\"flex items-center gap-3\">\n <SidebarTrigger />\n <h1 className=\"hidden text-base font-semibold sm:block\">{title}</h1>\n </div>\n\n <div className=\"flex items-center gap-2\">\n <div className=\"relative hidden md:block\">\n <MagnifyingGlass className=\"pointer-events-none absolute top-1/2 left-3 z-10 size-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"h-9 w-64 pl-9\"\n />\n </div>\n\n <div className=\"flex items-center rounded-md border p-0.5\">\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n className={cn(\"rounded-sm\", viewMode === \"grid\" && \"bg-muted\")}\n onClick={() => setViewMode(\"grid\")}\n >\n <SquaresFour className=\"size-4\" />\n </Button>\n <Button\n variant=\"ghost\"\n size=\"icon-xs\"\n className={cn(\"rounded-sm\", viewMode === \"list\" && \"bg-muted\")}\n onClick={() => setViewMode(\"list\")}\n >\n <List className=\"size-4\" />\n </Button>\n </div>\n\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button variant=\"outline\" size=\"sm\" className=\"hidden sm:flex\">\n <ArrowsDownUp className=\"size-4\" />\n <span className=\"hidden lg:inline\">\n {currentSort?.label.split(\" \")[0]}\n </span>\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs text-muted-foreground\">\n Sort by\n </DropdownMenuLabel>\n {sortOptions.map((option) => (\n <DropdownMenuItem\n key={option.value}\n onClick={() => setSortBy(option.value)}\n className=\"flex items-center justify-between\"\n >\n {option.label}\n {sortBy === option.value && <Check className=\"size-4\" />}\n </DropdownMenuItem>\n ))}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button\n variant=\"outline\"\n size=\"sm\"\n className={cn(\n \"hidden sm:flex\",\n filterType !== \"all\" && \"border-primary text-primary\"\n )}\n >\n <SlidersHorizontal className=\"size-4\" />\n <span className=\"hidden lg:inline\">\n {filterType !== \"all\" ? currentFilter?.label : \"Filter\"}\n </span>\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\" className=\"w-48\">\n <DropdownMenuGroup>\n <DropdownMenuLabel className=\"text-xs text-muted-foreground\">\n Filter by\n </DropdownMenuLabel>\n {filterOptions.map((option) => (\n <DropdownMenuItem\n key={option.value}\n onClick={() => setFilterType(option.value)}\n className=\"flex items-center justify-between\"\n >\n {option.label}\n {filterType === option.value && (\n <Check className=\"size-4\" />\n )}\n </DropdownMenuItem>\n ))}\n {filterType !== \"all\" && (\n <>\n <DropdownMenuSeparator />\n <DropdownMenuItem\n onClick={() => setFilterType(\"all\")}\n className=\"text-muted-foreground\"\n >\n Clear filter\n </DropdownMenuItem>\n </>\n )}\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n\n <Button size=\"sm\" className=\"hidden sm:flex\">\n <Plus className=\"size-4\" />\n Add Bookmark\n </Button>\n\n <ThemeToggle />\n </div>\n </div>\n </header>\n )\n}\n"
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/sidebar.tsx",
|
|
40
|
+
"type": "registry:component",
|
|
41
|
+
"target": "components/example-apps/bookmarks/components/dashboard/sidebar.tsx",
|
|
42
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport Link from \"next/link\"\nimport { usePathname } from \"next/navigation\"\nimport {\n Archive,\n Bookmark,\n BookOpen,\n CaretDown,\n CaretRight,\n Check,\n Code,\n Folder,\n Gear,\n MagnifyingGlass,\n Palette,\n Plus,\n SignOut,\n Sparkle,\n Star,\n Tag,\n Trash,\n User,\n Wrench,\n} from \"@phosphor-icons/react\"\n\nimport { Avatar, AvatarFallback, AvatarImage } from \"@loveui/ui/ui/avatar\"\nimport { Input } from \"@loveui/ui/ui/input\"\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport {\n Sidebar,\n SidebarContent,\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarMenu,\n SidebarMenuButton,\n SidebarMenuItem,\n} from \"@/components/ui/sidebar\"\n\nimport { cn } from \"../../lib/utils\"\nimport { collections, tags } from \"../../mock-data/bookmarks\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\n\nconst collectionIcons: Record<string, React.ElementType> = {\n bookmark: Bookmark,\n palette: Palette,\n code: Code,\n wrench: Wrench,\n \"book-open\": BookOpen,\n sparkles: Sparkle,\n}\n\nconst navItems = [\n { icon: Star, label: \"Favorites\", href: \"/favorites\" },\n { icon: Archive, label: \"Archive\", href: \"/archive\" },\n { icon: Trash, label: \"Trash\", href: \"/trash\" },\n]\n\nexport function BookmarksSidebar({\n ...props\n}: React.ComponentProps<typeof Sidebar>) {\n const pathname = usePathname()\n const [collectionsOpen, setCollectionsOpen] = React.useState(true)\n const [tagsOpen, setTagsOpen] = React.useState(true)\n const {\n selectedCollection,\n setSelectedCollection,\n selectedTags,\n toggleTag,\n clearTags,\n } = useBookmarksStore()\n\n const isHomePage = pathname === \"/\"\n\n return (\n <Sidebar collapsible=\"offcanvas\" className=\"lg:border-r-0!\" {...props}>\n <SidebarHeader className=\"p-5 pb-0\">\n <div className=\"flex items-center justify-between\">\n <DropdownMenu>\n <DropdownMenuTrigger className=\"flex items-center gap-2 outline-none\">\n <div className=\"flex size-7 items-center justify-center overflow-hidden rounded-full bg-linear-to-br from-blue-400 via-indigo-500 to-violet-500 shadow-lg ring-1 ring-white/40\" />\n <span className=\"font-medium text-muted-foreground\">LoveUI</span>\n <CaretDown className=\"size-3 text-muted-foreground\" />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"start\" className=\"w-56\">\n <DropdownMenuGroup>\n <DropdownMenuLabel>Workspaces</DropdownMenuLabel>\n <DropdownMenuItem>\n <div className=\"mr-2 size-5 rounded-full bg-linear-to-br from-blue-400 via-indigo-500 to-violet-500\" />\n LoveUI\n <Check className=\"ml-auto size-4\" />\n </DropdownMenuItem>\n <DropdownMenuItem>\n <div className=\"mr-2 size-5 rounded-full bg-linear-to-br from-emerald-400 to-cyan-500\" />\n Personal\n </DropdownMenuItem>\n <DropdownMenuItem>\n <div className=\"mr-2 size-5 rounded-full bg-linear-to-br from-orange-400 to-rose-500\" />\n Work\n </DropdownMenuItem>\n </DropdownMenuGroup>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <Plus className=\"mr-2 size-4\" />\n Create Workspace\n </DropdownMenuItem>\n </DropdownMenuGroup>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuGroup>\n <DropdownMenuItem>\n <User className=\"mr-2 size-4\" />\n Account Settings\n </DropdownMenuItem>\n <DropdownMenuItem>\n <Gear className=\"mr-2 size-4\" />\n Workspace Settings\n </DropdownMenuItem>\n </DropdownMenuGroup>\n\n <DropdownMenuSeparator />\n\n <DropdownMenuGroup>\n <DropdownMenuItem className=\"text-destructive\">\n <SignOut className=\"mr-2 size-4\" />\n Log out\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n <Avatar className=\"size-6.5\">\n <AvatarImage src=\"/cl.png\" />\n <AvatarFallback>CL</AvatarFallback>\n </Avatar>\n </div>\n </SidebarHeader>\n\n <SidebarContent className=\"px-5 pt-5\">\n <div className=\"relative mb-4\">\n <MagnifyingGlass className=\"pointer-events-none absolute top-1/2 left-3 z-10 size-4 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search Bookmarks...\"\n className=\"h-9 bg-background pr-10 pl-9\"\n />\n <div className=\"absolute top-1/2 right-2 -translate-y-1/2 rounded bg-muted px-1.5 py-0.5 text-[11px] font-medium text-muted-foreground\">\n ⌘K\n </div>\n </div>\n\n <SidebarGroup className=\"p-0\">\n <SidebarGroupLabel className=\"flex items-center gap-1.5 px-0 text-[10px] font-semibold tracking-wider text-muted-foreground\">\n <button\n onClick={() => setCollectionsOpen(!collectionsOpen)}\n className=\"flex cursor-pointer items-center gap-1.5\"\n >\n <CaretDown\n className={cn(\n \"size-3.5 transition-transform\",\n !collectionsOpen && \"-rotate-90\"\n )}\n />\n COLLECTIONS\n </button>\n </SidebarGroupLabel>\n {collectionsOpen && (\n <SidebarGroupContent>\n <SidebarMenu className=\"mt-2\">\n {collections.map((collection) => {\n const IconComponent =\n collectionIcons[collection.icon] || Folder\n const isActive =\n isHomePage && selectedCollection === collection.id\n return (\n <SidebarMenuItem key={collection.id}>\n <SidebarMenuButton\n render={\n <Link\n href=\"/\"\n onClick={() => {\n setSelectedCollection(collection.id)\n clearTags()\n }}\n />\n }\n isActive={isActive}\n className=\"h-[38px]\"\n >\n <IconComponent className=\"size-5\" />\n <span className=\"flex-1\">{collection.name}</span>\n <span className=\"text-xs text-muted-foreground\">\n {collection.count}\n </span>\n {isActive && (\n <CaretRight className=\"size-4 text-muted-foreground opacity-60\" />\n )}\n </SidebarMenuButton>\n </SidebarMenuItem>\n )\n })}\n </SidebarMenu>\n </SidebarGroupContent>\n )}\n </SidebarGroup>\n\n <SidebarGroup className=\"p-0\">\n <SidebarGroupLabel className=\"flex items-center gap-1.5 px-0 text-[10px] font-semibold tracking-wider text-muted-foreground\">\n <button\n onClick={() => setTagsOpen(!tagsOpen)}\n className=\"flex cursor-pointer items-center gap-1.5\"\n >\n <CaretDown\n className={cn(\n \"size-3.5 transition-transform\",\n !tagsOpen && \"-rotate-90\"\n )}\n />\n TAGS\n </button>\n {selectedTags.length > 0 && (\n <button\n onClick={(e) => {\n e.stopPropagation()\n clearTags()\n }}\n className=\"ml-auto text-[10px] text-muted-foreground hover:text-foreground\"\n >\n Clear\n </button>\n )}\n </SidebarGroupLabel>\n {tagsOpen && (\n <SidebarGroupContent>\n <div className=\"mt-2 flex flex-wrap gap-1.5\">\n {tags.map((tag) => (\n <button\n key={tag.id}\n onClick={() => toggleTag(tag.id)}\n className={cn(\n \"inline-flex items-center gap-1 rounded-md px-2 py-1 text-xs font-medium transition-colors\",\n selectedTags.includes(tag.id)\n ? \"bg-primary text-primary-foreground\"\n : tag.color\n )}\n >\n <Tag className=\"size-3\" />\n {tag.name}\n </button>\n ))}\n </div>\n </SidebarGroupContent>\n )}\n </SidebarGroup>\n\n <SidebarGroup className=\"p-0\">\n <SidebarGroupContent>\n <SidebarMenu>\n {navItems.map((item) => (\n <SidebarMenuItem key={item.label}>\n <SidebarMenuButton\n render={<Link href={item.href} />}\n isActive={pathname === item.href}\n className=\"h-[38px]\"\n >\n <item.icon className=\"size-5\" />\n <span>{item.label}</span>\n </SidebarMenuButton>\n </SidebarMenuItem>\n ))}\n </SidebarMenu>\n </SidebarGroupContent>\n </SidebarGroup>\n </SidebarContent>\n </Sidebar>\n )\n}\n"
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/stats-cards.tsx",
|
|
46
|
+
"type": "registry:component",
|
|
47
|
+
"target": "components/example-apps/bookmarks/components/dashboard/stats-cards.tsx",
|
|
48
|
+
"content": "\"use client\"\n\nimport { Bookmark, FolderOpen, Star, Tag } from \"@phosphor-icons/react\"\n\nimport { collections, tags } from \"../../mock-data/bookmarks\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\n\nconst stats = [\n {\n label: \"Total Bookmarks\",\n icon: Bookmark,\n color: \"bg-blue-500/10 text-blue-500\",\n },\n {\n label: \"Favorites\",\n icon: Star,\n color: \"bg-amber-500/10 text-amber-500\",\n },\n {\n label: \"Collections\",\n icon: FolderOpen,\n color: \"bg-violet-500/10 text-violet-500\",\n },\n {\n label: \"Tags Used\",\n icon: Tag,\n color: \"bg-emerald-500/10 text-emerald-500\",\n },\n]\n\nexport function StatsCards() {\n const { bookmarks } = useBookmarksStore()\n\n const values = [\n bookmarks.length,\n bookmarks.filter((b) => b.isFavorite).length,\n collections.length - 1,\n tags.length,\n ]\n\n return (\n <div className=\"grid grid-cols-2 gap-4 lg:grid-cols-4\">\n {stats.map((stat, index) => (\n <div\n key={stat.label}\n className=\"flex items-center gap-4 rounded-xl border bg-card p-4\"\n >\n <div\n className={`size-10 rounded-lg ${stat.color} flex items-center justify-center`}\n >\n <stat.icon className=\"size-5\" />\n </div>\n <div>\n <p className=\"text-2xl font-bold\">{values[index]}</p>\n <p className=\"text-sm text-muted-foreground\">{stat.label}</p>\n </div>\n </div>\n ))}\n </div>\n )\n}\n"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"path": "registry/example-apps/default/bookmarks/components/dashboard/trash-content.tsx",
|
|
52
|
+
"type": "registry:component",
|
|
53
|
+
"target": "components/example-apps/bookmarks/components/dashboard/trash-content.tsx",
|
|
54
|
+
"content": "\"use client\"\n\nimport Image from \"next/image\"\nimport {\n ArrowCounterClockwise,\n ArrowSquareOut,\n DotsThree,\n Trash,\n XCircle,\n} from \"@phosphor-icons/react\"\n\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuItem,\n DropdownMenuSeparator,\n DropdownMenuTrigger,\n} from \"@loveui/ui/ui/menu\"\n\nimport { cn } from \"../../lib/utils\"\nimport { type Bookmark } from \"../../mock-data/bookmarks\"\nimport { useBookmarksStore } from \"../../store/bookmarks-store\"\nimport { Button } from \"../ui/button\"\n\nfunction TrashedBookmarkCard({ bookmark }: { bookmark: Bookmark }) {\n const { restoreFromTrash, permanentlyDelete } = useBookmarksStore()\n\n return (\n <div className=\"group flex items-center gap-4 rounded-lg border bg-card p-4 opacity-75 transition-colors hover:bg-accent/50 hover:opacity-100\">\n <div className=\"flex size-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted\">\n <Image\n src={bookmark.favicon}\n alt={bookmark.title}\n width={24}\n height={24}\n className={cn(\n \"size-6 grayscale\",\n bookmark.hasDarkIcon && \"dark:invert\"\n )}\n />\n </div>\n\n <div className=\"min-w-0 flex-1\">\n <h3 className=\"truncate font-medium\">{bookmark.title}</h3>\n <p className=\"truncate text-sm text-muted-foreground\">{bookmark.url}</p>\n </div>\n\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => restoreFromTrash(bookmark.id)}\n >\n <ArrowCounterClockwise className=\"mr-1 size-4\" />\n Restore\n </Button>\n <DropdownMenu>\n <DropdownMenuTrigger\n render={\n <Button variant=\"ghost\" size=\"icon-xs\">\n <DotsThree className=\"size-4\" weight=\"bold\" />\n </Button>\n }\n />\n <DropdownMenuContent align=\"end\">\n <DropdownMenuGroup>\n <DropdownMenuItem\n onClick={() => window.open(bookmark.url, \"_blank\")}\n >\n <ArrowSquareOut className=\"mr-2 size-4\" />\n Open URL\n </DropdownMenuItem>\n </DropdownMenuGroup>\n <DropdownMenuSeparator />\n <DropdownMenuGroup>\n <DropdownMenuItem\n className=\"text-destructive\"\n onClick={() => permanentlyDelete(bookmark.id)}\n >\n <XCircle className=\"mr-2 size-4\" />\n Delete Permanently\n </DropdownMenuItem>\n </DropdownMenuGroup>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n </div>\n )\n}\n\nexport function TrashContent() {\n const { getTrashedBookmarks, trashedBookmarks } = useBookmarksStore()\n const filteredTrash = getTrashedBookmarks()\n\n return (\n <div className=\"w-full flex-1 overflow-auto\">\n <div className=\"space-y-6 p-4 md:p-6\">\n <div className=\"flex items-center justify-between gap-4 rounded-xl border bg-card p-4\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-10 items-center justify-center rounded-lg bg-destructive/10 text-destructive\">\n <Trash className=\"size-5\" />\n </div>\n <div>\n <h2 className=\"text-lg font-semibold\">Trash</h2>\n <p className=\"text-sm text-muted-foreground\">\n {trashedBookmarks.length} bookmark\n {trashedBookmarks.length !== 1 ? \"s\" : \"\"} in trash\n </p>\n </div>\n </div>\n {trashedBookmarks.length > 0 && (\n <p className=\"hidden text-xs text-muted-foreground sm:block\">\n Items in trash will be permanently deleted after 30 days\n </p>\n )}\n </div>\n\n <div className=\"flex flex-col gap-2\">\n {filteredTrash.map((bookmark) => (\n <TrashedBookmarkCard key={bookmark.id} bookmark={bookmark} />\n ))}\n </div>\n\n {trashedBookmarks.length === 0 && (\n <div className=\"flex flex-col items-center justify-center py-12 text-center\">\n <div className=\"mb-4 flex size-12 items-center justify-center rounded-full bg-muted\">\n <Trash className=\"size-6 text-muted-foreground\" />\n </div>\n <h3 className=\"mb-1 text-lg font-medium\">Trash is empty</h3>\n <p className=\"max-w-sm text-sm text-muted-foreground\">\n Deleted bookmarks will appear here. You can restore them or delete\n them permanently.\n </p>\n </div>\n )}\n </div>\n </div>\n )\n}\n"
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"path": "registry/example-apps/default/bookmarks/components/theme-provider.tsx",
|
|
58
|
+
"type": "registry:component",
|
|
59
|
+
"target": "components/example-apps/bookmarks/components/theme-provider.tsx",
|
|
60
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ThemeProvider as NextThemesProvider } from \"next-themes\"\n\nexport function ThemeProvider({\n children,\n ...props\n}: React.ComponentProps<typeof NextThemesProvider>) {\n return <NextThemesProvider {...props}>{children}</NextThemesProvider>\n}\n"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"path": "registry/example-apps/default/bookmarks/components/theme-toggle.tsx",
|
|
64
|
+
"type": "registry:component",
|
|
65
|
+
"target": "components/example-apps/bookmarks/components/theme-toggle.tsx",
|
|
66
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Moon, Sun } from \"@phosphor-icons/react\"\nimport { useTheme } from \"next-themes\"\n\nimport { Button } from \"./ui/button\"\n\nexport function ThemeToggle() {\n const { setTheme, theme } = useTheme()\n\n return (\n <Button\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setTheme(theme === \"light\" ? \"dark\" : \"light\")}\n >\n <Sun className=\"size-5 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90\" />\n <Moon className=\"absolute size-5 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0\" />\n <span className=\"sr-only\">Toggle theme</span>\n </Button>\n )\n}\n"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/avatar.tsx",
|
|
70
|
+
"type": "registry:ui",
|
|
71
|
+
"target": "components/example-apps/bookmarks/components/ui/avatar.tsx",
|
|
72
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Avatar as AvatarPrimitive } from \"@base-ui/react/avatar\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Avatar({\n className,\n size = \"default\",\n ...props\n}: AvatarPrimitive.Root.Props & {\n size?: \"default\" | \"sm\" | \"lg\"\n}) {\n return (\n <AvatarPrimitive.Root\n data-slot=\"avatar\"\n data-size={size}\n className={cn(\n \"group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarImage({ className, ...props }: AvatarPrimitive.Image.Props) {\n return (\n <AvatarPrimitive.Image\n data-slot=\"avatar-image\"\n className={cn(\n \"aspect-square size-full rounded-full object-cover\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarFallback({\n className,\n ...props\n}: AvatarPrimitive.Fallback.Props) {\n return (\n <AvatarPrimitive.Fallback\n data-slot=\"avatar-fallback\"\n className={cn(\n \"flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarBadge({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"avatar-badge\"\n className={cn(\n \"absolute right-0 bottom-0 z-10 inline-flex items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background select-none\",\n \"group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden\",\n \"group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2\",\n \"group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group\"\n className={cn(\n \"group/avatar-group flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction AvatarGroupCount({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"avatar-group-count\"\n className={cn(\n \"relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-sm text-muted-foreground ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Avatar,\n AvatarImage,\n AvatarFallback,\n AvatarGroup,\n AvatarGroupCount,\n AvatarBadge,\n}\n"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/button.tsx",
|
|
76
|
+
"type": "registry:ui",
|
|
77
|
+
"target": "components/example-apps/bookmarks/components/ui/button.tsx",
|
|
78
|
+
"content": "\"use client\"\n\nimport { Button as ButtonPrimitive } from \"@base-ui/react/button\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"../../lib/utils\"\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/80\",\n outline:\n \"border-border bg-background shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground\",\n ghost:\n \"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50\",\n destructive:\n \"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default:\n \"h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2\",\n xs: \"h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5\",\n lg: \"h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3\",\n icon: \"size-9\",\n \"icon-xs\":\n \"size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\":\n \"size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n )\n}\n\nexport { Button, buttonVariants }\n"
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/collapsible.tsx",
|
|
82
|
+
"type": "registry:ui",
|
|
83
|
+
"target": "components/example-apps/bookmarks/components/ui/collapsible.tsx",
|
|
84
|
+
"content": "\"use client\"\n\nimport { Collapsible as CollapsiblePrimitive } from \"@base-ui/react/collapsible\"\n\nfunction Collapsible({ ...props }: CollapsiblePrimitive.Root.Props) {\n return <CollapsiblePrimitive.Root data-slot=\"collapsible\" {...props} />\n}\n\nfunction CollapsibleTrigger({ ...props }: CollapsiblePrimitive.Trigger.Props) {\n return (\n <CollapsiblePrimitive.Trigger data-slot=\"collapsible-trigger\" {...props} />\n )\n}\n\nfunction CollapsibleContent({ ...props }: CollapsiblePrimitive.Panel.Props) {\n return (\n <CollapsiblePrimitive.Panel data-slot=\"collapsible-content\" {...props} />\n )\n}\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n"
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/dropdown-menu.tsx",
|
|
88
|
+
"type": "registry:ui",
|
|
89
|
+
"target": "components/example-apps/bookmarks/components/ui/dropdown-menu.tsx",
|
|
90
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\nimport { CaretRightIcon, CheckIcon } from \"@phosphor-icons/react\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {\n return <MenuPrimitive.Portal data-slot=\"dropdown-menu-portal\" {...props} />\n}\n\nfunction DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n align = \"start\",\n alignOffset = 0,\n side = \"bottom\",\n sideOffset = 4,\n className,\n ...props\n}: MenuPrimitive.Popup.Props &\n Pick<\n MenuPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n className=\"isolate z-50 outline-none\"\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-md bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 outline-none data-closed:overflow-hidden\",\n className\n )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {\n return <MenuPrimitive.Group data-slot=\"dropdown-menu-group\" {...props} />\n}\n\nfunction DropdownMenuLabel({\n className,\n inset,\n ...props\n}: MenuPrimitive.GroupLabel.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n data-inset={inset}\n className={cn(\n \"px-2 py-1.5 text-xs font-medium text-muted-foreground data-[inset]:pl-8\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuItem({\n className,\n inset,\n variant = \"default\",\n ...props\n}: MenuPrimitive.Item.Props & {\n inset?: boolean\n variant?: \"default\" | \"destructive\"\n}) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n data-inset={inset}\n data-variant={variant}\n className={cn(\n \"group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {\n return <MenuPrimitive.SubmenuRoot data-slot=\"dropdown-menu-sub\" {...props} />\n}\n\nfunction DropdownMenuSubTrigger({\n className,\n inset,\n children,\n ...props\n}: MenuPrimitive.SubmenuTrigger.Props & {\n inset?: boolean\n}) {\n return (\n <MenuPrimitive.SubmenuTrigger\n data-slot=\"dropdown-menu-sub-trigger\"\n data-inset={inset}\n className={cn(\n \"flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n {children}\n <CaretRightIcon className=\"ml-auto\" />\n </MenuPrimitive.SubmenuTrigger>\n )\n}\n\nfunction DropdownMenuSubContent({\n align = \"start\",\n alignOffset = -3,\n side = \"right\",\n sideOffset = 0,\n className,\n ...props\n}: React.ComponentProps<typeof DropdownMenuContent>) {\n return (\n <DropdownMenuContent\n data-slot=\"dropdown-menu-sub-content\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 w-auto min-w-[96px] rounded-md bg-popover p-1 text-popover-foreground shadow-lg ring-1 ring-foreground/10 duration-100\",\n className\n )}\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n checked,\n ...props\n}: MenuPrimitive.CheckboxItem.Props) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(\n \"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n checked={checked}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-checkbox-item-indicator\"\n >\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nfunction DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {\n return (\n <MenuPrimitive.RadioGroup\n data-slot=\"dropdown-menu-radio-group\"\n {...props}\n />\n )\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: MenuPrimitive.RadioItem.Props) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(\n \"relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n className\n )}\n {...props}\n >\n <span\n className=\"pointer-events-none absolute right-2 flex items-center justify-center\"\n data-slot=\"dropdown-menu-radio-item-indicator\"\n >\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuSeparator({\n className,\n ...props\n}: MenuPrimitive.Separator.Props) {\n return (\n <MenuPrimitive.Separator\n data-slot=\"dropdown-menu-separator\"\n className={cn(\"-mx-1 my-1 h-px bg-border\", className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuShortcut({\n className,\n ...props\n}: React.ComponentProps<\"span\">) {\n return (\n <span\n data-slot=\"dropdown-menu-shortcut\"\n className={cn(\n \"ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuPortal,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuGroup,\n DropdownMenuLabel,\n DropdownMenuItem,\n DropdownMenuCheckboxItem,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuSeparator,\n DropdownMenuShortcut,\n DropdownMenuSub,\n DropdownMenuSubTrigger,\n DropdownMenuSubContent,\n}\n"
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/input.tsx",
|
|
94
|
+
"type": "registry:ui",
|
|
95
|
+
"target": "components/example-apps/bookmarks/components/ui/input.tsx",
|
|
96
|
+
"content": "import * as React from \"react\"\nimport { Input as InputPrimitive } from \"@base-ui/react/input\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-2.5 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/separator.tsx",
|
|
100
|
+
"type": "registry:ui",
|
|
101
|
+
"target": "components/example-apps/bookmarks/components/ui/separator.tsx",
|
|
102
|
+
"content": "\"use client\"\n\nimport { Separator as SeparatorPrimitive } from \"@base-ui/react/separator\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Separator({\n className,\n orientation = \"horizontal\",\n ...props\n}: SeparatorPrimitive.Props) {\n return (\n <SeparatorPrimitive\n data-slot=\"separator\"\n orientation={orientation}\n className={cn(\n \"shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:w-px data-[orientation=vertical]:self-stretch\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Separator }\n"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/sheet.tsx",
|
|
106
|
+
"type": "registry:ui",
|
|
107
|
+
"target": "components/example-apps/bookmarks/components/ui/sheet.tsx",
|
|
108
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\nimport { XIcon } from \"@phosphor-icons/react\"\n\nimport { cn } from \"../../lib/utils\"\nimport { Button } from \"./button\"\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 z-50 bg-black/10 duration-100 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n showCloseButton?: boolean\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\n \"data-open:animate-in data-closed:animate-out data-[side=right]:data-closed:slide-out-to-right-10 data-[side=right]:data-open:slide-in-from-right-10 data-[side=left]:data-closed:slide-out-to-left-10 data-[side=left]:data-open:slide-in-from-left-10 data-[side=top]:data-closed:slide-out-to-top-10 data-[side=top]:data-open:slide-in-from-top-10 data-closed:fade-out-0 data-open:fade-in-0 data-[side=bottom]:data-closed:slide-out-to-bottom-10 data-[side=bottom]:data-open:slide-in-from-bottom-10 fixed z-50 flex flex-col gap-4 bg-background bg-clip-padding text-sm shadow-lg transition duration-200 ease-in-out data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-4 right-4\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-1.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"font-medium text-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/sidebar.tsx",
|
|
112
|
+
"type": "registry:ui",
|
|
113
|
+
"target": "components/example-apps/bookmarks/components/ui/sidebar.tsx",
|
|
114
|
+
"content": "\"use client\"\n\nimport * as React from \"react\"\nimport { mergeProps } from \"@base-ui/react/merge-props\"\nimport { useRender } from \"@base-ui/react/use-render\"\nimport { SidebarIcon } from \"@phosphor-icons/react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { useIsMobile } from \"../../hooks/use-mobile\"\nimport { cn } from \"../../lib/utils\"\nimport { Button } from \"./button\"\nimport { Input } from \"./input\"\nimport { Separator } from \"./separator\"\nimport {\n Sheet,\n SheetContent,\n SheetDescription,\n SheetHeader,\n SheetTitle,\n} from \"./sheet\"\nimport { Skeleton } from \"./skeleton\"\nimport { Tooltip, TooltipContent, TooltipTrigger } from \"./tooltip\"\n\nconst SIDEBAR_COOKIE_NAME = \"sidebar_state\"\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\nconst SIDEBAR_WIDTH = \"16rem\"\nconst SIDEBAR_WIDTH_MOBILE = \"18rem\"\nconst SIDEBAR_WIDTH_ICON = \"3rem\"\nconst SIDEBAR_KEYBOARD_SHORTCUT = \"b\"\n\ntype SidebarContextProps = {\n state: \"expanded\" | \"collapsed\"\n open: boolean\n setOpen: (open: boolean) => void\n openMobile: boolean\n setOpenMobile: (open: boolean) => void\n isMobile: boolean\n toggleSidebar: () => void\n}\n\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\n\nfunction useSidebar() {\n const context = React.useContext(SidebarContext)\n if (!context) {\n throw new Error(\"useSidebar must be used within a SidebarProvider.\")\n }\n\n return context\n}\n\nfunction SidebarProvider({\n defaultOpen = true,\n open: openProp,\n onOpenChange: setOpenProp,\n className,\n style,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n defaultOpen?: boolean\n open?: boolean\n onOpenChange?: (open: boolean) => void\n}) {\n const isMobile = useIsMobile()\n const [openMobile, setOpenMobile] = React.useState(false)\n\n // This is the internal state of the sidebar.\n // We use openProp and setOpenProp for control from outside the component.\n const [_open, _setOpen] = React.useState(defaultOpen)\n const open = openProp ?? _open\n const setOpen = React.useCallback(\n (value: boolean | ((value: boolean) => boolean)) => {\n const openState = typeof value === \"function\" ? value(open) : value\n if (setOpenProp) {\n setOpenProp(openState)\n } else {\n _setOpen(openState)\n }\n\n // This sets the cookie to keep the sidebar state.\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\n },\n [setOpenProp, open]\n )\n\n // Helper to toggle the sidebar.\n const toggleSidebar = React.useCallback(() => {\n return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open)\n }, [isMobile, setOpen, setOpenMobile])\n\n // Adds a keyboard shortcut to toggle the sidebar.\n React.useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n if (\n event.key === SIDEBAR_KEYBOARD_SHORTCUT &&\n (event.metaKey || event.ctrlKey)\n ) {\n event.preventDefault()\n toggleSidebar()\n }\n }\n\n window.addEventListener(\"keydown\", handleKeyDown)\n return () => window.removeEventListener(\"keydown\", handleKeyDown)\n }, [toggleSidebar])\n\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\n // This makes it easier to style the sidebar with Tailwind classes.\n const state = open ? \"expanded\" : \"collapsed\"\n\n const contextValue = React.useMemo<SidebarContextProps>(\n () => ({\n state,\n open,\n setOpen,\n isMobile,\n openMobile,\n setOpenMobile,\n toggleSidebar,\n }),\n [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar]\n )\n\n return (\n <SidebarContext.Provider value={contextValue}>\n <div\n data-slot=\"sidebar-wrapper\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH,\n \"--sidebar-width-icon\": SIDEBAR_WIDTH_ICON,\n ...style,\n } as any\n }\n className={cn(\n \"group/sidebar-wrapper flex min-h-svh w-full has-data-[variant=inset]:bg-sidebar\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n </SidebarContext.Provider>\n )\n}\n\nfunction Sidebar({\n side = \"left\",\n variant = \"sidebar\",\n collapsible = \"offcanvas\",\n className,\n children,\n ...props\n}: React.ComponentProps<\"div\"> & {\n side?: \"left\" | \"right\"\n variant?: \"sidebar\" | \"floating\" | \"inset\"\n collapsible?: \"offcanvas\" | \"icon\" | \"none\"\n}) {\n const { isMobile, state, openMobile, setOpenMobile } = useSidebar()\n\n if (collapsible === \"none\") {\n return (\n <div\n data-slot=\"sidebar\"\n className={cn(\n \"flex h-full w-(--sidebar-width) flex-col bg-sidebar text-sidebar-foreground\",\n className\n )}\n {...props}\n >\n {children}\n </div>\n )\n }\n\n if (isMobile) {\n return (\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\n <SheetContent\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar\"\n data-mobile=\"true\"\n className=\"top-[var(--sidebar-top-offset,0px)] h-[calc(100svh-var(--sidebar-top-offset,0px))] w-(--sidebar-width) bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden\"\n style={\n {\n \"--sidebar-width\": SIDEBAR_WIDTH_MOBILE,\n } as any\n }\n side={side}\n >\n <SheetHeader className=\"sr-only\">\n <SheetTitle>Sidebar</SheetTitle>\n <SheetDescription>Displays the mobile sidebar.</SheetDescription>\n </SheetHeader>\n <div className=\"flex h-full w-full flex-col\">{children}</div>\n </SheetContent>\n </Sheet>\n )\n }\n\n return (\n <div\n className=\"group peer hidden text-sidebar-foreground md:block\"\n data-state={state}\n data-collapsible={state === \"collapsed\" ? collapsible : \"\"}\n data-variant={variant}\n data-side={side}\n data-slot=\"sidebar\"\n >\n {/* This is what handles the sidebar gap on desktop */}\n <div\n data-slot=\"sidebar-gap\"\n className={cn(\n \"relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear\",\n \"group-data-[collapsible=offcanvas]:w-0\",\n \"group-data-[side=right]:rotate-180\",\n variant === \"floating\" || variant === \"inset\"\n ? \"group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon)\"\n )}\n />\n <div\n data-slot=\"sidebar-container\"\n className={cn(\n \"fixed top-[var(--sidebar-top-offset,0px)] bottom-0 z-10 hidden h-[calc(100svh-var(--sidebar-top-offset,0px))] w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex\",\n side === \"left\"\n ? \"left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]\"\n : \"right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]\",\n // Adjust the padding for floating and inset variants.\n variant === \"floating\" || variant === \"inset\"\n ? \"p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]\"\n : \"group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l\",\n className\n )}\n {...props}\n >\n <div\n data-sidebar=\"sidebar\"\n data-slot=\"sidebar-inner\"\n className=\"flex size-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:shadow-sm group-data-[variant=floating]:ring-1 group-data-[variant=floating]:ring-sidebar-border\"\n >\n {children}\n </div>\n </div>\n </div>\n )\n}\n\nfunction SidebarTrigger({\n className,\n onClick,\n ...props\n}: React.ComponentProps<typeof Button>) {\n const { toggleSidebar } = useSidebar()\n\n return (\n <Button\n data-sidebar=\"trigger\"\n data-slot=\"sidebar-trigger\"\n variant=\"ghost\"\n size=\"icon-sm\"\n className={cn(className)}\n onClick={(event) => {\n onClick?.(event)\n toggleSidebar()\n }}\n {...props}\n >\n <SidebarIcon />\n <span className=\"sr-only\">Toggle Sidebar</span>\n </Button>\n )\n}\n\nfunction SidebarRail({ className, ...props }: React.ComponentProps<\"button\">) {\n const { toggleSidebar } = useSidebar()\n\n return (\n <button\n data-sidebar=\"rail\"\n data-slot=\"sidebar-rail\"\n aria-label=\"Toggle Sidebar\"\n tabIndex={-1}\n onClick={toggleSidebar}\n title=\"Toggle Sidebar\"\n className={cn(\n \"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border sm:flex\",\n \"in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize\",\n \"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize\",\n \"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full hover:group-data-[collapsible=offcanvas]:bg-sidebar\",\n \"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2\",\n \"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarInset({ className, ...props }: React.ComponentProps<\"main\">) {\n return (\n <main\n data-slot=\"sidebar-inset\"\n className={cn(\n \"relative flex w-full flex-1 flex-col bg-background md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarInput({\n className,\n ...props\n}: React.ComponentProps<typeof Input>) {\n return (\n <Input\n data-slot=\"sidebar-input\"\n data-sidebar=\"input\"\n className={cn(\"h-8 w-full bg-background shadow-none\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-header\"\n data-sidebar=\"header\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-footer\"\n data-sidebar=\"footer\"\n className={cn(\"flex flex-col gap-2 p-2\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarSeparator({\n className,\n ...props\n}: React.ComponentProps<typeof Separator>) {\n return (\n <Separator\n data-slot=\"sidebar-separator\"\n data-sidebar=\"separator\"\n className={cn(\"mx-2 w-auto bg-sidebar-border\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-content\"\n data-sidebar=\"content\"\n className={cn(\n \"no-scrollbar flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarGroup({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group\"\n data-sidebar=\"group\"\n className={cn(\"relative flex w-full min-w-0 flex-col p-2\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarGroupLabel({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\"> & React.ComponentProps<\"div\">) {\n return useRender({\n defaultTagName: \"div\",\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 ring-sidebar-ring outline-hidden transition-[margin,opacity] duration-200 ease-linear group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0 focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-label\",\n sidebar: \"group-label\",\n },\n })\n}\n\nfunction SidebarGroupAction({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"button\"> & React.ComponentProps<\"button\">) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(\n \"absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-group-action\",\n sidebar: \"group-action\",\n },\n })\n}\n\nfunction SidebarGroupContent({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-group-content\"\n data-sidebar=\"group-content\"\n className={cn(\"w-full text-sm\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenu({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu\"\n data-sidebar=\"menu\"\n className={cn(\"flex w-full min-w-0 flex-col gap-1\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuItem({ className, ...props }: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-item\"\n data-sidebar=\"menu-item\"\n className={cn(\"group/menu-item relative\", className)}\n {...props}\n />\n )\n}\n\nconst sidebarMenuButtonVariants = cva(\n \"peer/menu-button group/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm ring-sidebar-ring outline-hidden transition-[width,height,padding] group-has-data-[sidebar=menu-action]/menu-item:pr-8 group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:bg-sidebar-accent data-active:font-medium data-active:text-sidebar-accent-foreground data-open:hover:bg-sidebar-accent data-open:hover:text-sidebar-accent-foreground [&_svg]:size-4 [&_svg]:shrink-0 [&>span:last-child]:truncate\",\n {\n variants: {\n variant: {\n default: \"hover:bg-sidebar-accent hover:text-sidebar-accent-foreground\",\n outline:\n \"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]\",\n },\n size: {\n default: \"h-8 text-sm\",\n sm: \"h-7 text-xs\",\n lg: \"h-12 text-sm group-data-[collapsible=icon]:p-0!\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction SidebarMenuButton({\n render,\n isActive = false,\n variant = \"default\",\n size = \"default\",\n tooltip,\n className,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n isActive?: boolean\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\n } & VariantProps<typeof sidebarMenuButtonVariants>) {\n const { isMobile, state } = useSidebar()\n const comp = useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(sidebarMenuButtonVariants({ variant, size }), className),\n },\n props\n ),\n render: !tooltip ? render : TooltipTrigger,\n state: {\n slot: \"sidebar-menu-button\",\n sidebar: \"menu-button\",\n size,\n active: isActive,\n },\n })\n\n if (!tooltip) {\n return comp\n }\n\n if (typeof tooltip === \"string\") {\n tooltip = {\n children: tooltip,\n }\n }\n\n return (\n <Tooltip>\n {comp}\n <TooltipContent\n side=\"right\"\n align=\"center\"\n hidden={state !== \"collapsed\" || isMobile}\n {...tooltip}\n />\n </Tooltip>\n )\n}\n\nfunction SidebarMenuAction({\n className,\n render,\n showOnHover = false,\n ...props\n}: useRender.ComponentProps<\"button\"> &\n React.ComponentProps<\"button\"> & {\n showOnHover?: boolean\n }) {\n return useRender({\n defaultTagName: \"button\",\n props: mergeProps<\"button\">(\n {\n className: cn(\n \"absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground ring-sidebar-ring outline-hidden transition-transform group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1 after:absolute after:-inset-2 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 md:after:hidden [&>svg]:size-4 [&>svg]:shrink-0\",\n showOnHover &&\n \"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 peer-data-active/menu-button:text-sidebar-accent-foreground data-open:opacity-100 md:opacity-0\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-action\",\n sidebar: \"menu-action\",\n },\n })\n}\n\nfunction SidebarMenuBadge({\n className,\n ...props\n}: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sidebar-menu-badge\"\n data-sidebar=\"menu-badge\"\n className={cn(\n \"pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium text-sidebar-foreground tabular-nums select-none group-data-[collapsible=icon]:hidden peer-hover/menu-button:text-sidebar-accent-foreground peer-data-active/menu-button:text-sidebar-accent-foreground peer-data-[size=default]/menu-button:top-1.5 peer-data-[size=lg]/menu-button:top-2.5 peer-data-[size=sm]/menu-button:top-1\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSkeleton({\n className,\n showIcon = false,\n ...props\n}: React.ComponentProps<\"div\"> & {\n showIcon?: boolean\n}) {\n // Random width between 50 to 90%.\n const [width] = React.useState(() => {\n return `${Math.floor(Math.random() * 40) + 50}%`\n })\n\n return (\n <div\n data-slot=\"sidebar-menu-skeleton\"\n data-sidebar=\"menu-skeleton\"\n className={cn(\"flex h-8 items-center gap-2 rounded-md px-2\", className)}\n {...props}\n >\n {showIcon && (\n <Skeleton\n className=\"size-4 rounded-md\"\n data-sidebar=\"menu-skeleton-icon\"\n />\n )}\n <Skeleton\n className=\"h-4 max-w-(--skeleton-width) flex-1\"\n data-sidebar=\"menu-skeleton-text\"\n style={\n {\n \"--skeleton-width\": width,\n } as any\n }\n />\n </div>\n )\n}\n\nfunction SidebarMenuSub({ className, ...props }: React.ComponentProps<\"ul\">) {\n return (\n <ul\n data-slot=\"sidebar-menu-sub\"\n data-sidebar=\"menu-sub\"\n className={cn(\n \"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5 group-data-[collapsible=icon]:hidden\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSubItem({\n className,\n ...props\n}: React.ComponentProps<\"li\">) {\n return (\n <li\n data-slot=\"sidebar-menu-sub-item\"\n data-sidebar=\"menu-sub-item\"\n className={cn(\"group/menu-sub-item relative\", className)}\n {...props}\n />\n )\n}\n\nfunction SidebarMenuSubButton({\n render,\n size = \"md\",\n isActive = false,\n className,\n ...props\n}: useRender.ComponentProps<\"a\"> &\n React.ComponentProps<\"a\"> & {\n size?: \"sm\" | \"md\"\n isActive?: boolean\n }) {\n return useRender({\n defaultTagName: \"a\",\n props: mergeProps<\"a\">(\n {\n className: cn(\n \"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground ring-sidebar-ring outline-hidden group-data-[collapsible=icon]:hidden hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-active:bg-sidebar-accent data-active:text-sidebar-accent-foreground data-[size=md]:text-sm data-[size=sm]:text-xs [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground\",\n className\n ),\n },\n props\n ),\n render,\n state: {\n slot: \"sidebar-menu-sub-button\",\n sidebar: \"menu-sub-button\",\n size,\n active: isActive,\n },\n })\n}\n\nexport {\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarGroup,\n SidebarGroupAction,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarHeader,\n SidebarInput,\n SidebarInset,\n SidebarMenu,\n SidebarMenuAction,\n SidebarMenuBadge,\n SidebarMenuButton,\n SidebarMenuItem,\n SidebarMenuSkeleton,\n SidebarMenuSub,\n SidebarMenuSubButton,\n SidebarMenuSubItem,\n SidebarProvider,\n SidebarRail,\n SidebarSeparator,\n SidebarTrigger,\n useSidebar,\n}\n"
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/skeleton.tsx",
|
|
118
|
+
"type": "registry:ui",
|
|
119
|
+
"target": "components/example-apps/bookmarks/components/ui/skeleton.tsx",
|
|
120
|
+
"content": "import type { ComponentPropsWithoutRef } from \"react\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction Skeleton({ className, ...props }: ComponentPropsWithoutRef<\"div\">) {\n return (\n <div\n data-slot=\"skeleton\"\n className={cn(\"animate-pulse rounded-md bg-muted\", className)}\n {...props}\n />\n )\n}\n\nexport { Skeleton }\n"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"path": "registry/example-apps/default/bookmarks/components/ui/tooltip.tsx",
|
|
124
|
+
"type": "registry:ui",
|
|
125
|
+
"target": "components/example-apps/bookmarks/components/ui/tooltip.tsx",
|
|
126
|
+
"content": "\"use client\"\n\nimport { Tooltip as TooltipPrimitive } from \"@base-ui/react/tooltip\"\n\nimport { cn } from \"../../lib/utils\"\n\nfunction TooltipProvider({\n delay = 0,\n ...props\n}: TooltipPrimitive.Provider.Props) {\n return (\n <TooltipPrimitive.Provider\n data-slot=\"tooltip-provider\"\n delay={delay}\n {...props}\n />\n )\n}\n\nfunction Tooltip({ ...props }: TooltipPrimitive.Root.Props) {\n return (\n <TooltipProvider>\n <TooltipPrimitive.Root data-slot=\"tooltip\" {...props} />\n </TooltipProvider>\n )\n}\n\nfunction TooltipTrigger({ ...props }: TooltipPrimitive.Trigger.Props) {\n return <TooltipPrimitive.Trigger data-slot=\"tooltip-trigger\" {...props} />\n}\n\nfunction TooltipContent({\n className,\n side = \"top\",\n sideOffset = 4,\n align = \"center\",\n alignOffset = 0,\n children,\n ...props\n}: TooltipPrimitive.Popup.Props &\n Pick<\n TooltipPrimitive.Positioner.Props,\n \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n >) {\n return (\n <TooltipPrimitive.Portal>\n <TooltipPrimitive.Positioner\n align={align}\n alignOffset={alignOffset}\n side={side}\n sideOffset={sideOffset}\n className=\"isolate z-50\"\n >\n <TooltipPrimitive.Popup\n data-slot=\"tooltip-content\"\n className={cn(\n \"data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit max-w-xs origin-(--transform-origin) rounded-md bg-foreground px-3 py-1.5 text-xs text-background\",\n className\n )}\n {...props}\n >\n {children}\n <TooltipPrimitive.Arrow className=\"z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5\" />\n </TooltipPrimitive.Popup>\n </TooltipPrimitive.Positioner>\n </TooltipPrimitive.Portal>\n )\n}\n\nexport { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }\n"
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
"path": "registry/example-apps/default/bookmarks/hooks/use-mobile.ts",
|
|
130
|
+
"type": "registry:hook",
|
|
131
|
+
"target": "components/example-apps/bookmarks/hooks/use-mobile.ts",
|
|
132
|
+
"content": "import * as React from \"react\"\n\nconst MOBILE_BREAKPOINT = 768\n\nexport function useIsMobile() {\n const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)\n\n React.useEffect(() => {\n const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)\n const onChange = () => {\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n }\n mql.addEventListener(\"change\", onChange)\n setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)\n return () => mql.removeEventListener(\"change\", onChange)\n }, [])\n\n return !!isMobile\n}\n"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"path": "registry/example-apps/default/bookmarks/index.tsx",
|
|
136
|
+
"type": "registry:file",
|
|
137
|
+
"target": "components/example-apps/bookmarks/index.tsx",
|
|
138
|
+
"content": "/**\n * Wrapper export for embedding the app in the docs app\n */\n\"use client\"\n\nimport { SidebarProvider } from \"@/components/ui/sidebar\"\n\nimport { BookmarksContent } from \"./components/dashboard/content\"\nimport { BookmarksHeader } from \"./components/dashboard/header\"\nimport { BookmarksSidebar } from \"./components/dashboard/sidebar\"\n\nexport default function BookmarksWrapper() {\n return (\n <SidebarProvider className=\"bg-sidebar\">\n <BookmarksSidebar />\n <div className=\"h-full min-h-0 w-full overflow-hidden lg:p-2\">\n <div className=\"bg-container flex h-full min-h-0 w-full flex-col items-center justify-start overflow-hidden bg-background lg:rounded-md lg:border\">\n <BookmarksHeader />\n <BookmarksContent />\n </div>\n </div>\n </SidebarProvider>\n )\n}\n"
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"path": "registry/example-apps/default/bookmarks/lib/utils.ts",
|
|
142
|
+
"type": "registry:lib",
|
|
143
|
+
"target": "components/example-apps/bookmarks/lib/utils.ts",
|
|
144
|
+
"content": "import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
"path": "registry/example-apps/default/bookmarks/mock-data/bookmarks.ts",
|
|
148
|
+
"type": "registry:lib",
|
|
149
|
+
"target": "components/example-apps/bookmarks/mock-data/bookmarks.ts",
|
|
150
|
+
"content": "export type Bookmark = {\n id: string\n title: string\n url: string\n description: string\n favicon: string\n collectionId: string\n tags: string[]\n createdAt: string\n isFavorite: boolean\n hasDarkIcon?: boolean\n}\n\nexport type Collection = {\n id: string\n name: string\n icon: string\n color: string\n count: number\n}\n\nexport type Tag = {\n id: string\n name: string\n color: string\n count: number\n}\n\nexport const collections: Collection[] = [\n {\n id: \"all\",\n name: \"All Bookmarks\",\n icon: \"bookmark\",\n color: \"neutral\",\n count: 24,\n },\n {\n id: \"design\",\n name: \"Design Resources\",\n icon: \"palette\",\n color: \"violet\",\n count: 8,\n },\n { id: \"dev\", name: \"Development\", icon: \"code\", color: \"blue\", count: 12 },\n { id: \"tools\", name: \"Tools\", icon: \"wrench\", color: \"amber\", count: 6 },\n {\n id: \"reading\",\n name: \"Reading List\",\n icon: \"book-open\",\n color: \"emerald\",\n count: 4,\n },\n {\n id: \"inspiration\",\n name: \"Inspiration\",\n icon: \"sparkles\",\n color: \"pink\",\n count: 5,\n },\n]\n\nexport const tags: Tag[] = [\n {\n id: \"react\",\n name: \"React\",\n color: \"bg-blue-500/10 text-blue-500\",\n count: 8,\n },\n {\n id: \"typescript\",\n name: \"TypeScript\",\n color: \"bg-blue-600/10 text-blue-600\",\n count: 6,\n },\n {\n id: \"ui\",\n name: \"UI/UX\",\n color: \"bg-violet-500/10 text-violet-500\",\n count: 5,\n },\n {\n id: \"nextjs\",\n name: \"Next.js\",\n color: \"bg-foreground/10 text-foreground\",\n count: 4,\n },\n {\n id: \"tailwind\",\n name: \"Tailwind\",\n color: \"bg-cyan-500/10 text-cyan-500\",\n count: 7,\n },\n {\n id: \"tutorial\",\n name: \"Tutorial\",\n color: \"bg-emerald-500/10 text-emerald-500\",\n count: 3,\n },\n {\n id: \"docs\",\n name: \"Documentation\",\n color: \"bg-amber-500/10 text-amber-500\",\n count: 5,\n },\n {\n id: \"free\",\n name: \"Free\",\n color: \"bg-green-500/10 text-green-500\",\n count: 4,\n },\n]\n\nexport const bookmarks: Bookmark[] = [\n {\n id: \"1\",\n title: \"Shadcn UI\",\n url: \"https://ui.shadcn.com\",\n description:\n \"Beautifully designed components built with Radix UI and Tailwind CSS.\",\n favicon: \"https://www.google.com/s2/favicons?domain=ui.shadcn.com&sz=64\",\n collectionId: \"dev\",\n tags: [\"react\", \"ui\", \"tailwind\"],\n createdAt: \"2024-01-15\",\n isFavorite: true,\n hasDarkIcon: true,\n },\n {\n id: \"2\",\n title: \"Vercel\",\n url: \"https://vercel.com\",\n description:\n \"Develop. Preview. Ship. The best frontend developer experience.\",\n favicon: \"https://www.google.com/s2/favicons?domain=vercel.com&sz=64\",\n collectionId: \"dev\",\n tags: [\"nextjs\"],\n createdAt: \"2024-01-14\",\n isFavorite: true,\n hasDarkIcon: true,\n },\n {\n id: \"3\",\n title: \"Tailwind CSS\",\n url: \"https://tailwindcss.com\",\n description: \"A utility-first CSS framework for rapid UI development.\",\n favicon: \"https://www.google.com/s2/favicons?domain=tailwindcss.com&sz=64\",\n collectionId: \"dev\",\n tags: [\"tailwind\", \"docs\"],\n createdAt: \"2024-01-13\",\n isFavorite: false,\n },\n {\n id: \"4\",\n title: \"Figma\",\n url: \"https://figma.com\",\n description: \"The collaborative interface design tool.\",\n favicon: \"https://www.google.com/s2/favicons?domain=figma.com&sz=64\",\n collectionId: \"design\",\n tags: [\"ui\", \"free\"],\n createdAt: \"2024-01-12\",\n isFavorite: true,\n },\n {\n id: \"5\",\n title: \"Dribbble\",\n url: \"https://dribbble.com\",\n description: \"Discover the world's top designers & creatives.\",\n favicon: \"https://www.google.com/s2/favicons?domain=dribbble.com&sz=64\",\n collectionId: \"inspiration\",\n tags: [\"ui\"],\n createdAt: \"2024-01-11\",\n isFavorite: false,\n },\n {\n id: \"6\",\n title: \"React Documentation\",\n url: \"https://react.dev\",\n description: \"The library for web and native user interfaces.\",\n favicon: \"https://www.google.com/s2/favicons?domain=react.dev&sz=64\",\n collectionId: \"dev\",\n tags: [\"react\", \"docs\", \"tutorial\"],\n createdAt: \"2024-01-10\",\n isFavorite: true,\n },\n {\n id: \"7\",\n title: \"TypeScript Handbook\",\n url: \"https://typescriptlang.org\",\n description: \"TypeScript is JavaScript with syntax for types.\",\n favicon:\n \"https://www.google.com/s2/favicons?domain=typescriptlang.org&sz=64\",\n collectionId: \"dev\",\n tags: [\"typescript\", \"docs\"],\n createdAt: \"2024-01-09\",\n isFavorite: false,\n },\n {\n id: \"8\",\n title: \"Next.js Documentation\",\n url: \"https://nextjs.org\",\n description: \"The React Framework for the Web.\",\n favicon: \"https://www.google.com/s2/favicons?domain=nextjs.org&sz=64\",\n collectionId: \"dev\",\n tags: [\"nextjs\", \"react\", \"docs\"],\n createdAt: \"2024-01-08\",\n isFavorite: true,\n hasDarkIcon: true,\n },\n {\n id: \"9\",\n title: \"Lucide Icons\",\n url: \"https://lucide.dev\",\n description: \"Beautiful & consistent icon toolkit made by the community.\",\n favicon: \"https://www.google.com/s2/favicons?domain=lucide.dev&sz=64\",\n collectionId: \"tools\",\n tags: [\"ui\", \"free\"],\n createdAt: \"2024-01-07\",\n isFavorite: false,\n },\n {\n id: \"10\",\n title: \"Radix UI\",\n url: \"https://radix-ui.com\",\n description: \"Unstyled, accessible components for building design systems.\",\n favicon: \"https://www.google.com/s2/favicons?domain=radix-ui.com&sz=64\",\n collectionId: \"dev\",\n tags: [\"react\", \"ui\"],\n createdAt: \"2024-01-06\",\n isFavorite: false,\n hasDarkIcon: true,\n },\n {\n id: \"11\",\n title: \"Linear\",\n url: \"https://linear.app\",\n description: \"The issue tracking tool you'll enjoy using.\",\n favicon: \"https://www.google.com/s2/favicons?domain=linear.app&sz=64\",\n collectionId: \"tools\",\n tags: [],\n createdAt: \"2024-01-05\",\n isFavorite: true,\n },\n {\n id: \"12\",\n title: \"Notion\",\n url: \"https://notion.so\",\n description:\n \"The all-in-one workspace for your notes, tasks, wikis, and databases.\",\n favicon: \"https://www.google.com/s2/favicons?domain=notion.so&sz=64\",\n collectionId: \"tools\",\n tags: [\"free\"],\n createdAt: \"2024-01-04\",\n isFavorite: false,\n hasDarkIcon: true,\n },\n {\n id: \"13\",\n title: \"Awwwards\",\n url: \"https://awwwards.com\",\n description:\n \"The awards of design, creativity and innovation on the internet.\",\n favicon: \"https://www.google.com/s2/favicons?domain=awwwards.com&sz=64\",\n collectionId: \"inspiration\",\n tags: [\"ui\"],\n createdAt: \"2024-01-03\",\n isFavorite: false,\n },\n {\n id: \"14\",\n title: \"Frontend Masters\",\n url: \"https://frontendmasters.com\",\n description: \"Advance your skills with in-depth, modern front-end courses.\",\n favicon:\n \"https://www.google.com/s2/favicons?domain=frontendmasters.com&sz=64\",\n collectionId: \"reading\",\n tags: [\"tutorial\", \"react\", \"typescript\"],\n createdAt: \"2024-01-02\",\n isFavorite: false,\n },\n {\n id: \"15\",\n title: \"CSS Tricks\",\n url: \"https://css-tricks.com\",\n description:\n \"Daily articles about CSS, HTML, JavaScript, and all things web design.\",\n favicon: \"https://www.google.com/s2/favicons?domain=css-tricks.com&sz=64\",\n collectionId: \"reading\",\n tags: [\"tutorial\", \"tailwind\"],\n createdAt: \"2024-01-01\",\n isFavorite: false,\n },\n {\n id: \"16\",\n title: \"Framer\",\n url: \"https://framer.com\",\n description: \"Ship sites with unmatched speed and style.\",\n favicon: \"https://www.google.com/s2/favicons?domain=framer.com&sz=64\",\n collectionId: \"design\",\n tags: [\"ui\"],\n createdAt: \"2023-12-31\",\n isFavorite: true,\n hasDarkIcon: true,\n },\n]\n"
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"path": "registry/example-apps/default/bookmarks/store/bookmarks-store.ts",
|
|
154
|
+
"type": "registry:lib",
|
|
155
|
+
"target": "components/example-apps/bookmarks/store/bookmarks-store.ts",
|
|
156
|
+
"content": "import { create } from \"zustand\"\n\nimport {\n bookmarks as initialBookmarks,\n type Bookmark,\n} from \"../mock-data/bookmarks\"\n\ntype ViewMode = \"grid\" | \"list\"\ntype SortBy = \"date-newest\" | \"date-oldest\" | \"alpha-az\" | \"alpha-za\"\ntype FilterType = \"all\" | \"favorites\" | \"with-tags\" | \"without-tags\"\n\ninterface BookmarksState {\n bookmarks: Bookmark[]\n archivedBookmarks: Bookmark[]\n trashedBookmarks: Bookmark[]\n selectedCollection: string\n selectedTags: string[]\n searchQuery: string\n viewMode: ViewMode\n sortBy: SortBy\n filterType: FilterType\n setSelectedCollection: (collectionId: string) => void\n toggleTag: (tagId: string) => void\n clearTags: () => void\n setSearchQuery: (query: string) => void\n setViewMode: (mode: ViewMode) => void\n setSortBy: (sort: SortBy) => void\n setFilterType: (filter: FilterType) => void\n toggleFavorite: (bookmarkId: string) => void\n archiveBookmark: (bookmarkId: string) => void\n restoreFromArchive: (bookmarkId: string) => void\n trashBookmark: (bookmarkId: string) => void\n restoreFromTrash: (bookmarkId: string) => void\n permanentlyDelete: (bookmarkId: string) => void\n getFilteredBookmarks: () => Bookmark[]\n getFavoriteBookmarks: () => Bookmark[]\n getArchivedBookmarks: () => Bookmark[]\n getTrashedBookmarks: () => Bookmark[]\n}\n\nexport const useBookmarksStore = create<BookmarksState>((set, get) => ({\n bookmarks: initialBookmarks,\n archivedBookmarks: [],\n trashedBookmarks: [],\n selectedCollection: \"all\",\n selectedTags: [],\n searchQuery: \"\",\n viewMode: \"grid\",\n sortBy: \"date-newest\",\n filterType: \"all\",\n\n setSelectedCollection: (collectionId) =>\n set({ selectedCollection: collectionId }),\n\n toggleTag: (tagId) =>\n set((state) => ({\n selectedTags: state.selectedTags.includes(tagId)\n ? state.selectedTags.filter((t) => t !== tagId)\n : [...state.selectedTags, tagId],\n })),\n\n clearTags: () => set({ selectedTags: [] }),\n\n setSearchQuery: (query) => set({ searchQuery: query }),\n\n setViewMode: (mode) => set({ viewMode: mode }),\n\n setSortBy: (sort) => set({ sortBy: sort }),\n\n setFilterType: (filter) => set({ filterType: filter }),\n\n toggleFavorite: (bookmarkId) =>\n set((state) => ({\n bookmarks: state.bookmarks.map((bookmark) =>\n bookmark.id === bookmarkId\n ? { ...bookmark, isFavorite: !bookmark.isFavorite }\n : bookmark\n ),\n })),\n\n archiveBookmark: (bookmarkId) =>\n set((state) => {\n const bookmark = state.bookmarks.find((b) => b.id === bookmarkId)\n if (!bookmark) return state\n return {\n bookmarks: state.bookmarks.filter((b) => b.id !== bookmarkId),\n archivedBookmarks: [...state.archivedBookmarks, bookmark],\n }\n }),\n\n restoreFromArchive: (bookmarkId) =>\n set((state) => {\n const bookmark = state.archivedBookmarks.find((b) => b.id === bookmarkId)\n if (!bookmark) return state\n return {\n archivedBookmarks: state.archivedBookmarks.filter(\n (b) => b.id !== bookmarkId\n ),\n bookmarks: [...state.bookmarks, bookmark],\n }\n }),\n\n trashBookmark: (bookmarkId) =>\n set((state) => {\n const bookmark = state.bookmarks.find((b) => b.id === bookmarkId)\n if (!bookmark) return state\n return {\n bookmarks: state.bookmarks.filter((b) => b.id !== bookmarkId),\n trashedBookmarks: [...state.trashedBookmarks, bookmark],\n }\n }),\n\n restoreFromTrash: (bookmarkId) =>\n set((state) => {\n const bookmark = state.trashedBookmarks.find((b) => b.id === bookmarkId)\n if (!bookmark) return state\n return {\n trashedBookmarks: state.trashedBookmarks.filter(\n (b) => b.id !== bookmarkId\n ),\n bookmarks: [...state.bookmarks, bookmark],\n }\n }),\n\n permanentlyDelete: (bookmarkId) =>\n set((state) => ({\n trashedBookmarks: state.trashedBookmarks.filter(\n (b) => b.id !== bookmarkId\n ),\n })),\n\n getFilteredBookmarks: () => {\n const state = get()\n let filtered = [...state.bookmarks]\n\n if (state.selectedCollection !== \"all\") {\n filtered = filtered.filter(\n (b) => b.collectionId === state.selectedCollection\n )\n }\n\n if (state.selectedTags.length > 0) {\n filtered = filtered.filter((b) =>\n state.selectedTags.some((tag) => b.tags.includes(tag))\n )\n }\n\n if (state.searchQuery) {\n const query = state.searchQuery.toLowerCase()\n filtered = filtered.filter(\n (b) =>\n b.title.toLowerCase().includes(query) ||\n b.description.toLowerCase().includes(query) ||\n b.url.toLowerCase().includes(query)\n )\n }\n\n switch (state.filterType) {\n case \"favorites\":\n filtered = filtered.filter((b) => b.isFavorite)\n break\n case \"with-tags\":\n filtered = filtered.filter((b) => b.tags.length > 0)\n break\n case \"without-tags\":\n filtered = filtered.filter((b) => b.tags.length === 0)\n break\n }\n\n switch (state.sortBy) {\n case \"date-newest\":\n filtered.sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n )\n break\n case \"date-oldest\":\n filtered.sort(\n (a, b) =>\n new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()\n )\n break\n case \"alpha-az\":\n filtered.sort((a, b) => a.title.localeCompare(b.title))\n break\n case \"alpha-za\":\n filtered.sort((a, b) => b.title.localeCompare(a.title))\n break\n }\n\n return filtered\n },\n\n getFavoriteBookmarks: () => {\n const state = get()\n let filtered = state.bookmarks.filter((b) => b.isFavorite)\n\n if (state.searchQuery) {\n const query = state.searchQuery.toLowerCase()\n filtered = filtered.filter(\n (b) =>\n b.title.toLowerCase().includes(query) ||\n b.description.toLowerCase().includes(query) ||\n b.url.toLowerCase().includes(query)\n )\n }\n\n switch (state.sortBy) {\n case \"date-newest\":\n filtered.sort(\n (a, b) =>\n new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()\n )\n break\n case \"date-oldest\":\n filtered.sort(\n (a, b) =>\n new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime()\n )\n break\n case \"alpha-az\":\n filtered.sort((a, b) => a.title.localeCompare(b.title))\n break\n case \"alpha-za\":\n filtered.sort((a, b) => b.title.localeCompare(a.title))\n break\n }\n\n return filtered\n },\n\n getArchivedBookmarks: () => {\n const state = get()\n let filtered = [...state.archivedBookmarks]\n\n if (state.searchQuery) {\n const query = state.searchQuery.toLowerCase()\n filtered = filtered.filter(\n (b) =>\n b.title.toLowerCase().includes(query) ||\n b.description.toLowerCase().includes(query) ||\n b.url.toLowerCase().includes(query)\n )\n }\n\n return filtered\n },\n\n getTrashedBookmarks: () => {\n const state = get()\n let filtered = [...state.trashedBookmarks]\n\n if (state.searchQuery) {\n const query = state.searchQuery.toLowerCase()\n filtered = filtered.filter(\n (b) =>\n b.title.toLowerCase().includes(query) ||\n b.description.toLowerCase().includes(query) ||\n b.url.toLowerCase().includes(query)\n )\n }\n\n return filtered\n },\n}))\n"
|
|
157
|
+
}
|
|
158
|
+
],
|
|
159
|
+
"categories": [
|
|
160
|
+
"example-app",
|
|
161
|
+
"productivity",
|
|
162
|
+
"bookmarks",
|
|
163
|
+
"organization",
|
|
164
|
+
"dashboard"
|
|
165
|
+
],
|
|
166
|
+
"dependencies": [
|
|
167
|
+
"@base-ui/react",
|
|
168
|
+
"@phosphor-icons/react",
|
|
169
|
+
"class-variance-authority",
|
|
170
|
+
"clsx",
|
|
171
|
+
"next-themes",
|
|
172
|
+
"tailwind-merge",
|
|
173
|
+
"zustand"
|
|
174
|
+
],
|
|
175
|
+
"registryDependencies": [
|
|
176
|
+
"https://www.loveui.dev/r/avatar.json",
|
|
177
|
+
"https://www.loveui.dev/r/input.json",
|
|
178
|
+
"https://www.loveui.dev/r/menu.json"
|
|
179
|
+
],
|
|
180
|
+
"meta": {
|
|
181
|
+
"source": "example-app",
|
|
182
|
+
"appName": "bookmarks",
|
|
183
|
+
"routes": [
|
|
184
|
+
{
|
|
185
|
+
"path": "/",
|
|
186
|
+
"title": "All Bookmarks",
|
|
187
|
+
"description": "Main bookmarks view with filtering and collections"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"path": "/favorites",
|
|
191
|
+
"title": "Favorites",
|
|
192
|
+
"description": "Favorite bookmarks"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"path": "/archive",
|
|
196
|
+
"title": "Archive",
|
|
197
|
+
"description": "Archived bookmarks"
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
"path": "/trash",
|
|
201
|
+
"title": "Trash",
|
|
202
|
+
"description": "Deleted bookmarks"
|
|
203
|
+
}
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/breadcrumb-custom-separator.tsx",
|
|
11
|
-
"content": "import Link from \"next/link\"\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\"\n\nexport default function BreadcrumbDemo() {\n return (\n <Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink render={<Link href=\"/\" />}
|
|
11
|
+
"content": "import Link from \"next/link\"\n\nimport {\n Breadcrumb,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\"\n\nexport default function BreadcrumbDemo() {\n return (\n <Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink render={<Link href=\"/\" />}>\n Updated Home\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator> / </BreadcrumbSeparator>\n <BreadcrumbItem>\n <BreadcrumbLink render={<Link href=\"/docs/components\" />}>\n Updated Components\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator> / </BreadcrumbSeparator>\n <BreadcrumbItem>\n <BreadcrumbPage>Updated Breadcrumb</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n )\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"files": [
|
|
10
10
|
{
|
|
11
11
|
"path": "registry/default/examples/breadcrumb-demo.tsx",
|
|
12
|
-
"content": "import Link from \"next/link\"\n\nimport {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\"\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Menu,\n MenuItem,\n MenuPopup,\n MenuTrigger,\n} from \"@/registry/default/ui/menu\"\n\nexport default function BreadcrumbDemo() {\n return (\n <Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink render={<Link href=\"/\" />}
|
|
12
|
+
"content": "import Link from \"next/link\"\n\nimport {\n Breadcrumb,\n BreadcrumbEllipsis,\n BreadcrumbItem,\n BreadcrumbLink,\n BreadcrumbList,\n BreadcrumbPage,\n BreadcrumbSeparator,\n} from \"@/registry/default/ui/breadcrumb\"\nimport { Button } from \"@/registry/default/ui/button\"\nimport {\n Menu,\n MenuItem,\n MenuPopup,\n MenuTrigger,\n} from \"@/registry/default/ui/menu\"\n\nexport default function BreadcrumbDemo() {\n return (\n <Breadcrumb>\n <BreadcrumbList>\n <BreadcrumbItem>\n <BreadcrumbLink render={<Link href=\"/\" />}>\n Updated Home\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <Menu>\n <MenuTrigger\n render={\n <Button size=\"icon-sm\" variant=\"ghost\" className=\"-m-1.5\" />\n }\n >\n <BreadcrumbEllipsis />\n </MenuTrigger>\n <MenuPopup align=\"start\">\n <MenuItem render={<Link href=\"/docs\" />}>Updated Docs</MenuItem>\n <MenuItem render={<Link href=\"/particles\" />}>\n Updated Particles\n </MenuItem>\n </MenuPopup>\n </Menu>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbLink render={<Link href=\"/docs/components\" />}>\n Updated Components\n </BreadcrumbLink>\n </BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem>\n <BreadcrumbPage>Updated Breadcrumb</BreadcrumbPage>\n </BreadcrumbItem>\n </BreadcrumbList>\n </Breadcrumb>\n )\n}\n",
|
|
13
13
|
"type": "registry:example"
|
|
14
14
|
}
|
|
15
15
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-demo.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDemo() {\n return <Button>Button</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDemo() {\n return <Button>Updated Button</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-destructive-outline.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDestructiveOutline() {\n return <Button variant=\"destructive-outline\">Delete</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDestructiveOutline() {\n return <Button variant=\"destructive-outline\">Updated Delete</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-destructive.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDestructive() {\n return <Button variant=\"destructive\">Delete</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDestructive() {\n return <Button variant=\"destructive\">Updated Delete</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-disabled.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDisabled() {\n return <Button disabled>Button</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonDisabled() {\n return <Button disabled>Updated Button</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-ghost.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonGhost() {\n return <Button variant=\"ghost\">Ghost</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonGhost() {\n return <Button variant=\"ghost\">Updated Ghost</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
package/public/r/button-lg.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-lg.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonLg() {\n return <Button size=\"lg\">Button</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonLg() {\n return <Button size=\"lg\">Updated Button</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
{
|
|
10
10
|
"path": "registry/default/examples/button-link.tsx",
|
|
11
|
-
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonLink() {\n return <Button variant=\"link\">Link</Button>\n}\n",
|
|
11
|
+
"content": "import { Button } from \"@/registry/default/ui/button\"\n\nexport default function ButtonLink() {\n return <Button variant=\"link\">Updated Link</Button>\n}\n",
|
|
12
12
|
"type": "registry:example"
|
|
13
13
|
}
|
|
14
14
|
],
|