canvas-ui-sdk 0.3.23 → 4.0.0
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/README.md +25 -5
- package/dist/charts.js +11 -6
- package/dist/charts.js.map +1 -1
- package/dist/index.d.ts +1233 -153
- package/dist/index.js +3562 -447
- package/dist/index.js.map +1 -1
- package/mcp/dist/index.js +1195 -149
- package/package.json +1 -1
- package/prompts/.cursorrules +96 -0
- package/prompts/.windsurfrules +96 -0
- package/prompts/CLAUDE.md +22 -0
- package/prompts/copilot-instructions.md +96 -0
- package/registry/blocks/activity-feed.json +12 -1
- package/registry/blocks/blog-cards.json +10 -2
- package/registry/blocks/bottom-action-bar.json +27 -0
- package/registry/blocks/bottom-input-chat-widget.json +9 -1
- package/registry/blocks/category-grid.json +10 -2
- package/registry/blocks/centered-hero.json +9 -1
- package/registry/blocks/chat-message.json +8 -1
- package/registry/blocks/circular-progress-bar-list.json +11 -1
- package/registry/blocks/confirmation-popup.json +10 -1
- package/registry/blocks/contact-form-popup.json +10 -1
- package/registry/blocks/content-dropzone.json +8 -0
- package/registry/blocks/content-with-image.json +9 -1
- package/registry/blocks/core-values-grid.json +10 -2
- package/registry/blocks/credit-card-display.json +9 -1
- package/registry/blocks/cta-banner.json +10 -2
- package/registry/blocks/destination-cards.json +10 -1
- package/registry/blocks/detail-drawer.json +10 -1
- package/registry/blocks/details-popup.json +10 -1
- package/registry/blocks/editable-list.json +29 -0
- package/registry/blocks/empty-state.json +10 -2
- package/registry/blocks/faq-accordion.json +9 -1
- package/registry/blocks/faqs-table.json +10 -1
- package/registry/blocks/feature-with-image.json +9 -1
- package/registry/blocks/featured-news-cards.json +10 -2
- package/registry/blocks/featured-places.json +10 -2
- package/registry/blocks/features-comparison.json +9 -1
- package/registry/blocks/feedback-popup.json +9 -1
- package/registry/blocks/filter-popover.json +8 -1
- package/registry/blocks/fixed-column-data-table.json +11 -1
- package/registry/blocks/flair-banner.json +9 -1
- package/registry/blocks/footer-navbar.json +9 -1
- package/registry/blocks/form-group.json +14 -3
- package/registry/blocks/form-popup.json +31 -0
- package/registry/blocks/gallery-section.json +10 -2
- package/registry/blocks/gradient-banner.json +10 -2
- package/registry/blocks/graph-metric-tiles.json +1 -1
- package/registry/blocks/grid-tiles-list.json +10 -1
- package/registry/blocks/hero-dark-centered.json +9 -1
- package/registry/blocks/hero-dark-with-image.json +9 -1
- package/registry/blocks/hero-fullwidth-image.json +9 -1
- package/registry/blocks/hero-section.json +9 -1
- package/registry/blocks/how-it-works.json +9 -1
- package/registry/blocks/image-feed-with-nested-comments.json +10 -1
- package/registry/blocks/image-popup.json +10 -1
- package/registry/blocks/invoice-popup.json +10 -1
- package/registry/blocks/large-image-labels-list.json +10 -1
- package/registry/blocks/list-popup.json +28 -0
- package/registry/blocks/loader.json +9 -1
- package/registry/blocks/login-branding-panel.json +10 -2
- package/registry/blocks/menu-section.json +9 -1
- package/registry/blocks/menufocus-template.json +9 -1
- package/registry/blocks/messenger-sidebar.json +11 -2
- package/registry/blocks/metrics-section.json +10 -2
- package/registry/blocks/mobile-bottom-nav.json +10 -2
- package/registry/blocks/monthly-calendar-widget.json +9 -1
- package/registry/blocks/multistep-form-popup.json +34 -0
- package/registry/blocks/nested-comments-table.json +9 -1
- package/registry/blocks/nested-data-table.json +10 -1
- package/registry/blocks/nps-survey-popup.json +27 -0
- package/registry/blocks/office-locations.json +10 -2
- package/registry/blocks/order-summary-sidebar.json +27 -0
- package/registry/blocks/page-header-section.json +9 -1
- package/registry/blocks/pagination.json +8 -1
- package/registry/blocks/participant-list.json +9 -1
- package/registry/blocks/persona-card.json +10 -1
- package/registry/blocks/personalize-feed-popup.json +27 -0
- package/registry/blocks/pill-tabs.json +9 -1
- package/registry/blocks/place-detail-panel.json +11 -1
- package/registry/blocks/pricing-cards.json +10 -2
- package/registry/blocks/pricing-cta.json +9 -1
- package/registry/blocks/pricing-plans-popup.json +10 -1
- package/registry/blocks/profile-card.json +12 -2
- package/registry/blocks/profile-grid-tiles-list.json +10 -1
- package/registry/blocks/profile-image-uploader.json +9 -1
- package/registry/blocks/profile-info-cards.json +10 -1
- package/registry/blocks/progress-bar.json +8 -1
- package/registry/blocks/prompt-template.json +1 -1
- package/registry/blocks/purchase-confirmation-popup.json +10 -1
- package/registry/blocks/reservation-card.json +26 -0
- package/registry/blocks/reviews-grid.json +10 -2
- package/registry/blocks/reviews-table.json +10 -1
- package/registry/blocks/screen-prompt-template.json +1 -1
- package/registry/blocks/search-bar.json +9 -2
- package/registry/blocks/search-sidebar.json +9 -2
- package/registry/blocks/settings-list-row.json +9 -1
- package/registry/blocks/share-project-popup.json +36 -0
- package/registry/blocks/sidebar-cards.json +10 -2
- package/registry/blocks/sidebar-profile-card.json +10 -2
- package/registry/blocks/slideshow-grid-tiles.json +10 -2
- package/registry/blocks/slideshow-popup.json +10 -1
- package/registry/blocks/small-edit-popup.json +29 -0
- package/registry/blocks/social-feed.json +10 -1
- package/registry/blocks/social-proof.json +9 -1
- package/registry/blocks/standard-data-table.json +13 -1
- package/registry/blocks/standard-list-with-image.json +10 -1
- package/registry/blocks/step-tracker.json +9 -1
- package/registry/blocks/store-location-map.json +9 -1
- package/registry/blocks/team-cards-grid.json +9 -1
- package/registry/blocks/team-circular-grid.json +9 -1
- package/registry/blocks/terms-of-service-popup.json +10 -1
- package/registry/blocks/testimonial-carousel.json +10 -2
- package/registry/blocks/tile-image-gallery.json +26 -0
- package/registry/blocks/title-group.json +10 -1
- package/registry/blocks/upvoting-posts-table.json +10 -1
- package/registry/blocks/vertical-how-it-works.json +9 -1
- package/registry/blocks/vertical-step-tracker.json +9 -1
- package/registry/blocks/video-chat-controls.json +9 -1
- package/registry/blocks/video-content-section.json +9 -1
- package/registry/blocks/video-playlist.json +9 -1
- package/registry/blocks/video-popup.json +9 -1
- package/registry/blocks/view-profile-popup.json +10 -1
- package/registry/blocks/webcam-preview.json +9 -1
- package/registry/hooks/use-css-variable-sync.json +10 -1
- package/registry/hooks/use-mobile.json +9 -1
- package/registry/index.json +1526 -147
- package/registry/layout/account-settings-shell.json +10 -1
- package/registry/layout/dashboard-shell.json +12 -1
- package/registry/layout/double-sidebar-shell.json +11 -2
- package/registry/layout/double-sidebar.json +9 -1
- package/registry/layout/header.json +10 -1
- package/registry/layout/icon-sidebar-shell.json +9 -1
- package/registry/layout/icon-sidebar.json +9 -1
- package/registry/layout/mobile-menu-shell.json +10 -1
- package/registry/layout/multistep-progressbar-shell.json +9 -1
- package/registry/layout/multistep-shell.json +11 -1
- package/registry/layout/multistep-sidebar-shell.json +10 -2
- package/registry/layout/project-context-shell.json +1 -1
- package/registry/layout/search-bar-shell.json +8 -1
- package/registry/layout/sidebar-nav.json +7 -1
- package/registry/layout/sidebar.json +9 -2
- package/registry/layout/standard-page-shell.json +10 -1
- package/registry/layout/vertical-multistep-shell.json +10 -1
- package/registry/ui/avatar.json +9 -1
- package/registry/ui/button.json +9 -1
- package/registry/ui/calendar.json +9 -1
- package/registry/ui/checkbox.json +8 -1
- package/registry/ui/date-input.json +9 -1
- package/registry/ui/dialog.json +8 -1
- package/registry/ui/dropdown-menu.json +8 -1
- package/registry/ui/file-uploader.json +9 -1
- package/registry/ui/image-uploader.json +9 -1
- package/registry/ui/input.json +8 -1
- package/registry/ui/label.json +8 -1
- package/registry/ui/line-tabs.json +9 -1
- package/registry/ui/multiselect-checkbox-field.json +9 -1
- package/registry/ui/multiselect-tags.json +9 -1
- package/registry/ui/popover.json +8 -1
- package/registry/ui/radio-group.json +9 -1
- package/registry/ui/range-input.json +8 -1
- package/registry/ui/scroll-area.json +8 -1
- package/registry/ui/searchbox.json +9 -1
- package/registry/ui/select.json +9 -1
- package/registry/ui/selectable-pills.json +11 -1
- package/registry/ui/separator.json +8 -1
- package/registry/ui/sheet.json +9 -1
- package/registry/ui/sidebar.json +8 -1
- package/registry/ui/skeleton.json +8 -1
- package/registry/ui/slider.json +10 -2
- package/registry/ui/switch.json +9 -1
- package/registry/ui/tabs.json +8 -1
- package/registry/ui/text-input.json +8 -1
- package/registry/ui/textarea.json +9 -1
- package/registry/ui/tooltip.json +8 -1
- package/registry/ui/typography.json +9 -1
- package/styles/tokens.reference.css +21 -0
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "standard-data-table",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Tabular data display with sortable columns, avatar-enhanced rows, and row action menus. Header includes result count, sort/filter dropdowns, and primary action button. Full-width block (~400-800px depending on rows). Dense, text-heavy. Use for user directories, order lists, inventory tables, or any structured row-based data.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"table",
|
|
7
|
+
"data",
|
|
8
|
+
"rows",
|
|
9
|
+
"sortable",
|
|
10
|
+
"directory",
|
|
11
|
+
"list",
|
|
12
|
+
"inventory",
|
|
13
|
+
"orders",
|
|
14
|
+
"users"
|
|
15
|
+
],
|
|
16
|
+
"visualWeight": "heavy",
|
|
5
17
|
"files": [
|
|
6
18
|
{
|
|
7
19
|
"path": "components/blocks/standard-data-table.tsx",
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "standard-list-with-image",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Vertical list of content items with square image thumbnails, title, author, date, description text, and tags. Header with sort/filter controls. Use for blog posts, articles, courses, events, or any content listing with images.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"list",
|
|
7
|
+
"articles",
|
|
8
|
+
"blog",
|
|
9
|
+
"content",
|
|
10
|
+
"thumbnails",
|
|
11
|
+
"courses"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "heavy",
|
|
5
14
|
"files": [
|
|
6
15
|
{
|
|
7
16
|
"path": "components/blocks/standard-list-with-image.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "step-tracker",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Horizontal multi-step progress indicator with numbered circles
|
|
4
|
+
"description": "Horizontal multi-step progress indicator with numbered circles connected by lines. Completed steps show checkmarks, current step is highlighted. Use in multi-step forms, wizards, or onboarding flows.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"steps",
|
|
7
|
+
"wizard",
|
|
8
|
+
"progress",
|
|
9
|
+
"tracker",
|
|
10
|
+
"multistep"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "light",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/step-tracker.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "store-location-map",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Location card with address text, directions button, and embedded map iframe. Uses TitleGroup for header. Use for store locators, office locations, or any place-based information display.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"map",
|
|
7
|
+
"location",
|
|
8
|
+
"address",
|
|
9
|
+
"directions",
|
|
10
|
+
"store"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/store-location-map.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "team-cards-grid",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "4-column grid of team member cards with portrait photos, name, and role/title text. Photos have responsive height. Use for team pages, about pages, staff directories, or leadership sections.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"team",
|
|
7
|
+
"members",
|
|
8
|
+
"people",
|
|
9
|
+
"staff",
|
|
10
|
+
"leadership"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/marketing/team-cards-grid.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "team-circular-grid",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Grid of team members with circular avatar photos, name, and role text. More compact than TeamCardsGrid. Use for advisory boards, small teams, or avatar-focused people grids.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"team",
|
|
7
|
+
"members",
|
|
8
|
+
"avatars",
|
|
9
|
+
"people",
|
|
10
|
+
"compact"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/marketing/team-circular-grid.tsx",
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "terms-of-service-popup",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "",
|
|
4
|
+
"description": "Scrollable content viewer modal for terms/legal documents with styled scrollbar and confirm/decline action buttons. Centered dialog (~450px tall). Use for terms of service, privacy policies, legal agreements, or any long-form content that needs acceptance.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"terms",
|
|
7
|
+
"legal",
|
|
8
|
+
"modal",
|
|
9
|
+
"agreement",
|
|
10
|
+
"policy",
|
|
11
|
+
"tos"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "medium",
|
|
5
14
|
"files": [
|
|
6
15
|
{
|
|
7
16
|
"path": "components/blocks/terms-of-service-popup.tsx",
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "testimonial-carousel",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Dark testimonial carousel
|
|
4
|
+
"description": "Dark-background testimonial carousel showing one quote at a time with author name, role, avatar, and left/right navigation arrows. Use for customer testimonials, user quotes, or endorsement sections.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"testimonials",
|
|
7
|
+
"quotes",
|
|
8
|
+
"reviews",
|
|
9
|
+
"social-proof",
|
|
10
|
+
"carousel"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/marketing/testimonial-carousel.tsx",
|
|
8
16
|
"type": "registry:block",
|
|
9
|
-
"content": "\"use client\";\n\nimport { CaretLeft, CaretRight } from \"@phosphor-icons/react\";\nimport { useState } from \"react\";\nimport { Typography } from \"../../ui/typography\";\nimport { AVATAR_NICOLE_PALMER, AVATAR_ETHAN_BROOKS } from \"../demo-avatars\";\n\ninterface Testimonial {\n id: string;\n quote: string;\n highlightedWords?: string[];\n author: string;\n location: string;\n image: string;\n}\n\nconst defaultTestimonials: Testimonial[] = [\n {\n id: \"1\",\n quote: '\"Great prices on incredible places! Booking is easy, and I always find the perfect stay. Highly recommend!\"',\n highlightedWords: [\"Great prices\", \"easy\"],\n author: \"Nicole Palmer\",\n location: \"San Francisco, California\",\n image: AVATAR_NICOLE_PALMER,\n },\n {\n id: \"2\",\n quote: '\"The experience was seamless from start to finish. I found exactly what I was looking for within minutes!\"',\n highlightedWords: [\"seamless\", \"minutes\"],\n author: \"Ethan Brooks\",\n location: \"New York, NY\",\n image: AVATAR_ETHAN_BROOKS,\n },\n];\n\ninterface TestimonialCarouselProps {\n testimonials?: Testimonial[];\n}\n\nexport function TestimonialCarousel({ testimonials = defaultTestimonials }: TestimonialCarouselProps) {\n const [currentIndex, setCurrentIndex] = useState(0);\n const current = testimonials[currentIndex];\n\n const handlePrev = () => {\n setCurrentIndex((prev) => (prev === 0 ? testimonials.length - 1 : prev - 1));\n };\n\n const handleNext = () => {\n setCurrentIndex((prev) => (prev === testimonials.length - 1 ? 0 : prev + 1));\n };\n\n // Function to highlight specific words\n const renderQuote = (quote: string, highlights?: string[]) => {\n if (!highlights || highlights.length === 0) return quote;\n \n let result = quote;\n highlights.forEach((word) => {\n result = result.replace(\n new RegExp(`(${word})`, \"gi\"),\n `<span style=\"color: var(--canvas-
|
|
17
|
+
"content": "\"use client\";\n\nimport { CaretLeft, CaretRight } from \"@phosphor-icons/react\";\nimport { useState } from \"react\";\nimport { Typography } from \"../../ui/typography\";\nimport { AVATAR_NICOLE_PALMER, AVATAR_ETHAN_BROOKS } from \"../demo-avatars\";\n\ninterface Testimonial {\n id: string;\n quote: string;\n highlightedWords?: string[];\n author: string;\n location: string;\n image: string;\n}\n\nconst defaultTestimonials: Testimonial[] = [\n {\n id: \"1\",\n quote: '\"Great prices on incredible places! Booking is easy, and I always find the perfect stay. Highly recommend!\"',\n highlightedWords: [\"Great prices\", \"easy\"],\n author: \"Nicole Palmer\",\n location: \"San Francisco, California\",\n image: AVATAR_NICOLE_PALMER,\n },\n {\n id: \"2\",\n quote: '\"The experience was seamless from start to finish. I found exactly what I was looking for within minutes!\"',\n highlightedWords: [\"seamless\", \"minutes\"],\n author: \"Ethan Brooks\",\n location: \"New York, NY\",\n image: AVATAR_ETHAN_BROOKS,\n },\n];\n\ninterface TestimonialCarouselProps {\n testimonials?: Testimonial[];\n /** Color variant: \"dark\" uses neutral dark section bg, \"primary\" uses primary-dark brand color */\n variant?: \"dark\" | \"primary\";\n}\n\nexport function TestimonialCarousel({ testimonials = defaultTestimonials, variant = \"dark\" }: TestimonialCarouselProps) {\n const isPrimary = variant === \"primary\";\n const [currentIndex, setCurrentIndex] = useState(0);\n const current = testimonials[currentIndex];\n\n const handlePrev = () => {\n setCurrentIndex((prev) => (prev === 0 ? testimonials.length - 1 : prev - 1));\n };\n\n const handleNext = () => {\n setCurrentIndex((prev) => (prev === testimonials.length - 1 ? 0 : prev + 1));\n };\n\n // Function to highlight specific words\n const renderQuote = (quote: string, highlights?: string[]) => {\n if (!highlights || highlights.length === 0) return quote;\n \n let result = quote;\n highlights.forEach((word) => {\n result = result.replace(\n new RegExp(`(${word})`, \"gi\"),\n `<span style=\"color: var(--canvas-primary);\">$1</span>`\n );\n });\n return <span dangerouslySetInnerHTML={{ __html: result }} />;\n };\n\n return (\n <section \n className=\"w-full px-4 md:px-8 lg:px-10 py-10 md:py-16\"\n style={{\n backgroundColor: isPrimary ? \"var(--canvas-flair-bg)\" : \"var(--canvas-dark-section-bg)\",\n }}\n >\n <div \n className=\"w-full max-w-[1200px] mx-auto flex flex-col lg:flex-row items-center\"\n style={{ gap: \"var(--spacing-6xl)\" }}\n >\n {/* Content */}\n <div className=\"flex-1 flex flex-col\" style={{ gap: \"var(--spacing-3xl)\" }}>\n <Typography variant=\"h3\" as=\"p\" style={{ color: \"white\" }}>\n {renderQuote(current.quote, current.highlightedWords)}\n </Typography>\n \n <div className=\"flex flex-col\" style={{ gap: \"var(--spacing-2xl)\" }}>\n <div>\n <Typography variant=\"body-l\" style={{ color: \"white\" }}>\n {current.author}\n </Typography>\n <Typography variant=\"body-l\" style={{ color: \"rgba(255, 255, 255, 0.7)\" }}>\n {current.location}\n </Typography>\n </div>\n \n {/* Navigation */}\n <div className=\"flex gap-5\">\n <button\n onClick={handlePrev}\n className=\"flex items-center justify-center hover:opacity-80 transition-opacity\"\n style={{\n width: \"48px\",\n height: \"48px\",\n backgroundColor: isPrimary ? \"color-mix(in srgb, var(--canvas-flair-bg) 70%, white)\" : \"var(--canvas-border)\",\n borderRadius: \"var(--spacing-md)\",\n }}\n >\n <CaretLeft size={32} style={{ color: isPrimary ? \"white\" : \"var(--canvas-text)\" }} weight=\"bold\" />\n </button>\n <button\n onClick={handleNext}\n className=\"flex items-center justify-center hover:opacity-80 transition-opacity\"\n style={{\n width: \"48px\",\n height: \"48px\",\n backgroundColor: isPrimary ? \"color-mix(in srgb, var(--canvas-flair-bg) 70%, white)\" : \"var(--canvas-border)\",\n borderRadius: \"var(--spacing-md)\",\n }}\n >\n <CaretRight size={32} style={{ color: isPrimary ? \"white\" : \"var(--canvas-text)\" }} weight=\"bold\" />\n </button>\n </div>\n </div>\n </div>\n \n {/* Image */}\n <div \n className=\"shrink-0 overflow-hidden hidden lg:block\"\n style={{\n width: \"320px\",\n height: \"400px\",\n borderRadius: \"var(--spacing-lg)\",\n }}\n >\n <img \n src={current.image} \n alt={current.author}\n className=\"w-full h-full object-cover\"\n />\n </div>\n </div>\n </section>\n );\n}\n"
|
|
10
18
|
}
|
|
11
19
|
],
|
|
12
20
|
"dependencies": [
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tile-image-gallery",
|
|
3
|
+
"type": "registry:block",
|
|
4
|
+
"description": "Hero image gallery with one large image on the left and a 2x2 grid of thumbnails on the right, plus a 'View all' button overlay. Full-width block (~400px tall). Use at the top of product detail pages, listing pages, or property pages for immersive visual browsing.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"gallery",
|
|
7
|
+
"images",
|
|
8
|
+
"photos",
|
|
9
|
+
"tiles",
|
|
10
|
+
"product",
|
|
11
|
+
"listing"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "spacer",
|
|
14
|
+
"files": [
|
|
15
|
+
{
|
|
16
|
+
"path": "components/blocks/tile-image-gallery.tsx",
|
|
17
|
+
"type": "registry:block",
|
|
18
|
+
"content": "\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface TileGalleryImage {\n /** Unique identifier */\n id: string;\n /** Image source URL */\n src: string;\n /** Alt text for the image */\n alt?: string;\n}\n\nexport interface TileImageGalleryProps {\n /** Array of images (first image is the large hero, next 4 fill the grid) */\n images?: TileGalleryImage[];\n /** Callback when \"View all\" button is clicked */\n onViewAll?: () => void;\n /** Label for the \"View all\" button */\n viewAllLabel?: string;\n /** Gallery height */\n height?: string;\n /** Additional class names */\n className?: string;\n}\n\n// ============================================================================\n// Default Data\n// ============================================================================\n\nconst DEFAULT_IMAGES: TileGalleryImage[] = [\n { id: \"1\", src: \"https://images.unsplash.com/photo-1590490360182-c33d955c4644?w=800&h=600&fit=crop\", alt: \"Hotel room\" },\n { id: \"2\", src: \"https://images.unsplash.com/photo-1566073771259-6a8506099945?w=400&h=300&fit=crop\", alt: \"Hotel exterior\" },\n { id: \"3\", src: \"https://images.unsplash.com/photo-1582719478250-c89cae4dc85b?w=400&h=300&fit=crop\", alt: \"Hotel lobby\" },\n { id: \"4\", src: \"https://images.unsplash.com/photo-1584132967334-10e028bd69f7?w=400&h=300&fit=crop\", alt: \"Hotel pool\" },\n { id: \"5\", src: \"https://images.unsplash.com/photo-1571896349842-33c89424de2d?w=400&h=300&fit=crop\", alt: \"Hotel view\" },\n];\n\n// ============================================================================\n// TileImageGallery\n// ============================================================================\n\n/**\n * Canvas Design System - Tile Image Gallery\n *\n * A hero image gallery with one large image on the left and four smaller\n * images in a 2x2 grid on the right, plus a \"View all\" button overlay.\n * On mobile, only the main image is shown.\n */\nexport function TileImageGallery({\n images = DEFAULT_IMAGES,\n onViewAll,\n viewAllLabel = \"View all\",\n height = \"360px\",\n className,\n}: TileImageGalleryProps) {\n const [main, ...rest] = images;\n const gridImages = rest.slice(0, 4);\n\n return (\n <div\n className={cn(\"relative w-full overflow-hidden\", className)}\n style={{ height }}\n >\n <div className=\"flex h-full\">\n {/* Main large image */}\n {main && (\n <div\n className=\"relative h-full shrink-0 w-full md:w-[57%]\"\n style={{\n borderRight: \"1px solid var(--canvas-background)\",\n }}\n >\n <img\n src={main.src}\n alt={main.alt ?? \"\"}\n className=\"absolute inset-0 w-full h-full object-cover\"\n />\n </div>\n )}\n\n {/* 2x2 thumbnail grid (hidden on mobile) */}\n <div className=\"hidden md:flex flex-1 flex-col min-w-0\">\n {/* Top row */}\n <div className=\"flex flex-1 min-h-0\">\n {gridImages[0] && (\n <div\n className=\"relative flex-1 min-w-0\"\n style={{\n borderRight: \"1px solid var(--canvas-background)\",\n borderBottom: \"1px solid var(--canvas-background)\",\n }}\n >\n <img\n src={gridImages[0].src}\n alt={gridImages[0].alt ?? \"\"}\n className=\"absolute inset-0 w-full h-full object-cover\"\n />\n </div>\n )}\n {gridImages[1] && (\n <div className=\"relative flex-1 min-w-0\">\n <img\n src={gridImages[1].src}\n alt={gridImages[1].alt ?? \"\"}\n className=\"absolute inset-0 w-full h-full object-cover\"\n />\n </div>\n )}\n </div>\n {/* Bottom row */}\n <div className=\"flex flex-1 min-h-0\">\n {gridImages[2] && (\n <div className=\"relative flex-1 min-w-0\">\n <img\n src={gridImages[2].src}\n alt={gridImages[2].alt ?? \"\"}\n className=\"absolute inset-0 w-full h-full object-cover\"\n />\n </div>\n )}\n {gridImages[3] && (\n <div\n className=\"relative flex-1 min-w-0\"\n style={{\n borderLeft: \"1px solid var(--canvas-background)\",\n borderTop: \"1px solid var(--canvas-background)\",\n }}\n >\n <img\n src={gridImages[3].src}\n alt={gridImages[3].alt ?? \"\"}\n className=\"absolute inset-0 w-full h-full object-cover\"\n />\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* View all button */}\n <div\n className=\"absolute\"\n style={{\n right: \"var(--spacing-xl)\",\n bottom: \"var(--spacing-xl)\",\n }}\n >\n <Button variant=\"neutral\" size=\"default\" onClick={onViewAll}>\n {viewAllLabel}\n </Button>\n </div>\n </div>\n );\n}\n"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"dependencies": [],
|
|
22
|
+
"registryDependencies": [
|
|
23
|
+
"lib/utils",
|
|
24
|
+
"ui/button"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "title-group",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "",
|
|
4
|
+
"description": "Header section with title, subtitle, optional sort dropdown, filter popover, and action button. Compact (~48px tall). Use as the header for any content block — pairs with data tables, lists, card grids, or any section that needs a scannable title landmark.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"title",
|
|
7
|
+
"header",
|
|
8
|
+
"section",
|
|
9
|
+
"sort",
|
|
10
|
+
"filter",
|
|
11
|
+
"action"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "light",
|
|
5
14
|
"files": [
|
|
6
15
|
{
|
|
7
16
|
"path": "components/blocks/title-group.tsx",
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "upvoting-posts-table",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Social feed with
|
|
4
|
+
"description": "Social feed with upvotable posts, comment threads, and nested replies. Each post has an upvote button with count, title, description, and author info. Use for feature request boards, community forums, Q&A sites, or feedback portals.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"forum",
|
|
7
|
+
"upvote",
|
|
8
|
+
"posts",
|
|
9
|
+
"community",
|
|
10
|
+
"feedback",
|
|
11
|
+
"feature-requests"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "heavy",
|
|
5
14
|
"files": [
|
|
6
15
|
{
|
|
7
16
|
"path": "components/blocks/upvoting-posts-table.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vertical-how-it-works",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Vertical
|
|
4
|
+
"description": "Vertical numbered list of steps with large step numbers, titles, and descriptions. Header with title and description. Light and dark variants. Use for process explanations, getting started guides, or numbered feature lists.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"steps",
|
|
7
|
+
"process",
|
|
8
|
+
"numbered",
|
|
9
|
+
"how-it-works",
|
|
10
|
+
"guide"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/marketing/vertical-how-it-works.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vertical-step-tracker",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Vertical step tracker for sidebar placement in multi-step flows.",
|
|
4
|
+
"description": "Vertical step tracker for sidebar placement in multi-step flows. Steps shown as a vertical list with numbers, titles, and optional descriptions. Use when horizontal space is limited.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"steps",
|
|
7
|
+
"wizard",
|
|
8
|
+
"progress",
|
|
9
|
+
"tracker",
|
|
10
|
+
"vertical"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "light",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/vertical-step-tracker.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "video-chat-controls",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Row of circular buttons for video calls: camera,
|
|
4
|
+
"description": "Row of circular toggle buttons for video/audio calls: camera on/off, microphone on/off, screen cast, and leave/end call. Use at the bottom of any video conferencing or audio call interface.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"video",
|
|
7
|
+
"call",
|
|
8
|
+
"controls",
|
|
9
|
+
"camera",
|
|
10
|
+
"microphone"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "light",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/video-chat-controls.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "video-content-section",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Video player area with metadata and
|
|
4
|
+
"description": "Video player area with title, metadata (views, date, channel), description text, and social actions. Use for video detail pages, course lessons, or media content pages.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"video",
|
|
7
|
+
"player",
|
|
8
|
+
"content",
|
|
9
|
+
"media",
|
|
10
|
+
"description"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "heavy",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/video-content-section.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "video-playlist",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "Sidebar playlist
|
|
4
|
+
"description": "Sidebar playlist of video items with thumbnails, titles, and duration. Current video highlighted. Use for course lessons, tutorial series, or any sequential video content.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"playlist",
|
|
7
|
+
"videos",
|
|
8
|
+
"lessons",
|
|
9
|
+
"course",
|
|
10
|
+
"tutorial"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/video-playlist.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "video-popup",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "",
|
|
4
|
+
"description": "YouTube video player modal displaying full-width video. Centered dialog. Use for video previews, tutorial popups, or any embedded video in a modal context.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"video",
|
|
7
|
+
"youtube",
|
|
8
|
+
"modal",
|
|
9
|
+
"player",
|
|
10
|
+
"tutorial"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/video-popup.tsx",
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "view-profile-popup",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "",
|
|
4
|
+
"description": "Profile card modal with gradient banner, overlapping avatar, star rating, flexible detail rows (text/tags/icons), message/more-options buttons, and optional profile link. Centered dialog (~400px tall). Use for user profile previews, contact cards, or member detail popups.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"profile",
|
|
7
|
+
"modal",
|
|
8
|
+
"user",
|
|
9
|
+
"avatar",
|
|
10
|
+
"rating",
|
|
11
|
+
"contact"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "medium",
|
|
5
14
|
"files": [
|
|
6
15
|
{
|
|
7
16
|
"path": "components/blocks/view-profile-popup.tsx",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcam-preview",
|
|
3
3
|
"type": "registry:block",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Video preview component showing a webcam or video feed with optional overlay controls. Use for video call self-view, camera preview, or live streaming interfaces.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"video",
|
|
7
|
+
"webcam",
|
|
8
|
+
"camera",
|
|
9
|
+
"preview",
|
|
10
|
+
"stream"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "medium",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "components/blocks/webcam-preview.tsx",
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-css-variable-sync",
|
|
3
3
|
"type": "registry:hook",
|
|
4
|
-
"description": "",
|
|
4
|
+
"description": "React hook that synchronizes CSS custom properties (design tokens) with a JavaScript theme object. Applies theme overrides by setting CSS variables on a target element. Use for runtime theme switching or dynamic theming.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"hook",
|
|
7
|
+
"css",
|
|
8
|
+
"variables",
|
|
9
|
+
"theme",
|
|
10
|
+
"sync",
|
|
11
|
+
"tokens"
|
|
12
|
+
],
|
|
13
|
+
"visualWeight": "light",
|
|
5
14
|
"files": [
|
|
6
15
|
{
|
|
7
16
|
"path": "hooks/use-css-variable-sync.ts",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "use-mobile",
|
|
3
3
|
"type": "registry:hook",
|
|
4
|
-
"description": "",
|
|
4
|
+
"description": "React hook that returns a boolean indicating if the viewport is mobile-sized (below 768px). Updates on window resize. Use for responsive behavior in components.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"hook",
|
|
7
|
+
"mobile",
|
|
8
|
+
"responsive",
|
|
9
|
+
"breakpoint",
|
|
10
|
+
"viewport"
|
|
11
|
+
],
|
|
12
|
+
"visualWeight": "light",
|
|
5
13
|
"files": [
|
|
6
14
|
{
|
|
7
15
|
"path": "hooks/use-mobile.ts",
|