astryx-dracula 0.5.1 → 0.7.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.
Files changed (120) hide show
  1. package/BRAND.md +57 -6
  2. package/README.md +16 -6
  3. package/USAGE.md +50 -50
  4. package/astryx-dracula.d.ts +2 -2
  5. package/astryx-dracula.js +49 -11
  6. package/astryx-dracula.variants.d.ts +2 -2
  7. package/icons.mjs +4 -0
  8. package/icons.tsx +8 -0
  9. package/package.json +23 -18
  10. package/shared/auth-chrome-config.ts +0 -4
  11. package/shared/auth-chrome.tsx +2 -3
  12. package/shared/chaptered-doc-config.ts +3 -2
  13. package/shared/chaptered-doc.tsx +1 -2
  14. package/shared/chart-hues.ts +21 -6
  15. package/shared/chart-legend.tsx +2 -2
  16. package/shared/data-bar.tsx +2 -2
  17. package/shared/order-desk.tsx +52 -54
  18. package/shared/revenue-chart.tsx +1 -1
  19. package/shared/scene-castle.tsx +21 -13
  20. package/shared/settings-data.ts +0 -6
  21. package/shared/settings-rows.tsx +1 -23
  22. package/templates/ai-chat-landing.template.mjs +1 -0
  23. package/templates/ai-chat-landing.tsx +30 -11
  24. package/templates/ai-chat.template.mjs +1 -0
  25. package/templates/ai-chat.tsx +9 -3
  26. package/templates/blank.template.mjs +1 -0
  27. package/templates/blank.tsx +4 -2
  28. package/templates/centered-hero.template.mjs +1 -0
  29. package/templates/centered-hero.tsx +5 -3
  30. package/templates/classic-gallery.template.mjs +1 -0
  31. package/templates/classic-gallery.tsx +9 -2
  32. package/templates/contact-form.template.mjs +1 -0
  33. package/templates/contact-form.tsx +13 -2
  34. package/templates/dashboard-portfolio.template.mjs +1 -0
  35. package/templates/dashboard-portfolio.tsx +21 -6
  36. package/templates/dashboard.template.mjs +1 -0
  37. package/templates/dashboard.tsx +9 -7
  38. package/templates/detail-page.template.mjs +1 -0
  39. package/templates/detail-page.tsx +28 -36
  40. package/templates/documentation-design.template.mjs +1 -0
  41. package/templates/documentation-design.tsx +8 -3
  42. package/templates/documentation-technical.template.mjs +1 -0
  43. package/templates/documentation-technical.tsx +11 -6
  44. package/templates/documentation.template.mjs +1 -0
  45. package/templates/documentation.tsx +16 -7
  46. package/templates/editor.template.mjs +1 -0
  47. package/templates/editor.tsx +4 -2
  48. package/templates/file-explorer.template.mjs +1 -0
  49. package/templates/file-explorer.tsx +4 -2
  50. package/templates/form-two-column.template.mjs +1 -0
  51. package/templates/form-two-column.tsx +19 -4
  52. package/templates/form-wizard.template.mjs +15 -0
  53. package/templates/form-wizard.tsx +878 -0
  54. package/templates/gallery-hero.template.mjs +1 -0
  55. package/templates/gallery-hero.tsx +14 -6
  56. package/templates/ide.template.mjs +1 -0
  57. package/templates/ide.tsx +187 -101
  58. package/templates/incident-console.template.mjs +1 -0
  59. package/templates/incident-console.tsx +137 -85
  60. package/templates/kanban-board.template.mjs +1 -0
  61. package/templates/kanban-board.tsx +51 -7
  62. package/templates/library.template.mjs +1 -0
  63. package/templates/library.tsx +15 -4
  64. package/templates/login-card.template.mjs +1 -0
  65. package/templates/login-card.tsx +4 -2
  66. package/templates/login-split.template.mjs +1 -0
  67. package/templates/login-split.tsx +8 -5
  68. package/templates/login-sso.template.mjs +1 -0
  69. package/templates/login-sso.tsx +13 -19
  70. package/templates/login.template.mjs +1 -0
  71. package/templates/login.tsx +4 -2
  72. package/templates/messaging-shell.template.mjs +1 -0
  73. package/templates/messaging-shell.tsx +114 -47
  74. package/templates/mixed-gallery.template.mjs +1 -0
  75. package/templates/mixed-gallery.tsx +10 -2
  76. package/templates/payment-form.template.mjs +1 -0
  77. package/templates/payment-form.tsx +34 -31
  78. package/templates/product-detail.template.mjs +1 -0
  79. package/templates/product-detail.tsx +21 -5
  80. package/templates/product-gallery.template.mjs +1 -0
  81. package/templates/product-gallery.tsx +12 -5
  82. package/templates/product-tour.template.mjs +1 -0
  83. package/templates/product-tour.tsx +21 -14
  84. package/templates/settings-dialog.template.mjs +1 -0
  85. package/templates/settings-dialog.tsx +10 -3
  86. package/templates/settings-sidebar.template.mjs +1 -0
  87. package/templates/settings-sidebar.tsx +609 -588
  88. package/templates/settings.template.mjs +1 -0
  89. package/templates/settings.tsx +11 -12
  90. package/templates/shell-nav.template.mjs +1 -0
  91. package/templates/shell-nav.tsx +47 -29
  92. package/templates/shell-side-nav.template.mjs +1 -0
  93. package/templates/shell-side-nav.tsx +88 -70
  94. package/templates/shell-top-nav.template.mjs +1 -0
  95. package/templates/shell-top-nav.tsx +102 -88
  96. package/templates/side-gallery.template.mjs +1 -0
  97. package/templates/side-gallery.tsx +4 -2
  98. package/templates/table-grouped.template.mjs +1 -0
  99. package/templates/table-grouped.tsx +150 -134
  100. package/templates/table-page-chart.template.mjs +1 -0
  101. package/templates/table-page-chart.tsx +4 -2
  102. package/templates/table-page-heatmap-status.template.mjs +1 -0
  103. package/templates/table-page-heatmap-status.tsx +4 -2
  104. package/templates/{table-page-shoe-store-heatmap.template.mjs → table-page-shoe-store.template.mjs} +1 -0
  105. package/templates/{table-page-shoe-store-heatmap.tsx → table-page-shoe-store.tsx} +5 -3
  106. package/templates/table-page.template.mjs +1 -0
  107. package/templates/table-page.tsx +12 -2
  108. package/templates/table-tree.template.mjs +16 -0
  109. package/templates/table-tree.tsx +707 -0
  110. package/templates/table.template.mjs +1 -0
  111. package/templates/table.tsx +4 -2
  112. package/templates/tech-report.template.mjs +1 -0
  113. package/templates/tech-report.tsx +18 -13
  114. package/templates/theme-showcase.template.mjs +1 -0
  115. package/templates/theme-showcase.tsx +41 -28
  116. package/templates/work-item-detail.template.mjs +8 -0
  117. package/templates/work-item-detail.tsx +1049 -0
  118. package/theme.css +71 -78
  119. package/theme.css.d.ts +9 -0
  120. package/tokens.css +79 -46
package/BRAND.md CHANGED
@@ -9,7 +9,7 @@ Source of truth is `astryx-theme.ts`. Do not add hexes; `bun run audit` enforces
9
9
  |---|---|---|
10
10
  | Background | #282A36 | page bg |
11
11
  | Current line | #6272A4 | line highlight, subtle borders (doubles as comment)[^current-line] |
12
- | Selection | #44475A | selected rows, quiet surfaces |
12
+ | Selection | #44475A | selected rows and text selection (a semantic, never an elevation step) |
13
13
  | Background Light | #343746 | cards, surfaces |
14
14
  | Background Lighter | #424450 | popovers, floating elements |
15
15
  | Background Dark | #21222C | shadows, on-fill text |
@@ -29,6 +29,56 @@ Source of truth is `astryx-theme.ts`. Do not add hexes; `bun run audit` enforces
29
29
 
30
30
  [^current-line]: Upstream pins both Current Line and Comment to #6272A4. This kit follows suit for line affordances, including scrollbar thumbs in `tokens.css`. Do not "correct" one of them to #44475A.
31
31
 
32
+ ### The spec's four palettes
33
+
34
+ `draculatheme.com/spec` publishes four palettes, and the theme draws on all of
35
+ them. Read the spec before calling a hex off-brand — `#DE5735` looks like a
36
+ stray Stone colour until you find **Functional Red** in the UI section.
37
+
38
+ | Palette | Hexes |
39
+ |---|---|
40
+ | Syntax | the twelve above |
41
+ | ANSI | `#21222C` black, the eight base hues, and the brights `#6272A4`, `#FF6E6E`, `#69FF94`, `#FFFFA5`, `#D6ACFF`, `#FF92DF`, `#A4FFFF`, `#FFFFFF` |
42
+ | UI | `#343746` light, `#424450` lighter, `#21222C` dark, `#191A21` darker |
43
+ | Functional | `#DE5735`, `#A39514`, `#089108`, `#0081D6`, `#815CD6` — interactive elements, borders and indicators, never status and never editor text |
44
+
45
+ The categorical chart set draws its teal and indigo from the ANSI brights
46
+ (`#A4FFFF`, `#D6ACFF`), which is why those two are spec values rather than
47
+ inventions.
48
+
49
+ ### Derived values
50
+
51
+ `scripts/check.ts` allows every hex in `@layer astryx-theme` only if it is in one
52
+ of those four palettes or named in `DERIVED_HEXES` with a reason. Anything else
53
+ fails the build and prints the hex. That gate exists because core's builder
54
+ inlines a token it derives instead of aliasing it, so any colour role the theme
55
+ does not pin keeps Stone's value — 0.7.10 shipped `#E9AF08` for warning text and
56
+ `#F77D77` for error, and the light-dark symmetry gate caught the first only
57
+ because its two branches happened to differ.
58
+
59
+ Six values are ours, each traceable to a spec value:
60
+
61
+ - `#9AA1BC` — secondary text, border-emphasized and the gray family. Comment is
62
+ the obvious pick and fails the 4.5 floor on every surface.
63
+ - `#B0B3C4` — chart axis and caption text, one step above secondary so an axis
64
+ reads over a grid.
65
+ - `#8C939B` — chart neutral, deliberately not a Dracula hue so a neutral series
66
+ is not read as one.
67
+ - `#FFD5CC` — the pale inverted error surface behind the inverted Toast.
68
+ - `#FF7575` — error **text**: the ANSI Bright Red lifted 5% toward Foreground.
69
+ Bright Red alone is 5.23:1 on the body but 4.33:1 on a surface, just under the
70
+ 4.5 floor the spec itself sets; the lift reads 5.46 and 4.52.
71
+
72
+ Pure black `#000000` is also allowed, for `on-light` and the overlay hover and
73
+ press steps; the spec never asks for black text, but a black overlay is how a
74
+ scrollbar and a pressed state darken.
75
+
76
+ Two legacy text tokens (`#8288A6`, `#4C5067`) are allowed too, contrast-gated at
77
+ their own floors rather than an AA threshold.
78
+
79
+ To add a colour, pin it in `astryx-theme.ts` against a spec value, or put it in
80
+ `DERIVED_HEXES` with the reason it exists.
81
+
32
82
  ## Semantic map (glimpse)
33
83
 
34
84
  - Purple links/titles unvisited. Visited falls back to text-base, hover goes primary + underline. Users learn purple means tappable title.
@@ -37,7 +87,7 @@ Source of truth is `astryx-theme.ts`. Do not add hexes; `bun run audit` enforces
37
87
 
38
88
  ## Borders
39
89
 
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.
90
+ `--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
91
 
42
92
  ## Charts
43
93
 
@@ -59,8 +109,9 @@ Each status scope redefines its muted token to the categorical tint
59
109
  (`--color-background-<hue>`, 10% accent wash) with a semantic accent border.
60
110
  Text on fills is always `#21222C`; spec never uses raw black. Links render accent
61
111
  with underline and resolve to foreground on hover. Focus and interactive edges
62
- use accent, not Functional Purple: `--color-functional-*` is pinned for spec parity
63
- (token compat — never encode status in these) and no shipped component consumes it.
112
+ use accent, not Functional Purple: `--color-functional-*` carries the spec's UI
113
+ Functional palette for interactive elements, borders and indicators — never a
114
+ status channel, and no shipped component consumes it today.
64
115
 
65
116
  ## Interactions
66
117
 
@@ -79,8 +130,8 @@ Radii flat and crisp (5px elements, 4px inner). Everything below is a core defau
79
130
  - 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
131
  - 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
132
  - 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.
133
+ - 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.
134
+ - `--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
135
  - 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
136
  - No color-scale config: HCT generation would fight the pinned hexes. No light mode, ever.
86
137
 
package/README.md CHANGED
@@ -10,13 +10,15 @@ 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
+ - The spec's four palettes (Syntax, ANSI, UI, Functional), with the ANSI bright row
15
+ available as `--dracula-ansi-bright-*` for emphasis and for a chart series past the base eight
14
16
  - Syntax theme plus chart series and sequential ramps
15
17
  - Prebuilt CSS plus runtime theme injection, or runtime injection alone for prototyping
16
18
  - WCAG contrast gates enforced in CI via `bun run audit`
17
19
  - JetBrains Mono fonts and Lucide icons, one runtime dependency (`lucide-react`)
18
20
  - Agent skill, `llms.txt`, and copy-paste quickstart for AI-assisted adoption
19
- - Around 45 themed pages in `templates/`, published as an Astryx integration pack and viewable live at `/astryx-dracula/#/templates`
21
+ - 48 themed pages in `templates/`, published as an Astryx integration pack and viewable live at `/astryx-dracula/#/templates`
20
22
 
21
23
  ## Installation
22
24
 
@@ -52,9 +54,9 @@ theme.css prebuilt output of bun run theme:build
52
54
  tokens.css plain-CSS :root mirror for any stack
53
55
  icons.tsx Lucide icon registry (runtime `lucide-react` dependency)
54
56
  fonts/ JetBrains Mono woff2 files
55
- templates/ around 45 themed pages plus integration specs
57
+ templates/ 48 themed pages, each with an XLE structure header
56
58
  shared/ reusable modules templates compose (23 files)
57
- scripts/check.ts palette, contrast, and packaging gates
59
+ scripts/check.ts palette, contrast, packaging, and XLE-header gates
58
60
  demo/ showcase source, deployed to GitHub Pages
59
61
  ```
60
62
 
@@ -62,14 +64,22 @@ demo/ showcase source, deployed to GitHub Pages
62
64
 
63
65
  | Command | Purpose |
64
66
  | -------------------- | ------------------------------------------ |
65
- | `bun run audit` | Palette plus contrast gates, fails on drift |
67
+ | `bun run audit` | Palette, contrast, packaging and XLE gates |
66
68
  | `bun run theme:build`| Rebuild `theme.css` from the source |
67
69
  | `bun run theme:check`| Fail if committed theme outputs are stale |
68
70
  | `bun run build` | Typecheck plus showcase build |
71
+ | `bun run fmt` | Format the source (`bun fmt`; style in `bunfig.toml`) |
72
+ | `bun run fmt:check` | Fail if the source is not formatted |
73
+ | `bun run lint` | `biome check`: lint plus import order. Formatting is `bun fmt` (Biome's formatter is off) |
74
+ | `bun audit` | Bun's builtin vulnerability scan — not this repo's `audit` script |
69
75
  | `bunx react-doctor@latest` | Component health scan (currently 100/100) |
70
76
 
77
+ `bun audit` is a bun builtin and `bun run audit` is the kit gate. Bun's own
78
+ command runs first, so the two never collide, but a bare `bun audit` checks
79
+ dependencies and says nothing about the palette.
80
+
71
81
  ## Attribution & License
72
82
 
73
- - **Astryx Design System**: Created by the Astryx team at Meta Platforms, Inc. under the [MIT License](https://github.com/facebook/astryx/blob/main/LICENSE). The template files in `templates/` (around 45) are derived from Astryx's open source page templates and adapted for the Dracula brand (pure Dracula spec retokening, recharts replaced with zero-dependency inline SVGs, heroicons mapped to Lucide, XLE/XLO structural expression headers, and responsive layout hardening).
83
+ - **Astryx Design System**: Created by the Astryx team at Meta Platforms, Inc. under the [MIT License](https://github.com/facebook/astryx/blob/main/LICENSE). The template files in `templates/` (46) are derived from Astryx's open source page templates and adapted for the Dracula brand (pure Dracula spec retokening, recharts replaced with zero-dependency inline SVGs, heroicons mapped to Lucide, XLE/XLO structural expression headers, and responsive layout hardening).
74
84
  - **Dracula Theme**: Color palette and specification by [Zeno Rocha and the Dracula Theme community](https://draculatheme.com).
75
85
  - **Package & Additions**: Released under the [MIT License](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
 
@@ -73,12 +73,12 @@ Then use `var(--color-primary)`, `var(--dracula-purple)`, `var(--space-gap)`.
73
73
 
74
74
  ## Templates
75
75
 
76
- Around 45 themed pages ship in `templates/`, each with a `<id>.template.mjs` spec, published
76
+ 48 themed pages ship in `templates/`, each with a `<id>.template.mjs` spec, published
77
77
  as an Astryx integration pack (`astryx.integration.mjs`). List this package in your
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.10
6
+ * Core: @astryxdesign/core@0.7.10
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.10
6
+ * Core: @astryxdesign/core@0.7.10
7
7
  */
8
8
 
9
9
  import { draculaIconRegistry } from "./icons.mjs";
@@ -81,6 +81,18 @@ export const astryxDraculaTheme = {
81
81
  "--duration-slow-min": "730ms",
82
82
  "--duration-slow": "975ms",
83
83
  "--duration-slow-max": "1300ms",
84
+ "--_astryx-pre-tempo-duration-fast-min": "130ms",
85
+ "--_astryx-pre-tempo-duration-fast": "175ms",
86
+ "--_astryx-pre-tempo-duration-fast-max": "235ms",
87
+ "--_astryx-pre-tempo-duration-medium-min": "310ms",
88
+ "--_astryx-pre-tempo-duration-medium": "410ms",
89
+ "--_astryx-pre-tempo-duration-medium-max": "545ms",
90
+ "--_astryx-pre-tempo-duration-slow-min": "730ms",
91
+ "--_astryx-pre-tempo-duration-slow": "975ms",
92
+ "--_astryx-pre-tempo-duration-slow-max": "1300ms",
93
+ "--_astryx-motion-tempo": "1",
94
+ "--ease-entrance": "cubic-bezier(0.24, 1, 0.4, 1)",
95
+ "--ease-move": "cubic-bezier(0.24, 1, 0.4, 1)",
84
96
  "--font-family-body": "\"JetBrains Mono\", monospace",
85
97
  "--font-family-heading": "\"JetBrains Mono\", monospace",
86
98
  "--font-family-code": "\"JetBrains Mono\", monospace",
@@ -98,6 +110,11 @@ export const astryxDraculaTheme = {
98
110
  "--color-syntax-property": "#F8F8F2",
99
111
  "--color-syntax-punctuation": "#F8F8F2",
100
112
  "--color-syntax-background": "#282A36",
113
+ "--color-syntax-added": "#50FA7B26",
114
+ "--color-syntax-removed": "#FF555526",
115
+ "--color-syntax-diff-header": "#44475A",
116
+ "--color-syntax-added-marker": "#50FA7B",
117
+ "--color-syntax-removed-marker": "#FF5555",
101
118
  "--radius-inner": "4px",
102
119
  "--radius-element": "5px",
103
120
  "--radius-container": "5px",
@@ -141,7 +158,7 @@ export const astryxDraculaTheme = {
141
158
  "--color-background-surface": "light-dark(#343746, #343746)",
142
159
  "--color-background-card": "light-dark(#343746, #343746)",
143
160
  "--color-background-popover": "light-dark(#424450, #424450)",
144
- "--color-background-muted": "light-dark(#44475A, #44475A)",
161
+ "--color-background-muted": "light-dark(#21222C, #21222C)",
145
162
  "--color-overlay": "light-dark(#191A21CC, #191A21CC)",
146
163
  "--color-overlay-hover": "light-dark(#0000001F, #0000001F)",
147
164
  "--color-overlay-pressed": "light-dark(#00000033, #00000033)",
@@ -156,6 +173,14 @@ export const astryxDraculaTheme = {
156
173
  "--color-text-secondary": "light-dark(#9AA1BC, #9AA1BC)",
157
174
  "--color-text-disabled": "light-dark(#6272A4, #6272A4)",
158
175
  "--color-text-accent": "light-dark(#BD93F9, #BD93F9)",
176
+ "--color-text-info": "light-dark(#8BE9FD, #8BE9FD)",
177
+ "--color-text-success": "light-dark(#50FA7B, #50FA7B)",
178
+ "--color-text-warning": "light-dark(#F1FA8C, #F1FA8C)",
179
+ "--color-text-error": "light-dark(#FF7575, #FF7575)",
180
+ "--color-on-info-muted": "light-dark(#8BE9FD, #8BE9FD)",
181
+ "--color-on-success-muted": "light-dark(#50FA7B, #50FA7B)",
182
+ "--color-on-warning-muted": "light-dark(#F1FA8C, #F1FA8C)",
183
+ "--color-on-error-muted": "light-dark(#FF7575, #FF7575)",
159
184
  "--color-icon-primary": "light-dark(#F8F8F2, #F8F8F2)",
160
185
  "--color-icon-secondary": "light-dark(#9AA1BC, #9AA1BC)",
161
186
  "--color-icon-disabled": "light-dark(#6272A4, #6272A4)",
@@ -452,12 +477,12 @@ export const astryxDraculaTheme = {
452
477
  "borderColor": "var(--color-error)"
453
478
  }
454
479
  },
455
- "statusdot": {
480
+ "status-dot": {
456
481
  "variant:info": {
457
482
  "backgroundColor": "#8BE9FD"
458
483
  }
459
484
  },
460
- "progressbar-fill": {
485
+ "progress-bar-fill": {
461
486
  "variant:accent": {
462
487
  "backgroundColor": "#BD93F9"
463
488
  },
@@ -488,7 +513,7 @@ export const astryxDraculaTheme = {
488
513
  "--color-error": "#FF5555"
489
514
  }
490
515
  },
491
- "textarea": {
516
+ "text-area": {
492
517
  "status:success": {
493
518
  "--color-success": "#50FA7B"
494
519
  },
@@ -541,6 +566,9 @@ export const astryxDraculaTheme = {
541
566
  },
542
567
  "status:error": {
543
568
  "--color-error": "#FF5555"
569
+ },
570
+ "variant:secondary": {
571
+ "fontWeight": "var(--font-weight-normal)"
544
572
  }
545
573
  },
546
574
  "multi-selector": {
@@ -552,6 +580,9 @@ export const astryxDraculaTheme = {
552
580
  },
553
581
  "status:error": {
554
582
  "--color-error": "#FF5555"
583
+ },
584
+ "variant:secondary": {
585
+ "fontWeight": "var(--font-weight-normal)"
555
586
  }
556
587
  },
557
588
  "typeahead": {
@@ -609,7 +640,12 @@ export const astryxDraculaTheme = {
609
640
  "boxShadow": "var(--shadow-low)"
610
641
  }
611
642
  },
612
- "hovercard": {
643
+ "hover-card": {
644
+ "base": {
645
+ "backgroundColor": "var(--color-background-popover)"
646
+ }
647
+ },
648
+ "drawer": {
613
649
  "base": {
614
650
  "backgroundColor": "var(--color-background-popover)"
615
651
  }
@@ -634,9 +670,9 @@ export const astryxDraculaTheme = {
634
670
  __onLight: {
635
671
  "tokens": {
636
672
  "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)"
673
+ "--color-text-primary": "light-dark(#F8F8F2, #F8F8F2)",
674
+ "--color-icon-primary": "light-dark(#F8F8F2, #F8F8F2)",
675
+ "--color-accent": "light-dark(#BD93F9, #BD93F9)"
640
676
  }
641
677
  },
642
678
  __adaptations: {
@@ -673,7 +709,9 @@ export const astryxDraculaTheme = {
673
709
  "fast": 175,
674
710
  "medium": 410,
675
711
  "slow": 975,
676
- "ratio": 0.75
712
+ "ratio": 0.75,
713
+ "tempo": 1,
714
+ "character": "standard"
677
715
  }
678
716
  },
679
717
  icons: draculaIconRegistry,
@@ -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.10
6
+ * Core: @astryxdesign/core@0.7.10
7
7
  */
8
8
 
9
9
  // Generated by astryx theme build
package/icons.mjs CHANGED
@@ -25,6 +25,7 @@ import {
25
25
  MoreHorizontal,
26
26
  Search,
27
27
  Square,
28
+ Upload,
28
29
  Wrench,
29
30
  X,
30
31
  XCircle
@@ -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
@@ -33,10 +33,17 @@ import {
33
33
  MoreHorizontal,
34
34
  Search,
35
35
  Square,
36
+ Upload,
36
37
  Wrench,
37
38
  X,
38
39
  XCircle,
39
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
40
47
  import React from "react";
41
48
 
42
49
  const iconProps = {
@@ -62,6 +69,7 @@ export const draculaIconRegistry: IconRegistry = {
62
69
  menu: <Menu {...iconProps} />,
63
70
  moreHorizontal: <MoreHorizontal {...iconProps} />,
64
71
  search: <Search {...iconProps} />,
72
+ upload: <Upload {...iconProps} />,
65
73
  arrowUp: <ArrowUp {...iconProps} />,
66
74
  arrowDown: <ArrowDown {...iconProps} />,
67
75
  arrowsUpDown: <ArrowUpDown {...iconProps} />,
package/package.json CHANGED
@@ -4,19 +4,20 @@
4
4
  "url": "https://github.com/yuzu-octopus/astryx-dracula/issues"
5
5
  },
6
6
  "dependencies": {
7
- "lucide-react": "^1.53.0"
7
+ "lucide-react": "1.70.0"
8
8
  },
9
9
  "description": "Pure Dracula brand theme for Astryx React sites. Dark-only tokens, syntax highlighting, and chart colors with prebuilt CSS.",
10
10
  "devDependencies": {
11
- "@astryxdesign/cli": "0.6.3",
12
- "@astryxdesign/core": "0.6.3",
13
- "@types/bun": "^1.4.2",
14
- "@types/node": "^26.6.4",
11
+ "@astryxdesign/cli": "0.7.10",
12
+ "@astryxdesign/core": "0.7.10",
13
+ "@biomejs/biome": "2.6.6",
14
+ "@types/bun": "1.4.4",
15
+ "@types/node": "26.6.6",
15
16
  "@types/react": "^19.3.0",
16
17
  "@types/react-dom": "^19.3.0",
17
- "@vitejs/plugin-react": "^6.1.2",
18
+ "@vitejs/plugin-react": "6.2.1",
18
19
  "typescript": "^7.0.2",
19
- "vite": "^8.3.3"
20
+ "vite": "8.3.6"
20
21
  },
21
22
  "exports": {
22
23
  "./shared/auth-chrome": "./shared/auth-chrome.tsx",
@@ -52,7 +53,10 @@
52
53
  "./astryx.integration.mjs": "./astryx.integration.mjs",
53
54
  "./package.json": "./package.json",
54
55
  "./templates/*": "./templates/*",
55
- "./theme.css": "./theme.css",
56
+ "./theme.css": {
57
+ "types": "./theme.css.d.ts",
58
+ "default": "./theme.css"
59
+ },
56
60
  "./tokens.css": "./tokens.css"
57
61
  },
58
62
  "files": [
@@ -67,6 +71,7 @@
67
71
  "icons.mjs",
68
72
  "icons.tsx",
69
73
  "shared/",
74
+ "theme.css.d.ts",
70
75
  "theme.css",
71
76
  "tokens.css",
72
77
  "templates/",
@@ -85,7 +90,7 @@
85
90
  "license": "MIT",
86
91
  "name": "astryx-dracula",
87
92
  "peerDependencies": {
88
- "@astryxdesign/core": "^0.6.3",
93
+ "@astryxdesign/core": "^0.7.2",
89
94
  "lucide-react": "^1.45.0",
90
95
  "react": ">=19.0.0",
91
96
  "react-dom": ">=19.0.0"
@@ -97,15 +102,18 @@
97
102
  "scripts": {
98
103
  "audit": "bun run fonts:sync && bun scripts/check.ts",
99
104
  "fonts:sync": "mkdir -p public/fonts && cp fonts/*.woff2 public/fonts/",
100
- "build": "tsc --noEmit && vite build",
105
+ "build": "bun check && vite build",
101
106
  "dev": "vite",
102
107
  "preview": "vite preview",
103
108
  "theme:build": "bun run icons:build && bunx astryx theme build astryx-theme.ts -o theme.css --icons-specifier ./icons.mjs",
104
- "icons:build": "bun build icons.tsx --outfile icons.mjs --format esm --external react --external lucide-react",
105
- "theme:check": "bun run icons:check && bunx astryx theme build astryx-theme.ts -o theme.css --icons-specifier ./icons.mjs --check --json | bun -e 'const r = JSON.parse(await Bun.stdin.text()); if (r.type !== \"theme.build.check\") { console.error(\"theme:check: unexpected CLI response \" + JSON.stringify(r).slice(0, 200)); process.exit(1); } const stale = r.data.stale.filter(s => s.path !== \"astryx-dracula.js\"); for (const s of stale) console.error(\"stale: \" + s.path + \" (\" + s.reason + \")\"); if (stale.length) process.exit(1); const entry = await import(\"./astryx-dracula.js\"); if (!entry.astryxDraculaTheme || !entry.draculaIconRegistry) { console.error(\"astryx-dracula.js is missing its theme or icon registry export\"); process.exit(1); } console.log(\"theme outputs up to date; astryx-dracula.js (hand-maintained) loads and exports\");' && bun run entry:check",
106
- "icons:check": "bun build icons.tsx --outfile .tmp-icons.mjs --format esm --external react --external lucide-react; s=$?; cmp -s .tmp-icons.mjs icons.mjs; c=$?; rm -f .tmp-icons.mjs; [ $s -eq 0 ] && [ $c -eq 0 ] || { echo 'stale: icons.mjs (rerun bun run icons:build)'; exit 1; }",
109
+ "icons:build": "NODE_ENV=production bun build icons.tsx --outfile icons.mjs --format esm --external react --external lucide-react",
110
+ "theme:check": "bun run icons:check && bunx astryx theme build astryx-theme.ts -o theme.css --icons-specifier ./icons.mjs --check --json | bun -e 'const r = JSON.parse(await Bun.stdin.text()); if (r.type !== \"theme.build.check\") { console.error(\"theme:check: unexpected CLI response \" + JSON.stringify(r).slice(0, 200)); process.exit(1); } const stale = r.data.stale; for (const s of stale) console.error(\"stale: \" + s.path + \" (\" + s.reason + \")\"); if (stale.length) process.exit(1); const entry = await import(\"./astryx-dracula.js\"); if (!entry.astryxDraculaTheme || !entry.draculaIconRegistry) { console.error(\"astryx-dracula.js is missing its theme or icon registry export\"); process.exit(1); } console.log(\"theme outputs up to date; astryx-dracula.js (hand-maintained) loads and exports\");' && bun run entry:check",
111
+ "icons:check": "NODE_ENV=production bun build icons.tsx --outfile .tmp-icons.mjs --format esm --external react --external lucide-react; s=$?; cmp -s .tmp-icons.mjs icons.mjs; c=$?; rm -f .tmp-icons.mjs; [ $s -eq 0 ] && [ $c -eq 0 ] || { echo 'stale: icons.mjs (rerun bun run icons:build)'; exit 1; }",
107
112
  "entry:check": "node -e \"const{pathToFileURL}=require('url');const{resolve}=require('path');import(pathToFileURL(resolve('astryx-dracula.js')).href).then(m=>{if(!m.astryxDraculaTheme||!m.draculaIconRegistry){console.error('astryx-dracula.js is missing its theme or icon registry export');process.exit(1)}console.log('astryx-dracula.js loads under plain Node ESM')}).catch(e=>{console.error('astryx-dracula.js is not importable by Node ESM: '+e.message);process.exit(1)})\"",
108
- "prepublishOnly": "bun run theme:check && bun run icons:check && bun run entry:check && bun run audit && tsc --noEmit && bunx react-doctor@latest --score"
113
+ "prepublishOnly": "bun audit && bun run theme:check && bun run icons:check && bun run entry:check && bun run audit && bun check && bun run fmt:check && bun run lint && bunx react-doctor@latest --score",
114
+ "fmt": "bun fmt '**/*.{ts,tsx,mjs,js,jsx,json,css}'",
115
+ "fmt:check": "bun fmt --check '**/*.{ts,tsx,mjs,js,jsx,json,css}'",
116
+ "lint": "biome check"
109
117
  },
110
118
  "sideEffects": [
111
119
  "**/*.css"
@@ -115,8 +123,5 @@
115
123
  "@astryxdesign/cli"
116
124
  ],
117
125
  "type": "module",
118
- "version": "0.5.1",
119
- "patchedDependencies": {
120
- "@astryxdesign/core@0.6.3": "patches/@astryxdesign%2Fcore@0.6.3.patch"
121
- }
126
+ "version": "0.7.0"
122
127
  }
@@ -12,7 +12,3 @@ export const authPageStyle: CSSProperties = {
12
12
  };
13
13
  // Cap the column at 400px but let it shrink to fit narrow screens.
14
14
  export const authContentStyle: CSSProperties = { width: "100%", maxWidth: 400 };
15
- // WCAG 1.3.5 autocomplete: TextInput forwards unknown props to <input> but its
16
- // prop type omits input-only attributes, so spread through a widened record.
17
- export const inputAutoComplete = (value: string) =>
18
- ({ autoComplete: value }) as Record<string, string>;