decantr 0.9.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/AGENTS.md +868 -0
- package/CHANGELOG.md +255 -0
- package/CLAUDE.md +178 -0
- package/LICENSE +21 -0
- package/README.md +229 -0
- package/cli/art.js +127 -0
- package/cli/commands/a11y.js +61 -0
- package/cli/commands/audit.js +225 -0
- package/cli/commands/build.js +38 -0
- package/cli/commands/dev.js +18 -0
- package/cli/commands/doctor.js +197 -0
- package/cli/commands/figma-sync.js +48 -0
- package/cli/commands/figma-tokens.js +55 -0
- package/cli/commands/generate.js +26 -0
- package/cli/commands/init.js +116 -0
- package/cli/commands/lint.js +209 -0
- package/cli/commands/mcp.js +530 -0
- package/cli/commands/migrate.js +175 -0
- package/cli/commands/test.js +38 -0
- package/cli/commands/validate.js +354 -0
- package/cli/index.js +113 -0
- package/package.json +95 -0
- package/reference/atoms.md +517 -0
- package/reference/behaviors.md +384 -0
- package/reference/build-tooling.md +275 -0
- package/reference/color-guidelines.md +965 -0
- package/reference/component-lifecycle.md +137 -0
- package/reference/compound-spacing.md +95 -0
- package/reference/decantation-process.md +499 -0
- package/reference/dev-server-routes.md +93 -0
- package/reference/form-system.md +253 -0
- package/reference/i18n.md +336 -0
- package/reference/icons.md +576 -0
- package/reference/llm-primer.md +953 -0
- package/reference/plugins.md +252 -0
- package/reference/registry-consumption.md +76 -0
- package/reference/router.md +217 -0
- package/reference/shells.md +116 -0
- package/reference/spatial-guidelines.md +541 -0
- package/reference/ssr.md +234 -0
- package/reference/state-data.md +215 -0
- package/reference/state-patterns.md +166 -0
- package/reference/state.md +194 -0
- package/reference/style-system.md +110 -0
- package/reference/tokens.md +460 -0
- package/src/app.js +19 -0
- package/src/chart/_animate.js +266 -0
- package/src/chart/_base.js +109 -0
- package/src/chart/_data.js +209 -0
- package/src/chart/_format.js +106 -0
- package/src/chart/_interact.js +364 -0
- package/src/chart/_palette.js +105 -0
- package/src/chart/_renderer.js +52 -0
- package/src/chart/_scene.js +262 -0
- package/src/chart/_shared.js +371 -0
- package/src/chart/index.js +637 -0
- package/src/chart/layouts/_layout-base.js +328 -0
- package/src/chart/layouts/cartesian.js +148 -0
- package/src/chart/layouts/hierarchy.js +562 -0
- package/src/chart/layouts/polar.js +101 -0
- package/src/chart/renderers/canvas.js +179 -0
- package/src/chart/renderers/svg.js +256 -0
- package/src/chart/renderers/webgpu.js +715 -0
- package/src/chart/types/_type-base.js +26 -0
- package/src/chart/types/area.js +134 -0
- package/src/chart/types/bar.js +173 -0
- package/src/chart/types/box-plot.js +125 -0
- package/src/chart/types/bubble.js +63 -0
- package/src/chart/types/candlestick.js +115 -0
- package/src/chart/types/chord.js +85 -0
- package/src/chart/types/combination.js +108 -0
- package/src/chart/types/funnel.js +68 -0
- package/src/chart/types/gauge.js +163 -0
- package/src/chart/types/heatmap.js +98 -0
- package/src/chart/types/histogram.js +71 -0
- package/src/chart/types/line.js +111 -0
- package/src/chart/types/org-chart.js +93 -0
- package/src/chart/types/pie.js +81 -0
- package/src/chart/types/radar.js +96 -0
- package/src/chart/types/radial.js +68 -0
- package/src/chart/types/range-area.js +55 -0
- package/src/chart/types/range-bar.js +61 -0
- package/src/chart/types/sankey.js +73 -0
- package/src/chart/types/scatter.js +66 -0
- package/src/chart/types/sparkline.js +81 -0
- package/src/chart/types/sunburst.js +69 -0
- package/src/chart/types/swimlane.js +88 -0
- package/src/chart/types/treemap.js +62 -0
- package/src/chart/types/waterfall.js +100 -0
- package/src/components/_base.js +1658 -0
- package/src/components/_behaviors.js +1140 -0
- package/src/components/_primitives.js +534 -0
- package/src/components/_qr-encoder.js +539 -0
- package/src/components/accordion.js +207 -0
- package/src/components/affix.js +62 -0
- package/src/components/alert-dialog.js +75 -0
- package/src/components/alert.js +47 -0
- package/src/components/aspect-ratio.js +24 -0
- package/src/components/avatar-group.js +55 -0
- package/src/components/avatar.js +38 -0
- package/src/components/back-top.js +75 -0
- package/src/components/badge.js +74 -0
- package/src/components/banner.js +68 -0
- package/src/components/breadcrumb.js +162 -0
- package/src/components/button.js +115 -0
- package/src/components/calendar.js +131 -0
- package/src/components/card.js +192 -0
- package/src/components/carousel.js +98 -0
- package/src/components/cascader.js +261 -0
- package/src/components/checkbox.js +80 -0
- package/src/components/chip.js +81 -0
- package/src/components/code-block.js +82 -0
- package/src/components/collapsible.js +50 -0
- package/src/components/color-palette.js +438 -0
- package/src/components/color-picker.js +314 -0
- package/src/components/combobox.js +181 -0
- package/src/components/command.js +174 -0
- package/src/components/comment.js +206 -0
- package/src/components/context-menu.js +76 -0
- package/src/components/data-table.js +724 -0
- package/src/components/date-picker.js +217 -0
- package/src/components/date-range-picker.js +244 -0
- package/src/components/datetime-picker.js +271 -0
- package/src/components/descriptions.js +68 -0
- package/src/components/drawer.js +179 -0
- package/src/components/dropdown.js +88 -0
- package/src/components/empty.js +41 -0
- package/src/components/float-button.js +90 -0
- package/src/components/form.js +106 -0
- package/src/components/hover-card.js +49 -0
- package/src/components/icon.js +87 -0
- package/src/components/image.js +97 -0
- package/src/components/index.js +117 -0
- package/src/components/input-group.js +75 -0
- package/src/components/input-number.js +155 -0
- package/src/components/input-otp.js +178 -0
- package/src/components/input.js +91 -0
- package/src/components/kbd.js +36 -0
- package/src/components/label.js +25 -0
- package/src/components/list.js +118 -0
- package/src/components/masked-input.js +236 -0
- package/src/components/mentions.js +165 -0
- package/src/components/menu.js +259 -0
- package/src/components/message.js +80 -0
- package/src/components/modal.js +147 -0
- package/src/components/navigation-menu.js +166 -0
- package/src/components/notification.js +84 -0
- package/src/components/pagination.js +104 -0
- package/src/components/placeholder.js +132 -0
- package/src/components/popconfirm.js +70 -0
- package/src/components/popover.js +58 -0
- package/src/components/progress.js +61 -0
- package/src/components/qrcode.js +251 -0
- package/src/components/radiogroup.js +120 -0
- package/src/components/range-slider.js +176 -0
- package/src/components/rate.js +186 -0
- package/src/components/resizable.js +83 -0
- package/src/components/result.js +57 -0
- package/src/components/scroll-area.js +43 -0
- package/src/components/segmented.js +97 -0
- package/src/components/select.js +165 -0
- package/src/components/separator.js +31 -0
- package/src/components/shell.js +407 -0
- package/src/components/skeleton.js +39 -0
- package/src/components/slider.js +141 -0
- package/src/components/sortable-list.js +176 -0
- package/src/components/space.js +42 -0
- package/src/components/spinner.js +112 -0
- package/src/components/splitter.js +147 -0
- package/src/components/statistic.js +136 -0
- package/src/components/steps.js +99 -0
- package/src/components/switch.js +95 -0
- package/src/components/table.js +44 -0
- package/src/components/tabs.js +216 -0
- package/src/components/tag.js +115 -0
- package/src/components/textarea.js +82 -0
- package/src/components/time-picker.js +153 -0
- package/src/components/time-range-picker.js +170 -0
- package/src/components/timeline.js +226 -0
- package/src/components/toast.js +71 -0
- package/src/components/toggle.js +213 -0
- package/src/components/tooltip.js +57 -0
- package/src/components/tour.js +159 -0
- package/src/components/transfer.js +163 -0
- package/src/components/tree-select.js +274 -0
- package/src/components/tree.js +141 -0
- package/src/components/typography.js +136 -0
- package/src/components/upload.js +118 -0
- package/src/components/visually-hidden.js +20 -0
- package/src/components/watermark.js +124 -0
- package/src/core/index.js +539 -0
- package/src/core/lifecycle.js +69 -0
- package/src/css/atoms.js +651 -0
- package/src/css/components.js +940 -0
- package/src/css/derive.js +1296 -0
- package/src/css/index.js +265 -0
- package/src/css/runtime.js +268 -0
- package/src/css/styles/addons/bioluminescent.js +93 -0
- package/src/css/styles/addons/clay.js +70 -0
- package/src/css/styles/addons/clean.js +57 -0
- package/src/css/styles/addons/command-center.js +143 -0
- package/src/css/styles/addons/dopamine.js +83 -0
- package/src/css/styles/addons/editorial.js +80 -0
- package/src/css/styles/addons/glassmorphism.js +99 -0
- package/src/css/styles/addons/liquid-glass.js +105 -0
- package/src/css/styles/addons/prismatic.js +100 -0
- package/src/css/styles/addons/retro.js +63 -0
- package/src/css/styles/auradecantism.js +96 -0
- package/src/css/theme-registry.js +444 -0
- package/src/data/entity.js +281 -0
- package/src/data/index.js +13 -0
- package/src/data/persist.js +225 -0
- package/src/data/query.js +839 -0
- package/src/data/realtime.js +299 -0
- package/src/data/url.js +177 -0
- package/src/data/worker.js +134 -0
- package/src/explorer/archetypes.js +243 -0
- package/src/explorer/atoms.js +228 -0
- package/src/explorer/charts.js +497 -0
- package/src/explorer/components.js +129 -0
- package/src/explorer/foundations.js +949 -0
- package/src/explorer/icons.js +178 -0
- package/src/explorer/patterns.js +247 -0
- package/src/explorer/recipes.js +194 -0
- package/src/explorer/shared/pattern-examples.js +1337 -0
- package/src/explorer/shared/showcase-renderer.js +958 -0
- package/src/explorer/shared/spec-table.js +41 -0
- package/src/explorer/shared/usage-links.js +87 -0
- package/src/explorer/shell-config.js +10 -0
- package/src/explorer/shells.js +551 -0
- package/src/explorer/styles.js +161 -0
- package/src/explorer/tokens.js +262 -0
- package/src/explorer/tools.js +525 -0
- package/src/form/index.js +804 -0
- package/src/i18n/index.js +251 -0
- package/src/icons/essential.js +479 -0
- package/src/icons/index.js +53 -0
- package/src/plugins/index.js +282 -0
- package/src/registry/archetypes/content-site.json +71 -0
- package/src/registry/archetypes/docs-explorer.json +23 -0
- package/src/registry/archetypes/ecommerce.json +104 -0
- package/src/registry/archetypes/financial-dashboard.json +77 -0
- package/src/registry/archetypes/index.json +41 -0
- package/src/registry/archetypes/portfolio.json +82 -0
- package/src/registry/archetypes/recipe-community.json +159 -0
- package/src/registry/archetypes/saas-dashboard.json +86 -0
- package/src/registry/architect/cross-cutting.json +45 -0
- package/src/registry/architect/domains/ecommerce.json +294 -0
- package/src/registry/architect/domains/financial-services.json +302 -0
- package/src/registry/architect/index.json +26 -0
- package/src/registry/architect/traits.json +379 -0
- package/src/registry/atoms.json +16 -0
- package/src/registry/chart-showcase.json +160 -0
- package/src/registry/chart.json +136 -0
- package/src/registry/components.json +8616 -0
- package/src/registry/core.json +216 -0
- package/src/registry/css.json +319 -0
- package/src/registry/data.json +135 -0
- package/src/registry/foundations.json +11 -0
- package/src/registry/icons.json +463 -0
- package/src/registry/index.json +101 -0
- package/src/registry/patterns/activity-feed.json +37 -0
- package/src/registry/patterns/article-content.json +27 -0
- package/src/registry/patterns/auth-form.json +37 -0
- package/src/registry/patterns/author-card.json +20 -0
- package/src/registry/patterns/card-grid.json +127 -0
- package/src/registry/patterns/category-nav.json +26 -0
- package/src/registry/patterns/chart-grid.json +36 -0
- package/src/registry/patterns/chat-interface.json +37 -0
- package/src/registry/patterns/checklist-card.json +55 -0
- package/src/registry/patterns/comparison-panel.json +27 -0
- package/src/registry/patterns/component-showcase.json +24 -0
- package/src/registry/patterns/contact-form.json +31 -0
- package/src/registry/patterns/cta-section.json +20 -0
- package/src/registry/patterns/data-table.json +37 -0
- package/src/registry/patterns/detail-header.json +83 -0
- package/src/registry/patterns/detail-panel.json +27 -0
- package/src/registry/patterns/explorer-shell.json +22 -0
- package/src/registry/patterns/filter-bar.json +33 -0
- package/src/registry/patterns/filter-sidebar.json +27 -0
- package/src/registry/patterns/form-sections.json +110 -0
- package/src/registry/patterns/goal-tracker.json +27 -0
- package/src/registry/patterns/hero.json +107 -0
- package/src/registry/patterns/index.json +47 -0
- package/src/registry/patterns/kpi-grid.json +36 -0
- package/src/registry/patterns/media-gallery.json +20 -0
- package/src/registry/patterns/order-history.json +20 -0
- package/src/registry/patterns/pagination.json +19 -0
- package/src/registry/patterns/photo-to-recipe.json +36 -0
- package/src/registry/patterns/pipeline-tracker.json +28 -0
- package/src/registry/patterns/post-list.json +27 -0
- package/src/registry/patterns/pricing-table.json +32 -0
- package/src/registry/patterns/scorecard.json +28 -0
- package/src/registry/patterns/search-bar.json +20 -0
- package/src/registry/patterns/specimen-grid.json +19 -0
- package/src/registry/patterns/stat-card.json +55 -0
- package/src/registry/patterns/stats-bar.json +55 -0
- package/src/registry/patterns/steps-card.json +55 -0
- package/src/registry/patterns/table-of-contents.json +19 -0
- package/src/registry/patterns/testimonials.json +21 -0
- package/src/registry/patterns/timeline.json +27 -0
- package/src/registry/patterns/token-inspector.json +21 -0
- package/src/registry/patterns/wizard.json +27 -0
- package/src/registry/recipe-auradecantism.json +69 -0
- package/src/registry/recipe-clean.json +65 -0
- package/src/registry/recipe-command-center.json +78 -0
- package/src/registry/router.json +73 -0
- package/src/registry/schema/README.md +197 -0
- package/src/registry/skeletons.json +259 -0
- package/src/registry/state.json +137 -0
- package/src/registry/tokens.json +40 -0
- package/src/router/hash.js +17 -0
- package/src/router/history.js +18 -0
- package/src/router/index.js +598 -0
- package/src/ssr/index.js +922 -0
- package/src/state/arrays.js +181 -0
- package/src/state/devtools.js +647 -0
- package/src/state/index.js +498 -0
- package/src/state/middleware.js +288 -0
- package/src/state/scheduler.js +206 -0
- package/src/state/store.js +300 -0
- package/src/tags/index.js +19 -0
- package/src/tannins/auth.js +396 -0
- package/src/test/dom.js +352 -0
- package/src/test/index.js +62 -0
- package/src/test/state.js +306 -0
- package/tools/a11y-audit.js +487 -0
- package/tools/analyzer.js +315 -0
- package/tools/audit.js +706 -0
- package/tools/builder.js +1422 -0
- package/tools/css-extract.js +188 -0
- package/tools/dev-server.js +316 -0
- package/tools/dts-gen.js +1260 -0
- package/tools/figma-components.js +329 -0
- package/tools/figma-patterns.js +516 -0
- package/tools/figma-plugin/code.js +453 -0
- package/tools/figma-plugin/manifest.json +14 -0
- package/tools/figma-plugin/ui.html +268 -0
- package/tools/figma-render.js +293 -0
- package/tools/figma-tokens.js +712 -0
- package/tools/figma-upload.js +318 -0
- package/tools/generate.js +738 -0
- package/tools/icons.js +133 -0
- package/tools/init-templates.js +265 -0
- package/tools/install-hooks.sh +5 -0
- package/tools/migrations/0.5.0.js +53 -0
- package/tools/migrations/0.6.0.js +95 -0
- package/tools/minify.js +170 -0
- package/tools/pre-commit +4 -0
- package/tools/registry.js +662 -0
- package/tools/reset-playground.js +61 -0
- package/tools/starter-templates/content-site/app.js +49 -0
- package/tools/starter-templates/content-site/essence.js +19 -0
- package/tools/starter-templates/content-site/pages.js +31 -0
- package/tools/starter-templates/ecommerce/app.js +50 -0
- package/tools/starter-templates/ecommerce/essence.js +19 -0
- package/tools/starter-templates/ecommerce/pages.js +31 -0
- package/tools/starter-templates/landing-page/app.js +38 -0
- package/tools/starter-templates/landing-page/essence.js +18 -0
- package/tools/starter-templates/landing-page/pages.js +21 -0
- package/tools/starter-templates/portfolio/app.js +45 -0
- package/tools/starter-templates/portfolio/essence.js +19 -0
- package/tools/starter-templates/portfolio/pages.js +33 -0
- package/tools/starter-templates/saas-dashboard/app.js +70 -0
- package/tools/starter-templates/saas-dashboard/essence.js +19 -0
- package/tools/starter-templates/saas-dashboard/pages.js +31 -0
- package/tools/verify-pack.js +203 -0
- package/types/chart.d.ts +77 -0
- package/types/components.d.ts +587 -0
- package/types/core.d.ts +89 -0
- package/types/css.d.ts +149 -0
- package/types/data.d.ts +238 -0
- package/types/form.d.ts +164 -0
- package/types/i18n.d.ts +51 -0
- package/types/icons.d.ts +27 -0
- package/types/index.d.ts +13 -0
- package/types/router.d.ts +116 -0
- package/types/ssr.d.ts +102 -0
- package/types/state.d.ts +83 -0
- package/types/tags.d.ts +62 -0
- package/types/tannins.d.ts +63 -0
- package/types/test.d.ts +48 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "detail-panel",
|
|
4
|
+
"name": "Detail Panel",
|
|
5
|
+
"description": "Full detail view for a single entity with a header section and tabbed content areas. Used for user profiles, product details, and record views.",
|
|
6
|
+
"components": ["Tabs", "Card", "Card.Header", "Card.Body", "Avatar", "Badge", "Button", "Separator", "Tooltip"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "stack",
|
|
9
|
+
"atoms": "_flex _flexCol _gap4 _p4",
|
|
10
|
+
"slots": {
|
|
11
|
+
"header": "Entity header with Avatar, title (_heading3), subtitle (_caption), status Badge, and action Buttons via _flex _gap3 _itemsCenter. Wrapped in Card.Header",
|
|
12
|
+
"tabs": "Tabs component with content panels. Common tabs: Overview, Details, Activity, Settings",
|
|
13
|
+
"tab-content": "Each tab panel contains domain-specific content using Cards, form fields, or activity-feed pattern"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"recipe_overrides": {
|
|
17
|
+
"command-center": {
|
|
18
|
+
"wrapper": "cc-frame",
|
|
19
|
+
"atoms": "cc-bar",
|
|
20
|
+
"notes": "Header uses cc-bar with cc-label for entity name. Status Badge gets cc-glow for active states. Tab bar uses cc-bar styling. Content areas get cc-scanline."
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"code": {
|
|
24
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Tabs, Badge, Separator, Descriptions, Button } from 'decantr/components';",
|
|
25
|
+
"example": "function DetailPanel() {\n const { div, h2, span } = tags;\n const entity = {\n name: 'Acme Corporation',\n active: true,\n status: 'Active',\n fields: [\n { label: 'Industry', value: 'Technology' },\n { label: 'Size', value: '500-1000 employees' },\n { label: 'Location', value: 'San Francisco, CA' },\n { label: 'Founded', value: '2018' }\n ]\n };\n\n return div({ class: css('_flex _col _gap4 _p4') },\n div({ class: css('_flex _aic _jcsb') },\n div({ class: css('_flex _aic _gap3') },\n h2({ class: css('_heading3') }, entity.name),\n Badge({ variant: entity.active ? 'success' : 'default' }, entity.status)\n ),\n div({ class: css('_flex _gap2') },\n Button({ variant: 'outline', size: 'sm' }, 'Edit'),\n Button({ variant: 'destructive', size: 'sm' }, 'Delete')\n )\n ),\n Separator(),\n Tabs({ items: [\n { label: 'Overview', content: () => Descriptions({ items: entity.fields }) },\n { label: 'Activity', content: () => div({ class: css('_p4 _fgmuted') }, 'Activity timeline...') },\n { label: 'Settings', content: () => div({ class: css('_p4 _fgmuted') }, 'Settings panel...') }\n ] })\n );\n}"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "explorer-shell",
|
|
4
|
+
"name": "Explorer Shell",
|
|
5
|
+
"description": "Application shell for documentation explorers: persistent header with search, collapsible sidebar with layered navigation, scrollable main content, and floating control panel.",
|
|
6
|
+
"components": ["Input", "Select", "Button"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "grid",
|
|
9
|
+
"atoms": "_flex _col _h[100vh]",
|
|
10
|
+
"slots": {
|
|
11
|
+
"header": "Fixed header bar with logo, search trigger (Cmd+K hint), and controls toggle",
|
|
12
|
+
"sidebar": "Collapsible nav sidebar with filter input and expandable layer groups",
|
|
13
|
+
"main": "Scrollable content area with max-width constraint",
|
|
14
|
+
"search-modal": "Full-screen search overlay with focus trap",
|
|
15
|
+
"hud-panel": "Floating control panel for style/mode/shape switching"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"code": {
|
|
19
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Input, Button, icon } from 'decantr/components';\nimport { link } from 'decantr/router';",
|
|
20
|
+
"example": "function ExplorerShell() {\n const { div, aside, main, header, span, nav } = tags;\n const [searchOpen, setSearchOpen] = createSignal(false);\n const sections = [\n { href: '#/foundations', icon: 'layers', label: 'Foundations' },\n { href: '#/components', icon: 'box', label: 'Components' },\n { href: '#/patterns', icon: 'layout', label: 'Patterns' },\n { href: '#/tokens', icon: 'palette', label: 'Tokens' }\n ];\n\n return div({ class: css('_grid _h[100vh]'), style: 'grid-template-columns:260px 1fr;grid-template-rows:auto 1fr' },\n aside({ class: css('_flex _col _gap1 _p3 _bgmuted _overflow[auto] _borderR'), style: 'grid-row:1/3' },\n Input({ placeholder: 'Search... (Cmd+K)', class: css('_mb3'), onfocus: () => setSearchOpen(true) }),\n nav({ class: css('_flex _col _gap1') },\n ...sections.map(s =>\n link({ href: s.href, class: css('_flex _aic _gap2 _p2 _px3 _r2 _textsm _fgfg _trans') },\n icon(s.icon), s.label\n )\n )\n )\n ),\n header({ class: css('_flex _aic _jcsb _px6 _py3 _borderB') },\n span({ class: css('_heading4') }, 'Explorer'),\n div({ class: css('_flex _gap2') },\n Button({ variant: 'ghost', size: 'sm', onclick: () => setSearchOpen(true) }, icon('search'))\n )\n ),\n main({ class: css('_flex _col _gap4 _p6 _overflow[auto]') },\n div({ class: css('_p4 _fgmuted') }, 'Select a section from the sidebar to begin exploring.')\n )\n );\n}"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "filter-bar",
|
|
4
|
+
"name": "Filter Bar",
|
|
5
|
+
"description": "Horizontal filter controls with search, dropdowns, date pickers, and active filter chips.",
|
|
6
|
+
"components": ["Input", "Select", "Button", "DatePicker", "Chip"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "row",
|
|
9
|
+
"atoms": "_flex _gap3 _aic _wrap _py3",
|
|
10
|
+
"slots": {
|
|
11
|
+
"search": "Search Input for keyword filtering",
|
|
12
|
+
"filters": "Select dropdowns and DatePicker controls",
|
|
13
|
+
"active-filters": "Chip list showing currently applied filters",
|
|
14
|
+
"actions": "Clear-all or apply Button actions"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"recipe_overrides": {
|
|
18
|
+
"auradecantism": {
|
|
19
|
+
"wrapper": "",
|
|
20
|
+
"atoms": "d-glass _r4 _px4 _py2",
|
|
21
|
+
"notes": "Filter bar in glass strip. Active filter chips use primary color."
|
|
22
|
+
},
|
|
23
|
+
"clean": {
|
|
24
|
+
"wrapper": "",
|
|
25
|
+
"atoms": "_borderB _pb3",
|
|
26
|
+
"notes": "Filter bar with bottom border. Simple, no background."
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"code": {
|
|
30
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Input, Select, Button, DatePicker, Chip } from 'decantr/components';",
|
|
31
|
+
"example": "function FilterBar() {\n const { div } = tags;\n const [search, setSearch] = createSignal('');\n const [category, setCategory] = createSignal('all');\n const [filters, setFilters] = createSignal([]);\n\n return div({ class: css('_flex _gap3 _aic _wrap _py3') },\n Input({ placeholder: 'Search...', value: search, onchange: e => setSearch(e.target.value), class: css('_w[240px]') }),\n Select({ value: category, onchange: v => { setCategory(v); if (v !== 'all') setFilters([...filters(), v]); },\n options: [\n { label: 'All Categories', value: 'all' },\n { label: 'Sales', value: 'sales' },\n { label: 'Marketing', value: 'marketing' }\n ] }),\n DatePicker({ placeholder: 'Date range' }),\n ...filters().map(f => Chip({ label: f, onClose: () => setFilters(filters().filter(x => x !== f)) })),\n filters().length > 0 ? Button({ variant: 'ghost', size: 'sm', onclick: () => setFilters([]) }, 'Clear All') : null\n );\n}"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "filter-sidebar",
|
|
4
|
+
"name": "Filter Sidebar",
|
|
5
|
+
"description": "Vertical filter panel with grouped controls for refining data views. Pairs with data-table or product-grid patterns.",
|
|
6
|
+
"components": ["Checkbox", "Select", "Switch", "Button", "Separator", "Accordion", "Input"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "stack",
|
|
9
|
+
"atoms": "_flex _flexCol _gap4 _p4 _wFull",
|
|
10
|
+
"slots": {
|
|
11
|
+
"search": "Optional keyword Input with icon at top",
|
|
12
|
+
"filter-groups": "Accordion sections each containing Checkbox lists, Select dropdowns, or Switch toggles",
|
|
13
|
+
"actions": "Bottom bar with apply Button (primary) and clear Button (ghost), separated by Separator"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"recipe_overrides": {
|
|
17
|
+
"command-center": {
|
|
18
|
+
"wrapper": "cc-frame-sm",
|
|
19
|
+
"atoms": "cc-scanline",
|
|
20
|
+
"notes": "Section headers use cc-label. Active filter counts use cc-data. Apply button gets cc-glow. Panel background uses cc-scanline."
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"code": {
|
|
24
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Checkbox, RadioGroup, Button, Accordion, Badge } from 'decantr/components';",
|
|
25
|
+
"example": "function FilterSidebar() {\n const { div, h3 } = tags;\n const categories = [\n { id: 'electronics', name: 'Electronics' },\n { id: 'clothing', name: 'Clothing' },\n { id: 'books', name: 'Books' },\n { id: 'home', name: 'Home & Garden' }\n ];\n const priceRanges = [\n { id: 'under25', label: 'Under $25' },\n { id: '25to50', label: '$25 - $50' },\n { id: '50to100', label: '$50 - $100' },\n { id: 'over100', label: 'Over $100' }\n ];\n const [selected, setSelected] = createSignal([]);\n\n return div({ class: css('_flex _col _gap4 _p4 _w[260px] _borderR _overflow[auto]') },\n h3({ class: css('_heading5') }, 'Filters'),\n Accordion({ items: [\n { title: 'Category', content: () =>\n div({ class: css('_flex _col _gap2') },\n ...categories.map(cat =>\n Checkbox({ label: cat.name, checked: selected().includes(cat.id),\n onchange: v => setSelected(v ? [...selected(), cat.id] : selected().filter(x => x !== cat.id))\n })\n )\n )\n },\n { title: 'Price Range', content: () =>\n RadioGroup({ options: priceRanges.map(r => ({ label: r.label, value: r.id })) })\n }\n ] }),\n Button({ variant: 'primary', class: css('_wfull') }, 'Apply Filters')\n );\n}"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v2.json",
|
|
3
|
+
"id": "form-sections",
|
|
4
|
+
"name": "Form Sections",
|
|
5
|
+
"description": "Grouped form fields organized into labeled sections with consistent spacing. Supports settings pages, content creation forms, and structured data entry via presets.",
|
|
6
|
+
"components": ["Input", "Select", "Switch", "Textarea", "Checkbox", "Button", "Separator"],
|
|
7
|
+
"default_preset": "settings",
|
|
8
|
+
"presets": {
|
|
9
|
+
"settings": {
|
|
10
|
+
"description": "Grouped form fields for settings pages and profile editing.",
|
|
11
|
+
"components": ["Input", "Select", "Switch", "Textarea", "Checkbox", "Button", "Separator"],
|
|
12
|
+
"blend": {
|
|
13
|
+
"layout": "stack",
|
|
14
|
+
"atoms": "_flex _flexCol _gap8 _p6 _mxAuto",
|
|
15
|
+
"slots": {
|
|
16
|
+
"section": "Repeating group: section title (_heading5), description (_caption _muted), then field rows separated by Separator",
|
|
17
|
+
"field-row": "Label + control pair via _flex _flexCol _gap1 or _grid _gc2 for side-by-side",
|
|
18
|
+
"actions": "Bottom bar with save Button (primary) and cancel Button (ghost) via _flex _gap3 _justifyEnd"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"code": {
|
|
22
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Input, Select, Textarea, Button, Separator } from 'decantr/components';",
|
|
23
|
+
"example": "function FormSections() {\n const { div, h3, p } = tags;\n\n const section = (title, desc, ...fields) =>\n div({ class: css('_flex _col _gap4') },\n div({}, h3({ class: css('_heading5') }, title), p({ class: css('_fgmuted _textsm') }, desc)),\n ...fields\n );\n\n return div({ class: css('_flex _col _gap8 _p6 _mw[720px]') },\n section('Personal Info', 'Basic contact details',\n div({ class: css('_grid _gc2 _gap4') },\n Input({ label: 'First Name' }),\n Input({ label: 'Last Name' })\n ),\n Input({ label: 'Email', type: 'email' })\n ),\n Separator(),\n section('Company', 'Organization details',\n Input({ label: 'Company Name' }),\n Select({ label: 'Industry', options: [{ label: 'Technology', value: 'tech' }, { label: 'Finance', value: 'finance' }] })\n ),\n Separator(),\n section('Notes', 'Additional information',\n Textarea({ label: 'Notes', rows: 4 })\n ),\n div({ class: css('_flex _jcfe _gap3') },\n Button({ variant: 'outline' }, 'Cancel'),\n Button({ variant: 'primary' }, 'Save')\n )\n );\n}"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"creation": {
|
|
27
|
+
"description": "Content creation form with photo upload, basics, metadata, and dynamic lists. For recipe/article creation.",
|
|
28
|
+
"components": ["Card", "Card.Header", "Card.Body", "Input", "Textarea", "InputNumber", "Segmented", "Button", "Upload", "Collapsible", "Chip", "Separator", "icon"],
|
|
29
|
+
"blend": {
|
|
30
|
+
"layout": "stack",
|
|
31
|
+
"atoms": "_flex _col _gap6 _mw[720px] _mxAuto _p4",
|
|
32
|
+
"slots": {
|
|
33
|
+
"photo": "Upload dropzone for cover photo",
|
|
34
|
+
"basics": "Card with title Input, description Textarea",
|
|
35
|
+
"metadata": "Card with numeric inputs and segmented controls",
|
|
36
|
+
"dynamic-lists": "Cards with dynamic add/remove rows for items",
|
|
37
|
+
"tags": "Tag input with Chip display",
|
|
38
|
+
"submit": "Publish Button with draft toggle"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"code": {
|
|
42
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Card, Input, Textarea, InputNumber, Segmented, Button, Upload, Collapsible, Chip, Separator, icon } from 'decantr/components';",
|
|
43
|
+
"example": "function CreationForm() {\n const { div, h3, label } = tags;\n const [title, setTitle] = createSignal('');\n const [items, setItems] = createSignal(['']);\n\n const addItem = () => setItems([...items(), '']);\n\n return div({ class: css('_flex _col _gap6 _mw[720px] _mxAuto _p4') },\n Upload({ accept: 'image/*', variant: 'dragger' }, 'Upload cover photo'),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, 'Basic Info')),\n Card.Body({ class: css('_flex _col _gap3') },\n Input({ label: 'Title', placeholder: 'Name', value: title, onchange: e => setTitle(e.target.value) }),\n Textarea({ label: 'Description', placeholder: 'Brief description...', rows: 3 })\n )\n ),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, 'Details')),\n Card.Body({ class: css('_flex _col _gap3') },\n div({ class: css('_grid _gc3 _gap3') },\n InputNumber({ label: 'Prep (min)', min: 0 }),\n InputNumber({ label: 'Cook (min)', min: 0 }),\n InputNumber({ label: 'Servings', min: 1 })\n ),\n Segmented({ label: 'Difficulty', options: ['Easy', 'Medium', 'Hard'] })\n )\n ),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, 'Items')),\n Card.Body({ class: css('_flex _col _gap2') },\n ...items().map((_, i) =>\n Input({ placeholder: `Item ${i + 1}` })\n ),\n Button({ variant: 'outline', size: 'sm', onclick: addItem }, icon('plus'), 'Add Item')\n )\n ),\n div({ class: css('_flex _jce _gap3') },\n Button({ variant: 'outline' }, 'Save Draft'),\n Button({ variant: 'primary' }, 'Publish')\n )\n );\n}"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"structured": {
|
|
47
|
+
"description": "Advanced structured form with tabular data entry, hierarchical sections, and auto-calculated fields.",
|
|
48
|
+
"components": ["Card", "Card.Header", "Card.Body", "Input", "Textarea", "InputNumber", "Select", "Segmented", "Button", "Upload", "Tabs", "Separator", "Badge", "icon"],
|
|
49
|
+
"blend": {
|
|
50
|
+
"layout": "stack",
|
|
51
|
+
"atoms": "_flex _col _gap6 _mw[840px] _mxAuto _p4",
|
|
52
|
+
"slots": {
|
|
53
|
+
"photo": "Upload dropzone for cover photo",
|
|
54
|
+
"basics": "Card with title, description, and scale selector",
|
|
55
|
+
"structured-items": "Card with tabular rows: multiple columns of inputs per row",
|
|
56
|
+
"hierarchical-sections": "Card with named sections, each containing ordered sub-items",
|
|
57
|
+
"timing-summary": "Auto-calculated totals display",
|
|
58
|
+
"metadata": "Card with categorization tags and metadata",
|
|
59
|
+
"submit": "Publish Button with draft toggle"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"code": {
|
|
63
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Card, Input, Textarea, InputNumber, Select, Segmented, Button, Upload, Tabs, Separator, Badge, icon } from 'decantr/components';",
|
|
64
|
+
"example": "function StructuredForm() {\n const { div, h3, span } = tags;\n const [items, setItems] = createSignal([{ qty: '', unit: '', name: '', prep: '' }]);\n const [sections, setSections] = createSignal([{ title: 'Main', steps: [{ text: '', time: 0 }] }]);\n const units = ['g', 'kg', 'ml', 'l', 'cup', 'tbsp', 'tsp', 'oz', 'lb', 'piece'];\n\n return div({ class: css('_flex _col _gap6 _mw[840px] _mxAuto _p4') },\n Upload({ accept: 'image/*', variant: 'dragger' }, 'Upload cover photo'),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, 'Basic Info')),\n Card.Body({ class: css('_flex _col _gap3') },\n Input({ label: 'Title', placeholder: 'Name' }),\n Textarea({ label: 'Description', rows: 3 }),\n Segmented({ label: 'Scale', options: ['1x', '2x', '4x'] })\n )\n ),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, 'Structured Items')),\n Card.Body({ class: css('_flex _col _gap2') },\n ...items().map((item, i) =>\n div({ class: css('_grid _gc4 _gap2 _aic') },\n InputNumber({ placeholder: 'Qty', size: 'sm' }),\n Select({ placeholder: 'Unit', options: units, size: 'sm' }),\n Input({ placeholder: 'Name', size: 'sm' }),\n Input({ placeholder: 'Notes', size: 'sm' })\n )\n ),\n Button({ variant: 'outline', size: 'sm' }, icon('plus'), 'Add Item')\n )\n ),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, 'Sections')),\n Card.Body({ class: css('_flex _col _gap4') },\n ...sections().map((sec, si) =>\n div({ class: css('_flex _col _gap3 _p3 _bgmuted _r4') },\n Input({ value: sec.title, placeholder: 'Section name', size: 'sm' }),\n ...sec.steps.map((step, i) =>\n div({ class: css('_flex _gap2 _aic') },\n Badge({ variant: 'outline' }, `${si + 1}.${i + 1}`),\n Textarea({ placeholder: 'Step description', rows: 2, class: css('_flex1') }),\n InputNumber({ placeholder: 'Min', size: 'sm', class: css('_w[80px]') })\n )\n ),\n Button({ variant: 'outline', size: 'sm' }, icon('plus'), 'Add Step')\n )\n ),\n Button({ variant: 'outline', size: 'sm' }, icon('plus'), 'Add Section')\n )\n ),\n div({ class: css('_flex _jce _gap3') },\n Button({ variant: 'outline' }, 'Save Draft'),\n Button({ variant: 'primary' }, 'Publish')\n )\n );\n}"
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
"default_blend": {
|
|
69
|
+
"layout": "stack",
|
|
70
|
+
"atoms": "_flex _flexCol _gap8 _p6 _mxAuto",
|
|
71
|
+
"slots": {
|
|
72
|
+
"section": "Repeating group: section title (_heading5), description (_caption _muted), then field rows separated by Separator",
|
|
73
|
+
"field-row": "Label + control pair via _flex _flexCol _gap1 or _grid _gc2 for side-by-side",
|
|
74
|
+
"actions": "Bottom bar with save Button (primary) and cancel Button (ghost) via _flex _gap3 _justifyEnd"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"recipe_overrides": {
|
|
78
|
+
"command-center": {
|
|
79
|
+
"wrapper": "cc-frame",
|
|
80
|
+
"atoms": "cc-grid",
|
|
81
|
+
"notes": "Section headers use cc-label. Required field indicators use cc-glow. Action bar uses cc-bar. Background uses cc-grid.",
|
|
82
|
+
"preset_notes": {
|
|
83
|
+
"creation": "Form sections use cc-frame-sm. Labels use cc-label. Submit button uses cc-glow.",
|
|
84
|
+
"structured": "Form sections use cc-frame-sm. Structured inputs use cc-grid layout. Timing data uses cc-data."
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"auradecantism": {
|
|
88
|
+
"wrapper": "",
|
|
89
|
+
"atoms": "",
|
|
90
|
+
"notes": "Form cards use d-glass. Section headers use d-gradient-text.",
|
|
91
|
+
"preset_notes": {
|
|
92
|
+
"creation": "Form cards use d-glass. Section headers use d-gradient-text. Submit button prominent.",
|
|
93
|
+
"structured": "Form cards use d-glass. Section headers use d-gradient-text. Structured table rows alternate opacity."
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
"clean": {
|
|
97
|
+
"wrapper": "",
|
|
98
|
+
"atoms": "",
|
|
99
|
+
"notes": "Standard form with subtle borders. Clean input styling.",
|
|
100
|
+
"preset_notes": {
|
|
101
|
+
"creation": "Standard form cards with subtle borders. Clean input styling.",
|
|
102
|
+
"structured": "Standard form cards with borders. Clean tabular layout."
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"code": {
|
|
107
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Input, Select, Textarea, Button, Separator } from 'decantr/components';",
|
|
108
|
+
"example": "function FormSections() {\n const { div, h3, p } = tags;\n\n const section = (title, desc, ...fields) =>\n div({ class: css('_flex _col _gap4') },\n div({}, h3({ class: css('_heading5') }, title), p({ class: css('_fgmuted _textsm') }, desc)),\n ...fields\n );\n\n return div({ class: css('_flex _col _gap8 _p6 _mw[720px]') },\n section('Personal Info', 'Basic contact details',\n div({ class: css('_grid _gc2 _gap4') },\n Input({ label: 'First Name' }),\n Input({ label: 'Last Name' })\n ),\n Input({ label: 'Email', type: 'email' })\n ),\n Separator(),\n section('Company', 'Organization details',\n Input({ label: 'Company Name' }),\n Select({ label: 'Industry', options: [{ label: 'Technology', value: 'tech' }, { label: 'Finance', value: 'finance' }] })\n ),\n Separator(),\n section('Notes', 'Additional information',\n Textarea({ label: 'Notes', rows: 4 })\n ),\n div({ class: css('_flex _jcfe _gap3') },\n Button({ variant: 'outline' }, 'Cancel'),\n Button({ variant: 'primary' }, 'Save')\n )\n );\n}"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "goal-tracker",
|
|
4
|
+
"name": "Goal Tracker",
|
|
5
|
+
"description": "Grid of metric cards comparing current values against targets. Each card shows label, current value, target value, variance (amount and percentage), progress indicator, and status badge (on-track/at-risk/behind).",
|
|
6
|
+
"components": ["Statistic", "Progress", "Badge", "icon", "Sparkline"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "grid",
|
|
9
|
+
"atoms": "_grid _gc3 _gap4 _p4",
|
|
10
|
+
"slots": {
|
|
11
|
+
"header": "Section title with _heading4, optional period selector (Select or Segmented)",
|
|
12
|
+
"cards": "Array of goal cards. Each card: Statistic (current), Progress (fraction toward target), Badge (on-track/at-risk/behind), variance display (delta amount + %), optional Sparkline for trend",
|
|
13
|
+
"summary": "Optional aggregate row showing overall achievement rate"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"recipe_overrides": {
|
|
17
|
+
"command-center": {
|
|
18
|
+
"wrapper": "cc-frame",
|
|
19
|
+
"atoms": "cc-grid",
|
|
20
|
+
"notes": "Goal values use cc-data. Status badges use cc-glow for critical (behind) items. Progress bars get cc-bar. Header uses cc-bar with cc-label."
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"code": {
|
|
24
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Statistic, Progress, Badge, icon } from 'decantr/components';\nimport { Sparkline } from 'decantr/chart';",
|
|
25
|
+
"example": "function GoalTracker() {\n const { div, h3, span } = tags;\n const goals = [\n { label: 'Revenue', current: 840000, target: 1000000, unit: '$', status: 'on-track', trend: [60, 68, 72, 78, 84] },\n { label: 'New Users', current: 3200, target: 5000, unit: '', status: 'at-risk', trend: [20, 24, 26, 28, 32] },\n { label: 'NPS Score', current: 72, target: 80, unit: '', status: 'on-track', trend: [65, 68, 70, 71, 72] }\n ];\n\n return div({ class: css('_flex _col _gap4 _p4') },\n h3({ class: css('_heading4') }, 'Goal Progress'),\n div({ class: css('_grid _gc3 _gap4') },\n ...goals.map(g =>\n div({ class: css('_flex _col _gap3 _p4 _b1 _r4') },\n div({ class: css('_flex _aic _jcsb') },\n span({ class: css('_textsm _bold') }, g.label),\n Badge({ variant: g.status === 'on-track' ? 'success' : g.status === 'at-risk' ? 'warning' : 'error' }, g.status)\n ),\n Statistic({ label: 'Current', value: g.current, suffix: g.unit }),\n Progress({ value: (g.current / g.target) * 100 }),\n div({ class: css('_flex _aic _jcsb _textxs _fgmuted') },\n span({}, `Target: ${g.target}${g.unit}`),\n span({}, `${Math.round((g.current / g.target) * 100)}%`)\n ),\n g.trend ? Sparkline({ data: g.trend, height: 32 }) : null\n )\n )\n )\n );\n}"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v2.json",
|
|
3
|
+
"id": "hero",
|
|
4
|
+
"name": "Hero Section",
|
|
5
|
+
"description": "Full-width hero with headline, subtext, CTA buttons, and optional media. Entry point for landing pages, recipe detail headers, and marketing sections.",
|
|
6
|
+
"components": ["Button", "icon"],
|
|
7
|
+
"default_preset": "landing",
|
|
8
|
+
"presets": {
|
|
9
|
+
"landing": {
|
|
10
|
+
"description": "Centered headline + CTA + optional media",
|
|
11
|
+
"components": ["Button", "icon"],
|
|
12
|
+
"blend": {
|
|
13
|
+
"layout": "stack",
|
|
14
|
+
"atoms": "_flex _flexCol _itemsCenter _textCenter _gap6 _py16 _px6",
|
|
15
|
+
"slots": {
|
|
16
|
+
"headline": "Primary heading, typically h1 with _heading1",
|
|
17
|
+
"description": "Supporting paragraph with _body _muted",
|
|
18
|
+
"cta-group": "Horizontal Button group with _flex _gap3",
|
|
19
|
+
"media": "Optional image, illustration, or chart component"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"code": {
|
|
23
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Button, icon } from 'decantr/components';",
|
|
24
|
+
"example": "function Hero() {\n const { div, h1, p } = tags;\n\n return div({ class: css('_flex _col _aic _tc _gap6 _py16 _px6') },\n h1({ class: css('_heading1') }, 'Build Faster, Ship Smarter'),\n p({ class: css('_body _fgmuted _mw[640px]') }, 'The AI-first framework that turns your ideas into production-ready applications in minutes, not months.'),\n div({ class: css('_flex _gap3') },\n Button({ variant: 'primary', size: 'lg' }, 'Get Started'),\n Button({ variant: 'outline', size: 'lg' }, icon('github'), 'View Source')\n )\n );\n}"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"image-overlay": {
|
|
28
|
+
"description": "Full-bleed image with gradient overlay, content at bottom. Used for recipe/cookbook detail headers.",
|
|
29
|
+
"components": ["Button", "Chip", "icon"],
|
|
30
|
+
"blend": {
|
|
31
|
+
"layout": "stack",
|
|
32
|
+
"atoms": "_relative _wfull _h[400px] _overflow[hidden] _r4",
|
|
33
|
+
"slots": {
|
|
34
|
+
"image": "Full-bleed background cover image with gradient overlay",
|
|
35
|
+
"top-bar": "Absolute top row: back button (left) + action buttons (right)",
|
|
36
|
+
"tags": "Optional horizontal Chip row for tags overlaid on image",
|
|
37
|
+
"title": "Title (_heading2) overlaid at bottom of image",
|
|
38
|
+
"description": "Short description overlaid below title"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
"code": {
|
|
42
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Button, Chip, icon } from 'decantr/components';\nimport { navigate } from 'decantr/router';",
|
|
43
|
+
"example": "function ImageOverlayHero({ item }) {\n const { div, h1, p, img } = tags;\n\n return div({ class: css('_relative _wfull _h[400px] _overflow[hidden] _r4') },\n img({ src: item.image, alt: item.title, class: css('_absolute _inset0 _wfull _hfull _object[cover]') }),\n div({ class: css('_absolute _inset0 _bg[linear-gradient(transparent_50%,rgba(0,0,0,0.8))]') }),\n div({ class: css('_absolute _top0 _left0 _right0 _flex _jcsb _p4') },\n Button({ variant: 'ghost', size: 'sm', onclick: () => navigate(-1) }, icon('arrow-left'), 'Back'),\n Button({ variant: 'ghost', size: 'sm' }, icon('edit'), 'Edit')\n ),\n div({ class: css('_absolute _bottom0 _left0 _right0 _p6 _flex _col _gap2') },\n div({ class: css('_flex _gap2') },\n ...(item.tags || []).map(t => Chip({ size: 'sm', variant: 'outline' }, t))\n ),\n h1({ class: css('_heading2 _fgfg') }, item.title),\n p({ class: css('_body _fgmuted') }, item.description)\n )\n );\n}"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"image-overlay-compact": {
|
|
47
|
+
"description": "Compact full-bleed image with overlay for collection headers. Shorter height, fewer slots.",
|
|
48
|
+
"components": ["Button", "Badge", "Avatar", "icon"],
|
|
49
|
+
"blend": {
|
|
50
|
+
"layout": "stack",
|
|
51
|
+
"atoms": "_relative _wfull _h[300px] _overflow[hidden] _r4",
|
|
52
|
+
"slots": {
|
|
53
|
+
"image": "Full-bleed background cover image with gradient overlay",
|
|
54
|
+
"top-actions": "Absolute top-right: edit and delete action Buttons",
|
|
55
|
+
"content": "Absolute bottom: title (_heading2), count Badge, author Avatar + name"
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
"code": {
|
|
59
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Button, Badge, Avatar, icon } from 'decantr/components';",
|
|
60
|
+
"example": "function CompactOverlayHero({ item }) {\n const { div, h1, span, img } = tags;\n\n return div({ class: css('_relative _wfull _h[300px] _overflow[hidden] _r4') },\n img({ src: item.cover, alt: item.title, class: css('_absolute _inset0 _wfull _hfull _object[cover]') }),\n div({ class: css('_absolute _inset0 _bg[linear-gradient(transparent_50%,rgba(0,0,0,0.8))]') }),\n div({ class: css('_absolute _top0 _right0 _p4 _flex _gap2') },\n Button({ variant: 'ghost', size: 'sm' }, icon('edit'), 'Edit'),\n Button({ variant: 'ghost', size: 'sm' }, icon('trash'), 'Delete')\n ),\n div({ class: css('_absolute _bottom0 _left0 _right0 _p6 _flex _col _gap2') },\n h1({ class: css('_heading2 _fgfg') }, item.title),\n div({ class: css('_flex _aic _gap3') },\n Badge({ variant: 'outline' }, `${item.count} items`),\n div({ class: css('_flex _aic _gap2') },\n Avatar({ src: item.author?.avatar, size: 'xs' }),\n span({ class: css('_textsm') }, item.author?.name)\n )\n )\n )\n );\n}"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"default_blend": {
|
|
65
|
+
"layout": "stack",
|
|
66
|
+
"atoms": "_flex _flexCol _itemsCenter _textCenter _gap6 _py16 _px6",
|
|
67
|
+
"slots": {
|
|
68
|
+
"headline": "Primary heading, typically h1 with _heading1",
|
|
69
|
+
"description": "Supporting paragraph with _body _muted",
|
|
70
|
+
"cta-group": "Horizontal Button group with _flex _gap3",
|
|
71
|
+
"media": "Optional image, illustration, or chart component"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"recipe_overrides": {
|
|
75
|
+
"command-center": {
|
|
76
|
+
"wrapper": "cc-frame",
|
|
77
|
+
"atoms": "cc-grid",
|
|
78
|
+
"notes": "Headline uses cc-label. CTA buttons get cc-glow on primary action. Background uses cc-grid overlay.",
|
|
79
|
+
"preset_notes": {
|
|
80
|
+
"image-overlay": "Hero image framed with cc-frame border. Tags use cc-label. Title uses cc-data.",
|
|
81
|
+
"image-overlay-compact": "Hero framed with cc-frame border. Title uses cc-data. Count badge uses cc-label."
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"auradecantism": {
|
|
85
|
+
"wrapper": "d-mesh",
|
|
86
|
+
"atoms": "",
|
|
87
|
+
"notes": "Hero section on d-mesh background. Headline uses d-gradient-text. CTA button gets aura-glow.",
|
|
88
|
+
"preset_notes": {
|
|
89
|
+
"image-overlay": "Gradient overlay uses d-mesh tones. Title uses d-gradient-text. Subtle aura-glow on action buttons.",
|
|
90
|
+
"image-overlay-compact": "Gradient overlay blends into d-mesh tones. Title uses d-gradient-text."
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"clean": {
|
|
94
|
+
"wrapper": "",
|
|
95
|
+
"atoms": "_bgmuted _r4",
|
|
96
|
+
"notes": "Hero on subtle muted background. No gradients or glass. Standard button styling.",
|
|
97
|
+
"preset_notes": {
|
|
98
|
+
"image-overlay": "Simple image with dark gradient overlay for text legibility. No extra effects.",
|
|
99
|
+
"image-overlay-compact": "Simple image with dark gradient overlay for text legibility."
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"code": {
|
|
104
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Button, icon } from 'decantr/components';",
|
|
105
|
+
"example": "function Hero() {\n const { div, h1, p } = tags;\n\n return div({ class: css('_flex _col _aic _tc _gap6 _py16 _px6') },\n h1({ class: css('_heading1') }, 'Build Faster, Ship Smarter'),\n p({ class: css('_body _fgmuted _mw[640px]') }, 'The AI-first framework that turns your ideas into production-ready applications in minutes, not months.'),\n div({ class: css('_flex _gap3') },\n Button({ variant: 'primary', size: 'lg' }, 'Get Started'),\n Button({ variant: 'outline', size: 'lg' }, icon('github'), 'View Source')\n )\n );\n}"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/patterns.v2.json",
|
|
3
|
+
"description": "Experience patterns — composable building blocks that archetypes reference. Each pattern maps to a Blend (concrete component composition) and can be overridden per recipe. v2 patterns support presets: named variants within a single pattern file.",
|
|
4
|
+
"patterns": {
|
|
5
|
+
"hero": { "name": "Hero", "file": "hero.json", "presets": ["landing", "image-overlay", "image-overlay-compact"] },
|
|
6
|
+
"kpi-grid": { "name": "KPI Grid", "file": "kpi-grid.json" },
|
|
7
|
+
"data-table": { "name": "Data Table", "file": "data-table.json" },
|
|
8
|
+
"activity-feed": { "name": "Activity Feed", "file": "activity-feed.json" },
|
|
9
|
+
"chart-grid": { "name": "Chart Grid", "file": "chart-grid.json" },
|
|
10
|
+
"card-grid": { "name": "Card Grid", "file": "card-grid.json", "presets": ["product", "content", "collection", "icon"] },
|
|
11
|
+
"filter-sidebar": { "name": "Filter Sidebar", "file": "filter-sidebar.json" },
|
|
12
|
+
"wizard": { "name": "Wizard", "file": "wizard.json" },
|
|
13
|
+
"detail-panel": { "name": "Detail Panel", "file": "detail-panel.json" },
|
|
14
|
+
"form-sections": { "name": "Form Sections", "file": "form-sections.json", "presets": ["settings", "creation", "structured"] },
|
|
15
|
+
"post-list": { "name": "Post List", "file": "post-list.json" },
|
|
16
|
+
"auth-form": { "name": "Auth Form", "file": "auth-form.json" },
|
|
17
|
+
"article-content": { "name": "Article Content", "file": "article-content.json" },
|
|
18
|
+
"category-nav": { "name": "Category Nav", "file": "category-nav.json" },
|
|
19
|
+
"timeline": { "name": "Timeline", "file": "timeline.json" },
|
|
20
|
+
"component-showcase": { "name": "Component Showcase", "file": "component-showcase.json" },
|
|
21
|
+
"pagination": { "name": "Pagination", "file": "pagination.json" },
|
|
22
|
+
"testimonials": { "name": "Testimonials", "file": "testimonials.json" },
|
|
23
|
+
"cta-section": { "name": "CTA Section", "file": "cta-section.json" },
|
|
24
|
+
"contact-form": { "name": "Contact Form", "file": "contact-form.json" },
|
|
25
|
+
"search-bar": { "name": "Search Bar", "file": "search-bar.json" },
|
|
26
|
+
"author-card": { "name": "Author Card", "file": "author-card.json" },
|
|
27
|
+
"table-of-contents": { "name": "Table of Contents", "file": "table-of-contents.json" },
|
|
28
|
+
"filter-bar": { "name": "Filter Bar", "file": "filter-bar.json" },
|
|
29
|
+
"detail-header": { "name": "Detail Header", "file": "detail-header.json", "presets": ["standard", "profile"] },
|
|
30
|
+
"media-gallery": { "name": "Media Gallery", "file": "media-gallery.json" },
|
|
31
|
+
"pricing-table": { "name": "Pricing Table", "file": "pricing-table.json" },
|
|
32
|
+
"order-history": { "name": "Order History", "file": "order-history.json" },
|
|
33
|
+
"specimen-grid": { "name": "Specimen Grid", "file": "specimen-grid.json" },
|
|
34
|
+
"token-inspector": { "name": "Token Inspector", "file": "token-inspector.json" },
|
|
35
|
+
"explorer-shell": { "name": "Explorer Shell", "file": "explorer-shell.json" },
|
|
36
|
+
"goal-tracker": { "name": "Goal Tracker", "file": "goal-tracker.json" },
|
|
37
|
+
"pipeline-tracker": { "name": "Pipeline Tracker", "file": "pipeline-tracker.json" },
|
|
38
|
+
"scorecard": { "name": "Scorecard", "file": "scorecard.json" },
|
|
39
|
+
"comparison-panel": { "name": "Comparison Panel", "file": "comparison-panel.json" },
|
|
40
|
+
"stats-bar": { "name": "Stats Bar", "file": "stats-bar.json" },
|
|
41
|
+
"checklist-card": { "name": "Checklist Card", "file": "checklist-card.json" },
|
|
42
|
+
"steps-card": { "name": "Steps Card", "file": "steps-card.json" },
|
|
43
|
+
"stat-card": { "name": "Stat Card", "file": "stat-card.json" },
|
|
44
|
+
"photo-to-recipe": { "name": "Photo to Recipe", "file": "photo-to-recipe.json" },
|
|
45
|
+
"chat-interface": { "name": "Chat Interface", "file": "chat-interface.json" }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "kpi-grid",
|
|
4
|
+
"name": "KPI Grid",
|
|
5
|
+
"description": "Responsive grid of metric cards showing key performance indicators. Each card displays a label, value, trend, and optional sparkline.",
|
|
6
|
+
"components": ["Statistic", "icon"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "grid",
|
|
9
|
+
"atoms": "_grid _gc4 _gap4 _p4",
|
|
10
|
+
"slots": {
|
|
11
|
+
"cards": "Array of Statistic instances with label, value, trend props",
|
|
12
|
+
"header": "Optional section title with _heading4 and filter controls"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"recipe_overrides": {
|
|
16
|
+
"command-center": {
|
|
17
|
+
"wrapper": "cc-frame",
|
|
18
|
+
"atoms": "cc-bar cc-grid",
|
|
19
|
+
"notes": "KPI values use cc-data and cc-glow for critical metrics. Section header uses cc-bar with cc-label. Background gets cc-grid."
|
|
20
|
+
},
|
|
21
|
+
"auradecantism": {
|
|
22
|
+
"wrapper": "d-glass",
|
|
23
|
+
"atoms": "_r4",
|
|
24
|
+
"notes": "Each KPI card wrapped in d-glass. Key values use d-gradient-text. Section header in d-gradient-text."
|
|
25
|
+
},
|
|
26
|
+
"clean": {
|
|
27
|
+
"wrapper": "",
|
|
28
|
+
"atoms": "_b1 _r4",
|
|
29
|
+
"notes": "Simple bordered cards. No glass or gradients. Tokens handle all visual styling."
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"code": {
|
|
33
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { Statistic, icon } from 'decantr/components';",
|
|
34
|
+
"example": "function KpiGrid() {\n const { div, h2 } = tags;\n return div({ class: css('_flex _col _gap4') },\n h2({ class: css('_heading4') }, 'Key Metrics'),\n div({ class: css('_grid _gc4 _gap4') },\n Statistic({ label: 'Revenue', value: 1248500, prefix: '$', trend: 'up', trendValue: '+12.5%' }),\n Statistic({ label: 'Users', value: 84230, trend: 'up', trendValue: '+8.1%' }),\n Statistic({ label: 'Orders', value: 6420, trend: 'down', trendValue: '-2.3%' }),\n Statistic({ label: 'Conversion', value: 3.24, suffix: '%', trend: 'up', trendValue: '+0.5%' })\n )\n );\n}"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "media-gallery",
|
|
4
|
+
"name": "Media Gallery",
|
|
5
|
+
"description": "Responsive image gallery with thumbnails, lightbox, and optional carousel.",
|
|
6
|
+
"components": ["Image", "Card", "Modal", "Button"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "grid",
|
|
9
|
+
"atoms": "_grid _gc3 _gap3",
|
|
10
|
+
"slots": {
|
|
11
|
+
"gallery-grid": "Grid of Image cards with click-to-expand",
|
|
12
|
+
"lightbox": "Modal overlay for full-size image viewing",
|
|
13
|
+
"thumbnails": "Optional thumbnail strip for navigation"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"code": {
|
|
17
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Image, Modal, Button, icon } from 'decantr/components';",
|
|
18
|
+
"example": "function MediaGallery() {\n const { div } = tags;\n const images = [\n { thumb: '/images/photo-1.jpg', full: '/images/photo-1-full.jpg', alt: 'Mountain landscape' },\n { thumb: '/images/photo-2.jpg', full: '/images/photo-2-full.jpg', alt: 'Ocean sunset' },\n { thumb: '/images/photo-3.jpg', full: '/images/photo-3-full.jpg', alt: 'Forest trail' },\n { thumb: '/images/photo-4.jpg', full: '/images/photo-4-full.jpg', alt: 'City skyline' },\n { thumb: '/images/photo-5.jpg', full: '/images/photo-5-full.jpg', alt: 'Desert dunes' },\n { thumb: '/images/photo-6.jpg', full: '/images/photo-6-full.jpg', alt: 'Snowy peaks' }\n ];\n const [selected, setSelected] = createSignal(null);\n\n return div({},\n div({ class: css('_grid _gcaf250 _gap3 _p4') },\n ...images.map((img, i) =>\n div({ class: css('_overflow[hidden] _r4 _pointer _trans'), onclick: () => setSelected(i) },\n Image({ src: img.thumb, alt: img.alt, class: css('_wfull _h[200px] _object[cover]') })\n )\n )\n ),\n Modal({ visible: () => selected() !== null, onClose: () => setSelected(null) },\n selected() !== null ? Image({ src: images[selected()].full, alt: images[selected()].alt, class: css('_mw[90vw] _mh[80vh] _object[contain]') }) : null\n )\n );\n}"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "order-history",
|
|
4
|
+
"name": "Order History",
|
|
5
|
+
"description": "Order listing table with status badges, date columns, and action links.",
|
|
6
|
+
"components": ["DataTable", "Badge", "Button"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "stack",
|
|
9
|
+
"atoms": "_flex _col _gap4",
|
|
10
|
+
"slots": {
|
|
11
|
+
"filters": "Optional filter controls for date range and status",
|
|
12
|
+
"order-table": "DataTable with order ID, date, status Badge, and total columns",
|
|
13
|
+
"pagination": "Bottom pagination row for navigating order pages"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"code": {
|
|
17
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { css } from 'decantr/css';\nimport { DataTable, Badge, Button } from 'decantr/components';",
|
|
18
|
+
"example": "function OrderHistory() {\n const { div, h3 } = tags;\n const orders = [\n { id: 'ORD-1042', date: '2026-03-10', items: 3, total: 129.99, status: 'delivered' },\n { id: 'ORD-1041', date: '2026-03-08', items: 1, total: 49.00, status: 'shipped' },\n { id: 'ORD-1040', date: '2026-03-05', items: 2, total: 84.50, status: 'processing' },\n { id: 'ORD-1039', date: '2026-03-01', items: 5, total: 212.75, status: 'delivered' }\n ];\n const columns = [\n { key: 'id', label: 'Order #', sortable: true },\n { key: 'date', label: 'Date', sortable: true },\n { key: 'items', label: 'Items' },\n { key: 'total', label: 'Total', sortable: true, render: row => `$${row.total.toFixed(2)}` },\n { key: 'status', label: 'Status', render: row =>\n Badge({ variant: row.status === 'delivered' ? 'success' : row.status === 'shipped' ? 'primary' : 'default' }, row.status)\n },\n { key: 'actions', label: '', render: row =>\n Button({ variant: 'ghost', size: 'sm' }, 'View')\n }\n ];\n\n return div({ class: css('_flex _col _gap4 _p4') },\n h3({ class: css('_heading4') }, 'Order History'),\n DataTable({ columns, data: orders, sortable: true, paginate: true, pageSize: 10 })\n );\n}"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "pagination",
|
|
4
|
+
"name": "Pagination",
|
|
5
|
+
"description": "Page navigation controls with page numbers, prev/next, and optional page-size selector.",
|
|
6
|
+
"components": ["Pagination", "Select", "Button"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "row",
|
|
9
|
+
"atoms": "_flex _jcc _aic _gap2 _py4",
|
|
10
|
+
"slots": {
|
|
11
|
+
"page-controls": "Pagination component with prev/next and numbered pages",
|
|
12
|
+
"page-size-selector": "Optional Select for rows-per-page control"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"code": {
|
|
16
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Pagination } from 'decantr/components';",
|
|
17
|
+
"example": "function PaginationPattern() {\n const { div, span } = tags;\n const total = 243;\n const pageSize = 10;\n const [page, setPage] = createSignal(1);\n const totalPages = Math.ceil(total / pageSize);\n\n return div({ class: css('_flex _aic _jcsb _py3') },\n span({ class: css('_textsm _fgmuted') },\n `Showing ${(page() - 1) * pageSize + 1}-${Math.min(page() * pageSize, total)} of ${total}`\n ),\n Pagination({ current: page, total: totalPages, onChange: setPage })\n );\n}"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://decantr.ai/schemas/pattern.v1.json",
|
|
3
|
+
"id": "photo-to-recipe",
|
|
4
|
+
"name": "Photo to Recipe",
|
|
5
|
+
"description": "Two-column AI generation layout: left column has a photo upload dropzone, right column displays AI-generated recipe output with title, ingredients, and instructions. Used for AI-powered recipe extraction from food photos.",
|
|
6
|
+
"components": ["Card", "Card.Header", "Card.Body", "Upload", "Button", "Spinner", "Separator", "icon"],
|
|
7
|
+
"default_blend": {
|
|
8
|
+
"layout": "grid",
|
|
9
|
+
"atoms": "_grid _gc2 _gap6 _p4 _aic",
|
|
10
|
+
"slots": {
|
|
11
|
+
"upload": "Left column: Upload dropzone with image preview, analyze Button",
|
|
12
|
+
"output": "Right column: Card showing AI-generated recipe with title, ingredients list, instructions, and 'Save Recipe' action"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"recipe_overrides": {
|
|
16
|
+
"command-center": {
|
|
17
|
+
"wrapper": "cc-frame",
|
|
18
|
+
"atoms": "cc-grid",
|
|
19
|
+
"notes": "Upload zone uses cc-frame-sm. AI output card uses cc-frame-sm with cc-data for generated text. Analyze button uses cc-glow."
|
|
20
|
+
},
|
|
21
|
+
"auradecantism": {
|
|
22
|
+
"wrapper": "d-mesh",
|
|
23
|
+
"atoms": "",
|
|
24
|
+
"notes": "Upload dropzone on d-glass. Output card on d-glass. AI badge uses d-gradient-text."
|
|
25
|
+
},
|
|
26
|
+
"clean": {
|
|
27
|
+
"wrapper": "",
|
|
28
|
+
"atoms": "",
|
|
29
|
+
"notes": "Standard two-column layout with bordered cards. Clean upload dropzone."
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"code": {
|
|
33
|
+
"imports": "import { tags } from 'decantr/tags';\nimport { createSignal } from 'decantr/state';\nimport { css } from 'decantr/css';\nimport { Card, Upload, Button, Spinner, Separator, icon } from 'decantr/components';",
|
|
34
|
+
"example": "function PhotoToRecipe() {\n const { div, h3, p, span, ul, li } = tags;\n const [analyzing, setAnalyzing] = createSignal(false);\n const [result, setResult] = createSignal(null);\n\n return div({ class: css('_grid _gc2 _gap6 _p4') },\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, icon('camera'), ' Upload Photo')),\n Card.Body({ class: css('_flex _col _gap4 _aic') },\n Upload({ accept: 'image/*', variant: 'dragger', class: css('_wfull') }, 'Drop a food photo here'),\n Button({ variant: 'primary', class: css('_wfull'), onclick: () => setAnalyzing(true) },\n analyzing() ? Spinner({ size: 'sm' }) : icon('sparkles'),\n analyzing() ? ' Analyzing...' : ' Generate Recipe'\n )\n )\n ),\n Card({},\n Card.Header({}, h3({ class: css('_heading5') }, icon('sparkles'), ' AI Generated Recipe')),\n Card.Body({ class: css('_flex _col _gap3') },\n result()\n ? div({},\n h3({ class: css('_heading4') }, result().title),\n Separator(),\n h3({ class: css('_heading6 _mt3') }, 'Ingredients'),\n ul({}, ...result().ingredients.map(i => li({}, i))),\n h3({ class: css('_heading6 _mt3') }, 'Instructions'),\n ul({}, ...result().steps.map((s, i) => li({}, `${i + 1}. ${s}`))),\n Button({ variant: 'primary', class: css('_mt4') }, 'Save Recipe')\n )\n : p({ class: css('_fgmuted _tc') }, 'Upload a photo to generate a recipe')\n )\n )\n );\n}"
|
|
35
|
+
}
|
|
36
|
+
}
|