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
package/src/css/index.js
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { resolveAtomDecl } from './atoms.js';
|
|
2
|
+
import { inject, injectResponsive, injectResponsivePseudo, injectContainer, injectGroupPeer, injectPseudo, BREAKPOINTS, CQ_WIDTHS } from './runtime.js';
|
|
3
|
+
export { extractCSS, reset, BREAKPOINTS, CQ_WIDTHS } from './runtime.js';
|
|
4
|
+
export {
|
|
5
|
+
setTheme, getTheme, getThemeMeta, registerTheme, getThemeList,
|
|
6
|
+
getActiveCSS, resetStyles, setAnimations, getAnimations,
|
|
7
|
+
setStyle, getStyle, getStyleList, registerStyle, mergePluginStyles,
|
|
8
|
+
setMode, getMode, getResolvedMode, onModeChange,
|
|
9
|
+
setShape, getShape, getShapeList,
|
|
10
|
+
setColorblindMode, getColorblindMode
|
|
11
|
+
} from './theme-registry.js';
|
|
12
|
+
|
|
13
|
+
/** @type {Map<string, string>} */
|
|
14
|
+
const customAtoms = new Map();
|
|
15
|
+
|
|
16
|
+
/** Regex to detect responsive prefix: _sm:, _md:, _lg:, _xl: */
|
|
17
|
+
const BP_RE = /^_(sm|md|lg|xl):(.+)$/;
|
|
18
|
+
|
|
19
|
+
/** Regex to detect container query prefix: _cq320:, _cq480:, _cq640:, _cq768:, _cq1024: */
|
|
20
|
+
const CQ_RE = /^_cq(\d+):(.+)$/;
|
|
21
|
+
|
|
22
|
+
/** Regex to detect group/peer state prefix: _gh:, _gf:, _ga:, _ph:, _pf:, _pa: */
|
|
23
|
+
const GP_RE = /^_(gh|gf|ga|ph|pf|pa):(.+)$/;
|
|
24
|
+
|
|
25
|
+
/** Regex to detect pseudo-class prefix: _h:, _f:, _fv:, _a:, _fw: */
|
|
26
|
+
const PSEUDO_RE = /^_(h|f|fv|a|fw):(.+)$/;
|
|
27
|
+
|
|
28
|
+
/** Valid pseudo-class prefixes */
|
|
29
|
+
const PSEUDO_SET = new Set(['h', 'f', 'fv', 'a', 'fw']);
|
|
30
|
+
|
|
31
|
+
/** Regex to detect opacity modifier: _bgprimary/50, _fgaccent/30 */
|
|
32
|
+
const ALPHA_RE = /^(_[a-zA-Z0-9]+)\/(\d+)$/;
|
|
33
|
+
|
|
34
|
+
/** Regex to detect arbitrary value: _w[512px], _bg[#1a1d24] */
|
|
35
|
+
const ARB_RE = /^_([a-zA-Z]+)\[([^\]]+)\]$/;
|
|
36
|
+
|
|
37
|
+
/** Valid container query widths as a Set for fast lookup */
|
|
38
|
+
const CQ_SET = new Set(CQ_WIDTHS);
|
|
39
|
+
|
|
40
|
+
/** Valid group/peer prefixes */
|
|
41
|
+
const GP_SET = new Set(['gh', 'gf', 'ga', 'ph', 'pf', 'pa']);
|
|
42
|
+
|
|
43
|
+
/** Property prefix map for arbitrary values */
|
|
44
|
+
const ARB_PROPS = {
|
|
45
|
+
w: 'width', h: 'height', mw: 'max-width', mh: 'max-height',
|
|
46
|
+
minw: 'min-width', minh: 'min-height',
|
|
47
|
+
p: 'padding', pt: 'padding-top', pr: 'padding-right', pb: 'padding-bottom', pl: 'padding-left',
|
|
48
|
+
px: 'padding-inline', py: 'padding-block',
|
|
49
|
+
m: 'margin', mt: 'margin-top', mr: 'margin-right', mb: 'margin-bottom', ml: 'margin-left',
|
|
50
|
+
mx: 'margin-inline', my: 'margin-block',
|
|
51
|
+
gap: 'gap', gx: 'column-gap', gy: 'row-gap',
|
|
52
|
+
t: 'font-size', fs: 'font-size', lh: 'line-height', fw: 'font-weight', ls: 'letter-spacing',
|
|
53
|
+
r: 'border-radius', bg: 'background', fg: 'color', bc: 'border-color',
|
|
54
|
+
bw: 'border-width', bt: 'border-top', bb: 'border-bottom', br: 'border-right', bl: 'border-left',
|
|
55
|
+
z: 'z-index', op: 'opacity',
|
|
56
|
+
top: 'top', right: 'right', bottom: 'bottom', left: 'left', inset: 'inset',
|
|
57
|
+
shadow: 'box-shadow', bf: 'backdrop-filter',
|
|
58
|
+
outline: 'outline', trans: 'transition', object: 'object-fit',
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Resolve an atom name to its CSS declaration.
|
|
63
|
+
* Handles: standard atoms, opacity modifiers (/N), and arbitrary values ([val]).
|
|
64
|
+
* @param {string} atomPart — e.g. '_p4', '_bgprimary/50', '_w[512px]'
|
|
65
|
+
* @returns {{ className: string, decl: string }|null}
|
|
66
|
+
*/
|
|
67
|
+
function resolveAtom(atomPart) {
|
|
68
|
+
// 1. Custom atoms first (user-defined via define())
|
|
69
|
+
const custom = customAtoms.get(atomPart);
|
|
70
|
+
if (custom) return { className: atomPart, decl: custom };
|
|
71
|
+
|
|
72
|
+
// 2. Algorithmic resolution (handles aliases, direct, patterns, residual)
|
|
73
|
+
const decl = resolveAtomDecl(atomPart);
|
|
74
|
+
if (decl) return { className: atomPart, decl };
|
|
75
|
+
|
|
76
|
+
// 3. Opacity modifier: _bgprimary/50
|
|
77
|
+
const alphaMatch = atomPart.match(ALPHA_RE);
|
|
78
|
+
if (alphaMatch) {
|
|
79
|
+
const [, base, alphaStr] = alphaMatch;
|
|
80
|
+
const baseDecl = customAtoms.get(base) || resolveAtomDecl(base);
|
|
81
|
+
if (baseDecl) {
|
|
82
|
+
const alpha = Number(alphaStr);
|
|
83
|
+
if (alpha >= 0 && alpha <= 100) {
|
|
84
|
+
// Extract property:var(--d-*) pattern for color-mix
|
|
85
|
+
const colorMatch = baseDecl.match(/^(background|color|border-color):(var\(--[^)]+\))$/);
|
|
86
|
+
if (colorMatch) {
|
|
87
|
+
const [, prop, varRef] = colorMatch;
|
|
88
|
+
return {
|
|
89
|
+
className: atomPart,
|
|
90
|
+
decl: `${prop}:color-mix(in srgb,${varRef} ${alpha}%,transparent)`,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 3. Arbitrary value: _w[512px]
|
|
99
|
+
const arbMatch = atomPart.match(ARB_RE);
|
|
100
|
+
if (arbMatch) {
|
|
101
|
+
const [, propPrefix, rawValue] = arbMatch;
|
|
102
|
+
const cssProp = ARB_PROPS[propPrefix] || ARB_PROPS[propPrefix.toLowerCase()];
|
|
103
|
+
if (cssProp) {
|
|
104
|
+
// Convert underscores to spaces in value (e.g., 0_4px_6px → 0 4px 6px)
|
|
105
|
+
const value = rawValue.replace(/_/g, ' ');
|
|
106
|
+
return { className: atomPart, decl: `${cssProp}:${value}` };
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Dev-mode warning for unresolved atoms (atoms start with _)
|
|
112
|
+
if (atomPart.startsWith('_') && typeof globalThis !== 'undefined' && globalThis.__DECANTR_DEV__) {
|
|
113
|
+
console.warn(`[decantr] Unknown atom: "${atomPart}" — no CSS will be generated. Check reference/atoms.md`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Escape special characters in a CSS class name for use in selectors.
|
|
121
|
+
* @param {string} cls
|
|
122
|
+
* @returns {string}
|
|
123
|
+
*/
|
|
124
|
+
function escapeClass(cls) {
|
|
125
|
+
return cls.replace(/:/g, '\\:').replace(/\//g, '\\/').replace(/\[/g, '\\[').replace(/\]/g, '\\]').replace(/#/g, '\\#').replace(/%/g, '\\%').replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/,/g, '\\,').replace(/\+/g, '\\+');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* @param {...string} classes
|
|
130
|
+
* @returns {string}
|
|
131
|
+
*/
|
|
132
|
+
export function css(...classes) {
|
|
133
|
+
const result = [];
|
|
134
|
+
for (let i = 0; i < classes.length; i++) {
|
|
135
|
+
const cls = classes[i];
|
|
136
|
+
if (!cls) continue;
|
|
137
|
+
// Support space-separated classes in a single string
|
|
138
|
+
const parts = cls.split(/\s+/);
|
|
139
|
+
for (const part of parts) {
|
|
140
|
+
if (!part) continue;
|
|
141
|
+
|
|
142
|
+
// Special handling: _group → d-group, _peer → d-peer
|
|
143
|
+
if (part === '_group') { result.push('d-group'); continue; }
|
|
144
|
+
if (part === '_peer') { result.push('d-peer'); continue; }
|
|
145
|
+
// Component-class atoms: _prose → d-prose, _divideY → d-divide-y, _divideX → d-divide-x
|
|
146
|
+
if (part === '_prose') { result.push('d-prose'); continue; }
|
|
147
|
+
if (part === '_divideY') { result.push('d-divide-y'); continue; }
|
|
148
|
+
if (part === '_divideX') { result.push('d-divide-x'); continue; }
|
|
149
|
+
|
|
150
|
+
// Check for responsive prefix: _sm:gc3 → atom _gc3 at breakpoint sm
|
|
151
|
+
const bpMatch = part.match(BP_RE);
|
|
152
|
+
if (bpMatch) {
|
|
153
|
+
const [, bp, innerAtom] = bpMatch;
|
|
154
|
+
// The inner atom may itself be a group/peer, opacity, or arbitrary
|
|
155
|
+
const gpInner = innerAtom.match(/^(gh|gf|ga|ph|pf|pa):(.+)$/);
|
|
156
|
+
if (gpInner) {
|
|
157
|
+
// Responsive + group/peer: not supported (too complex), pass through
|
|
158
|
+
result.push(part);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
// Check for responsive + pseudo: _sm:h:bgmuted
|
|
162
|
+
const pseudoInner = innerAtom.match(/^(h|f|fv|a|fw):(.+)$/);
|
|
163
|
+
if (pseudoInner) {
|
|
164
|
+
const [, pseudoPrefix, atomName] = pseudoInner;
|
|
165
|
+
const resolved = resolveAtom(`_${atomName}`);
|
|
166
|
+
if (resolved) {
|
|
167
|
+
const PSEUDO_NAMES = { h: 'hover', f: 'focus', fv: 'focus-visible', a: 'active', fw: 'focus-within' };
|
|
168
|
+
injectResponsivePseudo(part, resolved.decl, bp, PSEUDO_NAMES[pseudoPrefix]);
|
|
169
|
+
result.push(part);
|
|
170
|
+
} else {
|
|
171
|
+
result.push(part);
|
|
172
|
+
}
|
|
173
|
+
continue;
|
|
174
|
+
}
|
|
175
|
+
const resolved = resolveAtom(`_${innerAtom}`);
|
|
176
|
+
if (resolved) {
|
|
177
|
+
injectResponsive(part, resolved.decl, bp);
|
|
178
|
+
result.push(part);
|
|
179
|
+
} else {
|
|
180
|
+
result.push(part);
|
|
181
|
+
}
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Check for container query prefix: _cq640:gc3
|
|
186
|
+
const cqMatch = part.match(CQ_RE);
|
|
187
|
+
if (cqMatch) {
|
|
188
|
+
const width = Number(cqMatch[1]);
|
|
189
|
+
const innerAtom = cqMatch[2];
|
|
190
|
+
if (CQ_SET.has(width)) {
|
|
191
|
+
const resolved = resolveAtom(`_${innerAtom}`);
|
|
192
|
+
if (resolved) {
|
|
193
|
+
injectContainer(part, resolved.decl, width);
|
|
194
|
+
result.push(part);
|
|
195
|
+
} else {
|
|
196
|
+
result.push(part);
|
|
197
|
+
}
|
|
198
|
+
} else {
|
|
199
|
+
result.push(part);
|
|
200
|
+
}
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Check for group/peer state prefix: _gh:fgprimary
|
|
205
|
+
const gpMatch = part.match(GP_RE);
|
|
206
|
+
if (gpMatch) {
|
|
207
|
+
const [, prefix, atomName] = gpMatch;
|
|
208
|
+
const resolved = resolveAtom(`_${atomName}`);
|
|
209
|
+
if (resolved) {
|
|
210
|
+
injectGroupPeer(part, resolved.decl, prefix);
|
|
211
|
+
result.push(part);
|
|
212
|
+
} else {
|
|
213
|
+
result.push(part);
|
|
214
|
+
}
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check for pseudo-class prefix: _h:bgprimary, _fv:ring2, _a:scale95
|
|
219
|
+
const pseudoMatch = part.match(PSEUDO_RE);
|
|
220
|
+
if (pseudoMatch) {
|
|
221
|
+
const [, prefix, innerAtom] = pseudoMatch;
|
|
222
|
+
const resolved = resolveAtom(`_${innerAtom}`);
|
|
223
|
+
if (resolved) {
|
|
224
|
+
injectPseudo(part, resolved.decl, prefix);
|
|
225
|
+
result.push(part);
|
|
226
|
+
} else {
|
|
227
|
+
result.push(part);
|
|
228
|
+
}
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Try to resolve (handles direct, opacity, and arbitrary)
|
|
233
|
+
const resolved = resolveAtom(part);
|
|
234
|
+
if (resolved) {
|
|
235
|
+
// Pass escaped class name if it contains special CSS selector characters
|
|
236
|
+
const needsEscape = /[/\[\]#%(),+]/.test(resolved.className);
|
|
237
|
+
inject(resolved.className, resolved.decl, needsEscape ? escapeClass(resolved.className) : undefined);
|
|
238
|
+
result.push(part);
|
|
239
|
+
} else {
|
|
240
|
+
// Pass through unknown classes (user CSS)
|
|
241
|
+
result.push(part);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return result.join(' ');
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {string} name
|
|
250
|
+
* @param {string} declaration
|
|
251
|
+
*/
|
|
252
|
+
export function define(name, declaration) {
|
|
253
|
+
customAtoms.set(name, declaration);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Sanitizes a string for safe use in HTML attributes.
|
|
258
|
+
* Escapes <, >, ", ', & characters.
|
|
259
|
+
* @param {string} str
|
|
260
|
+
* @returns {string}
|
|
261
|
+
*/
|
|
262
|
+
export function sanitize(str) {
|
|
263
|
+
if (typeof str !== 'string') return '';
|
|
264
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
265
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/** @type {Set<string>} */
|
|
2
|
+
const injected = new Set();
|
|
3
|
+
|
|
4
|
+
/** @type {HTMLStyleElement|null} */
|
|
5
|
+
let styleEl = null;
|
|
6
|
+
|
|
7
|
+
/** @type {HTMLStyleElement|null} */
|
|
8
|
+
let layerEl = null;
|
|
9
|
+
|
|
10
|
+
/** Responsive breakpoints (mobile-first, min-width) */
|
|
11
|
+
export const BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280 };
|
|
12
|
+
const BP_ORDER = ['sm', 'md', 'lg', 'xl'];
|
|
13
|
+
|
|
14
|
+
/** Container query breakpoints */
|
|
15
|
+
export const CQ_WIDTHS = [320, 480, 640, 768, 1024];
|
|
16
|
+
|
|
17
|
+
/** @type {Record<string, HTMLStyleElement>|null} */
|
|
18
|
+
let bpEls = null;
|
|
19
|
+
|
|
20
|
+
/** @type {HTMLStyleElement|null} */
|
|
21
|
+
let cqEl = null;
|
|
22
|
+
|
|
23
|
+
/** CSS cascade layer order declaration */
|
|
24
|
+
const LAYER_ORDER = '@layer d.base,d.theme,d.atoms,d.user;';
|
|
25
|
+
|
|
26
|
+
// ─── Buffered injection ─────────────────────────────────────────
|
|
27
|
+
// Rules are buffered in arrays and flushed to DOM in batches via
|
|
28
|
+
// microtask, avoiding O(n²) string concatenation on textContent.
|
|
29
|
+
|
|
30
|
+
/** @type {string[]} */
|
|
31
|
+
let atomBuffer = [];
|
|
32
|
+
/** @type {Record<string, string[]>} */
|
|
33
|
+
let bpBuffers = {};
|
|
34
|
+
/** @type {string[]} */
|
|
35
|
+
let cqBuffer = [];
|
|
36
|
+
/** @type {boolean} */
|
|
37
|
+
let flushScheduled = false;
|
|
38
|
+
|
|
39
|
+
function scheduleFlush() {
|
|
40
|
+
if (flushScheduled) return;
|
|
41
|
+
flushScheduled = true;
|
|
42
|
+
if (typeof queueMicrotask === 'function') {
|
|
43
|
+
queueMicrotask(flushBuffers);
|
|
44
|
+
} else {
|
|
45
|
+
Promise.resolve().then(flushBuffers);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function flushBuffers() {
|
|
50
|
+
flushScheduled = false;
|
|
51
|
+
if (atomBuffer.length) {
|
|
52
|
+
const el = getStyleElement();
|
|
53
|
+
if (el) el.textContent = (el.textContent || '') + atomBuffer.join('');
|
|
54
|
+
atomBuffer.length = 0;
|
|
55
|
+
}
|
|
56
|
+
if (Object.keys(bpBuffers).length) {
|
|
57
|
+
const els = ensureBpElements();
|
|
58
|
+
if (els) {
|
|
59
|
+
for (const bp of BP_ORDER) {
|
|
60
|
+
if (bpBuffers[bp] && bpBuffers[bp].length) {
|
|
61
|
+
els[bp].textContent = (els[bp].textContent || '') + bpBuffers[bp].join('');
|
|
62
|
+
bpBuffers[bp].length = 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
bpBuffers = {};
|
|
67
|
+
}
|
|
68
|
+
if (cqBuffer.length) {
|
|
69
|
+
const el = ensureCqElement();
|
|
70
|
+
if (el) el.textContent = (el.textContent || '') + cqBuffer.join('');
|
|
71
|
+
cqBuffer.length = 0;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function ensureLayerOrder() {
|
|
76
|
+
if (layerEl) return;
|
|
77
|
+
if (typeof document === 'undefined') return;
|
|
78
|
+
layerEl = document.createElement('style');
|
|
79
|
+
layerEl.setAttribute('data-decantr-layers', '');
|
|
80
|
+
layerEl.textContent = LAYER_ORDER;
|
|
81
|
+
document.head.prepend(layerEl);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function getStyleElement() {
|
|
85
|
+
if (!styleEl) {
|
|
86
|
+
if (typeof document === 'undefined') return null;
|
|
87
|
+
ensureLayerOrder();
|
|
88
|
+
styleEl = document.createElement('style');
|
|
89
|
+
styleEl.setAttribute('data-decantr', '');
|
|
90
|
+
document.head.appendChild(styleEl);
|
|
91
|
+
}
|
|
92
|
+
return styleEl;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function ensureBpElements() {
|
|
96
|
+
if (bpEls) return bpEls;
|
|
97
|
+
if (typeof document === 'undefined') return null;
|
|
98
|
+
bpEls = {};
|
|
99
|
+
getStyleElement();
|
|
100
|
+
for (const bp of BP_ORDER) {
|
|
101
|
+
const el = document.createElement('style');
|
|
102
|
+
el.setAttribute(`data-decantr-${bp}`, '');
|
|
103
|
+
document.head.appendChild(el);
|
|
104
|
+
bpEls[bp] = el;
|
|
105
|
+
}
|
|
106
|
+
return bpEls;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* @param {string} className
|
|
111
|
+
* @param {string} declaration
|
|
112
|
+
* @param {string} [escapedName] — pre-escaped class name for special chars (/, [, ], etc.)
|
|
113
|
+
*/
|
|
114
|
+
export function inject(className, declaration, escapedName) {
|
|
115
|
+
if (injected.has(className)) return;
|
|
116
|
+
injected.add(className);
|
|
117
|
+
if (typeof document === 'undefined') return;
|
|
118
|
+
const sel = escapedName || className;
|
|
119
|
+
atomBuffer.push(`@layer d.atoms{.${sel}{${declaration}}}`);
|
|
120
|
+
scheduleFlush();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Inject a responsive (breakpoint-wrapped) atom.
|
|
125
|
+
* @param {string} className — e.g. '_sm:gc3'
|
|
126
|
+
* @param {string} declaration — CSS declaration(s)
|
|
127
|
+
* @param {string} bp — breakpoint key (sm|md|lg|xl)
|
|
128
|
+
*/
|
|
129
|
+
export function injectResponsive(className, declaration, bp) {
|
|
130
|
+
if (injected.has(className)) return;
|
|
131
|
+
injected.add(className);
|
|
132
|
+
if (typeof document === 'undefined') return;
|
|
133
|
+
const escaped = className.replace(/:/g, '\\:');
|
|
134
|
+
if (!bpBuffers[bp]) bpBuffers[bp] = [];
|
|
135
|
+
bpBuffers[bp].push(`@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}{${declaration}}}}`);
|
|
136
|
+
scheduleFlush();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function ensureCqElement() {
|
|
140
|
+
if (cqEl) return cqEl;
|
|
141
|
+
if (typeof document === 'undefined') return null;
|
|
142
|
+
getStyleElement();
|
|
143
|
+
cqEl = document.createElement('style');
|
|
144
|
+
cqEl.setAttribute('data-decantr-cq', '');
|
|
145
|
+
document.head.appendChild(cqEl);
|
|
146
|
+
return cqEl;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Inject a container query-wrapped atom.
|
|
151
|
+
* @param {string} className — e.g. '_cq640:gc3'
|
|
152
|
+
* @param {string} declaration — CSS declaration(s)
|
|
153
|
+
* @param {number} width — container min-width in px
|
|
154
|
+
*/
|
|
155
|
+
export function injectContainer(className, declaration, width) {
|
|
156
|
+
if (injected.has(className)) return;
|
|
157
|
+
injected.add(className);
|
|
158
|
+
if (typeof document === 'undefined') return;
|
|
159
|
+
const escaped = className.replace(/:/g, '\\:');
|
|
160
|
+
cqBuffer.push(`@layer d.atoms{@container(min-width:${width}px){.${escaped}{${declaration}}}}`);
|
|
161
|
+
scheduleFlush();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** State map for group/peer prefix → CSS pseudo selector */
|
|
165
|
+
const GP_STATE = {
|
|
166
|
+
gh: ['group', 'hover'], gf: ['group', 'focus-within'], ga: ['group', 'active'],
|
|
167
|
+
ph: ['peer', 'hover'], pf: ['peer', 'focus'], pa: ['peer', 'active'],
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Inject a group/peer state atom.
|
|
172
|
+
* @param {string} className — e.g. '_gh:fgprimary'
|
|
173
|
+
* @param {string} declaration — CSS declaration(s)
|
|
174
|
+
* @param {string} prefix — 'gh'|'gf'|'ga'|'ph'|'pf'|'pa'
|
|
175
|
+
*/
|
|
176
|
+
export function injectGroupPeer(className, declaration, prefix) {
|
|
177
|
+
if (injected.has(className)) return;
|
|
178
|
+
injected.add(className);
|
|
179
|
+
if (typeof document === 'undefined') return;
|
|
180
|
+
const escaped = className.replace(/:/g, '\\:').replace(/\//g, '\\/');
|
|
181
|
+
const [kind, state] = GP_STATE[prefix];
|
|
182
|
+
const combinator = kind === 'group' ? ' ' : ' ~ ';
|
|
183
|
+
atomBuffer.push(`@layer d.atoms{.d-${kind}:${state}${combinator}.${escaped}{${declaration}}}`);
|
|
184
|
+
scheduleFlush();
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Pseudo-class prefix map */
|
|
188
|
+
const PSEUDO_MAP = {
|
|
189
|
+
h: 'hover', f: 'focus', fv: 'focus-visible', a: 'active', fw: 'focus-within',
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Inject a pseudo-class atom.
|
|
194
|
+
* @param {string} className — e.g. '_h:bgprimary'
|
|
195
|
+
* @param {string} declaration — CSS declaration(s)
|
|
196
|
+
* @param {string} prefix — 'h'|'f'|'fv'|'a'|'fw'
|
|
197
|
+
*/
|
|
198
|
+
export function injectPseudo(className, declaration, prefix) {
|
|
199
|
+
if (injected.has(className)) return;
|
|
200
|
+
injected.add(className);
|
|
201
|
+
if (typeof document === 'undefined') return;
|
|
202
|
+
const escaped = className.replace(/:/g, '\\:').replace(/\//g, '\\/').replace(/\[/g, '\\[').replace(/\]/g, '\\]').replace(/#/g, '\\#').replace(/%/g, '\\%').replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/,/g, '\\,').replace(/\+/g, '\\+');
|
|
203
|
+
const pseudo = PSEUDO_MAP[prefix];
|
|
204
|
+
atomBuffer.push(`@layer d.atoms{.${escaped}:${pseudo}{${declaration}}}`);
|
|
205
|
+
scheduleFlush();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Inject a responsive + pseudo-class atom.
|
|
210
|
+
* @param {string} className — e.g. '_sm:h:bgprimary'
|
|
211
|
+
* @param {string} declaration — CSS declaration(s)
|
|
212
|
+
* @param {string} bp — breakpoint key (sm|md|lg|xl)
|
|
213
|
+
* @param {string} pseudo — pseudo-class name (hover|focus|focus-visible|active|focus-within)
|
|
214
|
+
*/
|
|
215
|
+
export function injectResponsivePseudo(className, declaration, bp, pseudo) {
|
|
216
|
+
if (injected.has(className)) return;
|
|
217
|
+
injected.add(className);
|
|
218
|
+
if (typeof document === 'undefined') return;
|
|
219
|
+
const escaped = className.replace(/:/g, '\\:').replace(/\//g, '\\/').replace(/\[/g, '\\[').replace(/\]/g, '\\]').replace(/#/g, '\\#').replace(/%/g, '\\%').replace(/\(/g, '\\(').replace(/\)/g, '\\)').replace(/,/g, '\\,').replace(/\+/g, '\\+');
|
|
220
|
+
if (!bpBuffers[bp]) bpBuffers[bp] = [];
|
|
221
|
+
bpBuffers[bp].push(`@layer d.atoms{@media(min-width:${BREAKPOINTS[bp]}px){.${escaped}:${pseudo}{${declaration}}}}`);
|
|
222
|
+
scheduleFlush();
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* @returns {string}
|
|
227
|
+
*/
|
|
228
|
+
export function extractCSS() {
|
|
229
|
+
flushBuffers();
|
|
230
|
+
let css = layerEl ? layerEl.textContent || '' : '';
|
|
231
|
+
css += styleEl ? styleEl.textContent || '' : '';
|
|
232
|
+
if (bpEls) {
|
|
233
|
+
for (const bp of BP_ORDER) {
|
|
234
|
+
if (bpEls[bp]) css += bpEls[bp].textContent || '';
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (cqEl) css += cqEl.textContent || '';
|
|
238
|
+
return css;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* @returns {Set<string>}
|
|
243
|
+
*/
|
|
244
|
+
export function getInjectedClasses() {
|
|
245
|
+
return new Set(injected);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function reset() {
|
|
249
|
+
injected.clear();
|
|
250
|
+
atomBuffer.length = 0;
|
|
251
|
+
bpBuffers = {};
|
|
252
|
+
cqBuffer.length = 0;
|
|
253
|
+
flushScheduled = false;
|
|
254
|
+
if (layerEl) {
|
|
255
|
+
layerEl.textContent = LAYER_ORDER;
|
|
256
|
+
}
|
|
257
|
+
if (styleEl) {
|
|
258
|
+
styleEl.textContent = '';
|
|
259
|
+
}
|
|
260
|
+
if (bpEls) {
|
|
261
|
+
for (const bp of BP_ORDER) {
|
|
262
|
+
if (bpEls[bp]) bpEls[bp].textContent = '';
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
if (cqEl) {
|
|
266
|
+
cqEl.textContent = '';
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bioluminescent — Deep ocean aesthetic. Organic glow.
|
|
3
|
+
* Luminescent edges on dark backgrounds, living and breathing UI.
|
|
4
|
+
* Glowing borders, pulsing animations, deep abyss backgrounds.
|
|
5
|
+
*/
|
|
6
|
+
export const bioluminescent = {
|
|
7
|
+
id: 'bioluminescent',
|
|
8
|
+
name: 'Bioluminescent',
|
|
9
|
+
seed: {
|
|
10
|
+
primary: '#00ffd5',
|
|
11
|
+
accent: '#7b61ff',
|
|
12
|
+
tertiary: '#ff6b9d',
|
|
13
|
+
neutral: '#6b8299',
|
|
14
|
+
success: '#00e676',
|
|
15
|
+
warning: '#ffab40',
|
|
16
|
+
error: '#ff5252',
|
|
17
|
+
info: '#40c4ff',
|
|
18
|
+
bg: '#f0fdf4',
|
|
19
|
+
bgDark: '#020817',
|
|
20
|
+
},
|
|
21
|
+
personality: {
|
|
22
|
+
radius: 'pill',
|
|
23
|
+
elevation: 'glow',
|
|
24
|
+
motion: 'smooth',
|
|
25
|
+
borders: 'none',
|
|
26
|
+
density: 'comfortable',
|
|
27
|
+
gradient: 'vivid',
|
|
28
|
+
},
|
|
29
|
+
typography: {
|
|
30
|
+
'--d-fw-heading': '500',
|
|
31
|
+
'--d-fw-title': '400',
|
|
32
|
+
'--d-ls-heading': '0.03em',
|
|
33
|
+
},
|
|
34
|
+
overrides: {
|
|
35
|
+
light: {
|
|
36
|
+
'--d-border': 'rgba(0,255,213,0.12)',
|
|
37
|
+
'--d-border-strong': 'rgba(0,255,213,0.22)',
|
|
38
|
+
'--d-field-bg': 'rgba(255,255,255,0.6)',
|
|
39
|
+
'--d-field-border': 'rgba(0,255,213,0.15)',
|
|
40
|
+
'--d-field-border-hover': 'rgba(0,255,213,0.3)',
|
|
41
|
+
'--d-item-hover-bg': 'rgba(0,255,213,0.06)',
|
|
42
|
+
},
|
|
43
|
+
dark: {
|
|
44
|
+
'--d-bg': '#020817',
|
|
45
|
+
'--d-fg': '#c8e6df',
|
|
46
|
+
'--d-muted-fg': '#5a8a7d',
|
|
47
|
+
'--d-border': 'rgba(0,255,213,0.1)',
|
|
48
|
+
'--d-border-strong': 'rgba(0,255,213,0.2)',
|
|
49
|
+
'--d-field-bg': 'rgba(0,255,213,0.04)',
|
|
50
|
+
'--d-field-border': 'rgba(0,255,213,0.12)',
|
|
51
|
+
'--d-field-border-hover': 'rgba(0,255,213,0.25)',
|
|
52
|
+
'--d-item-hover-bg': 'rgba(0,255,213,0.06)',
|
|
53
|
+
'--d-chart-0': '#00ffd5',
|
|
54
|
+
'--d-chart-1': '#7b61ff',
|
|
55
|
+
'--d-chart-2': '#ff6b9d',
|
|
56
|
+
'--d-chart-3': '#00e676',
|
|
57
|
+
'--d-chart-4': '#ffab40',
|
|
58
|
+
'--d-chart-5': '#40c4ff',
|
|
59
|
+
'--d-chart-6': '#e040fb',
|
|
60
|
+
'--d-chart-7': '#76ff03',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
components: [
|
|
64
|
+
'body{font-family:var(--d-font);background:var(--d-bg);color:var(--d-fg);line-height:var(--d-lh-normal);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}',
|
|
65
|
+
'::selection{background:rgba(0,255,213,0.25);color:var(--d-fg)}',
|
|
66
|
+
// Scrollbar — dark with glowing thumb
|
|
67
|
+
'::-webkit-scrollbar{width:6px;height:6px}',
|
|
68
|
+
'::-webkit-scrollbar-track{background:transparent}',
|
|
69
|
+
'::-webkit-scrollbar-thumb{background:rgba(0,255,213,0.2);border-radius:var(--d-radius-full)}',
|
|
70
|
+
'::-webkit-scrollbar-thumb:hover{background:rgba(0,255,213,0.4);box-shadow:0 0 8px rgba(0,255,213,0.3)}',
|
|
71
|
+
// Card — glowing edges
|
|
72
|
+
'.d-card{border:none;box-shadow:var(--d-elevation-1),0 0 1px rgba(0,255,213,0.2)}',
|
|
73
|
+
'.d-card-inner{box-shadow:none}',
|
|
74
|
+
// Modal — intense glow
|
|
75
|
+
'.d-modal-content{border:none;box-shadow:var(--d-elevation-3),0 0 2px rgba(0,255,213,0.3)}',
|
|
76
|
+
// Button — bioluminescent glow
|
|
77
|
+
'.d-btn-primary{box-shadow:0 0 12px rgba(0,255,213,0.25),0 0 4px rgba(0,255,213,0.15)}',
|
|
78
|
+
'.d-btn-primary:hover{box-shadow:0 0 20px rgba(0,255,213,0.35),0 0 8px rgba(0,255,213,0.2)}',
|
|
79
|
+
// Bioluminescent utilities
|
|
80
|
+
'@keyframes d-biolum-pulse{0%,100%{box-shadow:0 0 8px rgba(0,255,213,0.15)}50%{box-shadow:0 0 20px rgba(0,255,213,0.3),0 0 4px rgba(0,255,213,0.15)}}',
|
|
81
|
+
'.d-biolum-pulse{animation:d-biolum-pulse 3s ease-in-out infinite}',
|
|
82
|
+
'.d-biolum-edge{box-shadow:0 0 8px rgba(0,255,213,0.2),inset 0 0 8px rgba(0,255,213,0.05)}',
|
|
83
|
+
'.d-biolum-trail{transition:box-shadow var(--d-tr-normal) var(--d-ease-standard)}',
|
|
84
|
+
'.d-biolum-trail:hover{box-shadow:0 0 16px rgba(0,255,213,0.25),4px 0 12px rgba(123,97,255,0.15),-4px 0 12px rgba(255,107,157,0.15)}',
|
|
85
|
+
// Gradient text — oceanic
|
|
86
|
+
'.d-gradient-text{background:linear-gradient(135deg,var(--d-primary),var(--d-accent),var(--d-tertiary));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}',
|
|
87
|
+
'.d-gradient-text-alt{background:linear-gradient(135deg,var(--d-accent),var(--d-primary));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}',
|
|
88
|
+
// Mesh — underwater glow
|
|
89
|
+
'.d-mesh{background:radial-gradient(ellipse at 30% 60%,rgba(0,255,213,0.08) 0%,transparent 50%),radial-gradient(ellipse at 70% 30%,rgba(123,97,255,0.06) 0%,transparent 50%),radial-gradient(ellipse at 50% 90%,rgba(255,107,157,0.04) 0%,transparent 50%),var(--d-bg)}',
|
|
90
|
+
// Frosted dialog
|
|
91
|
+
'dialog::backdrop{background:rgba(2,8,23,0.6);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px)}',
|
|
92
|
+
].join(''),
|
|
93
|
+
};
|