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,137 @@
|
|
|
1
|
+
# Component Lifecycle & Cleanup
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Decantr components return raw `HTMLElement` nodes — not wrapper objects with lifecycle methods. This means cleanup (removing document listeners, clearing timers, disconnecting observers) requires explicit wiring. Without it, components leak resources when removed from the DOM.
|
|
6
|
+
|
|
7
|
+
## Cleanup Contract
|
|
8
|
+
|
|
9
|
+
**Every component that adds document-level listeners, timers, or observers MUST clean them up.** This applies to:
|
|
10
|
+
|
|
11
|
+
- `document.addEventListener(...)` — click-outside, escape-to-close, resize, scroll
|
|
12
|
+
- `setTimeout` / `setInterval` — debounced actions, animation timers, polling
|
|
13
|
+
- `IntersectionObserver` / `ResizeObserver` / `MutationObserver`
|
|
14
|
+
- `window.addEventListener(...)` — resize, scroll, popstate
|
|
15
|
+
|
|
16
|
+
## How Cleanup Works
|
|
17
|
+
|
|
18
|
+
### Pattern 1: Use `_behaviors.js` primitives (preferred)
|
|
19
|
+
|
|
20
|
+
All behavioral primitives in `_behaviors.js` return `{ destroy() }`. Components MUST call `.destroy()` when removed.
|
|
21
|
+
|
|
22
|
+
```javascript
|
|
23
|
+
import { createOverlay, createListbox, createFocusTrap } from './_behaviors.js';
|
|
24
|
+
|
|
25
|
+
export function Select(props) {
|
|
26
|
+
const trigger = /* ... */;
|
|
27
|
+
const panel = /* ... */;
|
|
28
|
+
|
|
29
|
+
const overlay = createOverlay(trigger, panel, { trigger: 'click' });
|
|
30
|
+
const listbox = createListbox(panel, { onSelect: /* ... */ });
|
|
31
|
+
|
|
32
|
+
// Wire cleanup to element removal
|
|
33
|
+
const el = h('div', { class: 'd-select' }, trigger, panel);
|
|
34
|
+
onDestroy(() => {
|
|
35
|
+
overlay.destroy();
|
|
36
|
+
listbox.destroy();
|
|
37
|
+
});
|
|
38
|
+
return el;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Pattern 2: Manual cleanup collection
|
|
43
|
+
|
|
44
|
+
For components that add their own listeners (not via behaviors):
|
|
45
|
+
|
|
46
|
+
```javascript
|
|
47
|
+
export function MyComponent(props) {
|
|
48
|
+
const cleanups = [];
|
|
49
|
+
|
|
50
|
+
const onResize = () => { /* ... */ };
|
|
51
|
+
window.addEventListener('resize', onResize);
|
|
52
|
+
cleanups.push(() => window.removeEventListener('resize', onResize));
|
|
53
|
+
|
|
54
|
+
const timer = setInterval(poll, 5000);
|
|
55
|
+
cleanups.push(() => clearInterval(timer));
|
|
56
|
+
|
|
57
|
+
const el = h('div', { /* ... */ });
|
|
58
|
+
onDestroy(() => cleanups.forEach(fn => fn()));
|
|
59
|
+
return el;
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Pattern 3: MutationObserver self-cleanup (last resort)
|
|
64
|
+
|
|
65
|
+
When `onDestroy` context is unavailable (e.g., dynamically created elements):
|
|
66
|
+
|
|
67
|
+
```javascript
|
|
68
|
+
const observer = new MutationObserver((mutations) => {
|
|
69
|
+
for (const m of mutations) {
|
|
70
|
+
for (const node of m.removedNodes) {
|
|
71
|
+
if (node === el || node.contains(el)) {
|
|
72
|
+
cleanup();
|
|
73
|
+
observer.disconnect();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
observer.observe(el.parentNode, { childList: true });
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Available `_behaviors.js` Primitives
|
|
82
|
+
|
|
83
|
+
| Primitive | Returns `destroy()`? | Use For |
|
|
84
|
+
|-----------|---------------------|---------|
|
|
85
|
+
| `createOverlay()` | Yes | Click-outside, escape, show/hide, ARIA expanded |
|
|
86
|
+
| `createListbox()` | Yes | Arrow-key navigation, selection, type-ahead |
|
|
87
|
+
| `createDisclosure()` | No (uses element listeners only) | Expand/collapse with animation |
|
|
88
|
+
| `createRovingTabindex()` | Yes | Tab navigation within groups |
|
|
89
|
+
| `createFocusTrap()` | Yes (via `deactivate()`) | Modal/drawer focus containment |
|
|
90
|
+
| `createDrag()` | Yes | Pointer-based drag interactions |
|
|
91
|
+
| `createVirtualScroll()` | Yes | Large list rendering |
|
|
92
|
+
| `createInfiniteScroll()` | Yes | Load-more sentinel |
|
|
93
|
+
| `createMasonry()` | Yes | Pinterest-style layout |
|
|
94
|
+
| `createScrollSpy()` | Yes (via `disconnect()`) | Section tracking |
|
|
95
|
+
| `createHotkey()` | Yes | Keyboard shortcuts |
|
|
96
|
+
|
|
97
|
+
## Checklist Before Shipping a Component
|
|
98
|
+
|
|
99
|
+
1. Does this component add `document.addEventListener`? -> Use `createOverlay` or collect cleanup
|
|
100
|
+
2. Does this component use `setTimeout`/`setInterval`? -> Clear on destroy
|
|
101
|
+
3. Does this component create an `Observer`? -> Disconnect on destroy
|
|
102
|
+
4. Does this component use `createOverlay`/`createListbox`/etc.? -> Call `.destroy()` via `onDestroy`
|
|
103
|
+
5. Does this component add `window.addEventListener`? -> Remove on destroy
|
|
104
|
+
|
|
105
|
+
## Known Components Needing Cleanup Audit
|
|
106
|
+
|
|
107
|
+
**Completed** (have `onDestroy` wired — verified March 2026):
|
|
108
|
+
- `modal.js` — uses `createFocusTrap`, cleanup via `onDestroy`
|
|
109
|
+
- `select.js` — `onDestroy` added
|
|
110
|
+
- `combobox.js` — `onDestroy` added
|
|
111
|
+
- `context-menu.js` — `onDestroy` added
|
|
112
|
+
- `tooltip.js` — `onDestroy` added
|
|
113
|
+
- `slider.js` — `onDestroy` added
|
|
114
|
+
- `image.js` — `onDestroy` added
|
|
115
|
+
- `data-table.js` — `onDestroy` added
|
|
116
|
+
- `dropdown.js` — `onDestroy` added
|
|
117
|
+
|
|
118
|
+
**Remaining** — components that may still benefit from migrating to `_behaviors.js` primitives:
|
|
119
|
+
- `slider.js` — document pointermove/pointerup (candidate for `createDrag`)
|
|
120
|
+
- `data-table.js` — document pointermove/pointerup for column resize (candidate for `createDrag`)
|
|
121
|
+
- `tour.js` — document keydown, window resize (has manual cleanup, could use `createHotkey`)
|
|
122
|
+
|
|
123
|
+
## Workbench & Tooling Lifecycle
|
|
124
|
+
|
|
125
|
+
The cleanup contract applies to **ALL code**, not just `src/components/`. Workbench explorer modules, docs site scripts, CLI preview tools — any code that adds event listeners, timers, or observers MUST wire `onDestroy` cleanup.
|
|
126
|
+
|
|
127
|
+
**Common violations in tooling code:**
|
|
128
|
+
|
|
129
|
+
- **Motion/animation demos** that add `mouseenter`/`mouseleave` listeners directly via `addEventListener` instead of element props (props are cleaned up with the element)
|
|
130
|
+
- **Search modals** that add `keydown` document listeners without cleanup
|
|
131
|
+
- **Live previews** that create `ResizeObserver` or `MutationObserver` without disconnecting
|
|
132
|
+
|
|
133
|
+
**Rule:** If a workbench explorer section adds listeners, it follows the same contract as a framework component. Use element event props (e.g. `onmouseenter`) for element-scoped events, and `onDestroy` + `_behaviors.js` for document-level listeners.
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
**See also:** `reference/behaviors.md`, `reference/compound-spacing.md`
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Compound Spacing, Offsets & Density
|
|
2
|
+
|
|
3
|
+
> **Strategic guide**: For the full spatial design language — proximity tiers, density zones, responsive behavior, visual weight, and decision tables — see `reference/spatial-guidelines.md`. This document covers the implementation contracts for compound components.
|
|
4
|
+
|
|
5
|
+
## Compound Spacing Contract
|
|
6
|
+
|
|
7
|
+
All compound components (Card, Modal, AlertDialog, Drawer) follow a unified spacing contract via `--d-compound-pad` and `--d-compound-gap`. This ensures consistent header/body/footer spacing across all overlay and container components.
|
|
8
|
+
|
|
9
|
+
| Section | Padding Rule |
|
|
10
|
+
|---------|-------------|
|
|
11
|
+
| **Header** | `var(--d-compound-pad) var(--d-compound-pad) 0` |
|
|
12
|
+
| **Body** | `var(--d-compound-gap) var(--d-compound-pad)` |
|
|
13
|
+
| **Body:last-child** | adds `padding-bottom: var(--d-compound-pad)` |
|
|
14
|
+
| **Footer** | `var(--d-compound-gap) var(--d-compound-pad) var(--d-compound-pad)` |
|
|
15
|
+
|
|
16
|
+
**Bordered footer exception:** When a compound footer has a visible `border-top` (e.g. Card), the border provides inter-section separation, so the footer uses `var(--d-compound-pad)` on all sides for vertical centering. The asymmetric `compound-gap` top is only appropriate when the gap alone is the separator (Modal, Drawer).
|
|
17
|
+
|
|
18
|
+
New compound components MUST follow this contract. Never hardcode padding in header/body/footer — use the compound tokens.
|
|
19
|
+
|
|
20
|
+
## Popup Offset Hierarchy
|
|
21
|
+
|
|
22
|
+
> Full elevation hierarchy and offset strategy: `reference/spatial-guidelines.md` §11 Z-Axis Spatial Rules.
|
|
23
|
+
|
|
24
|
+
All floating elements use offset tokens for trigger->panel distance. The hierarchy reflects visual weight:
|
|
25
|
+
|
|
26
|
+
`--d-offset-dropdown` (2px) < `--d-offset-menu` (4px) < `--d-offset-tooltip` (6px) < `--d-offset-popover` (8px)
|
|
27
|
+
|
|
28
|
+
New floating components MUST use the appropriate offset token, never hardcoded pixel values.
|
|
29
|
+
|
|
30
|
+
## Density Classes
|
|
31
|
+
|
|
32
|
+
> Full density rules, character mapping, and usage guidance: `reference/spatial-guidelines.md` §16 Density System Integration.
|
|
33
|
+
|
|
34
|
+
`.d-compact`, `.d-comfortable`, `.d-spacious` — cascade to children, override `--d-density-pad-x`, `--d-density-pad-y`, `--d-density-gap`, `--d-density-min-h`, `--d-density-text`, `--d-compound-pad`, `--d-compound-gap`
|
|
35
|
+
|
|
36
|
+
| Density | `--d-compound-pad` | `--d-compound-gap` | Controls | Interiors |
|
|
37
|
+
|---------|--------------------|--------------------|----------|-----------|
|
|
38
|
+
| compact | `var(--d-sp-3)` | `var(--d-sp-2)` | Tighter | Tighter |
|
|
39
|
+
| comfortable | `var(--d-sp-5)` | `var(--d-sp-3)` | Default | Default |
|
|
40
|
+
| spacious | `var(--d-sp-8)` | `var(--d-sp-4)` | Wider | Wider |
|
|
41
|
+
|
|
42
|
+
## Field Sizing Contract
|
|
43
|
+
|
|
44
|
+
> Component sizing tiers, touch targets, and inset patterns: `reference/spatial-guidelines.md` §7 Component Sizing.
|
|
45
|
+
|
|
46
|
+
All form components support a unified 4-tier sizing system (xs/sm/md/lg). Height is the primary constraint; padding and font-size follow.
|
|
47
|
+
|
|
48
|
+
**Core components** (Button, Select, Input, Toggle, Combobox) use per-component size classes (`.d-btn-sm`, `.d-select-sm .d-select`, `.d-input-sm`, etc.) that include `min-height` overrides.
|
|
49
|
+
|
|
50
|
+
**Picker components** (DatePicker, TimePicker, Cascader, TreeSelect, ColorPicker, Mentions, InputNumber, DateRangePicker, TimeRangePicker) use `.d-field-{size}` utility classes that override density tokens locally:
|
|
51
|
+
|
|
52
|
+
```css
|
|
53
|
+
.d-field-xs { --d-density-min-h:var(--d-field-h-xs); --d-density-pad-y:var(--d-field-py-xs); ... }
|
|
54
|
+
.d-field-sm { --d-density-min-h:var(--d-field-h-sm); ... }
|
|
55
|
+
.d-field-lg { --d-density-min-h:var(--d-field-h-lg); ... }
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Any child `.d-select`, `.d-input`, etc. inside a `.d-field-sm` wrapper inherits sm sizing via the density cascade — no per-component CSS needed.
|
|
59
|
+
|
|
60
|
+
**Tier ↔ density mapping:** compact defaults = sm tokens, comfortable defaults = md tokens, spacious defaults = lg tokens. This means setting density to "compact" automatically makes all form elements 28px height.
|
|
61
|
+
|
|
62
|
+
**Components with own size tokens:** Switch (`--d-switch-w/h/thumb-{tier}`), Checkbox/Radio (`--d-checkbox-size-{tier}`), InputOTP (`--d-otp-w/h/text-{tier}`).
|
|
63
|
+
|
|
64
|
+
## Prose System
|
|
65
|
+
|
|
66
|
+
`.d-prose` — auto-applies vertical rhythm to child elements. Use for long-form content (articles, documentation, modal descriptions).
|
|
67
|
+
|
|
68
|
+
- Base: `font-size:var(--d-text-base); line-height:var(--d-lh-relaxed)`
|
|
69
|
+
- Between siblings: `> * + * { margin-top: var(--d-sp-4) }`
|
|
70
|
+
- Headings: graduated margin-top (sp-12->sp-10->sp-8->sp-6) + margin-bottom (sp-4->sp-3)
|
|
71
|
+
- Lists: left padding, per-item spacing
|
|
72
|
+
- Blockquote: left border + padding + italic
|
|
73
|
+
- Code/pre: mono font, padding, surface background
|
|
74
|
+
- Tables: cell padding, bottom borders
|
|
75
|
+
|
|
76
|
+
Usage: `div({ class: 'd-prose' }, h1('Title'), p('Body text...'), ul(li('Item')))`
|
|
77
|
+
|
|
78
|
+
## Spacing Utilities
|
|
79
|
+
|
|
80
|
+
Child-spacing utilities use the `d-` prefix (not `_` atom prefix) because they require child combinators (`> * + *`) which cannot be expressed in the atom resolver.
|
|
81
|
+
|
|
82
|
+
| Class | Effect |
|
|
83
|
+
|-------|--------|
|
|
84
|
+
| `d-spacey-{1-24}` | `> * + * { margin-top: {scale} }` — vertical child spacing |
|
|
85
|
+
| `d-spacex-{1-24}` | `> * + * { margin-left: {scale} }` — horizontal child spacing |
|
|
86
|
+
| `d-dividey` | `> * + * { border-top: 1px solid var(--d-border) }` |
|
|
87
|
+
| `d-dividex` | `> * + * { border-left: 1px solid var(--d-border) }` |
|
|
88
|
+
| `d-dividey-strong` | `> * + * { border-top: 1px solid var(--d-border-strong) }` |
|
|
89
|
+
| `d-dividex-strong` | `> * + * { border-left: 1px solid var(--d-border-strong) }` |
|
|
90
|
+
|
|
91
|
+
Scale: 1 (0.25rem) through 24 (6rem). Same spacing scale as `_p`/`_m` atoms.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
**See also:** `reference/spatial-guidelines.md`, `reference/atoms.md`, `reference/tokens.md`
|