astryx-dracula 0.5.0 → 0.6.2

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.
Files changed (129) hide show
  1. package/BRAND.md +3 -3
  2. package/README.md +7 -4
  3. package/USAGE.md +49 -49
  4. package/astryx-dracula.d.ts +2 -2
  5. package/astryx-dracula.js +25 -9
  6. package/astryx-dracula.variants.d.ts +2 -2
  7. package/astryx.integration.mjs +1 -1
  8. package/icons.mjs +21 -17
  9. package/icons.tsx +69 -62
  10. package/package.json +125 -120
  11. package/shared/auth-chrome-config.ts +6 -6
  12. package/shared/auth-chrome.tsx +143 -144
  13. package/shared/auth-copy.ts +14 -14
  14. package/shared/chaptered-doc-config.ts +48 -51
  15. package/shared/chaptered-doc.tsx +267 -289
  16. package/shared/chart-hues.ts +25 -10
  17. package/shared/chart-labels.tsx +31 -30
  18. package/shared/chart-legend.tsx +55 -56
  19. package/shared/chart-panel-style.ts +3 -3
  20. package/shared/data-bar.tsx +97 -102
  21. package/shared/format-money.ts +1 -1
  22. package/shared/gallery-image.ts +6 -6
  23. package/shared/login-demo.ts +1 -1
  24. package/shared/metric-card.tsx +101 -105
  25. package/shared/metric-delta.tsx +28 -27
  26. package/shared/order-desk.tsx +205 -216
  27. package/shared/revenue-chart.tsx +145 -165
  28. package/shared/scene-castle.tsx +206 -291
  29. package/shared/scene-frame.tsx +33 -32
  30. package/shared/scene-hues.ts +17 -17
  31. package/shared/scene-tile.tsx +88 -92
  32. package/shared/settings-data.ts +119 -125
  33. package/shared/settings-rows.tsx +122 -159
  34. package/shared/sparkline.tsx +75 -88
  35. package/shared/sso-icons.tsx +10 -22
  36. package/shared/stars.tsx +16 -25
  37. package/templates/ai-chat-landing.template.mjs +5 -4
  38. package/templates/ai-chat-landing.tsx +473 -460
  39. package/templates/ai-chat.template.mjs +5 -4
  40. package/templates/ai-chat.tsx +543 -612
  41. package/templates/blank.template.mjs +5 -4
  42. package/templates/blank.tsx +18 -14
  43. package/templates/centered-hero.template.mjs +5 -4
  44. package/templates/centered-hero.tsx +55 -68
  45. package/templates/classic-gallery.template.mjs +5 -4
  46. package/templates/classic-gallery.tsx +97 -104
  47. package/templates/contact-form.template.mjs +5 -4
  48. package/templates/contact-form.tsx +247 -282
  49. package/templates/dashboard-portfolio.template.mjs +5 -4
  50. package/templates/dashboard-portfolio.tsx +717 -548
  51. package/templates/dashboard.template.mjs +5 -4
  52. package/templates/dashboard.tsx +596 -567
  53. package/templates/detail-page.template.mjs +5 -4
  54. package/templates/detail-page.tsx +546 -603
  55. package/templates/documentation-design.template.mjs +5 -4
  56. package/templates/documentation-design.tsx +231 -243
  57. package/templates/documentation-technical.template.mjs +5 -4
  58. package/templates/documentation-technical.tsx +236 -239
  59. package/templates/documentation.template.mjs +5 -4
  60. package/templates/documentation.tsx +267 -279
  61. package/templates/editor.template.mjs +5 -4
  62. package/templates/editor.tsx +844 -877
  63. package/templates/file-explorer.template.mjs +5 -4
  64. package/templates/file-explorer.tsx +566 -590
  65. package/templates/form-two-column.template.mjs +5 -4
  66. package/templates/form-two-column.tsx +195 -210
  67. package/templates/gallery-hero.template.mjs +5 -4
  68. package/templates/gallery-hero.tsx +93 -114
  69. package/templates/ide.template.mjs +5 -4
  70. package/templates/ide.tsx +407 -453
  71. package/templates/incident-console.template.mjs +5 -4
  72. package/templates/incident-console.tsx +593 -575
  73. package/templates/kanban-board.template.mjs +5 -4
  74. package/templates/kanban-board.tsx +665 -683
  75. package/templates/library.template.mjs +5 -4
  76. package/templates/library.tsx +409 -430
  77. package/templates/login-card.template.mjs +5 -4
  78. package/templates/login-card.tsx +63 -72
  79. package/templates/login-split.template.mjs +5 -4
  80. package/templates/login-split.tsx +192 -193
  81. package/templates/login-sso.template.mjs +5 -4
  82. package/templates/login-sso.tsx +257 -258
  83. package/templates/login.template.mjs +5 -4
  84. package/templates/login.tsx +53 -49
  85. package/templates/messaging-shell.template.mjs +5 -4
  86. package/templates/messaging-shell.tsx +556 -574
  87. package/templates/mixed-gallery.template.mjs +5 -4
  88. package/templates/mixed-gallery.tsx +60 -58
  89. package/templates/payment-form.template.mjs +5 -4
  90. package/templates/payment-form.tsx +882 -991
  91. package/templates/product-detail.template.mjs +5 -4
  92. package/templates/product-detail.tsx +261 -272
  93. package/templates/product-gallery.template.mjs +5 -4
  94. package/templates/product-gallery.tsx +126 -137
  95. package/templates/product-tour.template.mjs +5 -4
  96. package/templates/product-tour.tsx +741 -773
  97. package/templates/settings-dialog.template.mjs +5 -4
  98. package/templates/settings-dialog.tsx +688 -717
  99. package/templates/settings-sidebar.template.mjs +5 -4
  100. package/templates/settings-sidebar.tsx +762 -807
  101. package/templates/settings.template.mjs +5 -4
  102. package/templates/settings.tsx +289 -304
  103. package/templates/shell-nav.template.mjs +5 -4
  104. package/templates/shell-nav.tsx +212 -219
  105. package/templates/shell-side-nav.template.mjs +5 -4
  106. package/templates/shell-side-nav.tsx +135 -157
  107. package/templates/shell-top-nav.template.mjs +5 -4
  108. package/templates/shell-top-nav.tsx +182 -203
  109. package/templates/side-gallery.template.mjs +5 -4
  110. package/templates/side-gallery.tsx +85 -90
  111. package/templates/table-grouped.template.mjs +5 -4
  112. package/templates/table-grouped.tsx +1000 -1053
  113. package/templates/table-page-chart.template.mjs +5 -4
  114. package/templates/table-page-chart.tsx +400 -398
  115. package/templates/table-page-heatmap-status.template.mjs +5 -4
  116. package/templates/table-page-heatmap-status.tsx +483 -512
  117. package/templates/table-page-shoe-store-heatmap.template.mjs +5 -4
  118. package/templates/table-page-shoe-store-heatmap.tsx +748 -746
  119. package/templates/table-page.template.mjs +5 -4
  120. package/templates/table-page.tsx +396 -405
  121. package/templates/table.template.mjs +5 -4
  122. package/templates/table.tsx +92 -93
  123. package/templates/tech-report.template.mjs +5 -4
  124. package/templates/tech-report.tsx +1316 -1304
  125. package/templates/theme-showcase.template.mjs +5 -4
  126. package/templates/theme-showcase.tsx +871 -951
  127. package/theme.css +35 -77
  128. package/theme.css.d.ts +9 -0
  129. package/tokens.css +373 -380
package/BRAND.md CHANGED
@@ -37,7 +37,7 @@ Source of truth is `astryx-theme.ts`. Do not add hexes; `bun run audit` enforces
37
37
 
38
38
  ## Borders
39
39
 
40
- `--color-border` is Comment `#6272A4`. `--color-border-emphasized` is **`#9AA1BC`**, repinned from Comment: core tone-bumps that token to ≥3:1 for form-control boundaries, but `pin()` returns a literal so that guarantee is inert here, and the old value cleared *no* surface tier at 3:1 while the new one clears all four (5.56 / 4.60 / 3.77 / 3.57). `DropdownMenuRadioItem` reads it on a popover, so the popover tier is a real consumer. Known shortfall: the inverted surface at 2.40, which has no live consumer — recorded, not certified.
40
+ `--color-border` is Comment `#6272A4`. `--color-border-emphasized` is **`#9AA1BC`**, repinned from Comment: core tone-bumps that token to ≥3:1 for form-control boundaries, but `pin()` returns a literal so that guarantee is inert here, and the old value cleared *no* surface tier at 3:1 while the new one clears all four (5.56 / 4.60 / 3.77 / 3.57). Its live 0.7.2 consumers are form controls and content chrome — `Field`/`FileInput`/`NumberInput`/`InputGroupText`/`Kbd` borders, `Divider variant="strong"`, `Blockquote`'s rule, `HoverCard`'s dashed underline, `Tooltip`'s dashed underline, the checkbox/radio `Indicator`, `Calendar`'s today ring, `TreeList`'s branch lines, `ResizeHandle` and `Selector`'s focus restore. (`DropdownMenuRadioItem` read it in 0.6.3 and no longer does.) The popover tier is still a real adjacent tier for the popover surface itself. Known shortfall: the inverted surface at 2.40, which has no live consumer — recorded, not certified.
41
41
 
42
42
  ## Charts
43
43
 
@@ -79,8 +79,8 @@ Radii flat and crisp (5px elements, 4px inner). Everything below is a core defau
79
79
  - One runtime dependency: `lucide-react` (icons render from it at runtime, both the theme `draculaIconRegistry` in `icons.tsx` and every template's direct imports — `bun run audit` fails when a registered glyph stops resolving to a real export). Everything else is defined here.
80
80
  - Derived AA lifts (not spec hexes, same hues): secondary text #9AA1BC, muted text #8288A6, paragraph #B0B3C4. Subdue #4C5067 is chrome, below every text floor.
81
81
  - Icon glyphs from Lucide in `icons.tsx` (MIT). The theme also sets icon colors (primary, secondary, disabled, accent).
82
- - onDark: `--color-on-dark` is repinned to spec Foreground `#F8F8F2` — the spec has **no pure white**, so a `#FFFFFF` here is off-palette. The pair is **deliberately asymmetric** and should not be "fixed" into symmetry: on-dark = spec Foreground `#F8F8F2`, on-light = spec black `#000000`. `--color-tint-hover` is **`#FFFFFF` and ruled correct — do not repaint.** It looks like a second pure white next to the line above, and it is not: core only ever reads it as a `color-mix` **partner** at 5–20% (`CheckboxInput.tsx:115-138`, `Slider.tsx:252`), never as a paint, and it is core's own dark value (`tokens.stylex.ts:81`, `light-dark(black, white)`). Retinting it to a Dracula grey would silently change every mix core builds and break the only thing it is for. `#FFFFFF` is not on-palette; the *token* is.
83
- - `--color-data-neutral`: `#8C939B`, **inherited from core** (core declares `light-dark(#8494A3, #8C939B)` in `core/src/theme/domainTokens/dataTokens.ts`) and off-palette — neither a Dracula hex nor on our gray ramp, whose L60 computes to `#8A8EA8`. It stays because it reads fine on dark. The "Stone" label in an earlier line here was never an Astryx brand name: `grep -ril stone node_modules/@astryxdesign/` hits only a separate `@astryxdesign/theme-stone` package, not this value. **Open question, deliberately not answered:** the value is off-palette and we could ship a gray ramp step instead — but it is core's own default, and diverging from core on a data role buys brand purity at the cost of surprising anyone who ports a core chart. That trade is the human's.
82
+ - onDark: `--color-on-dark` is repinned to spec Foreground `#F8F8F2` — the spec has **no pure white**, so a `#FFFFFF` here is off-palette. The pair is **deliberately asymmetric** and should not be "fixed" into symmetry: on-dark = spec Foreground `#F8F8F2`, on-light = spec black `#000000`. `--color-tint-hover` is **`#FFFFFF` and ruled correct — do not repaint.** It looks like a second pure white next to the line above, and it is not: core only ever reads it as a `color-mix` **partner** at 5–20% (`Indicator/CheckboxIndicator.tsx:48,54,65,71`, `Indicator/RadioIndicator.tsx:48,54,62,68`, `Slider.tsx:290`, `Link.tsx:112,120,134`, `Switch.tsx:291,302`), never as a paint, and it is core's own dark value (`tokens.stylex.ts:83`, `light-dark(black, white)`). Retinting it to a Dracula grey would silently change every mix core builds and break the only thing it is for. `#FFFFFF` is not on-palette; the *token* is.
83
+ - `--color-data-neutral`: `#8C939B`, **pinned by this theme** — since core 0.7.0 the canonical data-colour defaults live in core's `dataVars` group and a concrete theme emits only what it authors, so this value is ours to own rather than core's — and off-palette — neither a Dracula hex nor on our gray ramp, whose L60 computes to `#8A8EA8`. It stays because it reads fine on dark. The "Stone" label in an earlier line here was never an Astryx brand name: `grep -ril stone node_modules/@astryxdesign/` hits only a separate `@astryxdesign/theme-stone` package, not this value. **Open question, deliberately not answered:** the value is off-palette and we could ship a gray ramp step instead — but it is core's own default, and diverging from core on a data role buys brand purity at the cost of surprising anyone who ports a core chart. That trade is the human's.
84
84
  - Tag accents: `--color-tag-<orange|pink|cyan|yellow|green|purple>`. The purple tag was **renamed from `blue`** — it always held `#BD93F9` (spec Purple) and never a blue. Dracula has no blue, so the value was right and the name was the lie. Historical trap for anyone who greps: `blue` is also the name of six *other* tokens that genuinely are Comment (`--color-background-blue`, `-border-`, `-icon-`, `-text-`, `--color-data-categorical-blue`, `--color-data-blue-1..5`), so a repo-wide find/replace on "blue" would silently repoint all six at Purple. A name that contradicts its own value is invisible to every contrast gate, which is why this needed a ruling rather than a threshold.
85
85
  - No color-scale config: HCT generation would fight the pinned hexes. No light mode, ever.
86
86
 
package/README.md CHANGED
@@ -10,7 +10,7 @@ Live showcase: https://yuzu-octopus.github.io/astryx-dracula/
10
10
 
11
11
  ## Features
12
12
 
13
- - Dracula tokens pinned in `astryx-theme.ts` (`grep -c "pin(" astryx-theme.ts` pins) (191 public props in the prebuilt `theme.css`, plus 3 private `--_*-radius` aliases; `tokens.css` is a full plain-CSS mirror, `grep -c "^ --" tokens.css` vars), dark-only. No gate asserts these counts — `bun run theme:check` asserts freshness, `bun run audit` asserts palette purity and contrast.
13
+ - Dracula tokens pinned in `astryx-theme.ts` (`grep -c "pin(" astryx-theme.ts` pins) (the public props the prebuilt `theme.css` ships, `grep -c "^ --" theme.css`, plus 3 private `--_*-radius` aliases; `tokens.css` mirrors the theme's colour, spacing, radius, type and motion tokens as plain `:root` custom properties, unlayered so it beats core's layers, `grep -c "^\s*--" tokens.css` vars), dark-only. No gate asserts these counts — `bun run theme:check` asserts freshness, `bun run audit` asserts palette purity and contrast.
14
14
  - Syntax theme plus chart series and sequential ramps
15
15
  - Prebuilt CSS plus runtime theme injection, or runtime injection alone for prototyping
16
16
  - WCAG contrast gates enforced in CI via `bun run audit`
@@ -52,9 +52,9 @@ theme.css prebuilt output of bun run theme:build
52
52
  tokens.css plain-CSS :root mirror for any stack
53
53
  icons.tsx Lucide icon registry (runtime `lucide-react` dependency)
54
54
  fonts/ JetBrains Mono woff2 files
55
- templates/ around 45 themed pages plus integration specs
55
+ templates/ around 45 themed pages, each with an XLE structure header
56
56
  shared/ reusable modules templates compose (23 files)
57
- scripts/check.ts palette, contrast, and packaging gates
57
+ scripts/check.ts palette, contrast, packaging, and XLE-header gates
58
58
  demo/ showcase source, deployed to GitHub Pages
59
59
  ```
60
60
 
@@ -62,10 +62,13 @@ demo/ showcase source, deployed to GitHub Pages
62
62
 
63
63
  | Command | Purpose |
64
64
  | -------------------- | ------------------------------------------ |
65
- | `bun run audit` | Palette plus contrast gates, fails on drift |
65
+ | `bun run audit` | Palette, contrast, packaging and XLE gates |
66
66
  | `bun run theme:build`| Rebuild `theme.css` from the source |
67
67
  | `bun run theme:check`| Fail if committed theme outputs are stale |
68
68
  | `bun run build` | Typecheck plus showcase build |
69
+ | `bun run fmt` | Format the source (`bun fmt`; style in `bunfig.toml`) |
70
+ | `bun run fmt:check` | Fail if the source is not formatted |
71
+ | `bun run lint` | Biome, lint only — the formatter is `bun fmt` |
69
72
  | `bunx react-doctor@latest` | Component health scan (currently 100/100) |
70
73
 
71
74
  ## Attribution & License
package/USAGE.md CHANGED
@@ -62,7 +62,7 @@ import '../tokens.css';
62
62
  ```
63
63
 
64
64
  Then use `var(--color-primary)`, `var(--dracula-purple)`, `var(--space-gap)`.
65
- `tokens.css` sets real `:root` values with `color-scheme: dark`, so first paint is correct with no runtime. It is a full plain-CSS mirror of the theme (`grep -c "^ --" tokens.css` `:root` vars, unlayered by design so it beats core layers with zero `!important`); edit the theme, not this file, then re-mirror.
65
+ `tokens.css` sets real `:root` values with `color-scheme: dark`, so first paint is correct with no runtime. It mirrors the theme's colour, spacing, radius, type and motion tokens as plain `:root` custom properties (`grep -c "^\s*--" tokens.css` vars, unlayered by design so it beats core layers with zero `!important`); edit the theme, not this file, then re-mirror.
66
66
 
67
67
  ## Migrating an existing site
68
68
 
@@ -78,7 +78,7 @@ as an Astryx integration pack (`astryx.integration.mjs`). List this package in y
78
78
  `astryx.config`, then scaffold any of them:
79
79
 
80
80
  ```bash
81
- bunx astryx template dashboard --package astryx-dracula
81
+ bunx @astryxdesign/cli template dashboard --package astryx-dracula ./src/pages/dashboard.tsx
82
82
  ```
83
83
 
84
84
  View them all live at `/astryx-dracula/#/templates` on the showcase (agent index: [AGENTS.snippet.md](AGENTS.snippet.md)). Pack rules: templates
@@ -97,36 +97,22 @@ falls back to `monospace`. `bun run audit` fails when the files are missing here
97
97
 
98
98
  No special config needed. This kit follows the glimpse path: prebuilt
99
99
  `@astryxdesign/core` CSS plus `<Theme>` injection. A stock Vite React
100
- config works. The only recommended extra is the CSS layer-order snippet so
101
- theme overrides beat component base styles (our repo `vite.config.ts` also
102
- sets a demo-only `base` path; do not copy that). Tailwind projects keep their
103
- own setup and add the snippet as a plain `<style>` tag in `index.html` — the
104
- layer names are the contract, not the Vite plugin:
105
-
106
- ```ts
107
- // vite.config.ts
108
- import { defineConfig } from 'vite';
109
- import react from '@vitejs/plugin-react';
110
-
111
- export default defineConfig({
112
- plugins: [
113
- {
114
- name: 'astryx-css-layer-order',
115
- transformIndexHtml() {
116
- return [
117
- {
118
- tag: 'style',
119
- children:
120
- '@layer reset, astryx-base, astryx-theme;',
121
- injectTo: 'head-prepend',
122
- },
123
- ];
124
- },
125
- },
126
- react(),
127
- ],
128
- });
129
- ```
100
+ config works.
101
+
102
+ **The CSS layer order is now declared by the packages themselves.** As of
103
+ core 0.7.x, `reset.css`, `astryx.css` and this kit's `theme.css` each open
104
+ with `@layer reset, astryx-base, astryx-theme;`, so theme overrides beat
105
+ component base styles no matter which order you import them in. The
106
+ layer-order snippet this kit used to recommend is therefore redundant: a
107
+ repeated `@layer` statement is a no-op once the order is established, and
108
+ whichever file lands first establishes the same order. Keep it only if you
109
+ load a DIFFERENT layer name set, and never rename the three layers — the
110
+ names are the contract.
111
+
112
+ This kit's own `tokens.css` is deliberately **unlayered**, so it beats every
113
+ core layer with no `!important`. That is why the demo still injects the
114
+ layer-order statement: it costs nothing and documents the contract in the
115
+ one file a reader opens first.
130
116
 
131
117
  Advanced: custom `astryx theme build` pipelines need the full StyleX
132
118
  source-compile setup. See the `/facebook/astryx` `apps/example-vite`
@@ -139,26 +125,20 @@ README. Not required for this kit.
139
125
  - Wrong colors after a theme edit: rebuild with `bun run theme:build`; `bun run theme:check` confirms staleness (it ignores `astryx-dracula.js` by design — that file is a build artifact, not a freshness signal).
140
126
  - Old `:root` `--color-*` overrides winning: delete them.
141
127
 
142
- ## Known upstream defects in `@astryxdesign/core@0.6.3`
128
+ ## Upstream defects in `@astryxdesign/core` — resolved
143
129
 
144
- This kit carries local patches for three defects in core, committed under `patches/` and wired through
145
- `patchedDependencies`. **Read this before assuming the patches reach you: they do not.** Bun and npm
146
- honour `patchedDependencies` only from the *root* project of an install. The patches apply when you
147
- clone or work in this repository; they do **not** propagate to a downstream app that installs
148
- `astryx-dracula` from npm, because core resolves through your own dependency tree. If you hit one of
149
- these in your own app, the fix is yours to carry.
130
+ This kit used to carry local patches for three core defects, under `patches/` and wired through
131
+ `patchedDependencies`. **All three were fixed upstream in `@astryxdesign/core@0.7.2`**, so the
132
+ patch directory and the `patchedDependencies` entry are gone. Nothing to carry downstream any more.
150
133
 
151
- | Defect | Symptom | Workaround |
152
- |---|---|---|
153
- | `ChatToolCalls` discards its `label` prop | The `label` prop is typed and documented ("Auto-generated from count if omitted") but the expanded group header always renders `"{count} tool calls"`. The prop is destructured away, so it cannot reach the DOM either. | Render your own header above the component, or wrap it. The internal header markup is not exported. |
154
- | `ToggleButton` drops `className` | A `className` passed to `ToggleButton` never reaches the DOM, even though `BaseProps` documents that it is kept. A sweep of all of core's `dist` found this to be the only component doing it, so it reads as an oversight rather than policy. | Style via `style` or `xstyle`, both of which do forward. Or use `Button` with `aria-pressed`, which honours `className`. |
155
- | `ChatToolCalls` `defaultIsExpanded` JSDoc is wrong | The type comment claims "true for ≤3 calls, false for >3". The implementation is an unconditional `?? false`. The behaviour is the JSDoc that is wrong, so no action is needed. | None. Documented so nobody codes against the comment. |
134
+ | Defect (core 0.6.3) | Status in 0.7.2 |
135
+ |---|---|
136
+ | `ChatToolCalls` discarded its `label` prop — the prop was destructured to `_customLabel` and never read, so the expanded group header always rendered `"{count} tool calls"`. | Fixed. The prop is destructured to `customLabel` and the header renders `customLabel ?? t('@astryx.chatToolCalls.groupLabel', …)`. |
137
+ | `ToggleButton` dropped `className` — destructured to `_className` and discarded, so it never reached the DOM. | Fixed. `className` is now merged into the inner `Button` via `mergeProps(themeProps(…), className)`. |
138
+ | `ChatToolCalls` `defaultIsExpanded` JSDoc claimed "true for ≤3 calls, false for >3" while the implementation was an unconditional `?? false`. | Fixed. The doc comment now reads `@default false`, which matches the code. |
156
139
 
157
- If you want the patches, copy `patches/@astryxdesign%2Fcore@0.6.3.patch` from the repository into
158
- your own root `package.json` under `patchedDependencies`. They are version-locked to `0.6.3`, so
159
- upgrading core makes them stop applying rather than silently mis-apply — which is the intended
160
- signal to delete them. Each hunk carries a comment naming the defect, so they are easy to drop once
161
- upstream ships a fix.
140
+ Because these were the only defects we ever patched, this repository now installs a stock
141
+ `@astryxdesign/core` with no `patchedDependencies` at all.
162
142
 
163
143
  ## Rules
164
144
 
@@ -186,3 +166,23 @@ Before tagging a release:
186
166
  3. Rebuild and gate: `bun run theme:build`, then `bun run theme:check`, then `bun run audit`, then `bunx react-doctor@latest` (must stay 100/100).
187
167
  4. Counts in the docs are cited with the command that produces them, so there is nothing to refresh by hand. If you find a bare numeral, replace it with its command.
188
168
  5. `npm publish` runs the same four gates itself via `prepublishOnly`, so a tree that fails cannot reach the registry. There is no publish workflow in CI — publishing is deliberately a human step.
169
+
170
+ ### The toolchain
171
+
172
+ One tool per job, so nothing formats the same bytes twice:
173
+
174
+ - **`bun`** installs, runs scripts, typechecks (`bun check`) and formats (`bun fmt`). The format style
175
+ lives in `bunfig.toml` — tabs, 100 columns, semicolons, double quotes.
176
+ - **Biome** still runs, but as the **linter** only (`bun run lint`); its formatter is off in
177
+ `biome.json`. The lint rules are the part worth keeping: unused imports, non-null assertions,
178
+ `!important`, import organisation.
179
+ - **Markdown is not formatted by either tool.** `bun fmt` restructures markdown — emphasis marks,
180
+ list spacing, blockquote reflow — which is churn prose never had, so the `fmt` scripts name the
181
+ code extensions explicitly.
182
+ - **The generated outputs are never formatted.** `theme.css`, `astryx-dracula.js`, the `.d.ts`
183
+ files and `icons.mjs` are build products, compared byte-for-byte against a fresh build by
184
+ `theme:check` and `icons:check`. A formatter that touches them breaks the freshness gate, so
185
+ they are listed in `.gitignore` (they stay tracked, and npm's `files` array still ships them).
186
+ - **`bun build` needs `NODE_ENV=production`.** Bun 1.4.4 defaults the bundler to the
187
+ *development* JSX runtime, so an unbundled build emitted `jsxDEV` and would have shipped
188
+ React's dev build inside the package. `icons:build` sets it.
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: astryx-theme.ts
4
4
  * Command: astryx theme build astryx-theme.ts --out theme.css
5
- * CLI: @astryxdesign/cli@0.6.3
6
- * Core: @astryxdesign/core@0.6.3
5
+ * CLI: @astryxdesign/cli@0.7.2
6
+ * Core: @astryxdesign/core@0.7.2
7
7
  */
8
8
 
9
9
  /// <reference path="./astryx-dracula.variants.d.ts" />
package/astryx-dracula.js CHANGED
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: astryx-theme.ts
4
4
  * Command: astryx theme build astryx-theme.ts --out theme.css
5
- * CLI: @astryxdesign/cli@0.6.3
6
- * Core: @astryxdesign/core@0.6.3
5
+ * CLI: @astryxdesign/cli@0.7.2
6
+ * Core: @astryxdesign/core@0.7.2
7
7
  */
8
8
 
9
9
  import { draculaIconRegistry } from "./icons.mjs";
@@ -98,6 +98,11 @@ export const astryxDraculaTheme = {
98
98
  "--color-syntax-property": "#F8F8F2",
99
99
  "--color-syntax-punctuation": "#F8F8F2",
100
100
  "--color-syntax-background": "#282A36",
101
+ "--color-syntax-added": "#50FA7B26",
102
+ "--color-syntax-removed": "#FF555526",
103
+ "--color-syntax-diff-header": "#44475A",
104
+ "--color-syntax-added-marker": "#50FA7B",
105
+ "--color-syntax-removed-marker": "#FF5555",
101
106
  "--radius-inner": "4px",
102
107
  "--radius-element": "5px",
103
108
  "--radius-container": "5px",
@@ -452,12 +457,12 @@ export const astryxDraculaTheme = {
452
457
  "borderColor": "var(--color-error)"
453
458
  }
454
459
  },
455
- "statusdot": {
460
+ "status-dot": {
456
461
  "variant:info": {
457
462
  "backgroundColor": "#8BE9FD"
458
463
  }
459
464
  },
460
- "progressbar-fill": {
465
+ "progress-bar-fill": {
461
466
  "variant:accent": {
462
467
  "backgroundColor": "#BD93F9"
463
468
  },
@@ -488,7 +493,7 @@ export const astryxDraculaTheme = {
488
493
  "--color-error": "#FF5555"
489
494
  }
490
495
  },
491
- "textarea": {
496
+ "text-area": {
492
497
  "status:success": {
493
498
  "--color-success": "#50FA7B"
494
499
  },
@@ -541,6 +546,9 @@ export const astryxDraculaTheme = {
541
546
  },
542
547
  "status:error": {
543
548
  "--color-error": "#FF5555"
549
+ },
550
+ "variant:secondary": {
551
+ "fontWeight": "var(--font-weight-normal)"
544
552
  }
545
553
  },
546
554
  "multi-selector": {
@@ -552,6 +560,9 @@ export const astryxDraculaTheme = {
552
560
  },
553
561
  "status:error": {
554
562
  "--color-error": "#FF5555"
563
+ },
564
+ "variant:secondary": {
565
+ "fontWeight": "var(--font-weight-normal)"
555
566
  }
556
567
  },
557
568
  "typeahead": {
@@ -609,7 +620,12 @@ export const astryxDraculaTheme = {
609
620
  "boxShadow": "var(--shadow-low)"
610
621
  }
611
622
  },
612
- "hovercard": {
623
+ "hover-card": {
624
+ "base": {
625
+ "backgroundColor": "var(--color-background-popover)"
626
+ }
627
+ },
628
+ "drawer": {
613
629
  "base": {
614
630
  "backgroundColor": "var(--color-background-popover)"
615
631
  }
@@ -634,9 +650,9 @@ export const astryxDraculaTheme = {
634
650
  __onLight: {
635
651
  "tokens": {
636
652
  "color-scheme": "light",
637
- "--color-text-primary": "var(--color-on-light)",
638
- "--color-icon-primary": "var(--color-on-light)",
639
- "--color-accent": "var(--color-on-light)"
653
+ "--color-text-primary": "light-dark(#F8F8F2, #F8F8F2)",
654
+ "--color-icon-primary": "light-dark(#F8F8F2, #F8F8F2)",
655
+ "--color-accent": "light-dark(#BD93F9, #BD93F9)"
640
656
  }
641
657
  },
642
658
  __adaptations: {
@@ -2,8 +2,8 @@
2
2
  * @generated by `astryx theme build` — do not edit manually.
3
3
  * Source: astryx-theme.ts
4
4
  * Command: astryx theme build astryx-theme.ts --out theme.css
5
- * CLI: @astryxdesign/cli@0.6.3
6
- * Core: @astryxdesign/core@0.6.3
5
+ * CLI: @astryxdesign/cli@0.7.2
6
+ * Core: @astryxdesign/core@0.7.2
7
7
  */
8
8
 
9
9
  // Generated by astryx theme build
@@ -1,3 +1,3 @@
1
1
  export default {
2
- templates: './templates',
2
+ templates: "./templates",
3
3
  };
package/icons.mjs CHANGED
@@ -1,33 +1,34 @@
1
1
  // icons.tsx
2
2
  import {
3
- X,
3
+ AlertTriangle,
4
+ ArrowDown,
5
+ ArrowUp,
6
+ ArrowUpDown,
7
+ Calendar,
8
+ Check,
9
+ CheckCheck,
10
+ CheckCircle,
4
11
  ChevronDown,
5
12
  ChevronLeft,
6
13
  ChevronRight,
7
14
  ChevronsLeft,
8
15
  ChevronsRight,
9
- Check,
10
- CheckCircle,
11
- XCircle,
12
- AlertTriangle,
13
- Info,
14
- Calendar,
15
16
  Clock,
17
+ Columns,
18
+ Copy,
16
19
  ExternalLink,
20
+ EyeOff,
21
+ Filter,
22
+ Info,
17
23
  Menu,
24
+ Mic,
18
25
  MoreHorizontal,
19
26
  Search,
20
- ArrowUp,
21
- ArrowDown,
22
- ArrowUpDown,
23
- Filter,
24
- EyeOff,
25
- Columns,
26
- Copy,
27
- CheckCheck,
28
- Wrench,
29
27
  Square,
30
- Mic
28
+ Upload,
29
+ Wrench,
30
+ X,
31
+ XCircle
31
32
  } from "lucide-react";
32
33
  import { jsx } from "react/jsx-runtime";
33
34
  var iconProps = {
@@ -86,6 +87,9 @@ var draculaIconRegistry = {
86
87
  search: /* @__PURE__ */ jsx(Search, {
87
88
  ...iconProps
88
89
  }),
90
+ upload: /* @__PURE__ */ jsx(Upload, {
91
+ ...iconProps
92
+ }),
89
93
  arrowUp: /* @__PURE__ */ jsx(ArrowUp, {
90
94
  ...iconProps
91
95
  }),
package/icons.tsx CHANGED
@@ -6,72 +6,79 @@
6
6
  * icon components bundled with the theme, not with @astryxdesign/core.
7
7
  */
8
8
 
9
- import React from 'react';
10
- import type {IconRegistry} from '@astryxdesign/core/Icon';
11
-
9
+ import type { IconRegistry } from "@astryxdesign/core/Icon";
12
10
  import {
13
- X,
14
- ChevronDown,
15
- ChevronLeft,
16
- ChevronRight,
17
- ChevronsLeft,
18
- ChevronsRight,
19
- Check,
20
- CheckCircle,
21
- XCircle,
22
- AlertTriangle,
23
- Info,
24
- Calendar,
25
- Clock,
26
- ExternalLink,
27
- Menu,
28
- MoreHorizontal,
29
- Search,
30
- ArrowUp,
31
- ArrowDown,
32
- ArrowUpDown,
33
- Filter,
34
- EyeOff,
35
- Columns,
36
- Copy,
37
- CheckCheck,
38
- Wrench,
39
- Square,
40
- Mic,
41
- } from 'lucide-react';
11
+ AlertTriangle,
12
+ ArrowDown,
13
+ ArrowUp,
14
+ ArrowUpDown,
15
+ Calendar,
16
+ Check,
17
+ CheckCheck,
18
+ CheckCircle,
19
+ ChevronDown,
20
+ ChevronLeft,
21
+ ChevronRight,
22
+ ChevronsLeft,
23
+ ChevronsRight,
24
+ Clock,
25
+ Columns,
26
+ Copy,
27
+ ExternalLink,
28
+ EyeOff,
29
+ Filter,
30
+ Info,
31
+ Menu,
32
+ Mic,
33
+ MoreHorizontal,
34
+ Search,
35
+ Square,
36
+ Upload,
37
+ Wrench,
38
+ X,
39
+ XCircle,
40
+ } from "lucide-react";
41
+ // The Astryx theme loader evaluates this file to read the icon registry, and
42
+ // it evaluates JSX with the CLASSIC runtime, so React has to be in scope
43
+ // here even though the app's own bundler uses the automatic one. Without it,
44
+ // `astryx theme build` fails with "React is not defined" — so this import is
45
+ // load-bearing and must not be removed as "unused".
46
+ // biome-ignore lint/correctness/noUnusedImports: the theme loader needs React in scope for the classic JSX runtime
47
+ import React from "react";
42
48
 
43
49
  const iconProps = {
44
- size: '1em',
45
- 'aria-hidden': true as const,
50
+ size: "1em",
51
+ "aria-hidden": true as const,
46
52
  };
47
53
 
48
54
  export const draculaIconRegistry: IconRegistry = {
49
- close: <X {...iconProps} />,
50
- chevronDown: <ChevronDown {...iconProps} />,
51
- chevronLeft: <ChevronLeft {...iconProps} />,
52
- chevronRight: <ChevronRight {...iconProps} />,
53
- chevronsLeft: <ChevronsLeft {...iconProps} />,
54
- chevronsRight: <ChevronsRight {...iconProps} />,
55
- check: <Check {...iconProps} />,
56
- success: <CheckCircle {...iconProps} />,
57
- error: <XCircle {...iconProps} />,
58
- warning: <AlertTriangle {...iconProps} />,
59
- info: <Info {...iconProps} />,
60
- calendar: <Calendar {...iconProps} />,
61
- clock: <Clock {...iconProps} />,
62
- externalLink: <ExternalLink {...iconProps} />,
63
- menu: <Menu {...iconProps} />,
64
- moreHorizontal: <MoreHorizontal {...iconProps} />,
65
- search: <Search {...iconProps} />,
66
- arrowUp: <ArrowUp {...iconProps} />,
67
- arrowDown: <ArrowDown {...iconProps} />,
68
- arrowsUpDown: <ArrowUpDown {...iconProps} />,
69
- funnel: <Filter {...iconProps} />,
70
- eyeSlash: <EyeOff {...iconProps} />,
71
- viewColumns: <Columns {...iconProps} />,
72
- copy: <Copy {...iconProps} />,
73
- checkDouble: <CheckCheck {...iconProps} />,
74
- wrench: <Wrench {...iconProps} />,
75
- stop: <Square {...iconProps} />,
76
- microphone: <Mic {...iconProps} />,
55
+ close: <X {...iconProps} />,
56
+ chevronDown: <ChevronDown {...iconProps} />,
57
+ chevronLeft: <ChevronLeft {...iconProps} />,
58
+ chevronRight: <ChevronRight {...iconProps} />,
59
+ chevronsLeft: <ChevronsLeft {...iconProps} />,
60
+ chevronsRight: <ChevronsRight {...iconProps} />,
61
+ check: <Check {...iconProps} />,
62
+ success: <CheckCircle {...iconProps} />,
63
+ error: <XCircle {...iconProps} />,
64
+ warning: <AlertTriangle {...iconProps} />,
65
+ info: <Info {...iconProps} />,
66
+ calendar: <Calendar {...iconProps} />,
67
+ clock: <Clock {...iconProps} />,
68
+ externalLink: <ExternalLink {...iconProps} />,
69
+ menu: <Menu {...iconProps} />,
70
+ moreHorizontal: <MoreHorizontal {...iconProps} />,
71
+ search: <Search {...iconProps} />,
72
+ upload: <Upload {...iconProps} />,
73
+ arrowUp: <ArrowUp {...iconProps} />,
74
+ arrowDown: <ArrowDown {...iconProps} />,
75
+ arrowsUpDown: <ArrowUpDown {...iconProps} />,
76
+ funnel: <Filter {...iconProps} />,
77
+ eyeSlash: <EyeOff {...iconProps} />,
78
+ viewColumns: <Columns {...iconProps} />,
79
+ copy: <Copy {...iconProps} />,
80
+ checkDouble: <CheckCheck {...iconProps} />,
81
+ wrench: <Wrench {...iconProps} />,
82
+ stop: <Square {...iconProps} />,
83
+ microphone: <Mic {...iconProps} />,
77
84
  };