@open-mercato/core 0.7.1-develop.7202.1.a52dc6707c → 0.8.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/.turbo/turbo-build.log +1 -1
- package/build.mjs +11 -0
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js +23 -0
- package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js +2 -2
- package/dist/modules/customers/backend/customers/people/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +2 -1
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/lib/detailHelpers.js +4 -0
- package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
- package/dist/modules/customers/lib/todoCompatibility.js +5 -0
- package/dist/modules/customers/lib/todoCompatibility.js.map +2 -2
- package/dist/modules/design_system/backend/design-system/page.meta.js +3 -2
- package/dist/modules/design_system/backend/design-system/page.meta.js.map +2 -2
- package/dist/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
- package/dist/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
- package/dist/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
- package/dist/modules/design_system/gallery/assets/avatar-photo.png +0 -0
- package/dist/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
- package/dist/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-ada.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-avax.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-brand.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-btc.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-dot.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-eth.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-history.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-link.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-more.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-sol.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-star.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
- package/dist/modules/design_system/gallery/assets/crypto-trx.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-wei.png +0 -0
- package/dist/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
- package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js +67 -0
- package/dist/modules/design_system/gallery/assets/cryptocurrency-artwork.js.map +7 -0
- package/dist/modules/design_system/gallery/assets/github-logo.png +0 -0
- package/dist/modules/design_system/gallery/assets/images.d.js +1 -0
- package/dist/modules/design_system/gallery/assets/images.d.js.map +7 -0
- package/dist/modules/design_system/gallery/assets/input-european-union.svg +18 -0
- package/dist/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
- package/dist/modules/design_system/gallery/assets/marketing-artwork.js +83 -0
- package/dist/modules/design_system/gallery/assets/marketing-artwork.js.map +7 -0
- package/dist/modules/design_system/gallery/assets/menu-apex.svg +18 -0
- package/dist/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
- package/dist/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
- package/dist/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
- package/dist/modules/design_system/gallery/assets/select-google.png +0 -0
- package/dist/modules/design_system/gallery/assets/select-poland.png +0 -0
- package/dist/modules/design_system/gallery/assets/selection-artwork.js +5 -0
- package/dist/modules/design_system/gallery/assets/selection-artwork.js.map +7 -0
- package/dist/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
- package/dist/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
- package/dist/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
- package/dist/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
- package/dist/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
- package/dist/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
- package/dist/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
- package/dist/modules/design_system/gallery/assets/style-studio-product.png +0 -0
- package/dist/modules/design_system/gallery/assets/upload-images.js +8 -0
- package/dist/modules/design_system/gallery/assets/upload-images.js.map +7 -0
- package/dist/modules/design_system/gallery/components/BrandStylePreview.js +74 -0
- package/dist/modules/design_system/gallery/components/BrandStylePreview.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CodeSnippet.js +31 -31
- package/dist/modules/design_system/gallery/components/CodeSnippet.js.map +2 -2
- package/dist/modules/design_system/gallery/components/ColorPlayground.js +408 -0
- package/dist/modules/design_system/gallery/components/ColorPlayground.js.map +7 -0
- package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js +166 -0
- package/dist/modules/design_system/gallery/components/ColorStudioCompositions.js.map +7 -0
- package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js +182 -0
- package/dist/modules/design_system/gallery/components/ColorStudioSpecimen.js.map +7 -0
- package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js +80 -0
- package/dist/modules/design_system/gallery/components/CompactEntrySpecimen.js.map +7 -0
- package/dist/modules/design_system/gallery/components/ComponentIndex.js +42 -0
- package/dist/modules/design_system/gallery/components/ComponentIndex.js.map +7 -0
- package/dist/modules/design_system/gallery/components/DesignSystemHome.js +69 -0
- package/dist/modules/design_system/gallery/components/DesignSystemHome.js.map +7 -0
- package/dist/modules/design_system/gallery/components/EntryCard.js +47 -41
- package/dist/modules/design_system/gallery/components/EntryCard.js.map +2 -2
- package/dist/modules/design_system/gallery/components/EntryHeader.js +68 -0
- package/dist/modules/design_system/gallery/components/EntryHeader.js.map +7 -0
- package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js +19 -0
- package/dist/modules/design_system/gallery/components/FamilyEntryPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/components/FoundationGuide.js +46 -0
- package/dist/modules/design_system/gallery/components/FoundationGuide.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryLink.js +21 -0
- package/dist/modules/design_system/gallery/components/GalleryLink.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryNavigation.js +82 -0
- package/dist/modules/design_system/gallery/components/GalleryNavigation.js.map +7 -0
- package/dist/modules/design_system/gallery/components/GalleryShell.js +147 -67
- package/dist/modules/design_system/gallery/components/GalleryShell.js.map +3 -3
- package/dist/modules/design_system/gallery/components/IconsBrowser.js +33 -0
- package/dist/modules/design_system/gallery/components/IconsBrowser.js.map +7 -0
- package/dist/modules/design_system/gallery/components/SourceLibrary.js +93 -0
- package/dist/modules/design_system/gallery/components/SourceLibrary.js.map +7 -0
- package/dist/modules/design_system/gallery/components/StyleAgents.js +139 -0
- package/dist/modules/design_system/gallery/components/StyleAgents.js.map +7 -0
- package/dist/modules/design_system/gallery/components/ThemeTokenReference.js +101 -0
- package/dist/modules/design_system/gallery/components/ThemeTokenReference.js.map +7 -0
- package/dist/modules/design_system/gallery/components/VariantPreview.js +2 -2
- package/dist/modules/design_system/gallery/components/VariantPreview.js.map +2 -2
- package/dist/modules/design_system/gallery/components/colorPreview.js +58 -0
- package/dist/modules/design_system/gallery/components/colorPreview.js.map +7 -0
- package/dist/modules/design_system/gallery/components/colorStudio.js +218 -0
- package/dist/modules/design_system/gallery/components/colorStudio.js.map +7 -0
- package/dist/modules/design_system/gallery/components/styleAgentBranding.js +46 -0
- package/dist/modules/design_system/gallery/components/styleAgentBranding.js.map +7 -0
- package/dist/modules/design_system/gallery/components/themeTokens.js +32 -0
- package/dist/modules/design_system/gallery/components/themeTokens.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js +194 -0
- package/dist/modules/design_system/gallery/demos/ai-product-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/ai-product.js +423 -0
- package/dist/modules/design_system/gallery/demos/ai-product.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/buttons.js +289 -0
- package/dist/modules/design_system/gallery/demos/buttons.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/cryptocurrency.js +1708 -0
- package/dist/modules/design_system/gallery/demos/cryptocurrency.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/feeds-code.generated.js +92 -0
- package/dist/modules/design_system/gallery/demos/feeds-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/feeds.js +148 -0
- package/dist/modules/design_system/gallery/demos/feeds.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/file-upload.js +72 -0
- package/dist/modules/design_system/gallery/demos/file-upload.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/foundation-reference-data.js +4875 -0
- package/dist/modules/design_system/gallery/demos/foundation-reference-data.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/foundation-references.js +188 -0
- package/dist/modules/design_system/gallery/demos/foundation-references.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/key-components-code.generated.js +6 -0
- package/dist/modules/design_system/gallery/demos/key-components-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/key-components.js +127 -0
- package/dist/modules/design_system/gallery/demos/key-components.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js +98 -0
- package/dist/modules/design_system/gallery/demos/marketing-controls-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/marketing-controls.js +134 -0
- package/dist/modules/design_system/gallery/demos/marketing-controls.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js +195 -0
- package/dist/modules/design_system/gallery/demos/marketing-widgets-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/marketing-widgets.js +586 -0
- package/dist/modules/design_system/gallery/demos/marketing-widgets.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/menu-fixtures.js +40 -0
- package/dist/modules/design_system/gallery/demos/menu-fixtures.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/menu-sources.js +295 -0
- package/dist/modules/design_system/gallery/demos/menu-sources.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/menus.js +150 -0
- package/dist/modules/design_system/gallery/demos/menus.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/rating-reviews.js +53 -0
- package/dist/modules/design_system/gallery/demos/rating-reviews.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/registered-icons.js +104 -0
- package/dist/modules/design_system/gallery/demos/registered-icons.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/selection-cards.js +99 -0
- package/dist/modules/design_system/gallery/demos/selection-cards.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/shell-code.generated.js +189 -0
- package/dist/modules/design_system/gallery/demos/shell-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/shell.js +330 -0
- package/dist/modules/design_system/gallery/demos/shell.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/source-artwork.js +120 -0
- package/dist/modules/design_system/gallery/demos/source-artwork.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js +125 -0
- package/dist/modules/design_system/gallery/demos/source-filters-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/source-filters.js +185 -0
- package/dist/modules/design_system/gallery/demos/source-filters.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/source-icons.js +69 -0
- package/dist/modules/design_system/gallery/demos/source-icons.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js +150 -0
- package/dist/modules/design_system/gallery/demos/table-cells-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/table-cells.js +181 -0
- package/dist/modules/design_system/gallery/demos/table-cells.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/text-inputs.js +113 -0
- package/dist/modules/design_system/gallery/demos/text-inputs.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js +41 -0
- package/dist/modules/design_system/gallery/demos/time-picker-code.generated.js.map +7 -0
- package/dist/modules/design_system/gallery/demos/time-picker.js +41 -0
- package/dist/modules/design_system/gallery/demos/time-picker.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/banners.js +123 -60
- package/dist/modules/design_system/gallery/entries/banners.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/buttons-snippets.js +433 -0
- package/dist/modules/design_system/gallery/entries/buttons-snippets.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/buttons.js +127 -148
- package/dist/modules/design_system/gallery/entries/buttons.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/charts.js +532 -186
- package/dist/modules/design_system/gallery/entries/charts.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/dates.js +191 -3
- package/dist/modules/design_system/gallery/entries/dates.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/detail.js +118 -77
- package/dist/modules/design_system/gallery/entries/detail.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/display.js +1449 -240
- package/dist/modules/design_system/gallery/entries/display.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/feedback.js +1058 -132
- package/dist/modules/design_system/gallery/entries/feedback.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/filters.js +231 -103
- package/dist/modules/design_system/gallery/entries/filters.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/foundations.js +368 -57
- package/dist/modules/design_system/gallery/entries/foundations.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/icons.js +29 -91
- package/dist/modules/design_system/gallery/entries/icons.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/inputs-snippets.js +154 -0
- package/dist/modules/design_system/gallery/entries/inputs-snippets.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/inputs.js +2043 -306
- package/dist/modules/design_system/gallery/entries/inputs.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/library.js +20 -0
- package/dist/modules/design_system/gallery/entries/library.js.map +7 -0
- package/dist/modules/design_system/gallery/entries/messages.js +121 -103
- package/dist/modules/design_system/gallery/entries/messages.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/navigation.js +676 -103
- package/dist/modules/design_system/gallery/entries/navigation.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/notifications.js +131 -78
- package/dist/modules/design_system/gallery/entries/notifications.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/overlays.js +611 -203
- package/dist/modules/design_system/gallery/entries/overlays.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/scaffolding.js +1175 -120
- package/dist/modules/design_system/gallery/entries/scaffolding.js.map +2 -2
- package/dist/modules/design_system/gallery/entries/schedule.js +79 -54
- package/dist/modules/design_system/gallery/entries/schedule.js.map +2 -2
- package/dist/modules/design_system/gallery/presentation.js +108 -0
- package/dist/modules/design_system/gallery/presentation.js.map +7 -0
- package/dist/modules/design_system/gallery/registry.js +8 -5
- package/dist/modules/design_system/gallery/registry.js.map +2 -2
- package/dist/modules/design_system/gallery/source-library.generated.js +5 -0
- package/dist/modules/design_system/gallery/source-library.generated.js.map +7 -0
- package/dist/modules/design_system/i18n/de.json +7167 -0
- package/dist/modules/design_system/i18n/en.json +7167 -0
- package/dist/modules/design_system/i18n/es.json +7167 -0
- package/dist/modules/design_system/i18n/ko.json +7167 -0
- package/dist/modules/design_system/i18n/pl.json +7167 -0
- package/dist/modules/push_notifications/lib/queue.js +1 -31
- package/dist/modules/push_notifications/lib/queue.js.map +2 -2
- package/jest.config.cjs +1 -0
- package/jest.mocks/image.js +1 -0
- package/package.json +8 -9
- package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +50 -0
- package/src/modules/customers/backend/customers/companies/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +2 -1
- package/src/modules/customers/backend/customers/people/[id]/page.tsx +2 -2
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +2 -1
- package/src/modules/customers/lib/detailHelpers.ts +4 -0
- package/src/modules/customers/lib/todoCompatibility.ts +10 -0
- package/src/modules/design_system/backend/design-system/page.meta.ts +3 -2
- package/src/modules/design_system/gallery/assets/README.md +30 -0
- package/src/modules/design_system/gallery/assets/ai-prompt-image.png +0 -0
- package/src/modules/design_system/gallery/assets/avatar-illustration.png +0 -0
- package/src/modules/design_system/gallery/assets/avatar-memoji.png +0 -0
- package/src/modules/design_system/gallery/assets/avatar-photo.png +0 -0
- package/src/modules/design_system/gallery/assets/blog-photo-0.png +0 -0
- package/src/modules/design_system/gallery/assets/contact-support-portrait.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-ada.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-avax.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-bnb.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-brand.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-btc.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-clock.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-crown.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-dot.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-eth.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-hbar.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-history.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-link.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-menu.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-metamask.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-more.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-phantom.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-rewards.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-sad-face.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-sol.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-star.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-status-cancelled.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-status-pending.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-status-success.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-status-warning.svg +3 -0
- package/src/modules/design_system/gallery/assets/crypto-trx.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-usdc.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-usdt.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-walletconnect.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-wei.png +0 -0
- package/src/modules/design_system/gallery/assets/crypto-xrp.png +0 -0
- package/src/modules/design_system/gallery/assets/cryptocurrency-artwork.ts +63 -0
- package/src/modules/design_system/gallery/assets/github-logo.png +0 -0
- package/src/modules/design_system/gallery/assets/images.d.ts +9 -0
- package/src/modules/design_system/gallery/assets/input-european-union.svg +18 -0
- package/src/modules/design_system/gallery/assets/landing-teams-01.png +0 -0
- package/src/modules/design_system/gallery/assets/marketing-artwork.ts +79 -0
- package/src/modules/design_system/gallery/assets/menu-apex.svg +18 -0
- package/src/modules/design_system/gallery/assets/menu-mastercard.svg +7 -0
- package/src/modules/design_system/gallery/assets/menu-spotify.svg +4 -0
- package/src/modules/design_system/gallery/assets/menu-united-states.svg +16 -0
- package/src/modules/design_system/gallery/assets/select-google.png +0 -0
- package/src/modules/design_system/gallery/assets/select-poland.png +0 -0
- package/src/modules/design_system/gallery/assets/selection-artwork.ts +1 -0
- package/src/modules/design_system/gallery/assets/social-apple-filled.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-apple-stroke.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-dropbox-filled.svg +5 -0
- package/src/modules/design_system/gallery/assets/social-dropbox-stroke.svg +5 -0
- package/src/modules/design_system/gallery/assets/social-facebook-filled.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-facebook-stroke.svg +10 -0
- package/src/modules/design_system/gallery/assets/social-github-filled.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-github-stroke.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-google-filled.svg +7 -0
- package/src/modules/design_system/gallery/assets/social-google-stroke.svg +7 -0
- package/src/modules/design_system/gallery/assets/social-linkedin-filled.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-linkedin-stroke.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-x-filled.svg +4 -0
- package/src/modules/design_system/gallery/assets/social-x-stroke.svg +4 -0
- package/src/modules/design_system/gallery/assets/style-studio-product.png +0 -0
- package/src/modules/design_system/gallery/assets/upload-images.ts +5 -0
- package/src/modules/design_system/gallery/components/BrandStylePreview.tsx +94 -0
- package/src/modules/design_system/gallery/components/CodeSnippet.tsx +34 -34
- package/src/modules/design_system/gallery/components/ColorPlayground.tsx +324 -0
- package/src/modules/design_system/gallery/components/ColorStudioCompositions.tsx +96 -0
- package/src/modules/design_system/gallery/components/ColorStudioSpecimen.tsx +164 -0
- package/src/modules/design_system/gallery/components/CompactEntrySpecimen.tsx +65 -0
- package/src/modules/design_system/gallery/components/ComponentIndex.tsx +47 -0
- package/src/modules/design_system/gallery/components/DesignSystemHome.tsx +66 -0
- package/src/modules/design_system/gallery/components/EntryCard.tsx +52 -37
- package/src/modules/design_system/gallery/components/EntryHeader.tsx +80 -0
- package/src/modules/design_system/gallery/components/FamilyEntryPreview.tsx +22 -0
- package/src/modules/design_system/gallery/components/FoundationGuide.tsx +43 -0
- package/src/modules/design_system/gallery/components/GalleryLink.tsx +19 -0
- package/src/modules/design_system/gallery/components/GalleryNavigation.tsx +86 -0
- package/src/modules/design_system/gallery/components/GalleryShell.tsx +149 -63
- package/src/modules/design_system/gallery/components/IconsBrowser.tsx +40 -0
- package/src/modules/design_system/gallery/components/SourceLibrary.tsx +90 -0
- package/src/modules/design_system/gallery/components/StyleAgents.tsx +115 -0
- package/src/modules/design_system/gallery/components/ThemeTokenReference.tsx +76 -0
- package/src/modules/design_system/gallery/components/VariantPreview.tsx +2 -2
- package/src/modules/design_system/gallery/components/colorPreview.ts +63 -0
- package/src/modules/design_system/gallery/components/colorStudio.ts +260 -0
- package/src/modules/design_system/gallery/components/styleAgentBranding.ts +42 -0
- package/src/modules/design_system/gallery/components/themeTokens.ts +26 -0
- package/src/modules/design_system/gallery/demos/ai-product-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/ai-product.tsx +188 -0
- package/src/modules/design_system/gallery/demos/buttons.tsx +331 -0
- package/src/modules/design_system/gallery/demos/cryptocurrency.tsx +1943 -0
- package/src/modules/design_system/gallery/demos/feeds-code.generated.ts +4 -0
- package/src/modules/design_system/gallery/demos/feeds.tsx +82 -0
- package/src/modules/design_system/gallery/demos/file-upload.tsx +61 -0
- package/src/modules/design_system/gallery/demos/foundation-reference-data.ts +4872 -0
- package/src/modules/design_system/gallery/demos/foundation-references.tsx +140 -0
- package/src/modules/design_system/gallery/demos/key-components-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/key-components.tsx +106 -0
- package/src/modules/design_system/gallery/demos/marketing-controls-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/marketing-controls.tsx +92 -0
- package/src/modules/design_system/gallery/demos/marketing-widgets-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/marketing-widgets.tsx +189 -0
- package/src/modules/design_system/gallery/demos/menu-fixtures.tsx +48 -0
- package/src/modules/design_system/gallery/demos/menu-sources.ts +5 -0
- package/src/modules/design_system/gallery/demos/menus.tsx +122 -0
- package/src/modules/design_system/gallery/demos/rating-reviews.tsx +44 -0
- package/src/modules/design_system/gallery/demos/registered-icons.tsx +117 -0
- package/src/modules/design_system/gallery/demos/selection-cards.tsx +97 -0
- package/src/modules/design_system/gallery/demos/shell-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/shell.tsx +183 -0
- package/src/modules/design_system/gallery/demos/source-artwork.tsx +88 -0
- package/src/modules/design_system/gallery/demos/source-filters-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/source-filters.tsx +119 -0
- package/src/modules/design_system/gallery/demos/source-icons.tsx +62 -0
- package/src/modules/design_system/gallery/demos/table-cells-code.generated.ts +3 -0
- package/src/modules/design_system/gallery/demos/table-cells.tsx +144 -0
- package/src/modules/design_system/gallery/demos/text-inputs.tsx +90 -0
- package/src/modules/design_system/gallery/demos/time-picker-code.generated.ts +5 -0
- package/src/modules/design_system/gallery/demos/time-picker.tsx +31 -0
- package/src/modules/design_system/gallery/entries/banners.tsx +143 -94
- package/src/modules/design_system/gallery/entries/buttons-snippets.ts +432 -0
- package/src/modules/design_system/gallery/entries/buttons.tsx +125 -196
- package/src/modules/design_system/gallery/entries/charts.tsx +545 -233
- package/src/modules/design_system/gallery/entries/dates.tsx +171 -3
- package/src/modules/design_system/gallery/entries/detail.tsx +142 -115
- package/src/modules/design_system/gallery/entries/display.tsx +1691 -319
- package/src/modules/design_system/gallery/entries/feedback.tsx +1082 -169
- package/src/modules/design_system/gallery/entries/filters.tsx +238 -143
- package/src/modules/design_system/gallery/entries/foundations.tsx +404 -61
- package/src/modules/design_system/gallery/entries/icons.tsx +31 -117
- package/src/modules/design_system/gallery/entries/inputs-snippets.ts +156 -0
- package/src/modules/design_system/gallery/entries/inputs.tsx +2146 -503
- package/src/modules/design_system/gallery/entries/library.tsx +16 -0
- package/src/modules/design_system/gallery/entries/messages.tsx +114 -106
- package/src/modules/design_system/gallery/entries/navigation.tsx +782 -192
- package/src/modules/design_system/gallery/entries/notifications.tsx +145 -120
- package/src/modules/design_system/gallery/entries/overlays.tsx +696 -280
- package/src/modules/design_system/gallery/entries/scaffolding.tsx +1192 -158
- package/src/modules/design_system/gallery/entries/schedule.tsx +72 -58
- package/src/modules/design_system/gallery/presentation.ts +106 -0
- package/src/modules/design_system/gallery/registry.ts +8 -6
- package/src/modules/design_system/gallery/source-library.generated.ts +2 -0
- package/src/modules/design_system/i18n/de.json +7112 -3
- package/src/modules/design_system/i18n/en.json +7112 -3
- package/src/modules/design_system/i18n/es.json +7112 -3
- package/src/modules/design_system/i18n/ko.json +7112 -3
- package/src/modules/design_system/i18n/pl.json +7112 -3
- package/src/modules/push_notifications/AGENTS.md +9 -5
- package/src/modules/push_notifications/lib/queue.ts +15 -44
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import { ArrowLeft, BookOpen, ChevronDown, ChevronRight, Folder, Mail, Menu, MoreHorizontal, MoreVertical, PanelLeft, Plus, Search, User, X, Zap } from 'lucide-react'
|
|
3
|
+
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
4
|
+
import { cn } from '@open-mercato/shared/lib/utils'
|
|
5
|
+
import { Button } from '@open-mercato/ui/primitives/button'
|
|
6
|
+
import { Input } from '@open-mercato/ui/primitives/input'
|
|
7
|
+
import { SearchInput } from '@open-mercato/ui/primitives/search-input'
|
|
8
|
+
import { FieldLabel } from '@open-mercato/ui/primitives/label'
|
|
9
|
+
import { HintText } from '@open-mercato/ui/primitives/hint-text'
|
|
10
|
+
import { KeyIconGlyph } from '@open-mercato/ui/primitives/key-icon'
|
|
11
|
+
import { DigitInput } from '@open-mercato/ui/primitives/digit-input'
|
|
12
|
+
import { CounterInput } from '@open-mercato/ui/primitives/counter-input'
|
|
13
|
+
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '@open-mercato/ui/primitives/select'
|
|
14
|
+
import { Popover, PopoverTrigger, PopoverContent } from '@open-mercato/ui/primitives/popover'
|
|
15
|
+
import { CheckboxField } from '@open-mercato/ui/primitives/checkbox-field'
|
|
16
|
+
import { SocialButton } from '@open-mercato/ui/primitives/social-button'
|
|
17
|
+
import { Avatar } from '@open-mercato/ui/primitives/avatar'
|
|
18
|
+
import { Badge } from '@open-mercato/ui/primitives/badge'
|
|
19
|
+
import { Sidebar } from '@open-mercato/ui/primitives/sidebar'
|
|
20
|
+
import { PromptArea } from '@open-mercato/ui/primitives/prompt-area'
|
|
21
|
+
import { FileFormatIcon } from '@open-mercato/ui/primitives/file-format-icon'
|
|
22
|
+
import { aiProductArtwork } from '@open-mercato/ui/assets/ai-product-artwork'
|
|
23
|
+
import promptImage from '../assets/ai-prompt-image.png'
|
|
24
|
+
import avatarPhoto from '../assets/avatar-photo.png'
|
|
25
|
+
import googleIcon from '../assets/select-google.png'
|
|
26
|
+
|
|
27
|
+
type ButtonProps = React.ComponentProps<typeof Button>
|
|
28
|
+
|
|
29
|
+
const prefix = 'design_system.gallery.examples.aiProduct.'
|
|
30
|
+
const source = (asset: string | { readonly src: string }) => typeof asset === 'string' ? asset : asset.src
|
|
31
|
+
|
|
32
|
+
function AiIconButton({ size = 32, tone = 'default', appearance = 'plain', className, children, ...props }: Omit<ButtonProps, 'size'> & { size?: 20 | 24 | 28 | 32; tone?: 'default' | 'error'; appearance?: 'plain' | 'stroke' | 'lighter' }) {
|
|
33
|
+
const content = React.isValidElement<{ className?: string }>(children) && children.type !== 'img'
|
|
34
|
+
? React.cloneElement(children, { className: cn(children.props.className, size === 24 ? 'size-4.5' : 'size-5') })
|
|
35
|
+
: children
|
|
36
|
+
return <Button type="button" variant="ghost" size="icon" data-slot="ai-icon-button" data-size={size} data-tone={tone} data-appearance={appearance} className={cn(
|
|
37
|
+
'shrink-0 p-0',
|
|
38
|
+
size === 32 ? 'size-8 rounded-md' : size === 28 ? 'size-7 rounded-md' : size === 24 ? 'size-6 rounded-sm' : 'size-5 rounded-sm',
|
|
39
|
+
appearance !== 'plain' && 'rounded-ai-control',
|
|
40
|
+
appearance === 'stroke' ? 'bg-background shadow-xs ring-1 ring-inset ring-border' : appearance === 'lighter' ? 'bg-muted' : 'bg-background',
|
|
41
|
+
tone === 'error' ? 'text-status-error-text hover:bg-status-error-bg hover:text-status-error-text aria-pressed:bg-status-error-bg aria-pressed:text-status-error-text' : 'text-muted-foreground hover:bg-muted hover:text-foreground aria-pressed:bg-muted aria-pressed:text-foreground',
|
|
42
|
+
appearance !== 'plain' && 'aria-pressed:bg-primary aria-pressed:text-primary-foreground',
|
|
43
|
+
className,
|
|
44
|
+
)} {...props}>{content}</Button>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function AiModelSelect({ value, onChange, compact = false, className }: { value: string; onChange: (value: string) => void; compact?: boolean; className?: string }) {
|
|
48
|
+
const t = useT()
|
|
49
|
+
return <Select value={value} onValueChange={onChange}><SelectTrigger aria-label={t(`${prefix}model`)} data-slot="ai-model-select" className={cn('h-7 w-auto min-w-19.75 gap-1 rounded-ai-control border-0 bg-muted py-1 pl-2 pr-1 text-sm leading-5 shadow-none hover:bg-accent [&>svg]:size-5', compact && 'h-5 bg-transparent p-0', className)}><SelectValue /></SelectTrigger><SelectContent>{['GPT-4', 'GPT-3.5'].map(model => <SelectItem key={model} value={model}>{model}</SelectItem>)}</SelectContent></Select>
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
type PromptAttachment = { id: string; name: string; image?: string; objectUrl?: boolean }
|
|
53
|
+
|
|
54
|
+
export function AiPromptExample({ compact = false, attachment = 'none' }: { compact?: boolean; attachment?: 'none' | 'file' | 'image' }) {
|
|
55
|
+
const t = useT()
|
|
56
|
+
const [value, setValue] = React.useState('')
|
|
57
|
+
const [model, setModel] = React.useState('GPT-4')
|
|
58
|
+
const [lastPrompt, setLastPrompt] = React.useState('')
|
|
59
|
+
const [files, setFiles] = React.useState<PromptAttachment[]>(attachment === 'none' ? [] : [{ id: 'source', name: t(`${prefix}${attachment === 'image' ? 'imageName' : 'fileName'}`), image: attachment === 'image' ? source(promptImage) : undefined }])
|
|
60
|
+
const upload = React.useRef<HTMLInputElement>(null)
|
|
61
|
+
const attachmentId = React.useRef(0)
|
|
62
|
+
const objectUrls = React.useRef(new Set<string>())
|
|
63
|
+
React.useEffect(() => () => { for (const url of objectUrls.current) URL.revokeObjectURL(url) }, [])
|
|
64
|
+
const remove = (id: string) => setFiles(current => current.filter(file => {
|
|
65
|
+
if (file.id !== id) return true
|
|
66
|
+
if (file.objectUrl && file.image) { URL.revokeObjectURL(file.image); objectUrls.current.delete(file.image) }
|
|
67
|
+
return false
|
|
68
|
+
}))
|
|
69
|
+
const submit = (message: string) => { setLastPrompt(`${model}: ${message}`); setValue('') }
|
|
70
|
+
return <div className={cn('grid max-w-full gap-4', compact ? 'w-93.5' : 'w-175')}>
|
|
71
|
+
<PromptArea compact={compact} value={value} onValueChange={setValue} onSubmit={submit} inputLabel={t(`${prefix}prompt`)} submitLabel={t(`${prefix}saveDraft`)} placeholder={t(`${prefix}placeholder`)} information={<><Zap aria-hidden="true" className="size-4 shrink-0" /><span>{t(`${prefix}premium`)}</span><span aria-hidden="true">·</span><Popover><PopoverTrigger asChild><Button type="button" variant="ghost" className="h-4 rounded-sm p-0 text-xs font-medium leading-4">{t(`${prefix}upgrade`)}</Button></PopoverTrigger><PopoverContent className="text-sm">{t(`${prefix}localOnly`)}</PopoverContent></Popover></>}
|
|
72
|
+
toolbar={<><AiIconButton size={28} appearance="lighter" aria-label={t(`${prefix}addFile`)} onClick={() => upload.current?.click()}><Plus aria-hidden="true" /></AiIconButton><AiModelSelect value={model} onChange={setModel} /></>}
|
|
73
|
+
attachments={files.length ? files.map(file => file.image ? <div key={file.id} className="relative size-24 shrink-0"><img src={file.image} alt={file.name} className="size-24 rounded-xl object-cover" /><AiIconButton size={20} aria-label={`${t(`${prefix}remove`)} ${file.name}`} className="absolute right-1.5 top-1.5 rounded-full bg-primary text-primary-foreground hover:bg-primary-hover hover:text-primary-foreground" onClick={() => remove(file.id)}><X aria-hidden="true" /></AiIconButton></div> : <div key={file.id} className="flex h-15 max-w-full items-center gap-3 rounded-xl bg-muted py-2.5 pl-3 pr-4"><FileFormatIcon format={file.name.includes('.') ? file.name.split('.').pop()?.toUpperCase().slice(0, 5) ?? 'FILE' : 'FILE'} /><div className="grid min-w-0 gap-1"><span className="truncate text-sm font-medium">{file.name}</span><span className="text-xs text-muted-foreground">{t(`${prefix}localFile`)}</span></div><AiIconButton size={20} aria-label={`${t(`${prefix}remove`)} ${file.name}`} onClick={() => remove(file.id)}><X aria-hidden="true" /></AiIconButton></div>) : undefined} />
|
|
74
|
+
<input ref={upload} type="file" className="sr-only" tabIndex={-1} aria-label={t(`${prefix}attachmentInput`)} multiple onChange={event => { const selected = Array.from(event.target.files ?? []); setFiles(current => [...current, ...selected.map(file => { const image = file.type.startsWith('image/') ? URL.createObjectURL(file) : undefined; if (image) objectUrls.current.add(image); return { id: `attachment-${attachmentId.current++}`, name: file.name, image, objectUrl: Boolean(image) } })]); event.target.value = '' }} />
|
|
75
|
+
<p className="text-xs leading-4 text-muted-foreground">{t(`${prefix}localOnly`)}</p>
|
|
76
|
+
{lastPrompt ? <output className="rounded-md border border-border p-3 text-sm">{t(`${prefix}saved`)} {lastPrompt}</output> : null}
|
|
77
|
+
</div>
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function AiIconButtonExamples({ chat = false }: { chat?: boolean }) {
|
|
81
|
+
const t = useT()
|
|
82
|
+
const [active, setActive] = React.useState<string[]>([])
|
|
83
|
+
const toggle = (key: string) => setActive(items => items.includes(key) ? items.filter(item => item !== key) : [...items, key])
|
|
84
|
+
return <div className="grid gap-5">{chat ? <div className="flex gap-5">{(['stroke', 'lighter'] as const).map(appearance => <AiIconButton key={appearance} size={28} appearance={appearance} aria-label={`${t(`${prefix}toggleControl`)} ${appearance}`} aria-pressed={active.includes(appearance)} onClick={() => toggle(appearance)}><Plus aria-hidden="true" /></AiIconButton>)}</div> : (['default', 'error'] as const).map(tone => <div key={tone} className="flex items-center gap-5">{([32, 28, 24, 20] as const).map(size => <AiIconButton key={size} size={size} tone={tone} aria-label={`${t(`${prefix}${tone}`)} ${size}`} aria-pressed={active.includes(`${tone}-${size}`)} onClick={() => toggle(`${tone}-${size}`)}><ChevronDown aria-hidden="true" /></AiIconButton>)}</div>)}</div>
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function AiNavItem({ children, icon = true, leading, mobile = false, active = false, className, ...props }: ButtonProps & { icon?: boolean; leading?: React.ReactNode; mobile?: boolean; active?: boolean }) {
|
|
88
|
+
return <Button type="button" variant="ghost" size="sm" data-slot="ai-nav-item" data-mobile={mobile} data-leading={icon} aria-current={active ? 'page' : undefined} className={cn('group h-8 w-61 max-w-full justify-start gap-2 rounded-md bg-background py-1.5 pl-1.5 pr-2 text-sm font-medium leading-5 text-muted-foreground hover:bg-muted hover:text-foreground', active && 'bg-muted text-foreground', !icon && 'hover:pl-2.5', !icon && active && 'pl-2.5', className)} {...props}>
|
|
89
|
+
{icon ? leading ?? <Folder aria-hidden="true" className="size-5" /> : null}<span className="min-w-0 flex-1 truncate text-left">{children}</span>{icon ? <ChevronRight aria-hidden="true" className={cn('size-4.5 shrink-0', !mobile && !active && 'hidden group-hover:block group-focus-visible:block')} /> : <MoreVertical aria-hidden="true" className={cn('size-4.5 shrink-0', !mobile && (active ? 'hidden' : 'hidden group-hover:block group-focus-visible:block'))} />}
|
|
90
|
+
</Button>
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function AiNavigationExamples() {
|
|
94
|
+
const t = useT()
|
|
95
|
+
const [active, setActive] = React.useState<string[]>([])
|
|
96
|
+
return <div className="grid gap-4">{[false, true].flatMap(mobile => [true, false].map(icon => { const key = `${mobile}-${icon}`; return <AiNavItem key={key} icon={icon} mobile={mobile} active={active.includes(key)} onClick={() => setActive(values => values.includes(key) ? values.filter(value => value !== key) : [...values, key])}>{t(`${prefix}projects`)}</AiNavItem> }))}</div>
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function AiSearchExamples() {
|
|
100
|
+
const t = useT()
|
|
101
|
+
const [query, setQuery] = React.useState('')
|
|
102
|
+
return <div className="grid w-64 max-w-full gap-4">{(['default', 'sm'] as const).map(size => <SearchInput key={size} size={size} value={query} onChange={setQuery} clearable={false} aria-label={`${t(`${prefix}search`)} ${size}`} placeholder={t(`${prefix}searchPlaceholder`)} className={cn('rounded-lg border-0 px-2 shadow-none focus-within:bg-background [&>svg]:size-5', size === 'sm' ? 'bg-background hover:bg-muted' : 'bg-muted')} />)}<output className="text-xs text-muted-foreground">{t(`${prefix}query`)} {query}</output></div>
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function AiAuthExamples({ kind = 'icons' }: { kind?: 'icons' | 'social' | 'text' | 'digits' }) {
|
|
106
|
+
const t = useT()
|
|
107
|
+
const [value, setValue] = React.useState('')
|
|
108
|
+
const [clicked, setClicked] = React.useState(false)
|
|
109
|
+
const id = React.useId()
|
|
110
|
+
if (kind === 'icons') return <div className="grid w-full max-w-lg grid-cols-2 gap-6 sm:grid-cols-4">{(['signIn', 'signUp', 'reset', 'verification', 'signInGray', 'signUpGray', 'resetGray', 'verificationGray'] as const).map(key => <div key={key} className="grid justify-items-center gap-2"><span className="flex size-14 items-center justify-center rounded-full border border-status-neutral-bg bg-background"><img src={aiProductArtwork[key]} alt="" className="size-8" /></span><span className="text-xs text-muted-foreground">{t(`${prefix}${key.replace('Gray', '')}`)}{key.endsWith('Gray') ? ` · ${t(`${prefix}gray`)}` : ''}</span></div>)}</div>
|
|
111
|
+
if (kind === 'social') return <div className="grid gap-3"><SocialButton type="button" brand="google" appearance="stroke" className="h-auto min-h-10 w-fit max-w-full whitespace-normal py-2 text-left" onClick={() => setClicked(true)}><img src={source(googleIcon)} alt="" className="size-5 shrink-0" /><span className="min-w-0">{t(`${prefix}google`)}</span></SocialButton>{clicked ? <output className="max-w-sm text-xs text-muted-foreground">{t(`${prefix}localOnly`)}</output> : null}</div>
|
|
112
|
+
if (kind === 'digits') return <div className="grid gap-4">{[false, true].map(disabled => <DigitInput key={String(disabled)} length={4} value={disabled ? '1234' : value} onChange={setValue} disabled={disabled} aria-label={`${t(`${prefix}verification`)} ${disabled ? t(`${prefix}disabled`) : t(`${prefix}editable`)}`} cellClassName="size-12 sm:w-12 rounded-ai-input px-2 py-2.5 text-lg leading-6" />)}<output className="text-xs text-muted-foreground">{value}</output></div>
|
|
113
|
+
return <div className="grid w-83 max-w-full gap-5">{[false, true].map(disabled => <div key={String(disabled)} data-slot="ai-text-input" className="grid gap-1"><FieldLabel htmlFor={`${id}-${disabled}`} disabled={disabled} required>{t(`${prefix}email`)}</FieldLabel><Input id={`${id}-${disabled}`} type="email" value={disabled ? 'james@example.com' : value} onChange={event => setValue(event.target.value)} disabled={disabled} aria-required aria-describedby={`${id}-${disabled}-hint`} placeholder="hello@alignui.com" leading={<Mail aria-hidden="true" className="size-5 text-muted-foreground" />} size="lg" className="rounded-ai-input" /><HintText id={`${id}-${disabled}-hint`} state={disabled ? 'disabled' : 'default'} leading={<KeyIconGlyph name="information" />} className="pt-1">{t(`${prefix}hint`)}</HintText></div>)}</div>
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function AiSettingsExamples() {
|
|
117
|
+
const t = useT()
|
|
118
|
+
const [tab, setTab] = React.useState('people')
|
|
119
|
+
const [size, setSize] = React.useState('medium')
|
|
120
|
+
const [count, setCount] = React.useState<number | null>(30)
|
|
121
|
+
const [model, setModel] = React.useState('GPT-4')
|
|
122
|
+
return <div className="grid gap-6"><div className="grid gap-2">{(['people', 'profile'] as const).map(value => <Button key={value} type="button" variant="ghost" data-slot="ai-settings-item" aria-pressed={tab === value} className="h-auto min-h-10 w-56 max-w-full justify-start gap-2 rounded-lg bg-background px-3 py-2 text-sm text-muted-foreground hover:bg-muted aria-pressed:bg-muted aria-pressed:text-foreground" onClick={() => setTab(value)}>{value === 'profile' ? <span aria-hidden="true"><Avatar size={20} label="James Brown" src={source(avatarPhoto)} /></span> : <User aria-hidden="true" className="size-5" />}<span className="min-w-0 flex-1 whitespace-normal text-left">{value === 'profile' ? 'James Brown' : t(`${prefix}people`)}</span>{tab === value ? <ChevronRight aria-hidden="true" className="size-4.5" /> : null}</Button>)}</div><output className="text-sm text-muted-foreground">{t(`${prefix}${tab}`)}</output>
|
|
123
|
+
<div className="flex flex-wrap items-center gap-5"><Select value={size} onValueChange={setSize}><SelectTrigger data-slot="ai-size-select" aria-label={t(`${prefix}responseLength`)} className="w-auto min-w-28 gap-2 rounded-lg [&>svg]:size-5"><SelectValue /></SelectTrigger><SelectContent>{['small', 'medium', 'large'].map(value => <SelectItem key={value} value={value}>{t(`${prefix}${value}`)}</SelectItem>)}</SelectContent></Select><CounterInput data-slot="ai-counter" value={count} min={0} max={99} onChange={setCount} size="default" aria-label={t(`${prefix}historyLimit`)} decrementAriaLabel={t(`${prefix}decrease`)} incrementAriaLabel={t(`${prefix}increase`)} className="w-28 rounded-lg" inputClassName="text-sm" /><AiModelSelect value={model} onChange={setModel} className="h-9 px-3 py-2" /></div>
|
|
124
|
+
</div>
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function AiNewChatButton({ onClick }: { onClick: () => void }) {
|
|
128
|
+
const t = useT()
|
|
129
|
+
return <Button type="button" variant="ghost" data-slot="ai-new-chat" className="h-auto min-h-8 w-61 max-w-full justify-start gap-2 rounded-md p-1.5 text-sm text-status-success-text hover:bg-status-success-bg hover:text-status-success-text" onClick={onClick}><span aria-hidden="true" className="flex size-5 items-center justify-center rounded-full bg-status-success-solid text-status-success-solid-foreground"><Plus className="size-3.5" /></span><span className="min-w-0 whitespace-normal text-left">{t(`${prefix}newChat`)}</span></Button>
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function AiNewChatExample() {
|
|
133
|
+
const t = useT()
|
|
134
|
+
const [draft, setDraft] = React.useState(0)
|
|
135
|
+
return <div className="grid gap-3"><AiNewChatButton onClick={() => setDraft(value => value + 1)} /><output className="text-xs text-muted-foreground">{t(`${prefix}draftNumber`, { number: draft })}</output></div>
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function AiDivider() {
|
|
139
|
+
return <div role="separator" className="flex h-1 shrink-0 items-center px-1.5"><span className="h-px w-full bg-border" /></div>
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function AiSidebarExample({ search = '01', initialCollapsed = false }: { search?: '01' | '02' | '03'; initialCollapsed?: boolean }) {
|
|
143
|
+
const t = useT()
|
|
144
|
+
const [collapsed, setCollapsed] = React.useState(initialCollapsed)
|
|
145
|
+
const [query, setQuery] = React.useState('')
|
|
146
|
+
const [active, setActive] = React.useState('projects')
|
|
147
|
+
const [draft, setDraft] = React.useState(0)
|
|
148
|
+
const newChat = () => { setDraft(value => value + 1); setActive('newChat') }
|
|
149
|
+
const searchControl = <SearchInput value={query} onChange={setQuery} clearable={false} aria-label={t(`${prefix}search`)} placeholder={t(`${prefix}searchPlaceholder`)} className="h-9 w-61 max-w-full rounded-lg border-0 bg-muted px-2 shadow-none [&>svg]:size-5" />
|
|
150
|
+
const searchPopover = <Popover><PopoverTrigger asChild><AiIconButton aria-label={t(`${prefix}search`)}><Search aria-hidden="true" /></AiIconButton></PopoverTrigger><PopoverContent className="w-auto p-3">{searchControl}<p className="mt-2 text-xs text-muted-foreground">{t(`${prefix}query`)} {query}</p></PopoverContent></Popover>
|
|
151
|
+
const groups = [
|
|
152
|
+
{ label: 'pinned', items: ['launchPlan', 'researchNotes', 'contentIdeas'], icon: true },
|
|
153
|
+
{ label: 'recent', items: ['quarterlyReport', 'emailDraft', 'meetingNotes'], icon: false },
|
|
154
|
+
{ label: 'yesterday', items: ['campaignIdeas', 'productBrief', 'supportReply', 'weeklyPlan', 'projectSummary'], icon: false },
|
|
155
|
+
]
|
|
156
|
+
return <div className="flex max-w-full flex-wrap items-start gap-5">
|
|
157
|
+
<Sidebar collapsed={collapsed} aria-label={t(`${prefix}sidebar`)} className={cn('max-w-full rounded-lg border border-border', collapsed ? 'w-18 gap-5 border-0 p-5' : 'w-68 gap-4 border-0 px-3.5 pb-3.5 pt-5')}>
|
|
158
|
+
<div className="flex shrink-0 flex-col gap-5"><div className="flex h-8 items-center justify-between">
|
|
159
|
+
{collapsed ? <AiIconButton aria-label={t(`${prefix}expand`)} onClick={() => setCollapsed(false)}><img src={aiProductArtwork.logo} alt="" className="size-8" /></AiIconButton> : <><img src={aiProductArtwork.logo} alt={t(`${prefix}brand`)} className="size-8" /><div className="flex gap-1">{search === '02' ? searchPopover : null}<AiIconButton aria-label={t(`${prefix}collapse`)} onClick={() => setCollapsed(true)}><PanelLeft aria-hidden="true" /></AiIconButton></div></>}
|
|
160
|
+
</div>{!collapsed && search === '01' ? searchControl : null}</div>
|
|
161
|
+
{collapsed ? <><AiDivider /><div className="flex flex-1 flex-col gap-3"><AiIconButton aria-label={t(`${prefix}newChat`)} onClick={newChat}><Plus aria-hidden="true" /></AiIconButton><AiIconButton aria-label={t(`${prefix}projects`)} aria-pressed={active === 'projects'} onClick={() => setActive('projects')}><Folder aria-hidden="true" /></AiIconButton><AiIconButton aria-label={t(`${prefix}library`)} aria-pressed={active === 'library'} onClick={() => setActive('library')}><BookOpen aria-hidden="true" /></AiIconButton>{searchPopover}</div><AiDivider /></> : <>
|
|
162
|
+
<div className="grid shrink-0 gap-1"><AiNewChatButton onClick={newChat} /><AiNavItem active={active === 'projects'} onClick={() => setActive('projects')}>{t(`${prefix}projects`)}</AiNavItem><AiNavItem leading={<BookOpen aria-hidden="true" className="size-5" />} active={active === 'library'} onClick={() => setActive('library')}>{t(`${prefix}library`)}</AiNavItem>{search === '03' ? <Popover><PopoverTrigger asChild><Button type="button" variant="ghost" className="h-8 justify-start gap-2 rounded-md p-1.5 text-sm text-muted-foreground"><Search aria-hidden="true" className="size-5" />{t(`${prefix}search`)}</Button></PopoverTrigger><PopoverContent className="w-auto p-3">{searchControl}</PopoverContent></Popover> : null}</div>
|
|
163
|
+
<AiDivider /><div className="flex min-h-0 flex-1 flex-col gap-4 overflow-auto">
|
|
164
|
+
{groups.map((group, groupIndex) => <React.Fragment key={group.label}>{groupIndex === 1 ? <AiDivider /> : null}<div className="grid shrink-0 gap-2"><h3 className="px-1.5 text-xs font-medium leading-4 text-muted-foreground">{t(`${prefix}${group.label}`)}</h3><div className="grid gap-1">{group.items.filter(item => t(`${prefix}${item}`).toLocaleLowerCase().includes(query.toLocaleLowerCase())).map(item => <AiNavItem key={item} icon={group.icon} active={active === item} onClick={() => setActive(item)}>{t(`${prefix}${item}`)}</AiNavItem>)}</div></div></React.Fragment>)}
|
|
165
|
+
</div><AiDivider />
|
|
166
|
+
</>}
|
|
167
|
+
<Popover><PopoverTrigger asChild><Button type="button" variant="ghost" aria-label={t(`${prefix}profile`)} data-slot="ai-sidebar-profile" className={cn('shrink-0 justify-start rounded-md text-left', collapsed ? 'size-8 p-0' : 'h-13 gap-3 p-1.5')}><Avatar label="James Brown" size={collapsed ? 32 : 40} />{!collapsed ? <><span className="flex min-w-0 flex-1 flex-col gap-1"><span className="flex items-center gap-1 text-sm font-medium leading-5">James Brown <Badge size={16} appearance="light">Pro</Badge></span><span className="truncate text-xs font-normal leading-4 text-muted-foreground">james@example.com</span></span><MoreVertical aria-hidden="true" className="size-4.5" /></> : null}</Button></PopoverTrigger><PopoverContent className="w-64 text-sm"><p className="font-medium">James Brown</p><p className="mt-2 text-muted-foreground">{t(`${prefix}localOnly`)}</p></PopoverContent></Popover>
|
|
168
|
+
</Sidebar><output aria-live="polite" className="grid max-w-xs gap-2 text-sm text-muted-foreground"><span>{t(`${prefix}selected`)} {t(`${prefix}${active}`)}</span><span>{t(`${prefix}draftNumber`, { number: draft })}</span>{query ? <span>{t(`${prefix}query`)} {query}</span> : null}</output>
|
|
169
|
+
</div>
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export function AiMobileNavigationExample({ kind = 'default' }: { kind?: 'default' | 'in-projects' | 'projects' | 'project-details' }) {
|
|
173
|
+
const t = useT()
|
|
174
|
+
const [model, setModel] = React.useState('GPT-4')
|
|
175
|
+
const [selected, setSelected] = React.useState('projects')
|
|
176
|
+
const [draft, setDraft] = React.useState(0)
|
|
177
|
+
const [project, setProject] = React.useState('')
|
|
178
|
+
const [name, setName] = React.useState('')
|
|
179
|
+
const [createOpen, setCreateOpen] = React.useState(false)
|
|
180
|
+
const [pinned, setPinned] = React.useState(false)
|
|
181
|
+
const id = React.useId()
|
|
182
|
+
const menu = <Popover><PopoverTrigger asChild><AiIconButton aria-label={t(`${prefix}menu`)}><Menu aria-hidden="true" /></AiIconButton></PopoverTrigger><PopoverContent className="grid w-auto gap-1 p-2">{['projects', 'library'].map(item => <AiNavItem key={item} mobile active={selected === item} onClick={() => setSelected(item)}>{t(`${prefix}${item}`)}</AiNavItem>)}</PopoverContent></Popover>
|
|
183
|
+
const more = <Popover><PopoverTrigger asChild><AiIconButton size={kind === 'project-details' ? 24 : 32} aria-label={t(`${prefix}more`)}><MoreHorizontal aria-hidden="true" /></AiIconButton></PopoverTrigger><PopoverContent className="w-64"><CheckboxField checked={pinned} onCheckedChange={value => setPinned(value === true)} label={t(`${prefix}pinProject`)} /></PopoverContent></Popover>
|
|
184
|
+
const create = () => { if (!name.trim()) return; setProject(name.trim()); setName(''); setCreateOpen(false) }
|
|
185
|
+
return <div className="grid w-full min-w-0 max-w-sm grid-cols-1 gap-4"><header data-slot="ai-mobile-navigation" data-kind={kind} className={cn('flex h-16 w-full min-w-0 items-center gap-2 bg-background px-2 py-3 sm:px-4', kind === 'project-details' ? 'sm:gap-2.5' : 'sm:gap-3.5')}>
|
|
186
|
+
{kind === 'project-details' ? <><AiIconButton size={20} aria-label={t(`${prefix}allProjects`)} onClick={() => setSelected('projects')}><ArrowLeft aria-hidden="true" /></AiIconButton><span className="flex-1 text-sm font-medium">{t(`${prefix}allProjects`)}</span><div className="flex gap-2"><AiIconButton size={24} aria-label={t(`${prefix}newChat`)} onClick={() => setDraft(value => value + 1)}><Plus aria-hidden="true" /></AiIconButton>{more}</div></> : <>{menu}{kind === 'projects' ? <div className="flex flex-1 justify-end"><Popover open={createOpen} onOpenChange={setCreateOpen}><PopoverTrigger asChild><Button type="button" size="sm" variant="outline" className="w-auto shrink-0 gap-2 rounded-lg"><Plus aria-hidden="true" className="size-5" />{t(`${prefix}addProject`)}</Button></PopoverTrigger><PopoverContent className="w-72"><form className="grid gap-3" onSubmit={event => { event.preventDefault(); create() }} onKeyDown={event => { if (event.key === 'Enter' && (event.ctrlKey || event.metaKey)) { event.preventDefault(); create() } }}><FieldLabel htmlFor={id} required>{t(`${prefix}projectName`)}</FieldLabel><Input id={id} value={name} onChange={event => setName(event.target.value)} autoFocus /><Button type="submit" size="sm" disabled={!name.trim()}>{t(`${prefix}addProject`)}</Button></form></PopoverContent></Popover></div> : <><div className="flex min-w-0 flex-1 flex-col gap-1"><AiModelSelect value={model} onChange={setModel} compact />{kind === 'in-projects' ? <span className="truncate text-xs leading-4 text-muted-foreground">{t(`${prefix}launchPlan`)}</span> : null}</div><AiIconButton aria-label={t(`${prefix}newChat`)} onClick={() => setDraft(value => value + 1)}><Plus aria-hidden="true" /></AiIconButton>{more}</>}</>}
|
|
187
|
+
</header><output aria-live="polite" className="grid gap-1 text-xs text-muted-foreground"><span>{t(`${prefix}selected`)} {t(`${prefix}${selected}`)}</span><span>{t(`${prefix}draftNumber`, { number: draft })}</span>{project ? <span>{t(`${prefix}createdProject`)} {project}</span> : null}{pinned ? <span>{t(`${prefix}pinProject`)}</span> : null}</output></div>
|
|
188
|
+
}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import * as React from 'react'
|
|
4
|
+
import { MoreHorizontal, Pencil, Plus, Trash2 } from 'lucide-react'
|
|
5
|
+
import { useT } from '@open-mercato/shared/lib/i18n/context'
|
|
6
|
+
import { Button } from '@open-mercato/ui/primitives/button'
|
|
7
|
+
import { IconButton } from '@open-mercato/ui/primitives/icon-button'
|
|
8
|
+
import { CompactButton } from '@open-mercato/ui/primitives/compact-button'
|
|
9
|
+
import { LinkButton } from '@open-mercato/ui/primitives/link-button'
|
|
10
|
+
import { SocialButton } from '@open-mercato/ui/primitives/social-button'
|
|
11
|
+
import { FancyButton } from '@open-mercato/ui/primitives/fancy-button'
|
|
12
|
+
import { ButtonGroup } from '@open-mercato/ui/primitives/button-group'
|
|
13
|
+
import { Spinner } from '@open-mercato/ui/primitives/spinner'
|
|
14
|
+
import appleFilled from '../assets/social-apple-filled.svg'
|
|
15
|
+
import githubFilled from '../assets/social-github-filled.svg'
|
|
16
|
+
import xFilled from '../assets/social-x-filled.svg'
|
|
17
|
+
import googleFilled from '../assets/social-google-filled.svg'
|
|
18
|
+
import facebookFilled from '../assets/social-facebook-filled.svg'
|
|
19
|
+
import dropboxFilled from '../assets/social-dropbox-filled.svg'
|
|
20
|
+
import linkedinFilled from '../assets/social-linkedin-filled.svg'
|
|
21
|
+
import appleStroke from '../assets/social-apple-stroke.svg'
|
|
22
|
+
import githubStroke from '../assets/social-github-stroke.svg'
|
|
23
|
+
import xStroke from '../assets/social-x-stroke.svg'
|
|
24
|
+
import googleStroke from '../assets/social-google-stroke.svg'
|
|
25
|
+
import facebookStroke from '../assets/social-facebook-stroke.svg'
|
|
26
|
+
import dropboxStroke from '../assets/social-dropbox-stroke.svg'
|
|
27
|
+
import linkedinStroke from '../assets/social-linkedin-stroke.svg'
|
|
28
|
+
|
|
29
|
+
export const socialProviders = [
|
|
30
|
+
{ brand: 'apple', name: 'Apple', filled: appleFilled, stroke: appleStroke },
|
|
31
|
+
{ brand: 'github', name: 'GitHub', filled: githubFilled, stroke: githubStroke },
|
|
32
|
+
{ brand: 'x', name: 'X', filled: xFilled, stroke: xStroke },
|
|
33
|
+
{ brand: 'google', name: 'Google', filled: googleFilled, stroke: googleStroke },
|
|
34
|
+
{ brand: 'facebook', name: 'Facebook', filled: facebookFilled, stroke: facebookStroke },
|
|
35
|
+
{ brand: 'dropbox', name: 'Dropbox', filled: dropboxFilled, stroke: dropboxStroke },
|
|
36
|
+
{ brand: 'linkedin', name: 'LinkedIn', filled: linkedinFilled, stroke: linkedinStroke },
|
|
37
|
+
] as const
|
|
38
|
+
|
|
39
|
+
export function SocialButtonsDemo({ appearance, iconOnly = false }: { appearance: 'filled' | 'stroke'; iconOnly?: boolean }) {
|
|
40
|
+
const t = useT()
|
|
41
|
+
return (
|
|
42
|
+
<div className="flex flex-wrap gap-3 p-1">
|
|
43
|
+
{socialProviders.map((provider) => {
|
|
44
|
+
const asset = provider[appearance]
|
|
45
|
+
const source = typeof asset === 'string' ? asset : asset.src
|
|
46
|
+
const label = t('design_system.gallery.examples.buttons.provider', { brand: provider.name })
|
|
47
|
+
const useForeground = appearance === 'stroke' && ['apple', 'github', 'x'].includes(provider.brand)
|
|
48
|
+
return (
|
|
49
|
+
<SocialButton key={provider.brand} brand={provider.brand} appearance={appearance} iconOnly={iconOnly} aria-label={iconOnly ? label : undefined}>
|
|
50
|
+
{useForeground ? (
|
|
51
|
+
<span aria-hidden="true" className="size-5 shrink-0 bg-current" style={{ maskImage: `url("${source}")`, maskSize: 'contain', maskPosition: 'center', maskRepeat: 'no-repeat' }} />
|
|
52
|
+
) : <img src={source} alt="" aria-hidden="true" className="size-5 shrink-0" />}
|
|
53
|
+
{!iconOnly && label}
|
|
54
|
+
</SocialButton>
|
|
55
|
+
)
|
|
56
|
+
})}
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function CompactButtonExample({ appearance, size, fullRadius, initialPressed, disabled }: {
|
|
62
|
+
appearance: 'stroke' | 'ghost' | 'white' | 'modifiable'
|
|
63
|
+
size: 20 | 24
|
|
64
|
+
fullRadius: boolean
|
|
65
|
+
initialPressed: boolean
|
|
66
|
+
disabled: boolean
|
|
67
|
+
}) {
|
|
68
|
+
const t = useT()
|
|
69
|
+
const [pressed, setPressed] = React.useState(initialPressed)
|
|
70
|
+
return (
|
|
71
|
+
<CompactButton appearance={appearance} size={size} fullRadius={fullRadius} disabled={disabled}
|
|
72
|
+
aria-label={t('design_system.gallery.examples.buttons.compactAction')}
|
|
73
|
+
aria-pressed={disabled ? undefined : pressed} onClick={() => setPressed((value) => !value)}>
|
|
74
|
+
<Plus aria-hidden="true" />
|
|
75
|
+
</CompactButton>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function CompactButtonMatrix({ initialPressed = false, disabled = false }: { initialPressed?: boolean; disabled?: boolean }) {
|
|
80
|
+
return (
|
|
81
|
+
<div className="grid w-full gap-4 sm:grid-cols-2">
|
|
82
|
+
{(['stroke', 'ghost', 'white', 'modifiable'] as const).map((appearance) => (
|
|
83
|
+
<div key={appearance} className={appearance === 'modifiable' ? 'grid gap-4 rounded-md bg-primary p-4 text-primary-foreground' : appearance === 'white' ? 'grid gap-4 rounded-md border border-border bg-muted p-4' : 'grid gap-4 rounded-md border border-border p-4'}>
|
|
84
|
+
<code className="text-xs">{appearance}</code>
|
|
85
|
+
<div className="flex flex-wrap gap-6">
|
|
86
|
+
{([20, 24] as const).flatMap((size) => [false, true].map((fullRadius) => (
|
|
87
|
+
<div key={`${size}-${fullRadius}`} className="flex flex-col items-center gap-2">
|
|
88
|
+
<CompactButtonExample appearance={appearance} size={size} fullRadius={fullRadius} initialPressed={initialPressed} disabled={disabled} />
|
|
89
|
+
<code className="text-xs">{size}px · {fullRadius ? 'full' : '6px'}</code>
|
|
90
|
+
</div>
|
|
91
|
+
)))}
|
|
92
|
+
</div>
|
|
93
|
+
</div>
|
|
94
|
+
))}
|
|
95
|
+
</div>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function CompactButtonDisabledPreview() {
|
|
100
|
+
const t = useT()
|
|
101
|
+
return (
|
|
102
|
+
<div className="grid w-full gap-4">
|
|
103
|
+
<p className="max-w-prose text-sm text-muted-foreground">{t('design_system.gallery.examples.buttons.compactDisabledNote')}</p>
|
|
104
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
105
|
+
{(['stroke', 'modifiable'] as const).map((appearance) => (
|
|
106
|
+
<div key={appearance} className={appearance === 'modifiable' ? 'grid gap-4 rounded-md bg-primary p-4 text-primary-foreground' : 'grid gap-4 rounded-md border border-border p-4'}>
|
|
107
|
+
<code className="text-xs">{appearance === 'modifiable' ? 'modifiable' : 'stroke · ghost · white'}</code>
|
|
108
|
+
<div className="flex flex-wrap gap-6">
|
|
109
|
+
{([20, 24] as const).flatMap((size) => [false, true].map((fullRadius) => (
|
|
110
|
+
<div key={`${size}-${fullRadius}`} className="flex flex-col items-center gap-2">
|
|
111
|
+
<CompactButton appearance={appearance} size={size} fullRadius={fullRadius} disabled
|
|
112
|
+
aria-label={t('design_system.gallery.examples.buttons.compactAction')}>
|
|
113
|
+
<Plus aria-hidden="true" />
|
|
114
|
+
</CompactButton>
|
|
115
|
+
<code className="text-xs">{size}px · {fullRadius ? 'full' : '6px'}</code>
|
|
116
|
+
</div>
|
|
117
|
+
)))}
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
))}
|
|
121
|
+
</div>
|
|
122
|
+
</div>
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export function ButtonGroupMatrix({ content = false }: { content?: boolean }) {
|
|
127
|
+
const t = useT()
|
|
128
|
+
return (
|
|
129
|
+
<div className="grid w-full min-w-0 gap-6">
|
|
130
|
+
{([24, 32, 36] as const).flatMap((size) => (content ? [5] : [2, 3, 4, 5, 6]).map((count) => (
|
|
131
|
+
<div key={`${size}-${count}`} className="grid min-w-0 gap-2">
|
|
132
|
+
<code className="text-xs text-muted-foreground">{size}px · {count}</code>
|
|
133
|
+
<div className="max-w-full overflow-x-auto p-1">
|
|
134
|
+
<ButtonGroup size={size} aria-label={t('design_system.gallery.examples.buttons.groupActions')}>
|
|
135
|
+
{content ? (
|
|
136
|
+
<>
|
|
137
|
+
<Button type="button" variant="outline">{t('design_system.gallery.examples.buttons.groupItem', { number: 1 })}</Button>
|
|
138
|
+
<Button type="button" variant="outline"><Pencil aria-hidden="true" />{t('design_system.gallery.examples.buttons.groupItem', { number: 2 })}</Button>
|
|
139
|
+
<Button type="button" variant="outline">{t('design_system.gallery.examples.buttons.groupItem', { number: 3 })}<Plus aria-hidden="true" /></Button>
|
|
140
|
+
<Button type="button" variant="outline"><Pencil aria-hidden="true" />{t('design_system.gallery.examples.buttons.groupItem', { number: 4 })}<Plus aria-hidden="true" /></Button>
|
|
141
|
+
<IconButton aria-label={t('design_system.gallery.examples.buttons.moreActions')}><MoreHorizontal aria-hidden="true" /></IconButton>
|
|
142
|
+
</>
|
|
143
|
+
) : Array.from({ length: count }, (_, index) => (
|
|
144
|
+
<Button key={index} type="button" variant="outline">{t('design_system.gallery.examples.buttons.groupItem', { number: index + 1 })}</Button>
|
|
145
|
+
))}
|
|
146
|
+
</ButtonGroup>
|
|
147
|
+
</div>
|
|
148
|
+
</div>
|
|
149
|
+
)))}
|
|
150
|
+
</div>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function ButtonStatePreview({ loading = false }: { loading?: boolean }) {
|
|
155
|
+
const t = useT()
|
|
156
|
+
return (
|
|
157
|
+
<Button type="button" disabled aria-busy={loading || undefined}>
|
|
158
|
+
{loading ? <Spinner size="sm" className="motion-reduce:animate-none" /> : null}
|
|
159
|
+
{t(loading ? 'design_system.gallery.samples.states.saving' : 'design_system.gallery.samples.primaryAction')}
|
|
160
|
+
</Button>
|
|
161
|
+
)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function PrimaryButtonPreview() {
|
|
165
|
+
const t = useT()
|
|
166
|
+
return <Button type="button" variant="primary-filled">{t('design_system.gallery.samples.primaryAction')}</Button>
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function DisabledIconButtonPreview() {
|
|
170
|
+
const t = useT()
|
|
171
|
+
return (
|
|
172
|
+
<IconButton type="button" variant="outline" disabled aria-label={t('design_system.gallery.samples.states.edit')}>
|
|
173
|
+
<Pencil aria-hidden="true" />
|
|
174
|
+
</IconButton>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function ButtonButtonsDefaultSample() {
|
|
179
|
+
const t = useT()
|
|
180
|
+
return (<Button>{t('design_system.gallery.samples.primaryAction')}</Button>)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function ButtonButtonsDestructiveSample() {
|
|
184
|
+
const t = useT()
|
|
185
|
+
return (<Button variant="destructive">{t('design_system.gallery.sampleCopy.delete')}</Button>)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function ButtonButtonsDestructiveOutlineSample() {
|
|
189
|
+
const t = useT()
|
|
190
|
+
return (<Button variant="destructive-outline">{t('design_system.gallery.sampleCopy.delete')}</Button>)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export function ButtonButtonsDestructiveSoftSample() {
|
|
194
|
+
const t = useT()
|
|
195
|
+
return (<Button variant="destructive-soft">{t('design_system.gallery.sampleCopy.deleteDraft')}</Button>)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export function ButtonButtonsDestructiveGhostSample() {
|
|
199
|
+
const t = useT()
|
|
200
|
+
return (<Button variant="destructive-ghost">{t('design_system.gallery.samples.hr.remove')}</Button>)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function ButtonButtonsOutlineSample() {
|
|
204
|
+
const t = useT()
|
|
205
|
+
return (<Button variant="outline">{t('design_system.gallery.samples.overlay.cancel')}</Button>)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
export function ButtonButtonsSecondarySample() {
|
|
209
|
+
const t = useT()
|
|
210
|
+
return (<Button variant="secondary">{t('design_system.gallery.sampleCopy.duplicate')}</Button>)
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function ButtonButtonsGhostSample() {
|
|
214
|
+
const t = useT()
|
|
215
|
+
return (<Button variant="ghost">{t('design_system.gallery.sampleCopy.dismiss')}</Button>)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function ButtonButtonsMutedSample() {
|
|
219
|
+
const t = useT()
|
|
220
|
+
return (<Button variant="muted">{t('design_system.gallery.sampleCopy.showMore')}</Button>)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export function ButtonButtonsLinkSample() {
|
|
224
|
+
const t = useT()
|
|
225
|
+
return (<Button variant="link">{t('design_system.gallery.samples.banner.details')}</Button>)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function ButtonButtonsSizesSample() {
|
|
229
|
+
const t = useT()
|
|
230
|
+
return (<>
|
|
231
|
+
<Button size="lg">{t('design_system.gallery.sampleCopy.large')}</Button>
|
|
232
|
+
<Button size="default">{t('design_system.gallery.examples.aiProduct.default')}</Button>
|
|
233
|
+
<Button size="sm">{t('design_system.gallery.sampleCopy.small')}</Button>
|
|
234
|
+
<Button size="2xs">{t('design_system.gallery.sampleCopy.2xsmall')}</Button>
|
|
235
|
+
<Button size="icon" aria-label={t('design_system.gallery.examples.separator.add')}>
|
|
236
|
+
<Plus />
|
|
237
|
+
</Button>
|
|
238
|
+
</>)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export function IconButtonButtonsVariantsSample() {
|
|
242
|
+
const t = useT()
|
|
243
|
+
return (<>
|
|
244
|
+
<IconButton variant="primary" aria-label={t('design_system.gallery.examples.separator.add')}>
|
|
245
|
+
<Plus />
|
|
246
|
+
</IconButton>
|
|
247
|
+
<IconButton variant="outline" aria-label={t('design_system.gallery.sampleCopy.edit')}>
|
|
248
|
+
<Pencil />
|
|
249
|
+
</IconButton>
|
|
250
|
+
<IconButton variant="ghost" aria-label={t('design_system.gallery.samples.richEditor.labels.more')}>
|
|
251
|
+
<MoreHorizontal />
|
|
252
|
+
</IconButton>
|
|
253
|
+
<IconButton variant="white" aria-label={t('design_system.gallery.sampleCopy.edit')}>
|
|
254
|
+
<Pencil />
|
|
255
|
+
</IconButton>
|
|
256
|
+
<IconButton variant="destructive" aria-label={t('design_system.gallery.sampleCopy.delete')}>
|
|
257
|
+
<Trash2 />
|
|
258
|
+
</IconButton>
|
|
259
|
+
</>)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function IconButtonButtonsSizesSample() {
|
|
263
|
+
const t = useT()
|
|
264
|
+
return (<>
|
|
265
|
+
<IconButton size="lg" aria-label={t('design_system.gallery.sampleCopy.edit')}>
|
|
266
|
+
<Pencil />
|
|
267
|
+
</IconButton>
|
|
268
|
+
<IconButton size="default" aria-label={t('design_system.gallery.sampleCopy.edit')}>
|
|
269
|
+
<Pencil />
|
|
270
|
+
</IconButton>
|
|
271
|
+
<IconButton size="sm" aria-label={t('design_system.gallery.sampleCopy.edit')}>
|
|
272
|
+
<Pencil />
|
|
273
|
+
</IconButton>
|
|
274
|
+
<IconButton size="xs" aria-label={t('design_system.gallery.sampleCopy.edit')}>
|
|
275
|
+
<Pencil />
|
|
276
|
+
</IconButton>
|
|
277
|
+
</>)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
export function IconButtonButtonsFullRadiusSample() {
|
|
281
|
+
const t = useT()
|
|
282
|
+
return (<IconButton fullRadius aria-label={t('design_system.gallery.examples.separator.add')}>
|
|
283
|
+
<Plus />
|
|
284
|
+
</IconButton>)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export function LinkButtonButtonsAsAnchorSample() {
|
|
288
|
+
const t = useT()
|
|
289
|
+
return (<LinkButton asChild>
|
|
290
|
+
<a href="#gallery-entry-link-button">{t('design_system.gallery.sampleCopy.openLink')}</a>
|
|
291
|
+
</LinkButton>)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export function FancyButtonButtonsIntentsSample() {
|
|
295
|
+
const t = useT()
|
|
296
|
+
return (<>
|
|
297
|
+
<FancyButton intent="neutral">{t('design_system.gallery.sampleCopy.neutral')}</FancyButton>
|
|
298
|
+
<FancyButton intent="basic">{t('design_system.gallery.sampleCopy.basic')}</FancyButton>
|
|
299
|
+
<FancyButton intent="primary">{t('design_system.gallery.sampleCopy.primary')}</FancyButton>
|
|
300
|
+
<FancyButton intent="destructive">{t('design_system.gallery.sampleCopy.destructive')}</FancyButton>
|
|
301
|
+
</>)
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export function FancyButtonButtonsSizesSample() {
|
|
305
|
+
const t = useT()
|
|
306
|
+
return (<>
|
|
307
|
+
<FancyButton size="default">{t('design_system.gallery.examples.aiProduct.default')}</FancyButton>
|
|
308
|
+
<FancyButton size="sm">{t('design_system.gallery.sampleCopy.small')}</FancyButton>
|
|
309
|
+
<FancyButton size="xs">{t('design_system.gallery.sampleCopy.xsmall')}</FancyButton>
|
|
310
|
+
</>)
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function ButtonGroupButtonsHorizontalSample() {
|
|
314
|
+
const t = useT()
|
|
315
|
+
return (<ButtonGroup>
|
|
316
|
+
<Button variant="outline">{t('design_system.gallery.samples.hr.save')}</Button>
|
|
317
|
+
<Button variant="outline">{t('design_system.gallery.sampleCopy.saveNew')}</Button>
|
|
318
|
+
<IconButton size="lg" aria-label={t('design_system.gallery.samples.richEditor.labels.more')}>
|
|
319
|
+
<MoreHorizontal />
|
|
320
|
+
</IconButton>
|
|
321
|
+
</ButtonGroup>)
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export function ButtonGroupButtonsVerticalSample() {
|
|
325
|
+
const t = useT()
|
|
326
|
+
return (<ButtonGroup orientation="vertical" size="sm">
|
|
327
|
+
<Button variant="outline" size="sm">{t('design_system.gallery.sampleCopy.top')}</Button>
|
|
328
|
+
<Button variant="outline" size="sm">{t('design_system.gallery.sampleCopy.middle')}</Button>
|
|
329
|
+
<Button variant="outline" size="sm">{t('design_system.gallery.sampleCopy.bottom')}</Button>
|
|
330
|
+
</ButtonGroup>)
|
|
331
|
+
}
|