@fusion.dev/helix-docs 0.1.0 → 0.3.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/content/metrics.mdx +12 -12
- package/dist/catalog.js +0 -141
- package/dist/naming.js +0 -20
- package/dist/reference.js +1 -59
- package/dist/registry.js +0 -44
- package/dist/sections.js +0 -24
- package/dist/sources.generated.js +12 -17
- package/package.json +3 -3
package/content/metrics.mdx
CHANGED
|
@@ -59,10 +59,10 @@ repository does that. The per-component tables are what a page pays.
|
|
|
59
59
|
| Package | Raw | Gzip | Brotli | |
|
|
60
60
|
|---|---|---|---|---|
|
|
61
61
|
| `@fusion.dev/helix-core` | 134,650 | 44,269 | 37,972 | Element base class, mixins, decorators, floating positioning. |
|
|
62
|
-
| `@fusion.dev/helix-headless` | 519,
|
|
62
|
+
| `@fusion.dev/helix-headless` | 519,154 | 131,672 | 103,150 | Every headless family, which is what the barrel means. |
|
|
63
63
|
| `@fusion.dev/helix-icons` | 47,484 | 14,907 | 12,553 | The whole glyph set. |
|
|
64
64
|
| `@fusion.dev/helix-theme` | 3,288 | 1,571 | 1,355 | The derivation engine. Build time for most consumers, runtime for a theme switcher. |
|
|
65
|
-
| `@fusion.dev/helix` | 956,713 | 216,
|
|
65
|
+
| `@fusion.dev/helix` | 956,713 | 216,820 | 158,985 | Every styled family. |
|
|
66
66
|
| `lit` | 15,394 | 6,118 | 5,460 | Not ours. Here so it can be subtracted from every row above it. |
|
|
67
67
|
|
|
68
68
|
## The stylesheets
|
|
@@ -85,9 +85,9 @@ is the whole cost of adopting the base layer on its own.
|
|
|
85
85
|
|
|
86
86
|
**Most of a first component is the runtime under it.** The median styled family is 13,974 bytes gzipped alone and adds 2,409 to a page that already has Helix on it, so 83 percent of the first one is shared and 17 percent is the component. Ten typical components are one plus nine additions rather than ten of the first number, and the pair of columns below is what lets that be worked out rather than guessed.
|
|
87
87
|
|
|
88
|
-
Across the tier: the cheapest is `code` at 9,065 gzipped alone, the dearest `data-table` at 49,868, over 93 components. Every family at once is 216,
|
|
88
|
+
Across the tier: the cheapest is `code` at 9,065 gzipped alone, the dearest `data-table` at 49,868, over 93 components. Every family at once is 216,820.
|
|
89
89
|
|
|
90
|
-
**No family imports a barrel, and the `barrels` rule in `fusion workspace` is what keeps it that way.** `@fusion.dev/helix-headless` is `sideEffects` over every module in `dist`, which is true of a file that calls `customElements.define` and which means a bundler may drop none of it: one `import { HelixHeadlessButton } from '@fusion.dev/helix-headless'` costs 131,
|
|
90
|
+
**No family imports a barrel, and the `barrels` rule in `fusion workspace` is what keeps it that way.** `@fusion.dev/helix-headless` is `sideEffects` over every module in `dist`, which is true of a file that calls `customElements.define` and which means a bundler may drop none of it: one `import { HelixHeadlessButton } from '@fusion.dev/helix-headless'` costs 131,672 bytes gzipped whatever else the page does, which is 9 times the median family measured above. The styled tier imports the family it extends instead, all 93 of them, and the check refuses the shape rather than the package name, so the rule follows `sideEffects` wherever it goes.
|
|
91
91
|
|
|
92
92
|
The headless tier never had the problem, and it is the control: `@fusion.dev/helix-core` is `sideEffects: false`, and a headless family is a median of 16,187 bytes gzipped alone.
|
|
93
93
|
|
|
@@ -126,7 +126,7 @@ Four other libraries of custom elements, pinned and measured on 2026-08-24 by `t
|
|
|
126
126
|
| | Material Web | 50,155 | 14,577 | 12,935 |
|
|
127
127
|
| | Shoelace | 37,833 | 11,814 | 10,568 |
|
|
128
128
|
| | Spectrum | 62,322 | 15,059 | 13,321 |
|
|
129
|
-
| `tabs` | **Helix** | 40,196 | 12,
|
|
129
|
+
| `tabs` | **Helix** | 40,196 | 12,348 | 10,882 |
|
|
130
130
|
| | Carbon | 578,766 | 73,537 | 43,235 |
|
|
131
131
|
| | Material Web | 38,883 | 12,820 | 11,368 |
|
|
132
132
|
| | Shoelace | 54,573 | 17,140 | 15,068 |
|
|
@@ -254,7 +254,7 @@ Structure, accessibility, state and form participation. No presentation, and no
|
|
|
254
254
|
| `steps` | 82,900 | 27,205 | 22,347 | 6,303 | 1,832 | 1,249 |
|
|
255
255
|
| `switch` | 34,314 | 11,106 | 9,826 | 1,798 | 832 | 358 |
|
|
256
256
|
| `table` | 31,861 | 10,274 | 9,086 | 4,373 | 1,299 | 831 |
|
|
257
|
-
| `tabs` | 33,935 | 11,
|
|
257
|
+
| `tabs` | 33,935 | 11,060 | 9,721 | 4,469 | 1,277 | 735 |
|
|
258
258
|
| `tag` | 74,439 | 24,760 | 20,435 | 897 | 464 | 219 |
|
|
259
259
|
| `textarea` | 37,001 | 11,743 | 10,362 | 4,115 | 1,414 | 884 |
|
|
260
260
|
| `time-input` | 136,201 | 43,547 | 36,687 | 28,643 | 7,661 | 6,120 |
|
|
@@ -353,7 +353,7 @@ The headless tier plus presentation. This is what `bun add @fusion.dev/helix` gi
|
|
|
353
353
|
| `steps` | 96,252 | 29,575 | 24,410 | 19,643 | 4,202 | 3,353 |
|
|
354
354
|
| `switch` | 38,603 | 12,160 | 10,668 | 6,072 | 1,891 | 1,318 |
|
|
355
355
|
| `table` | 35,190 | 10,865 | 9,580 | 7,692 | 1,916 | 1,378 |
|
|
356
|
-
| `tabs` | 40,196 | 12,
|
|
356
|
+
| `tabs` | 40,196 | 12,348 | 10,882 | 10,719 | 2,597 | 1,971 |
|
|
357
357
|
| `tag` | 77,633 | 25,634 | 21,148 | 4,076 | 1,245 | 995 |
|
|
358
358
|
| `text` | 29,734 | 9,670 | 8,508 | 3,922 | 958 | 605 |
|
|
359
359
|
| `textarea` | 40,350 | 12,544 | 11,034 | 7,447 | 2,227 | 1,615 |
|
|
@@ -381,12 +381,12 @@ column is what was removed rather than part of what remains.
|
|
|
381
381
|
|
|
382
382
|
| Package | Unpacked | Files | Source maps stripped | Runtime dependencies |
|
|
383
383
|
|---|---|---|---|---|
|
|
384
|
-
| `@fusion.dev/helix-core` |
|
|
385
|
-
| `@fusion.dev/helix-headless` |
|
|
386
|
-
| `@fusion.dev/helix-icons` |
|
|
384
|
+
| `@fusion.dev/helix-core` | 655,135 | 113 | 154,658 | `@floating-ui/dom`, `@fusion.dev/helix-icons` |
|
|
385
|
+
| `@fusion.dev/helix-headless` | 8,636,163 | 422 | 699,239 | `@fusion.dev/helix-core`, `@fusion.dev/helix-icons`, `uqr` |
|
|
386
|
+
| `@fusion.dev/helix-icons` | 65,943 | 11 | 20,928 | none |
|
|
387
387
|
| `@fusion.dev/helix-styles` | 83,277 | 5 | 0 | none |
|
|
388
|
-
| `@fusion.dev/helix-theme` |
|
|
389
|
-
| `@fusion.dev/helix` | 9,
|
|
388
|
+
| `@fusion.dev/helix-theme` | 461,551 | 8 | 4,699 | none |
|
|
389
|
+
| `@fusion.dev/helix` | 9,306,931 | 718 | 278,170 | `@fusion.dev/helix-core`, `@fusion.dev/helix-headless`, `@fusion.dev/helix-styles` |
|
|
390
390
|
|
|
391
391
|
## Not measured yet
|
|
392
392
|
|
package/dist/catalog.js
CHANGED
|
@@ -1,85 +1,25 @@
|
|
|
1
1
|
import { displayName, startCase, tierOf } from './naming.js';
|
|
2
2
|
import { place } from './reference.js';
|
|
3
|
-
/**
|
|
4
|
-
* The canonical example's slug, named once because three places ask for it.
|
|
5
|
-
*
|
|
6
|
-
* The tier pairing, the first-position pin and the label all read it. A fact
|
|
7
|
-
* three places hold is a fact that drifts.
|
|
8
|
-
*/
|
|
9
3
|
const CANONICAL = 'preview';
|
|
10
|
-
/* The headless twin's slug, and the suffix every other one carries. */
|
|
11
4
|
const HEADLESS = 'headless';
|
|
12
5
|
const HEADLESS_SUFFIX = /\.headless$/;
|
|
13
|
-
/**
|
|
14
|
-
* Drops `undefined` from a union.
|
|
15
|
-
*
|
|
16
|
-
* Every reflected property is optional, because the default state of a Helix
|
|
17
|
-
* component is the absent attribute: a reflected default would put an attribute
|
|
18
|
-
* on the host that a React consumer's server markup never had. That makes the
|
|
19
|
-
* declared type `'primary' | 'neutral' | undefined`, and the `undefined` is an
|
|
20
|
-
* implementation detail of how the default is expressed rather than a value
|
|
21
|
-
* anyone sets.
|
|
22
|
-
*/
|
|
23
6
|
const withoutUndefined = (text) => text
|
|
24
7
|
.split('|')
|
|
25
8
|
.map((part) => part.trim())
|
|
26
9
|
.filter((part) => part !== 'undefined')
|
|
27
10
|
.join(' | ');
|
|
28
|
-
/**
|
|
29
|
-
* A method the platform calls, rather than one a consumer does.
|
|
30
|
-
*
|
|
31
|
-
* `formResetCallback` and its siblings are public because the platform has to
|
|
32
|
-
* reach them, and they are 55 of the 152 public methods in the library:
|
|
33
|
-
* documenting them puts a reader's own `focus()` and `show()` in a minority on
|
|
34
|
-
* their own component's page. Matching the suffix rather than listing the names
|
|
35
|
-
* covers the custom-element lifecycle and the form-associated one together, and
|
|
36
|
-
* keeps covering them when the platform adds a third.
|
|
37
|
-
*/
|
|
38
11
|
const PLATFORM_CALLBACK = /Callback$/;
|
|
39
|
-
/** Public only. Private and protected are the component's business. */
|
|
40
12
|
const isPublic = (row) => row.privacy === undefined || row.privacy === 'public';
|
|
41
|
-
/**
|
|
42
|
-
* Properties, with the default each one falls back to.
|
|
43
|
-
*
|
|
44
|
-
* Fields rather than attributes: an attribute carries no default in the
|
|
45
|
-
* manifest, so a table built from attributes can say a component takes a
|
|
46
|
-
* property and never what it does when you leave it alone.
|
|
47
|
-
*/
|
|
48
13
|
const properties = (rows) => (rows ?? [])
|
|
49
|
-
/* Instance fields only. A static is the class's, not an element's, and the
|
|
50
|
-
two that reach here are the platform's rather than ours:
|
|
51
|
-
`shadowRootOptions` is Lit's and `formAssociated` is the flag the browser
|
|
52
|
-
reads to decide a control participates in a form. Thirty-five rows across
|
|
53
|
-
the library, none of them anything a consumer sets on a tag. */
|
|
54
|
-
/* `@internal` needs nothing here: the analyzer drops a member carrying it
|
|
55
|
-
before the manifest is written. */
|
|
56
14
|
.filter((row) => row.kind === 'field' && isPublic(row) && row.static !== true)
|
|
57
15
|
.map((row) => ({
|
|
58
|
-
/* `undefined` is not a default, it is the absence of one, and the
|
|
59
|
-
analyzer records the initializer verbatim. Printed, the column reads
|
|
60
|
-
"undefined" for every optional property, which is a table telling a
|
|
61
|
-
reader a word rather than a value. Blank says the same thing and says
|
|
62
|
-
it quietly. */
|
|
63
16
|
default: row.default === 'undefined' ? '' : (row.default ?? ''),
|
|
64
17
|
description: row.description ?? '',
|
|
65
18
|
name: row.name ?? '',
|
|
66
|
-
/* A getter reads as a field in the manifest and assigning to one throws,
|
|
67
|
-
which is the same trap the React generator already skips these for. In
|
|
68
|
-
a table they are indistinguishable from a property a reader may set:
|
|
69
|
-
`AvatarGroup.avatars` sat beside its slot looking like a second way to
|
|
70
|
-
pass the same thing, and there is no second way. A hundred and
|
|
71
|
-
fifty-five of them. */
|
|
72
19
|
readonly: row.readonly === true,
|
|
73
|
-
/* From `@reference` on the property. A row for `command` can say it is
|
|
74
|
-
the Invoker Commands API and point at where that is specified, which a
|
|
75
|
-
description sentence can gesture at and cannot carry. */
|
|
76
20
|
references: row.helix?.references ?? [],
|
|
77
21
|
type: withoutUndefined(row.type?.text ?? ''),
|
|
78
22
|
}));
|
|
79
|
-
/**
|
|
80
|
-
* Methods, typed by the signature a caller writes rather than by a return type
|
|
81
|
-
* alone. `(next: string) => boolean` says what to pass; `boolean` does not.
|
|
82
|
-
*/
|
|
83
23
|
const methods = (rows) => (rows ?? [])
|
|
84
24
|
.filter((row) => row.kind === 'method' && isPublic(row) && !PLATFORM_CALLBACK.test(row.name ?? ''))
|
|
85
25
|
.map((row) => {
|
|
@@ -97,60 +37,14 @@ const members = (rows) => (rows ?? []).map((row) => ({
|
|
|
97
37
|
name: row.name ?? '',
|
|
98
38
|
type: withoutUndefined(row.type?.text ?? ''),
|
|
99
39
|
}));
|
|
100
|
-
/**
|
|
101
|
-
* An annotation comment: a leading `@` inside an HTML comment, and its line.
|
|
102
|
-
*
|
|
103
|
-
* **Only comments that begin with `@`.** An example is allowed one comment
|
|
104
|
-
* about its own scaffolding, and those are written for the reader:
|
|
105
|
-
* `<!-- Preview frame: the submit is swallowed. -->` exists so nobody copies
|
|
106
|
-
* `onsubmit="event.preventDefault()"` into production. Stripping every comment
|
|
107
|
-
* would take that note with it. The sigil is what separates a line addressed to
|
|
108
|
-
* this documentation system from a line addressed to a person.
|
|
109
|
-
*/
|
|
110
40
|
const ANNOTATION = /^[^\S\n]*<!--\s*@[\s\S]*?-->[^\S\n]*\n?/gm;
|
|
111
|
-
/**
|
|
112
|
-
* The example's markup as a reader should receive it.
|
|
113
|
-
*
|
|
114
|
-
* `@summary` is metadata about the example rather than part of it: the cem
|
|
115
|
-
* plugin lifts it into the manifest and the reference prints it as the
|
|
116
|
-
* description, so left in place it makes the copy button hand back a comment
|
|
117
|
-
* describing the thing you just copied.
|
|
118
|
-
*
|
|
119
|
-
* Stripped here rather than at the reader, because every consumer of the
|
|
120
|
-
* catalog wants the same thing and a site that trimmed it in its own renderer
|
|
121
|
-
* would leave the sandbox and any other consumer showing it.
|
|
122
|
-
*/
|
|
123
41
|
const withoutAnnotations = (html) => html.replace(ANNOTATION, '').trimStart();
|
|
124
|
-
/**
|
|
125
|
-
* The examples of one family, named and ordered.
|
|
126
|
-
*
|
|
127
|
-
* The prose comes from the manifest and the markup from the caller. The
|
|
128
|
-
* composition plugin reads the same folder and records what each example is;
|
|
129
|
-
* the payload stays on disk because it is large and the manifest is parsed by
|
|
130
|
-
* everything. Keyed by slug so the two halves cannot drift into each other's
|
|
131
|
-
* order.
|
|
132
|
-
*/
|
|
133
42
|
const examplesOf = (slug, declared, sources) => {
|
|
134
43
|
const described = new Map((declared?.examples ?? []).map((entry) => [entry.slug ?? '', entry.description ?? '']));
|
|
135
|
-
/* Keyed on slug the same way the descriptions are, and for the same reason:
|
|
136
|
-
the manifest half and the on-disk half are matched rather than zipped, so
|
|
137
|
-
the two cannot drift into each other's order. */
|
|
138
44
|
const layouts = new Map((declared?.examples ?? []).map((entry) => [entry.slug ?? '', entry.layout ?? '']));
|
|
139
45
|
const minimums = new Map((declared?.examples ?? []).map((entry) => [entry.slug ?? '', entry.min ?? 0]));
|
|
140
46
|
return (sources
|
|
141
47
|
.filter((source) => source.family === slug)
|
|
142
|
-
/* `preview` first, then alphabetical, with each headless twin directly
|
|
143
|
-
behind the example it mirrors.
|
|
144
|
-
|
|
145
|
-
By slug, never by filename. Comparing `compact-counts.html` against
|
|
146
|
-
`compact.html` puts the longer name first, `-` preceding `.`, which is
|
|
147
|
-
a list ordered by a file extension no reader ever sees.
|
|
148
|
-
|
|
149
|
-
**Pair on the mirrored name, not on the raw slug.** Sorting on the raw
|
|
150
|
-
slug puts the twin wherever the tier's name happens to fall in the
|
|
151
|
-
alphabet, which is only ever right by luck. The tabs have to show the
|
|
152
|
-
same list on both tiers, and `mirrored` below is that relationship: sort
|
|
153
|
-
on it and the position follows from the pairing. */
|
|
154
48
|
.sort((a, b) => {
|
|
155
49
|
const pairOf = (slug) => slug === HEADLESS ? CANONICAL : slug.replace(HEADLESS_SUFFIX, '');
|
|
156
50
|
const twin = (slug) => (slug === HEADLESS || HEADLESS_SUFFIX.test(slug) ? 1 : 0);
|
|
@@ -162,14 +56,6 @@ const examplesOf = (slug, declared, sources) => {
|
|
|
162
56
|
return twin(a.slug) - twin(b.slug);
|
|
163
57
|
})
|
|
164
58
|
.map((source) => {
|
|
165
|
-
/* Which styled example this one is the headless twin of. `headless` is
|
|
166
|
-
the twin of `preview`, and `<name>.headless` of `<name>`. This is the
|
|
167
|
-
one place that has to know the pairing, because a headless example is
|
|
168
|
-
not named for itself. */
|
|
169
|
-
/* Read once and narrowed here rather than spread from the map
|
|
170
|
-
directly: `get` answers `string | undefined`, and under
|
|
171
|
-
`exactOptionalPropertyTypes` an optional property will not take the
|
|
172
|
-
`undefined`. */
|
|
173
59
|
const layout = layouts.get(source.slug);
|
|
174
60
|
const min = minimums.get(source.slug);
|
|
175
61
|
const mirrored = source.slug === HEADLESS ? CANONICAL : source.slug.replace(HEADLESS_SUFFIX, '');
|
|
@@ -177,14 +63,6 @@ const examplesOf = (slug, declared, sources) => {
|
|
|
177
63
|
css: source.css,
|
|
178
64
|
description: described.get(source.slug) ?? '',
|
|
179
65
|
html: withoutAnnotations(source.html),
|
|
180
|
-
/* **The label is the file's name, with no special case.** `startCase`
|
|
181
|
-
gives "Preview" for the canonical example on its own.
|
|
182
|
-
|
|
183
|
-
**A headless example takes the name of the one it mirrors**, so the two
|
|
184
|
-
tiers show the same list rather than a list that changes its labels
|
|
185
|
-
when a reader changes a preference. Only one of a pair is ever on
|
|
186
|
-
screen, the tier deciding which, so a differing name would be the only
|
|
187
|
-
thing suggesting they are different examples. */
|
|
188
66
|
label: startCase(mirrored),
|
|
189
67
|
...(layout ? { layout } : {}),
|
|
190
68
|
...(min ? { min } : {}),
|
|
@@ -194,15 +72,6 @@ const examplesOf = (slug, declared, sources) => {
|
|
|
194
72
|
};
|
|
195
73
|
}));
|
|
196
74
|
};
|
|
197
|
-
/**
|
|
198
|
-
* Every family across the given manifests, alphabetical, each with its elements
|
|
199
|
-
* and examples.
|
|
200
|
-
*
|
|
201
|
-
* The family a declaration belongs to comes from where its file is rather than
|
|
202
|
-
* from its tag name, which is the same reasoning `place()` carries for the
|
|
203
|
-
* reference: `helix-button-group` is one family and `helix-tab` is a part
|
|
204
|
-
* of another, and nothing in the name says which.
|
|
205
|
-
*/
|
|
206
75
|
export const catalog = (manifests, examples = []) => {
|
|
207
76
|
const byFamily = new Map();
|
|
208
77
|
for (const manifest of manifests) {
|
|
@@ -221,8 +90,6 @@ export const catalog = (manifests, examples = []) => {
|
|
|
221
90
|
}
|
|
222
91
|
return [...byFamily.entries()]
|
|
223
92
|
.map(([slug, entries]) => {
|
|
224
|
-
/* The family's own description comes from its styled root: the element
|
|
225
|
-
whose tag is the family name, rather than a part of it. */
|
|
226
93
|
const root = entries.find((entry) => entry.tagName === `helix-${slug}`) ??
|
|
227
94
|
entries[0];
|
|
228
95
|
return {
|
|
@@ -243,10 +110,6 @@ export const catalog = (manifests, examples = []) => {
|
|
|
243
110
|
})),
|
|
244
111
|
label: displayName(entry.tagName),
|
|
245
112
|
methods: methods(entry.members),
|
|
246
|
-
/* From the manifest, not by stripping the family name off the
|
|
247
|
-
label. The composition plugin already derives this from the
|
|
248
|
-
folder, and "Avatar Group" minus "Avatar" is a string operation
|
|
249
|
-
that happens to work until a part's name contains the family's. */
|
|
250
113
|
part: entry.helix?.part ?? '',
|
|
251
114
|
properties: properties(entry.members),
|
|
252
115
|
slots: members(entry.slots),
|
|
@@ -254,9 +117,6 @@ export const catalog = (manifests, examples = []) => {
|
|
|
254
117
|
tagName: entry.tagName,
|
|
255
118
|
tier: tierOf(entry.tagName),
|
|
256
119
|
}))
|
|
257
|
-
/* Styled first, then headless. Alphabetical order would put the
|
|
258
|
-
headless tier on top, which is the one most readers never reach
|
|
259
|
-
for. */
|
|
260
120
|
.sort((a, b) => Number(a.tier === 'headless') - Number(b.tier === 'headless') ||
|
|
261
121
|
a.tagName.localeCompare(b.tagName)),
|
|
262
122
|
examples: examplesOf(slug, root.helix, examples),
|
|
@@ -270,5 +130,4 @@ export const catalog = (manifests, examples = []) => {
|
|
|
270
130
|
})
|
|
271
131
|
.sort((a, b) => a.label.localeCompare(b.label));
|
|
272
132
|
};
|
|
273
|
-
/** The family of a given slug, from an already-built catalog. */
|
|
274
133
|
export const findInCatalog = (families, slug) => families.find((family) => family.slug === slug);
|
package/dist/naming.js
CHANGED
|
@@ -1,28 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Display names for components.
|
|
3
|
-
*
|
|
4
|
-
* The product is Helix, so every component being called "HelixCard" inside the
|
|
5
|
-
* Helix site is noise: it repeats the one thing the reader already knows on
|
|
6
|
-
* every row of the sidebar. The tag keeps its prefix, because that is a real
|
|
7
|
-
* identifier a consumer types.
|
|
8
|
-
*/
|
|
9
|
-
/**
|
|
10
|
-
* Words a slug spells in lower case that are read as letters.
|
|
11
|
-
*
|
|
12
|
-
* Capitalizing the first letter of `qr` gives `Qr`, which is a word nobody says.
|
|
13
|
-
* A slug is lower case because a URL is, and the initialism it came from is
|
|
14
|
-
* lost by the time this sees it, so it has to be put back by name. Kept small
|
|
15
|
-
* and explicit rather than guessed at from length: `ui`, `id` and `api` are
|
|
16
|
-
* initialisms and `is`, `on` and `to` are not.
|
|
17
|
-
*/
|
|
18
1
|
const INITIALISMS = new Set(['api', 'css', 'html', 'id', 'qr', 'ui', 'url']);
|
|
19
|
-
/** `app-header` becomes `App Header`, and `qr-code` becomes `QR Code`. */
|
|
20
2
|
export const startCase = (slug) => slug
|
|
21
3
|
.split('-')
|
|
22
4
|
.filter(Boolean)
|
|
23
5
|
.map((word) => INITIALISMS.has(word) ? word.toUpperCase() : word.charAt(0).toUpperCase() + word.slice(1))
|
|
24
6
|
.join(' ');
|
|
25
|
-
/** `helix-app-header` becomes `App Header`, `helix-headless-card` becomes `Card`. */
|
|
26
7
|
export const displayName = (tagName) => startCase(tagName.replace(/^helix-(?:headless-)?/, ''));
|
|
27
|
-
/** Which tier a tag belongs to, read from the prefix rather than the manifest. */
|
|
28
8
|
export const tierOf = (tagName) => tagName.startsWith('helix-headless-') ? 'headless' : 'styled';
|
package/dist/reference.js
CHANGED
|
@@ -1,26 +1,10 @@
|
|
|
1
1
|
import { startCase } from './naming.js';
|
|
2
|
-
/**
|
|
3
|
-
* Whether a member belongs in a reference at all.
|
|
4
|
-
*
|
|
5
|
-
* Public only, and nothing inherited from `HelixElement`. Every component in
|
|
6
|
-
* the library extends it, so its members would appear on all of them: an
|
|
7
|
-
* `internals` field and two lifecycle methods that exist so components do not
|
|
8
|
-
* have to think about the shadow root. Printing them everywhere says the same
|
|
9
|
-
* infrastructural thing once per component and buries the four properties a
|
|
10
|
-
* consumer came to read.
|
|
11
|
-
*
|
|
12
|
-
* `HelixFormElement` is deliberately not on that list. What it contributes is
|
|
13
|
-
* form participation, which is the API of a form control.
|
|
14
|
-
*/
|
|
15
2
|
const INFRASTRUCTURE = new Set(['HelixElement']);
|
|
16
3
|
const isPublic = (member) => member.privacy !== 'private' &&
|
|
17
4
|
member.privacy !== 'protected' &&
|
|
18
5
|
!INFRASTRUCTURE.has(member.inheritedFrom?.name ?? '');
|
|
19
|
-
/** A cell's worth of a description: the first paragraph, on one line. */
|
|
20
6
|
const cell = (text) => (text ?? '').split('\n\n')[0]?.replace(/\s+/g, ' ').replace(/\|/g, '\\|').trim() ?? '';
|
|
21
|
-
/** A type, escaped so its unions do not end the column they are in. */
|
|
22
7
|
const code = (text) => text ? `\`${text.replace(/\|/g, '\\|')}\`` : '-';
|
|
23
|
-
/** A markdown table, or nothing at all where there are no rows to put in one. */
|
|
24
8
|
const table = (depth, heading, columns, rows) => {
|
|
25
9
|
if (rows.length === 0) {
|
|
26
10
|
return '';
|
|
@@ -30,24 +14,10 @@ const table = (depth, heading, columns, rows) => {
|
|
|
30
14
|
const body = rows.map((row) => `| ${row.join(' | ')} |`).join('\n');
|
|
31
15
|
return `\n${'#'.repeat(depth)} ${heading}\n\n${head}\n${rule}\n${body}\n`;
|
|
32
16
|
};
|
|
33
|
-
/**
|
|
34
|
-
* The family and part a declaration belongs to, from where its file is.
|
|
35
|
-
*
|
|
36
|
-
* Not from the tag name. A tag is a string the family prefix can only be
|
|
37
|
-
* guessed out of: `helix-button-group` is one family and `helix-tab` is a
|
|
38
|
-
* part of another, and nothing in the name says which. The path says both.
|
|
39
|
-
*/
|
|
40
17
|
export const place = (path) => {
|
|
41
18
|
const [, family = '', part = ''] = /^src\/([^/]+)\/([^/]+)\//.exec(path ?? '') ?? [];
|
|
42
19
|
return { family, part };
|
|
43
20
|
};
|
|
44
|
-
/**
|
|
45
|
-
* Every family in a manifest, alphabetical, each with its parts.
|
|
46
|
-
*
|
|
47
|
-
* Root first inside a family, then the rest alphabetically. A family reads from
|
|
48
|
-
* the thing that holds the others, and `item` before `root` is alphabetical
|
|
49
|
-
* order telling you about the alphabet rather than about the component.
|
|
50
|
-
*/
|
|
51
21
|
export const referenceFamilies = (manifest) => {
|
|
52
22
|
const families = new Map();
|
|
53
23
|
for (const module of manifest.modules ?? []) {
|
|
@@ -69,7 +39,6 @@ export const referenceFamilies = (manifest) => {
|
|
|
69
39
|
parts: [...parts].sort((a, b) => a.part === 'root' ? -1 : b.part === 'root' ? 1 : a.part.localeCompare(b.part)),
|
|
70
40
|
}));
|
|
71
41
|
};
|
|
72
|
-
/** The tables for one element, in the order they are printed. */
|
|
73
42
|
const element = (depth, declaration, part) => {
|
|
74
43
|
const { attributes = [], cssParts = [], cssProperties = [], description, events = [], members = [], slots = [], summary, superclass, tagName, } = declaration;
|
|
75
44
|
const lines = [`${'#'.repeat(depth)} ${startCase(part)} (\`${tagName}\`)`, ''];
|
|
@@ -100,26 +69,14 @@ const element = (depth, declaration, part) => {
|
|
|
100
69
|
])).trimEnd(), table(depth + 1, 'Events', ['Event', 'Type', 'Description'], events.map((event) => [`\`${event.name}\``, code(event.type?.text), cell(event.description)])).trimEnd(), table(depth + 1, 'Slots', ['Slot', 'Description'], slots.map((slot) => [
|
|
101
70
|
slot.name ? `\`${slot.name}\`` : '*(default)*',
|
|
102
71
|
cell(slot.description),
|
|
103
|
-
])).trimEnd(), table(depth + 1, 'Parts', ['Part', 'Description'], cssParts.map((one) => [`\`${one.name}\``, cell(one.description)])).trimEnd(),
|
|
104
|
-
/* A "From" column, because a hook can now arrive from a component this one
|
|
105
|
-
borrowed a stylesheet from rather than be its own. Without it a borrowed
|
|
106
|
-
`--icon-button-radii` reads on the Copy Button page as a hook Copy Button
|
|
107
|
-
named, and a consumer who guesses `--copy-button-radii` from that gets
|
|
108
|
-
nothing. */
|
|
109
|
-
table(depth + 1, 'Custom properties', ['Property', 'From', 'Description'], cssProperties.map((one) => [
|
|
72
|
+
])).trimEnd(), table(depth + 1, 'Parts', ['Part', 'Description'], cssParts.map((one) => [`\`${one.name}\``, cell(one.description)])).trimEnd(), table(depth + 1, 'Custom properties', ['Property', 'From', 'Description'], cssProperties.map((one) => [
|
|
110
73
|
`\`${one.name}\``,
|
|
111
74
|
one.inheritedFrom?.name ? `\`${one.inheritedFrom.name}\`` : '-',
|
|
112
75
|
cell(one.description),
|
|
113
76
|
])).trimEnd(), '');
|
|
114
77
|
return lines;
|
|
115
78
|
};
|
|
116
|
-
/**
|
|
117
|
-
* The leading `<!-- @summary -->` comment, which the description above already
|
|
118
|
-
* carries. It is how an example declares its own one-liner to the analyzer, so
|
|
119
|
-
* it belongs in the file and not a second time in the prose beside it.
|
|
120
|
-
*/
|
|
121
79
|
const withoutSummary = (html) => html.replace(/^<!--\s*@summary[\s\S]*?-->\n*/, '');
|
|
122
|
-
/** One family's examples, as the markdown a reader or an agent can run. */
|
|
123
80
|
const shown = (depth, examples) => {
|
|
124
81
|
if (examples.length === 0) {
|
|
125
82
|
return [];
|
|
@@ -137,17 +94,6 @@ const shown = (depth, examples) => {
|
|
|
137
94
|
}
|
|
138
95
|
return lines;
|
|
139
96
|
};
|
|
140
|
-
/**
|
|
141
|
-
* A manifest, as the markdown reference for everything in it.
|
|
142
|
-
*
|
|
143
|
-
* The caller supplies the manifest and whatever preamble belongs above it, so
|
|
144
|
-
* the same renderer serves the whole-library document in `docs/` and a
|
|
145
|
-
* per-family page without either one knowing about the other.
|
|
146
|
-
*
|
|
147
|
-
* **A single family gets no heading naming it**, because the title already
|
|
148
|
-
* does: a document about the accordion should not say Accordion twice before
|
|
149
|
-
* its first sentence. More than one and the headings are what separate them.
|
|
150
|
-
*/
|
|
151
97
|
export const reference = (manifest, options = {}) => {
|
|
152
98
|
const front = options.frontmatter ?? [];
|
|
153
99
|
const lines = [
|
|
@@ -160,10 +106,6 @@ export const reference = (manifest, options = {}) => {
|
|
|
160
106
|
];
|
|
161
107
|
const wanted = options.families;
|
|
162
108
|
const families = referenceFamilies(manifest).filter((entry) => wanted === undefined || wanted.includes(entry.family));
|
|
163
|
-
/* Everything under a family heading sits one level deeper than it would in a
|
|
164
|
-
document that has no family heading to sit under. Without this a page about
|
|
165
|
-
one component opens at `###`, which is a heading level with nothing above
|
|
166
|
-
it and reads as a fragment of a larger file. */
|
|
167
109
|
const depth = families.length > 1 ? 3 : 2;
|
|
168
110
|
for (const { family, parts } of families) {
|
|
169
111
|
if (families.length > 1) {
|
package/dist/registry.js
CHANGED
|
@@ -1,40 +1,8 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Documentation registry for Helix.
|
|
3
|
-
*
|
|
4
|
-
* Docs are a package rather than a folder inside a site so that the docs are
|
|
5
|
-
* pinned to the version of the code they describe. A site renders this
|
|
6
|
-
* registry; it does not own it.
|
|
7
|
-
*
|
|
8
|
-
* **There is no version axis in here.** The package version is the version:
|
|
9
|
-
* `@fusion.dev/helix-docs@0.2.0` documents Helix 0.2.0, because every package in a
|
|
10
|
-
* domain moves in lockstep. A `versions` array beside that would be a second
|
|
11
|
-
* source of truth with nothing keeping the two in step, and the first time they
|
|
12
|
-
* disagreed the registry would win over the package that shipped it.
|
|
13
|
-
*
|
|
14
|
-
* A site serving several versions installs several versions, which is the
|
|
15
|
-
* mechanism npm already provides and the only one that cannot drift.
|
|
16
|
-
*
|
|
17
|
-
* **Nothing about a page is written here.** `pages.generated.ts` is derived
|
|
18
|
-
* from each file's frontmatter by `turbo run docs`, because the frontmatter is
|
|
19
|
-
* what a `.md` consumer receives and a second copy would be a second source of
|
|
20
|
-
* truth. This module is the types and the reading of them; `sections.ts` is the
|
|
21
|
-
* spine that frontmatter has nowhere to live.
|
|
22
|
-
*/
|
|
23
1
|
import { docPages } from './pages.generated.js';
|
|
24
2
|
import { docSections } from './sections.js';
|
|
25
3
|
export { docPages as pages, docSections as sections };
|
|
26
4
|
export const findPage = (slug) => docPages.find((page) => page.slug === slug);
|
|
27
|
-
/** Case-insensitive, so `Tokens` and `tokens` do not sort into two groups. */
|
|
28
5
|
const byTitle = (a, b) => a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1;
|
|
29
|
-
/**
|
|
30
|
-
* The pages of one section, in the order a sidebar renders them.
|
|
31
|
-
*
|
|
32
|
-
* **Alphabetical, except a section that is a path, and except one pinned entry
|
|
33
|
-
* page where a section has one.** The exemption is the same one `AGENTS.md`
|
|
34
|
-
* grants positional arguments and middleware chains, that ordering is skipped
|
|
35
|
-
* where order is semantic. Written down so a section is not silently reordered
|
|
36
|
-
* by whoever next notices it is not alphabetical.
|
|
37
|
-
*/
|
|
38
6
|
const ordered = (pages, section) => {
|
|
39
7
|
if (section.path) {
|
|
40
8
|
return [...pages].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
|
@@ -43,17 +11,6 @@ const ordered = (pages, section) => {
|
|
|
43
11
|
const rest = pages.filter((page) => !page.pinned).sort(byTitle);
|
|
44
12
|
return [...pinned, ...rest];
|
|
45
13
|
};
|
|
46
|
-
/**
|
|
47
|
-
* The whole sidebar: every declared section, its pages in render order, and
|
|
48
|
-
* each page's children beneath it.
|
|
49
|
-
*
|
|
50
|
-
* A section with no pages cannot appear, because `turbo run docs -- --check` refuses
|
|
51
|
-
* to generate one. Children are alphabetical, because nesting exists for the
|
|
52
|
-
* per-framework installation pages and a reader picking their framework out of
|
|
53
|
-
* a list is looking one up rather than reading a sequence, and then the
|
|
54
|
-
* `trailing` ones, which are the pages that answer "none of the above" and
|
|
55
|
-
* which the alphabet was interleaving with the answers they follow from.
|
|
56
|
-
*/
|
|
57
14
|
export const navigation = () => docSections.map((section) => {
|
|
58
15
|
const own = docPages.filter((page) => page.section === section.title && page.parent === undefined);
|
|
59
16
|
return {
|
|
@@ -66,5 +23,4 @@ export const navigation = () => docSections.map((section) => {
|
|
|
66
23
|
})),
|
|
67
24
|
};
|
|
68
25
|
});
|
|
69
|
-
/** Path to a page's MDX, relative to the package root. */
|
|
70
26
|
export const contentPath = (page) => `content/${page.slug}.mdx`;
|
package/dist/sections.js
CHANGED
|
@@ -1,26 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The navigation's spine: which sections exist, in what order, and how each
|
|
3
|
-
* one orders the pages inside it.
|
|
4
|
-
*
|
|
5
|
-
* **Hand-authored, where the pages are not.** A page's own facts come from its
|
|
6
|
-
* frontmatter and are generated into `pages.generated.ts`, because the
|
|
7
|
-
* frontmatter is what a `.md` consumer actually receives and a second copy in
|
|
8
|
-
* a registry is a second source of truth. A section is not a page and has no
|
|
9
|
-
* frontmatter to derive from, so it is written here.
|
|
10
|
-
*
|
|
11
|
-
* **A section with no pages is not declared.** A navigation entry is the
|
|
12
|
-
* strongest existence claim a site can make, so a section is added with the
|
|
13
|
-
* pages that fill it rather than ahead of them. `turbo run docs -- --check` fails
|
|
14
|
-
* on an empty section rather than rendering a heading with nothing under it.
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* Every section, in the order the sidebar renders them.
|
|
18
|
-
*
|
|
19
|
-
* Deliberately an array rather than an alphabetized record: this is the one
|
|
20
|
-
* place where order is the content. Foundations sits above Theming because a
|
|
21
|
-
* reader needs the vocabulary before the thing that changes it, and no
|
|
22
|
-
* alphabetization expresses that.
|
|
23
|
-
*/
|
|
24
1
|
export const docSections = [
|
|
25
2
|
{ path: true, title: 'Getting started' },
|
|
26
3
|
{ title: 'Foundations' },
|
|
@@ -28,5 +5,4 @@ export const docSections = [
|
|
|
28
5
|
{ title: 'Essentials' },
|
|
29
6
|
{ title: 'Tooling' },
|
|
30
7
|
];
|
|
31
|
-
/** The section of a given name, if it is declared. */
|
|
32
8
|
export const findSection = (title) => docSections.find((section) => section.title === title);
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every page's MDX, inlined by `turbo run docs`. Do not edit: the files in
|
|
3
|
-
* `content/` are the source, and `turbo run docs -- --check` fails when this module
|
|
4
|
-
* and they disagree.
|
|
5
|
-
*/
|
|
6
1
|
export const docSources = {
|
|
7
2
|
accessibility: `---
|
|
8
3
|
description: What the library guarantees, what it cannot, and where the line is.
|
|
@@ -1918,10 +1913,10 @@ repository does that. The per-component tables are what a page pays.
|
|
|
1918
1913
|
| Package | Raw | Gzip | Brotli | |
|
|
1919
1914
|
|---|---|---|---|---|
|
|
1920
1915
|
| \`@fusion.dev/helix-core\` | 134,650 | 44,269 | 37,972 | Element base class, mixins, decorators, floating positioning. |
|
|
1921
|
-
| \`@fusion.dev/helix-headless\` | 519,
|
|
1916
|
+
| \`@fusion.dev/helix-headless\` | 519,154 | 131,672 | 103,150 | Every headless family, which is what the barrel means. |
|
|
1922
1917
|
| \`@fusion.dev/helix-icons\` | 47,484 | 14,907 | 12,553 | The whole glyph set. |
|
|
1923
1918
|
| \`@fusion.dev/helix-theme\` | 3,288 | 1,571 | 1,355 | The derivation engine. Build time for most consumers, runtime for a theme switcher. |
|
|
1924
|
-
| \`@fusion.dev/helix\` | 956,713 | 216,
|
|
1919
|
+
| \`@fusion.dev/helix\` | 956,713 | 216,820 | 158,985 | Every styled family. |
|
|
1925
1920
|
| \`lit\` | 15,394 | 6,118 | 5,460 | Not ours. Here so it can be subtracted from every row above it. |
|
|
1926
1921
|
|
|
1927
1922
|
## The stylesheets
|
|
@@ -1944,9 +1939,9 @@ is the whole cost of adopting the base layer on its own.
|
|
|
1944
1939
|
|
|
1945
1940
|
**Most of a first component is the runtime under it.** The median styled family is 13,974 bytes gzipped alone and adds 2,409 to a page that already has Helix on it, so 83 percent of the first one is shared and 17 percent is the component. Ten typical components are one plus nine additions rather than ten of the first number, and the pair of columns below is what lets that be worked out rather than guessed.
|
|
1946
1941
|
|
|
1947
|
-
Across the tier: the cheapest is \`code\` at 9,065 gzipped alone, the dearest \`data-table\` at 49,868, over 93 components. Every family at once is 216,
|
|
1942
|
+
Across the tier: the cheapest is \`code\` at 9,065 gzipped alone, the dearest \`data-table\` at 49,868, over 93 components. Every family at once is 216,820.
|
|
1948
1943
|
|
|
1949
|
-
**No family imports a barrel, and the \`barrels\` rule in \`fusion workspace\` is what keeps it that way.** \`@fusion.dev/helix-headless\` is \`sideEffects\` over every module in \`dist\`, which is true of a file that calls \`customElements.define\` and which means a bundler may drop none of it: one \`import { HelixHeadlessButton } from '@fusion.dev/helix-headless'\` costs 131,
|
|
1944
|
+
**No family imports a barrel, and the \`barrels\` rule in \`fusion workspace\` is what keeps it that way.** \`@fusion.dev/helix-headless\` is \`sideEffects\` over every module in \`dist\`, which is true of a file that calls \`customElements.define\` and which means a bundler may drop none of it: one \`import { HelixHeadlessButton } from '@fusion.dev/helix-headless'\` costs 131,672 bytes gzipped whatever else the page does, which is 9 times the median family measured above. The styled tier imports the family it extends instead, all 93 of them, and the check refuses the shape rather than the package name, so the rule follows \`sideEffects\` wherever it goes.
|
|
1950
1945
|
|
|
1951
1946
|
The headless tier never had the problem, and it is the control: \`@fusion.dev/helix-core\` is \`sideEffects: false\`, and a headless family is a median of 16,187 bytes gzipped alone.
|
|
1952
1947
|
|
|
@@ -1985,7 +1980,7 @@ Four other libraries of custom elements, pinned and measured on 2026-08-24 by \`
|
|
|
1985
1980
|
| | Material Web | 50,155 | 14,577 | 12,935 |
|
|
1986
1981
|
| | Shoelace | 37,833 | 11,814 | 10,568 |
|
|
1987
1982
|
| | Spectrum | 62,322 | 15,059 | 13,321 |
|
|
1988
|
-
| \`tabs\` | **Helix** | 40,196 | 12,
|
|
1983
|
+
| \`tabs\` | **Helix** | 40,196 | 12,348 | 10,882 |
|
|
1989
1984
|
| | Carbon | 578,766 | 73,537 | 43,235 |
|
|
1990
1985
|
| | Material Web | 38,883 | 12,820 | 11,368 |
|
|
1991
1986
|
| | Shoelace | 54,573 | 17,140 | 15,068 |
|
|
@@ -2113,7 +2108,7 @@ Structure, accessibility, state and form participation. No presentation, and no
|
|
|
2113
2108
|
| \`steps\` | 82,900 | 27,205 | 22,347 | 6,303 | 1,832 | 1,249 |
|
|
2114
2109
|
| \`switch\` | 34,314 | 11,106 | 9,826 | 1,798 | 832 | 358 |
|
|
2115
2110
|
| \`table\` | 31,861 | 10,274 | 9,086 | 4,373 | 1,299 | 831 |
|
|
2116
|
-
| \`tabs\` | 33,935 | 11,
|
|
2111
|
+
| \`tabs\` | 33,935 | 11,060 | 9,721 | 4,469 | 1,277 | 735 |
|
|
2117
2112
|
| \`tag\` | 74,439 | 24,760 | 20,435 | 897 | 464 | 219 |
|
|
2118
2113
|
| \`textarea\` | 37,001 | 11,743 | 10,362 | 4,115 | 1,414 | 884 |
|
|
2119
2114
|
| \`time-input\` | 136,201 | 43,547 | 36,687 | 28,643 | 7,661 | 6,120 |
|
|
@@ -2212,7 +2207,7 @@ The headless tier plus presentation. This is what \`bun add @fusion.dev/helix\`
|
|
|
2212
2207
|
| \`steps\` | 96,252 | 29,575 | 24,410 | 19,643 | 4,202 | 3,353 |
|
|
2213
2208
|
| \`switch\` | 38,603 | 12,160 | 10,668 | 6,072 | 1,891 | 1,318 |
|
|
2214
2209
|
| \`table\` | 35,190 | 10,865 | 9,580 | 7,692 | 1,916 | 1,378 |
|
|
2215
|
-
| \`tabs\` | 40,196 | 12,
|
|
2210
|
+
| \`tabs\` | 40,196 | 12,348 | 10,882 | 10,719 | 2,597 | 1,971 |
|
|
2216
2211
|
| \`tag\` | 77,633 | 25,634 | 21,148 | 4,076 | 1,245 | 995 |
|
|
2217
2212
|
| \`text\` | 29,734 | 9,670 | 8,508 | 3,922 | 958 | 605 |
|
|
2218
2213
|
| \`textarea\` | 40,350 | 12,544 | 11,034 | 7,447 | 2,227 | 1,615 |
|
|
@@ -2240,12 +2235,12 @@ column is what was removed rather than part of what remains.
|
|
|
2240
2235
|
|
|
2241
2236
|
| Package | Unpacked | Files | Source maps stripped | Runtime dependencies |
|
|
2242
2237
|
|---|---|---|---|---|
|
|
2243
|
-
| \`@fusion.dev/helix-core\` |
|
|
2244
|
-
| \`@fusion.dev/helix-headless\` |
|
|
2245
|
-
| \`@fusion.dev/helix-icons\` |
|
|
2238
|
+
| \`@fusion.dev/helix-core\` | 655,135 | 113 | 154,658 | \`@floating-ui/dom\`, \`@fusion.dev/helix-icons\` |
|
|
2239
|
+
| \`@fusion.dev/helix-headless\` | 8,636,163 | 422 | 699,239 | \`@fusion.dev/helix-core\`, \`@fusion.dev/helix-icons\`, \`uqr\` |
|
|
2240
|
+
| \`@fusion.dev/helix-icons\` | 65,943 | 11 | 20,928 | none |
|
|
2246
2241
|
| \`@fusion.dev/helix-styles\` | 83,277 | 5 | 0 | none |
|
|
2247
|
-
| \`@fusion.dev/helix-theme\` |
|
|
2248
|
-
| \`@fusion.dev/helix\` | 9,
|
|
2242
|
+
| \`@fusion.dev/helix-theme\` | 461,551 | 8 | 4,699 | none |
|
|
2243
|
+
| \`@fusion.dev/helix\` | 9,306,931 | 718 | 278,170 | \`@fusion.dev/helix-core\`, \`@fusion.dev/helix-headless\`, \`@fusion.dev/helix-styles\` |
|
|
2249
2244
|
|
|
2250
2245
|
## Not measured yet
|
|
2251
2246
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusion.dev/helix-docs",
|
|
3
3
|
"description": "Versioned documentation content and registry for Helix.",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ross Sheppard <ross.sheppard@fusion.dev>",
|
|
7
7
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
],
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"scripts": {
|
|
28
|
-
"build": "tsc -p tsconfig.json",
|
|
28
|
+
"build": "tsc -p tsconfig.json && tsc -p tsconfig.types.json",
|
|
29
29
|
"docs": "node scripts/build-docs.mjs",
|
|
30
30
|
"peers": "bun scripts/build-peers.mjs",
|
|
31
31
|
"test": "bun test src",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"bugs": "https://github.com/project-fusion/fusion/issues",
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@fusion.dev/helix-cem": "0.
|
|
37
|
+
"@fusion.dev/helix-cem": "0.3.0",
|
|
38
38
|
"@fusion.dev/scripts": "0.0.0-dev"
|
|
39
39
|
},
|
|
40
40
|
"homepage": "https://fusion.dev",
|