@mildastudio/milda 0.1.0 → 0.2.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.
@@ -0,0 +1,1485 @@
1
+ type Id = string;
2
+ interface TypeRef {
3
+ kind: 'ref';
4
+ ref: Id;
5
+ }
6
+ type TypeExpr = {
7
+ kind: 'string';
8
+ } | {
9
+ kind: 'number';
10
+ min?: number;
11
+ max?: number;
12
+ } | {
13
+ kind: 'boolean';
14
+ } | {
15
+ kind: 'enum';
16
+ values: string[];
17
+ } | {
18
+ kind: 'context';
19
+ group: Id;
20
+ } | {
21
+ kind: 'union';
22
+ members: TypeExpr[];
23
+ } | TypeRef | {
24
+ kind: 'array';
25
+ item: TypeExpr;
26
+ } | {
27
+ kind: 'object';
28
+ fields: ObjectField[];
29
+ } | {
30
+ kind: 'component';
31
+ componentIds?: Id[];
32
+ };
33
+ interface ObjectField {
34
+ id: Id;
35
+ name: string;
36
+ type: TypeExpr;
37
+ required: boolean;
38
+ description?: string;
39
+ }
40
+ type PropValue = string | number | boolean | PropValue[] | {
41
+ [key: string]: PropValue;
42
+ };
43
+ type Metadata = Record<string, PropValue>;
44
+ interface SharedType {
45
+ id: Id;
46
+ name: string;
47
+ description?: string;
48
+ definition: TypeExpr;
49
+ }
50
+ type ParamBinding = {
51
+ prop: Id;
52
+ } | {
53
+ static: PropValue;
54
+ };
55
+ interface DocumentMeta {
56
+ id: Id;
57
+ name: string;
58
+ version: string;
59
+ description?: string;
60
+ createdAt?: string;
61
+ updatedAt?: string;
62
+ }
63
+ type DocumentKind = 'prelude' | 'design-system';
64
+ interface MildaDocumentBase {
65
+ milda: string;
66
+ kind: DocumentKind;
67
+ prelude: string;
68
+ meta: DocumentMeta;
69
+ }
70
+ interface TokenRef {
71
+ ref: Id;
72
+ }
73
+ type PrimitiveTokenType = 'color' | 'spacing' | 'radius' | 'size' | 'shadow' | 'typography' | 'fontFamily' | 'fontWeight' | 'duration' | 'opacity' | 'blur' | 'tonal' | 'border' | 'lineHeight' | 'easing' | 'gradient' | 'fontSize' | 'letterSpacing';
74
+ type FacetTokenType = 'elevation' | 'ring' | 'backdrop' | 'none';
75
+ type TokenType = PrimitiveTokenType | FacetTokenType;
76
+ type ColorSpace = 'srgb' | 'display-p3' | 'oklch' | 'hsl';
77
+ interface ColorValue {
78
+ space: ColorSpace;
79
+ channels: number[];
80
+ alpha?: number;
81
+ }
82
+ /**
83
+ * The neutral length units (0038). `fixed` is a density-independent length (CSS px,
84
+ * Android dp, iOS pt, Figma px); `scaled` is a multiple of the user's text size (CSS
85
+ * rem, Android sp, iOS Dynamic Type). The surface spells them `12px` and `scaled(12)`;
86
+ * `dp`/`sp`/`rem` are read as synonyms but never emitted.
87
+ */
88
+ type DimensionUnit = 'scaled' | 'fixed' | 'percent' | 'em';
89
+ interface DimensionValue {
90
+ value: number;
91
+ unit: DimensionUnit;
92
+ }
93
+ /**
94
+ * A length that is an INTENT rather than a measurement (0038). `pill` is "fully
95
+ * rounded": on the web it lowers to a large px radius, on iOS to a capsule, on Android
96
+ * to a circle shape, in Figma to a clamped corner radius. Spelling it as a keyword is
97
+ * what lets each target lower it correctly instead of pattern-matching `9999px`.
98
+ */
99
+ type LengthKeyword = 'pill';
100
+ interface LengthKeywordValue {
101
+ keyword: LengthKeyword;
102
+ }
103
+ type LengthValue = DimensionValue | LengthKeywordValue;
104
+ type ColorOrRef = ColorValue | TokenRef;
105
+ type DimensionOrRef = DimensionValue | TokenRef;
106
+ interface ShadowLayer {
107
+ offsetX: DimensionValue;
108
+ offsetY: DimensionValue;
109
+ blur: DimensionValue;
110
+ spread: DimensionValue;
111
+ color: ColorOrRef;
112
+ inset: boolean;
113
+ }
114
+ interface ShadowValue {
115
+ layers: ShadowLayer[];
116
+ }
117
+ type FontCategory = 'sans' | 'serif' | 'mono' | 'display';
118
+ /**
119
+ * Where the face comes from (added 2026-08-06 with the fontFamily token surface).
120
+ *
121
+ * Without it a family read back from a file could only ever be "some family called Inter":
122
+ * whether it is a platform stack, a bundled Google Font (and under which licence), or a file
123
+ * the project uploaded is exactly what a generator has to know to EMIT it - a @font-face, a
124
+ * stylesheet link, or nothing at all. Optional, so every existing document stays valid and is
125
+ * read as a plain named family.
126
+ */
127
+ type FontProvenance = {
128
+ kind: 'system';
129
+ } | {
130
+ kind: 'google';
131
+ license?: string;
132
+ } | {
133
+ kind: 'custom';
134
+ };
135
+ interface FontFamilyValue {
136
+ /** The family name, or - for a system face - the platform stack itself. */
137
+ family: string;
138
+ fallback: string[];
139
+ category: FontCategory;
140
+ assetId?: Id | null;
141
+ source?: FontProvenance;
142
+ }
143
+ interface FontWeightValue {
144
+ weight: number;
145
+ }
146
+ interface TypographyValue {
147
+ family: TokenRef | FontFamilyValue;
148
+ size: DimensionValue;
149
+ weight: number;
150
+ lineHeight: DimensionValue | {
151
+ ratio: number;
152
+ };
153
+ letterSpacing: DimensionValue;
154
+ italic?: boolean;
155
+ uppercase?: boolean;
156
+ }
157
+ interface DurationValue {
158
+ ms: number;
159
+ }
160
+ interface OpacityValue {
161
+ value: number;
162
+ }
163
+ interface BlurValue {
164
+ radius: DimensionValue;
165
+ }
166
+ interface TonalValue {
167
+ level: number;
168
+ }
169
+ type BorderWidth = 'hairline' | 'thin' | 'thick' | DimensionValue;
170
+ type BorderStyle = 'solid' | 'dashed' | 'dotted' | 'none';
171
+ interface BorderValue {
172
+ width: BorderWidth;
173
+ style: BorderStyle;
174
+ color: ColorOrRef;
175
+ }
176
+ interface NoneValue {
177
+ none: true;
178
+ }
179
+ interface RatioValue {
180
+ value: number;
181
+ }
182
+ interface EasingValue {
183
+ keyword?: string;
184
+ cubicBezier?: [number, number, number, number];
185
+ css?: string;
186
+ }
187
+ interface GradientValue {
188
+ css: string;
189
+ }
190
+ interface TokenValueSchemaByType {
191
+ color: ColorValue;
192
+ spacing: DimensionValue;
193
+ radius: LengthValue;
194
+ size: DimensionValue;
195
+ shadow: ShadowValue;
196
+ typography: TypographyValue;
197
+ fontFamily: FontFamilyValue;
198
+ fontWeight: FontWeightValue;
199
+ duration: DurationValue;
200
+ opacity: OpacityValue;
201
+ blur: BlurValue;
202
+ tonal: TonalValue;
203
+ border: BorderValue;
204
+ fontSize: DimensionValue;
205
+ letterSpacing: DimensionValue;
206
+ lineHeight: RatioValue;
207
+ easing: EasingValue;
208
+ gradient: GradientValue;
209
+ elevation: NoneValue;
210
+ ring: NoneValue;
211
+ backdrop: NoneValue;
212
+ none: NoneValue;
213
+ }
214
+ type AnyTokenValue = TokenValueSchemaByType[TokenType];
215
+ interface RawTokenValue<T extends TokenType = TokenType> {
216
+ kind: 'raw';
217
+ value: TokenValueSchemaByType[T];
218
+ }
219
+ interface AliasTokenValue {
220
+ kind: 'alias';
221
+ by: Id;
222
+ refs: Record<string, Id>;
223
+ }
224
+ interface EscapeTokenValue {
225
+ kind: 'escape';
226
+ raw: string;
227
+ note?: string;
228
+ }
229
+ /**
230
+ * Which space a computed COLOUR does its maths in.
231
+ *
232
+ * Wider than `ColorSpace` on purpose: that type is about how a colour LITERAL is spelled, and
233
+ * the surface can only spell four. A perceptual space like Oklab is a legitimate place to do
234
+ * the arithmetic even though no literal is written in it, so narrowing this to ColorSpace
235
+ * would silently move a token's maths to a different space on the way through the file.
236
+ */
237
+ type ComputeSpace = 'srgb' | 'display-p3' | 'oklch' | 'hsl' | 'oklab' | 'lab' | 'lch';
238
+ /**
239
+ * One step of a computed value. Two vocabularies in one union, exactly as the IR has them:
240
+ * a colour is lightened and mixed, a measurement is scaled and rounded. Which one applies
241
+ * follows the TOKEN'S TYPE, not a discriminant here.
242
+ *
243
+ * Amounts are 0..1 fractions (the surface writes them as percentages), `degrees` is a hue
244
+ * rotation, and `delta` / `to` are density-independent pixels - the neutral unit, so a step
245
+ * means the same thing on every platform.
246
+ */
247
+ type ComputeOp = {
248
+ op: 'lighten' | 'darken' | 'saturate' | 'desaturate' | 'alpha';
249
+ amount: number;
250
+ } | {
251
+ op: 'rotate';
252
+ degrees: number;
253
+ } | {
254
+ op: 'mix';
255
+ with: Id;
256
+ amount: number;
257
+ } | {
258
+ op: 'scale';
259
+ factor: number;
260
+ } | {
261
+ op: 'offset';
262
+ delta: number;
263
+ } | {
264
+ op: 'round';
265
+ to: number;
266
+ };
267
+ /**
268
+ * A value DERIVED from another token: "the accent, 20% lighter", "the body size × 1.25".
269
+ *
270
+ * `base` and a `mix` operand are token IDS, like an alias's `refs` - and for the same reason:
271
+ * the canonical AST names tokens, it does not embed anonymous values. An inline literal
272
+ * written in either position is hoisted to a synthesized token by the parser (and printed
273
+ * back as the literal by the emitter), which is the mechanism alias slots already use.
274
+ */
275
+ interface ComputeTokenValue {
276
+ kind: 'compute';
277
+ base: Id;
278
+ ops: ComputeOp[];
279
+ /** Colour only; absent means the IR's own default (OKLCH). */
280
+ space?: ComputeSpace;
281
+ }
282
+ type TokenValue<T extends TokenType = TokenType> = RawTokenValue<T> | AliasTokenValue | EscapeTokenValue | ComputeTokenValue;
283
+ interface Token$1<T extends TokenType = TokenType> {
284
+ id: Id;
285
+ name: string;
286
+ type: T;
287
+ value: TokenValue<T>;
288
+ description?: string;
289
+ }
290
+ interface Layer {
291
+ id: Id;
292
+ name: string;
293
+ order: number;
294
+ tokens: Token$1[];
295
+ }
296
+ interface Context {
297
+ id: Id;
298
+ name: string;
299
+ }
300
+ interface ContextGroup {
301
+ id: Id;
302
+ name: string;
303
+ contexts: Context[];
304
+ }
305
+ declare const TOKEN_VALUE_KIND: Record<TokenType, 'color' | 'dimension' | 'shadow' | 'typography' | 'fontFamily' | 'fontWeight' | 'duration' | 'opacity' | 'blur' | 'tonal' | 'border' | 'ratio' | 'easing' | 'gradient' | 'facet'>;
306
+ /** What a part IS. Neutral by design - the platform element is a target decision. */
307
+ declare const NODE_KINDS: readonly string[];
308
+ /** Where a part came from: the archetype, or the author. */
309
+ declare const NODE_ORIGINS: readonly string[];
310
+ /** The interactions an emission (or a demo action) can fire on. */
311
+ declare const INTERACTION_KINDS: readonly string[];
312
+ /** Control realization (0016) and group realization (0022). */
313
+ declare const CONTROL_REALIZATIONS: readonly string[];
314
+ declare const GROUP_REALIZATIONS: readonly string[];
315
+ /** Presentation intent (0022 §8), surface-spelled. */
316
+ declare const PRESENTATION_KINDS: readonly string[];
317
+ /** A media part's type (0028). */
318
+ declare const MEDIA_TYPES: readonly string[];
319
+ /** A table cell's role. */
320
+ declare const CELL_MODIFIERS: readonly string[];
321
+ /** The modifiers a `slot` statement accepts after its arity and content spec. */
322
+ declare const SLOT_MODIFIERS: readonly string[];
323
+ /** The structural roles a slot can play in a disclosure. */
324
+ declare const SLOT_ROLES: readonly string[];
325
+ /** How a behaviour/config field's value is read. `node`/`nodes` name a part BY PATH. */
326
+ type FieldType = 'string' | 'number' | 'boolean' | 'node' | 'nodes';
327
+ declare const BEHAVIOR_FIELDS: Readonly<Record<string, Readonly<Record<string, FieldType>>>>;
328
+ /** The behaviour kinds, in the surface's kebab spelling (`focus-trap`). */
329
+ declare const BEHAVIOR_KINDS: readonly string[];
330
+ type ConfigFieldSpec = {
331
+ kind: 'boolean';
332
+ } | {
333
+ kind: 'number';
334
+ } | {
335
+ kind: 'numbers';
336
+ } | {
337
+ kind: 'enum';
338
+ values: readonly string[];
339
+ } | {
340
+ kind: 'enums';
341
+ values: readonly string[];
342
+ };
343
+ interface ConfigSurface {
344
+ /** The node field this block configures. */
345
+ field: string;
346
+ fields: Readonly<Record<string, ConfigFieldSpec>>;
347
+ /** True for a single-valued surface written `severity danger` rather than as a block. */
348
+ single?: boolean;
349
+ }
350
+ declare const PART_CONFIGS: Readonly<Record<string, ConfigSurface>>;
351
+ /** The block-shaped config surfaces - read as a config only when a `{` follows the word,
352
+ * which is what keeps `overlay { … }` apart from the `overlay` paint facet. */
353
+ declare const PART_CONFIG_NAMES: ReadonlySet<string>;
354
+ /** The single-valued config surfaces (`severity danger`). */
355
+ declare const PART_CONFIG_WORDS: readonly string[];
356
+ /** The prose blocks, whose keyword IS their kind. */
357
+ declare const DOC_PROSE_KINDS: readonly string[];
358
+ /** The transclusion blocks - each names what it shows, by name. */
359
+ declare const DOC_TRANSCLUSIONS: readonly string[];
360
+ declare const DOC_BLOCK_KEYWORDS: readonly string[];
361
+ /** Statement keywords inside `docs { … }` and inside a `page { … }`'s header. */
362
+ declare const DOCS_KEYWORDS: readonly string[];
363
+ declare const DOCS_SITE_KEYS: readonly string[];
364
+ declare const DOCS_FOOTER_KEYWORDS: readonly string[];
365
+ declare const ASSET_KINDS: readonly string[];
366
+ /** The fields every asset carries, whatever its kind. `url`/`data` are the two shapes the
367
+ * bytes can take: beside the file, or in it. */
368
+ declare const ASSET_BASE_KEYS: readonly string[];
369
+ /** Per-kind metadata, validated on lowering. */
370
+ declare const ASSET_FIELDS: Readonly<Record<string, Readonly<Record<string, FieldType | 'strings'>>>>;
371
+ /** The value each asset kind's fields take, in the surface's kebab spelling. */
372
+ declare const ASSET_FIELD_KEYS: Readonly<Record<string, readonly string[]>>;
373
+ interface LiteralChannel {
374
+ /** The channel's name, as the docs and the argument hint call it. */
375
+ name: string;
376
+ /** What it accepts, in one phrase. */
377
+ hint: string;
378
+ /** An in-range value, for a pre-filled call. */
379
+ sample: string;
380
+ }
381
+ interface LiteralFnSpec {
382
+ channels: readonly LiteralChannel[];
383
+ /** Whether a trailing alpha is accepted (`… / 50%`, or a bare fourth channel). */
384
+ alpha: boolean;
385
+ /** One line on what the function is. */
386
+ doc: string;
387
+ }
388
+ declare const VALUE_LITERAL_FNS: Readonly<Record<string, LiteralFnSpec>>;
389
+ /** The colour-space literals, in the order a picker should offer them. */
390
+ declare const COLOR_LITERAL_FNS: readonly string[];
391
+ /**
392
+ * Spellings a reader accepts for a function it already has. In CSS Color 4 `rgba`/`hsla` ARE
393
+ * `rgb`/`hsl` - the alpha is a fourth channel either way - and someone coming from CSS writes
394
+ * the four-letter name without thinking about it. Read, never offered, never written: the
395
+ * canonical name is the target. (The same treatment `rem`/`dp`/`sp` get on the length side.)
396
+ */
397
+ declare const COLOR_LITERAL_ALIASES: Readonly<Record<string, string>>;
398
+ /** Every spelling of a colour function the reader accepts - the canonical ones and the aliases.
399
+ * What a highlighter needs: `rgba(1 0 0 / 0.5)` is a colour literal, so its payload is a value
400
+ * and not four identifiers. */
401
+ declare const COLOR_LITERAL_SPELLINGS: readonly string[];
402
+ /** Colour words that name a value rather than a token. `transparent` is the absence of a colour,
403
+ * which every platform has a spelling for; the Studio seeds one (a tab's resting border). */
404
+ declare const COLOR_KEYWORDS: readonly string[];
405
+ /** The length-valued literals (0038). */
406
+ declare const LENGTH_LITERAL_FNS: readonly string[];
407
+ /** What a stack's children flow along. `layers` draws them on top of each other. */
408
+ declare const LAYOUT_DIRECTIONS: readonly ['row', 'column', 'layers'];
409
+ type LayoutDirection = (typeof LAYOUT_DIRECTIONS)[number];
410
+ /** Cross-axis placement (vertical in a `layers` stack). */
411
+ declare const LAYOUT_ALIGNS: readonly ['start', 'center', 'end', 'stretch', 'baseline'];
412
+ type LayoutAlign = (typeof LAYOUT_ALIGNS)[number];
413
+ /** Main-axis placement (horizontal in a `layers` stack). */
414
+ declare const LAYOUT_DISTRIBUTES: readonly ['start', 'center', 'end', 'between', 'around', 'evenly'];
415
+ type LayoutDistribute = (typeof LAYOUT_DISTRIBUTES)[number];
416
+ declare const LAYOUT_WRAPS: readonly ['nowrap', 'wrap', 'wrap-reverse'];
417
+ type LayoutWrap = (typeof LAYOUT_WRAPS)[number];
418
+ /** How one axis of a part is sized (PRELUDE §4 "child sizing"). `weight`, `fixed` and `ratio`
419
+ * take an argument: `weight(2)`, `fixed(size.md)`, `ratio(16:9)`. */
420
+ declare const AXIS_INTENTS: readonly ['fit', 'fill', 'weight', 'fixed', 'ratio'];
421
+ type AxisIntentKind = (typeof AXIS_INTENTS)[number];
422
+ /** The clamps an axis intent may be followed by: `min(size.sm)`, `max(size.lg)`. */
423
+ declare const AXIS_CLAMPS: readonly ['min', 'max'];
424
+ /** Where a part sits relative to the flow. `pinned` and `bleed` take logical edges. */
425
+ declare const POSITION_KINDS: readonly ['flow', 'overlay', 'pinned', 'bleed'];
426
+ type PositionKind = (typeof POSITION_KINDS)[number];
427
+ /** Logical edges, so a design system reads the same in a right-to-left locale. */
428
+ declare const LOGICAL_EDGES: readonly ['block-start', 'block-end', 'inline-start', 'inline-end', 'block', 'inline', 'all'];
429
+ type LogicalEdge = (typeof LOGICAL_EDGES)[number];
430
+ /** The physical edge words the parser used to take, read as the logical edge each names in a
431
+ * horizontal left-to-right system. Read, never offered, never written - the `rgba` treatment. */
432
+ declare const PHYSICAL_EDGE_ALIASES: Readonly<Record<string, LogicalEdge>>;
433
+ /** The keys of the editor's layout record (`node.layout`), whose values are the words above:
434
+ * a direction, an alignment, a distribution, a wrap, an axis intent spelled as the surface
435
+ * spells it (`fill`, `weight(2)`, `ratio(16:9)`, a size token or a length), a clamp as a size
436
+ * token or a length, and a position as its surface words (`overlay`, `pinned block-start`). */
437
+ declare const LAYOUT_RECORD_KEYS: readonly ['direction', 'align', 'distribute', 'wrap', 'width', 'height', 'widthMin', 'widthMax', 'heightMin', 'heightMax', 'position'];
438
+ type LayoutRecordKey = (typeof LAYOUT_RECORD_KEYS)[number];
439
+ declare const EXAMPLE_KEYWORDS: readonly string[];
440
+ declare const DEMO_ACTION_OPS: readonly string[];
441
+ declare function kebab(s: string): string;
442
+ /** A surface kebab key → the IR's camelCase field (`week-starts-on` → `weekStartsOn`). */
443
+ declare function camelField(s: string): string;
444
+ declare const MILDA_SURFACE_VERSION = "0.8";
445
+ declare const PRELUDE_VERSION = "0.0.2";
446
+ type FacetName = 'fill' | 'ink' | 'border' | 'border.top' | 'border.right' | 'border.bottom' | 'border.left' | 'border.inline-start' | 'border.inline-end' | 'border.block-start' | 'border.block-end' | 'corner' | 'inset' | 'gap' | 'text' | 'textClamp' | 'textWrap' | 'weight' | 'font' | 'slant' | 'elevation' | 'overlay' | 'opacity' | 'ring' | 'backdrop';
447
+ type InsetValue = {
448
+ block?: Id;
449
+ inline?: Id;
450
+ } | {
451
+ top?: Id;
452
+ right?: Id;
453
+ bottom?: Id;
454
+ left?: Id;
455
+ } | {
456
+ all: Id;
457
+ };
458
+ type BorderFacetStyle = 'solid' | 'dashed' | 'dotted';
459
+ interface BorderFacetValue {
460
+ width?: Id;
461
+ color?: Id;
462
+ style?: BorderFacetStyle;
463
+ }
464
+ type FacetValue = {
465
+ token: Id;
466
+ } | {
467
+ literal: string | number | boolean;
468
+ } | {
469
+ inset: InsetValue;
470
+ } | {
471
+ border: BorderFacetValue;
472
+ } | {
473
+ raw: string;
474
+ };
475
+ type FacetMap = Partial<Record<FacetName, FacetValue>>;
476
+ type StackAxis = LayoutDirection;
477
+ type AxisIntent = 'fit' | 'fill' | {
478
+ weight: number;
479
+ } | {
480
+ fixed: Id;
481
+ } | {
482
+ ratio: {
483
+ w: number;
484
+ h: number;
485
+ };
486
+ };
487
+ interface AxisSize {
488
+ intent: AxisIntent;
489
+ min?: Id;
490
+ max?: Id;
491
+ }
492
+ type AxisSizeValue = AxisIntent | AxisSize;
493
+ type Distribute = LayoutDistribute;
494
+ type Align = LayoutAlign;
495
+ /** `pinned` and `bleed` name LOGICAL edges (PRELUDE §4, proposal 0003 §2a). */
496
+ type Position = 'flow' | 'overlay' | {
497
+ pinned: LogicalEdge[];
498
+ } | {
499
+ bleed: LogicalEdge[];
500
+ };
501
+ interface LayoutSpec {
502
+ stack?: StackAxis;
503
+ /** Reserved: read and reported, with no target yet (0056 §3.3). */
504
+ grid?: {
505
+ cols: number;
506
+ rows?: number;
507
+ };
508
+ /** The `flow` key, an alias of `wrap wrap` (0003 §2b). Read, never written. */
509
+ flow?: boolean;
510
+ wrap?: LayoutWrap;
511
+ gap?: Id;
512
+ inset?: InsetValue;
513
+ distribute?: Distribute;
514
+ align?: Align;
515
+ size?: {
516
+ width?: AxisSizeValue;
517
+ height?: AxisSizeValue;
518
+ };
519
+ position?: Position;
520
+ }
521
+ type StateName = 'pressed' | 'hovered' | 'focused' | 'active' | 'selected' | 'checked' | 'expanded' | 'open' | 'disabled' | 'readonly' | 'loading' | 'error' | 'success' | 'invalid' | 'valid' | 'indeterminate' | 'dragging' | 'empty' | 'complete' | 'first' | 'last' | 'odd' | 'even';
522
+ type Capability = 'input.keyboard' | 'input.pointer' | 'input.touch' | 'input.remote' | 'input.voice' | 'motion.haptic' | 'runtime.dynamic-color' | 'display.density' | 'a11y.screenreader' | 'platform.web' | 'platform.ios' | 'platform.android' | 'platform.tvos';
523
+ interface AtomParam {
524
+ name: string;
525
+ bind?: boolean;
526
+ }
527
+ interface AtomContextVar {
528
+ name: string;
529
+ type?: string;
530
+ init?: string;
531
+ }
532
+ interface AtomStateNode {
533
+ id: string;
534
+ initial?: boolean;
535
+ }
536
+ interface AtomEvent {
537
+ name: string;
538
+ args?: string[];
539
+ }
540
+ interface Emit {
541
+ event: string;
542
+ arg?: string | boolean | number;
543
+ }
544
+ interface Assignment {
545
+ target: string;
546
+ expr: string;
547
+ }
548
+ type TransitionTarget = string | {
549
+ expr: string;
550
+ };
551
+ interface Transition {
552
+ from: string;
553
+ on?: string;
554
+ after?: string;
555
+ when?: string;
556
+ to?: TransitionTarget;
557
+ ctx?: Assignment[];
558
+ emit?: Emit;
559
+ do?: string;
560
+ note?: string;
561
+ }
562
+ interface Expose {
563
+ state: string;
564
+ when: string;
565
+ arg?: string;
566
+ }
567
+ interface RequiresClause {
568
+ anyOf: Capability[];
569
+ when?: string;
570
+ }
571
+ interface Atom {
572
+ kind: 'atom';
573
+ name: string;
574
+ doc?: string;
575
+ requires?: RequiresClause[];
576
+ params?: AtomParam[];
577
+ context?: AtomContextVar[];
578
+ states?: AtomStateNode[];
579
+ events?: AtomEvent[];
580
+ transitions: Transition[];
581
+ exposes?: Expose[];
582
+ emits?: {
583
+ name: string;
584
+ }[];
585
+ modes?: string[];
586
+ note?: string;
587
+ }
588
+ type CoordEntry = {
589
+ kind: 'wire';
590
+ from: string;
591
+ to: string;
592
+ arg?: string;
593
+ when?: string;
594
+ } | {
595
+ kind: 'gate';
596
+ machine: string;
597
+ activeWhen: string;
598
+ } | {
599
+ kind: 'broadcast';
600
+ set: string;
601
+ event: string;
602
+ } | {
603
+ kind: 'aggregate';
604
+ op: 'all' | 'any' | 'count' | 'first';
605
+ set: string;
606
+ pred: string;
607
+ as?: string;
608
+ then?: string;
609
+ } | {
610
+ kind: 'arena';
611
+ over: string[];
612
+ exclusive: boolean;
613
+ } | {
614
+ kind: 'requiresFail';
615
+ gesture: string;
616
+ failsAfter: string;
617
+ };
618
+ interface UsesClause {
619
+ atom: string;
620
+ as: string;
621
+ params?: Record<string, string>;
622
+ }
623
+ interface CompositeBehavior {
624
+ kind: 'composite';
625
+ name: string;
626
+ builtFrom: string[];
627
+ uses?: UsesClause[];
628
+ composition?: CoordEntry[];
629
+ emits?: {
630
+ name: string;
631
+ }[];
632
+ note?: string;
633
+ }
634
+ type ArchetypeGroup = 'Actions' | 'Inputs' | 'Disclosure' | 'Navigation' | 'Collections' | 'Feedback' | 'Media';
635
+ interface ContentCategory {
636
+ level: 'phrase' | 'region';
637
+ interactive: boolean;
638
+ }
639
+ interface ArchetypeRealize {
640
+ target: string;
641
+ when?: string;
642
+ surface?: string;
643
+ browse?: string;
644
+ commit?: 'explicit' | 'continuous';
645
+ drop?: string[];
646
+ wire?: {
647
+ from: string;
648
+ to: string;
649
+ arg?: string;
650
+ }[];
651
+ note?: string;
652
+ }
653
+ type PartRole = 'container' | 'item' | 'text' | 'control' | 'input' | 'icon' | 'content';
654
+ interface AnatomyPart {
655
+ name: string;
656
+ role: PartRole;
657
+ optional?: boolean;
658
+ children?: AnatomyPart[];
659
+ }
660
+ interface ArchetypeDef {
661
+ kind: 'archetype';
662
+ name: string;
663
+ group: ArchetypeGroup;
664
+ contract: string;
665
+ produces: ContentCategory;
666
+ anatomy?: AnatomyPart[];
667
+ composes: string[];
668
+ uses?: UsesClause[];
669
+ composition?: CoordEntry[];
670
+ exposes?: Expose[];
671
+ emits?: {
672
+ name: string;
673
+ from?: string;
674
+ }[];
675
+ realize?: ArchetypeRealize[];
676
+ realizationNote?: string;
677
+ }
678
+ interface FacetDef {
679
+ name: FacetName;
680
+ covers: string;
681
+ divergence?: string;
682
+ }
683
+ interface StateDef {
684
+ name: StateName;
685
+ from: string;
686
+ }
687
+ interface CapabilityDef {
688
+ name: Capability;
689
+ note?: string;
690
+ status?: 'aspirational';
691
+ }
692
+ interface TaxonomyNote {
693
+ name: string;
694
+ note: string;
695
+ }
696
+ interface PreludeDocument extends MildaDocumentBase {
697
+ kind: 'prelude';
698
+ atoms: Atom[];
699
+ composites: CompositeBehavior[];
700
+ archetypes: ArchetypeDef[];
701
+ facets: FacetDef[];
702
+ states: StateDef[];
703
+ capabilities: CapabilityDef[];
704
+ decorations: TaxonomyNote[];
705
+ nonBehaviors: TaxonomyNote[];
706
+ }
707
+ interface PropDef {
708
+ id: Id;
709
+ name: string;
710
+ type: TypeExpr;
711
+ default?: PropValue;
712
+ required?: boolean;
713
+ requiredWhen?: Predicate;
714
+ description?: string;
715
+ global?: true;
716
+ binding?: string;
717
+ meta?: Metadata;
718
+ }
719
+ interface EventDef {
720
+ id?: Id;
721
+ name: string;
722
+ from?: string;
723
+ payload?: TypeExpr;
724
+ description?: string;
725
+ }
726
+ interface PropConstraint {
727
+ kind: 'one-of' | 'any-of' | 'exclusive';
728
+ props: string[];
729
+ }
730
+ interface Contract {
731
+ params: Record<string, ParamBinding>;
732
+ props: PropDef[];
733
+ events: EventDef[];
734
+ /** Absent when the props block states none. */
735
+ constraints?: PropConstraint[];
736
+ }
737
+ interface PartState {
738
+ layout?: LayoutSpec;
739
+ facets?: FacetMap;
740
+ }
741
+ type PredicateRef = {
742
+ kind: 'prop';
743
+ path: string;
744
+ } | {
745
+ kind: 'state';
746
+ state: string;
747
+ } | {
748
+ kind: 'context';
749
+ group: string;
750
+ } | {
751
+ kind: 'ancestor';
752
+ nodeId: string;
753
+ state: string;
754
+ };
755
+ type CompareOp = 'eq' | 'ne' | 'lt' | 'lte' | 'gt' | 'gte' | 'contains' | 'set' | 'unset';
756
+ type Predicate = {
757
+ kind: 'all';
758
+ items: Predicate[];
759
+ } | {
760
+ kind: 'any';
761
+ items: Predicate[];
762
+ } | {
763
+ kind: 'not';
764
+ item: Predicate;
765
+ } | {
766
+ kind: 'cmp';
767
+ ref: PredicateRef;
768
+ op: CompareOp;
769
+ value?: PropValue;
770
+ };
771
+ interface PartVariant {
772
+ when?: RealizeCond;
773
+ whenPredicate?: Predicate;
774
+ states?: StateName[];
775
+ facets?: FacetMap;
776
+ layout?: LayoutSpec;
777
+ }
778
+ type PartSlotArity = 'single' | 'optional' | 'many';
779
+ type PartSlotAccepts = {
780
+ kind: 'content';
781
+ } | {
782
+ kind: 'type';
783
+ ref: string;
784
+ } | {
785
+ kind: 'component';
786
+ ref: string;
787
+ };
788
+ /** A design-time-only fill for a slot (never generated): a literal string, a named
789
+ * example, or a list of either (the multi-item preview of a `many` slot). */
790
+ type PartSlotSample = {
791
+ kind: 'text';
792
+ text: string;
793
+ } | {
794
+ kind: 'example';
795
+ example: string;
796
+ } | {
797
+ kind: 'list';
798
+ items: PartSlotSample[];
799
+ };
800
+ interface PartSlot {
801
+ arity: PartSlotArity;
802
+ accepts: PartSlotAccepts;
803
+ /** The slot a consumer fills when they pass children positionally. */
804
+ default?: boolean;
805
+ /** The item field that keys a `many` slot's entries. */
806
+ keyedBy?: string;
807
+ /** The public name this slot is exposed under, when it differs from the part name. */
808
+ exposeAs?: string;
809
+ /** `trigger` / `panel` - the structural role a disclosure's slot plays. */
810
+ role?: string;
811
+ /** Authored doc prose for the slot (proposal 0018), transcluded by the docs page. */
812
+ description?: string;
813
+ sample?: PartSlotSample;
814
+ }
815
+ /** A value that is either a literal or BOUND to a prop. Mirrors core's `ContentValue`. */
816
+ type PartValue = {
817
+ kind: 'value';
818
+ value: PropValue;
819
+ } | {
820
+ kind: 'bind';
821
+ prop: string;
822
+ };
823
+ /** One conditional leg of a part's text (`when <predicate> -> <value>`). */
824
+ interface PartContentRule {
825
+ when?: Predicate;
826
+ value: PartValue;
827
+ }
828
+ /** A part's text content: a fixed string, or a default plus predicate-gated legs. */
829
+ type PartContent = {
830
+ kind: 'static';
831
+ text: string;
832
+ } | {
833
+ kind: 'dynamic';
834
+ default: PartValue;
835
+ rules: PartContentRule[];
836
+ };
837
+ /** Accessible naming (proposal 0013). `labelledBy`/`describedBy` name a part by PATH. */
838
+ interface PartA11y {
839
+ name?: PartValue;
840
+ labelledBy?: string;
841
+ describedBy?: string;
842
+ }
843
+ /** An event the part raises: `<event> on <interaction> [payload …]`. `event` is a
844
+ * declared event NAME (the surface never prints an internal event id). */
845
+ interface PartEmit {
846
+ event: string;
847
+ on: string;
848
+ payload?: PartValue;
849
+ signal?: string;
850
+ locked?: boolean;
851
+ }
852
+ /** A UI state driven by a prop (`bind state disabled disabled`). */
853
+ interface PartStateBinding {
854
+ state: string;
855
+ prop: string;
856
+ }
857
+ type PartRepeatSource = {
858
+ kind: 'prop';
859
+ prop: string;
860
+ } | {
861
+ kind: 'static';
862
+ items: PropValue[];
863
+ };
864
+ /** Repetition over a collection (`repeat items as item`). */
865
+ interface PartRepeat {
866
+ source: PartRepeatSource;
867
+ itemAlias: string;
868
+ }
869
+ /** One transition (proposal 0017). `duration`/`easing`/`delay` name TOKENS. */
870
+ interface PartMotionTransition {
871
+ facets?: string[];
872
+ duration: string;
873
+ easing?: string;
874
+ delay?: string;
875
+ }
876
+ /** A nested component (proposal 0012). `component` is the component NAME. */
877
+ interface PartInstance {
878
+ component: string;
879
+ props: Array<{
880
+ name: string;
881
+ value: PartValue;
882
+ }>;
883
+ }
884
+ /** Non-portable, target-specific content (proposal 0041 §4). Quarantined by design: a
885
+ * reader that does not know `target` must skip it rather than try to interpret it. */
886
+ interface PartForeign {
887
+ code: string;
888
+ label?: string;
889
+ target?: string;
890
+ }
891
+ interface PartCell {
892
+ header?: boolean;
893
+ scope?: 'col' | 'row';
894
+ }
895
+ type PartMediaSample = {
896
+ kind: 'asset';
897
+ asset: string;
898
+ } | {
899
+ kind: 'url';
900
+ url: string;
901
+ };
902
+ type PartMediaSource = {
903
+ kind: 'bind';
904
+ prop: string;
905
+ sample?: PartMediaSample;
906
+ } | {
907
+ kind: 'static';
908
+ asset: string;
909
+ };
910
+ /** A free behaviour (proposal 0041 §4): a closed vocabulary of interaction behaviours
911
+ * (`focus-trap`, `typeahead`, …), each a flat record of scalars and part paths. */
912
+ interface PartBehavior {
913
+ kind: string;
914
+ config: Metadata;
915
+ }
916
+ /** The per-archetype configuration surfaces (proposal 0034/0029/0035): `calendar { … }`,
917
+ * `tabs { … }`, `slider { … }`, … Each block is a flat record of scalars, keyed by the
918
+ * surface block name; the AST→IR adapter VALIDATES each into its typed shape rather
919
+ * than casting, because a `.milda` is untrusted input. */
920
+ type PartConfigs = Record<string, Metadata>;
921
+ interface Part {
922
+ layout?: LayoutSpec;
923
+ facets?: FacetMap;
924
+ kind?: string;
925
+ origin?: 'root' | 'archetype' | 'author';
926
+ locked?: boolean;
927
+ content?: PartContent;
928
+ a11y?: PartA11y;
929
+ emits?: PartEmit[];
930
+ stateBindings?: PartStateBinding[];
931
+ /** The prop this part's value is bound to (an input's `value`). */
932
+ valueBinding?: string;
933
+ /** The declared type of the value this part holds. */
934
+ value?: TypeExpr;
935
+ repeat?: PartRepeat;
936
+ cell?: PartCell;
937
+ /** Control realization (proposal 0016): `checkbox` | `switch`. */
938
+ control?: string;
939
+ /** Group realization (0022): `radio` | `segmented`. */
940
+ group?: string;
941
+ /** Presentation intent (0022 §8): `accessibleName` for an icon-only control. */
942
+ presentation?: string;
943
+ /** Media type of a content part: `img` | `video` | `audio` | `embed`. */
944
+ media?: string;
945
+ mediaSource?: PartMediaSource;
946
+ mediaAlt?: PartValue;
947
+ /** Navigation target of a link part - static or prop-bound. */
948
+ destination?: PartValue;
949
+ motion?: PartMotionTransition[];
950
+ instance?: PartInstance;
951
+ behaviors?: PartBehavior[];
952
+ foreign?: PartForeign;
953
+ configs?: PartConfigs;
954
+ /** Demo interactions (proposal 0021) - only meaningful inside an `example`. */
955
+ actions?: PartAction[];
956
+ slot?: PartSlot;
957
+ presence?: Predicate;
958
+ states?: Partial<Record<StateName, PartState>>;
959
+ variants?: PartVariant[];
960
+ }
961
+ type Anatomy = Record<string, Part>;
962
+ interface RealizeCond {
963
+ prop: string;
964
+ eq: string | number | boolean;
965
+ }
966
+ interface Wire {
967
+ from: string;
968
+ to: string;
969
+ arg?: string;
970
+ when?: RealizeCond;
971
+ }
972
+ interface PresentationRealize {
973
+ surface?: string;
974
+ place?: string;
975
+ flip?: boolean;
976
+ matchWidth?: boolean;
977
+ }
978
+ interface BrowseRealize {
979
+ mode?: string;
980
+ orient?: 'horizontal' | 'vertical';
981
+ wrap?: boolean;
982
+ }
983
+ interface CommitRealize {
984
+ mode: 'explicit' | 'continuous';
985
+ on?: string[];
986
+ live?: string;
987
+ settled?: string;
988
+ }
989
+ interface Realization {
990
+ target: string;
991
+ when: RealizeCond | null;
992
+ presentation?: PresentationRealize;
993
+ browse?: BrowseRealize;
994
+ commit?: CommitRealize;
995
+ surface?: string;
996
+ drop?: string[];
997
+ wire?: Wire[];
998
+ note?: string;
999
+ dismiss?: string[];
1000
+ backdrop?: string;
1001
+ }
1002
+ interface Composition {
1003
+ uses: UsesClause[];
1004
+ coordination: CoordEntry[];
1005
+ }
1006
+ interface Component {
1007
+ id: Id;
1008
+ name: string;
1009
+ description?: string;
1010
+ archetype: string;
1011
+ contract: Contract;
1012
+ anatomy: Anatomy;
1013
+ realize: Realization[];
1014
+ composition?: Composition;
1015
+ meta?: Metadata;
1016
+ group?: string;
1017
+ }
1018
+ interface ComponentGroupDecl {
1019
+ path: string;
1020
+ description?: string;
1021
+ }
1022
+ interface DemoVariable {
1023
+ type: TypeExpr;
1024
+ initial: PropValue;
1025
+ }
1026
+ interface Example {
1027
+ name: string;
1028
+ /** The component NAME this scene demonstrates; absent = a freestanding fixture. */
1029
+ for?: string;
1030
+ description?: string;
1031
+ demo?: Record<string, DemoVariable>;
1032
+ anatomy: Anatomy;
1033
+ }
1034
+ interface PartAction {
1035
+ on: string;
1036
+ op: 'set' | 'toggle';
1037
+ variable: string;
1038
+ value?: PropValue;
1039
+ }
1040
+ interface ProjectMetadataEntry {
1041
+ id: Id;
1042
+ key: string;
1043
+ type: TypeExpr;
1044
+ value?: PropValue;
1045
+ }
1046
+ /**
1047
+ * A prop declared ONCE for the whole system, which any component may take by reference
1048
+ * (proposal 0051 §5). Its default is the system-wide value; an instance overrides it by passing
1049
+ * the prop, exactly as it would a local one.
1050
+ *
1051
+ * It lives in the foundations rather than on a component because that is what it IS: a
1052
+ * system-wide decision, next to the context groups it usually names. A design system with a
1053
+ * `variant` dimension says so once - the Radix mapping restated the same five props on 49
1054
+ * components, and the restatement carried no information.
1055
+ */
1056
+ interface GlobalProp {
1057
+ id: Id;
1058
+ name: string;
1059
+ type: TypeExpr;
1060
+ /** The system-wide value. Absent means "no default" - for a context type, inherit the theme. */
1061
+ default?: PropValue;
1062
+ description?: string;
1063
+ }
1064
+ /**
1065
+ * How the system is meant to be put together (proposal 0052 §5): a top-level `rule`. Mirrors the
1066
+ * editor IR's `UsageRule` (@mildastudio/core) for the reason `Predicate` does - this package is
1067
+ * standalone - and is lowered to it by the AST adapter in `@mildastudio/generate`.
1068
+ *
1069
+ * Every reference is by NAME, so a rule naming a component another file declares survives a
1070
+ * per-file round trip; a reference nothing resolves is a warning, never a drop.
1071
+ */
1072
+ interface RuleSubject {
1073
+ kind: 'component' | 'archetype';
1074
+ name: string;
1075
+ where?: Predicate;
1076
+ }
1077
+ type UsageRule = {
1078
+ id: string;
1079
+ severity: 'error' | 'warning';
1080
+ rationale: string;
1081
+ } & ({
1082
+ kind: 'count';
1083
+ subject: RuleSubject;
1084
+ within: RuleSubject;
1085
+ min?: number;
1086
+ max?: number;
1087
+ } | {
1088
+ kind: 'never';
1089
+ subject: RuleSubject;
1090
+ within: RuleSubject;
1091
+ } | {
1092
+ kind: 'only-within';
1093
+ subject: RuleSubject;
1094
+ within: RuleSubject[];
1095
+ } | {
1096
+ kind: 'tokens-only';
1097
+ types: TokenType[];
1098
+ } | {
1099
+ kind: 'prefer';
1100
+ component: string;
1101
+ archetypes: string[];
1102
+ });
1103
+ interface Foundations {
1104
+ contextGroups: ContextGroup[];
1105
+ layers: Layer[];
1106
+ sharedTypes: SharedType[];
1107
+ metadata: ProjectMetadataEntry[];
1108
+ /** Absent when the system declares none, so a file that has never used one is unchanged. */
1109
+ globalProps?: GlobalProp[];
1110
+ /** Usage rules (0052 §5). Absent when the file declares none. */
1111
+ rules?: UsageRule[];
1112
+ }
1113
+ type DocBlockDecl = {
1114
+ kind: 'prose';
1115
+ prose: string;
1116
+ text: string;
1117
+ anchor?: string;
1118
+ } | {
1119
+ kind: 'divider';
1120
+ } | {
1121
+ kind: 'image';
1122
+ asset?: string;
1123
+ } | {
1124
+ kind: 'component';
1125
+ component?: string;
1126
+ } | {
1127
+ kind: 'componentProps';
1128
+ component?: string;
1129
+ } | {
1130
+ kind: 'componentEvents';
1131
+ component?: string;
1132
+ } | {
1133
+ kind: 'componentComposition';
1134
+ component?: string;
1135
+ } | {
1136
+ kind: 'componentProp';
1137
+ component?: string;
1138
+ prop?: string;
1139
+ } | {
1140
+ kind: 'componentEvent';
1141
+ component?: string;
1142
+ event?: string;
1143
+ } | {
1144
+ kind: 'example';
1145
+ example?: string;
1146
+ } | {
1147
+ kind: 'componentGroup';
1148
+ group?: string;
1149
+ } | {
1150
+ kind: 'tokens';
1151
+ tokenType?: string;
1152
+ } | {
1153
+ kind: 'swatch';
1154
+ tokenType?: string;
1155
+ };
1156
+ interface DocPageDecl {
1157
+ title: string;
1158
+ /** The sidebar section this page sits in. */
1159
+ group?: string;
1160
+ /** The parent page's TITLE, for a nested page. */
1161
+ parent?: string;
1162
+ blocks: DocBlockDecl[];
1163
+ }
1164
+ interface DocsSiteDecl {
1165
+ name?: string;
1166
+ tagline?: string;
1167
+ version?: string;
1168
+ searchPlaceholder?: string;
1169
+ }
1170
+ interface DocsFooterLinkDecl {
1171
+ label: string;
1172
+ href: string;
1173
+ }
1174
+ interface DocsFooterDecl {
1175
+ links: DocsFooterLinkDecl[];
1176
+ copyright?: string;
1177
+ }
1178
+ interface DocsDecl {
1179
+ pages: DocPageDecl[];
1180
+ site?: DocsSiteDecl;
1181
+ footer?: DocsFooterDecl;
1182
+ }
1183
+ interface AssetFolderDecl {
1184
+ /** The folder's PATH (`Brand/Icons`), which is its nesting written down. */
1185
+ path: string;
1186
+ }
1187
+ interface AssetDecl {
1188
+ kind: string;
1189
+ name: string;
1190
+ /** The containing folder's path; absent = the library root. */
1191
+ folder?: string;
1192
+ mimeType?: string;
1193
+ sizeBytes?: number;
1194
+ uploadedAt?: string;
1195
+ /** Where the bytes live. A `data:` URI here makes the file self-contained. */
1196
+ url?: string;
1197
+ tags?: string[];
1198
+ /** Per-kind metadata (`width`, `viewBox`, `fontWeight`, …), validated on lowering. */
1199
+ props: Record<string, PropValue>;
1200
+ }
1201
+ interface AssetsDecl {
1202
+ folders: AssetFolderDecl[];
1203
+ assets: AssetDecl[];
1204
+ }
1205
+ interface IconSetDecl {
1206
+ /** The set's prefix in its provider's namespace (`lucide`, `ph`), which is what resolves. */
1207
+ prefix: string;
1208
+ name: string;
1209
+ provider?: string;
1210
+ license?: string;
1211
+ /** Four representative glyph names a preview shows for the set. */
1212
+ samples?: string[];
1213
+ }
1214
+ type IconDecl = {
1215
+ kind: 'set';
1216
+ prefix: string;
1217
+ name: string;
1218
+ label?: string;
1219
+ /** The glyph's vendored SVG body, so a generated package needs no CDN (proposal 0019). */
1220
+ svg?: string;
1221
+ } | {
1222
+ kind: 'custom';
1223
+ name: string;
1224
+ /** The NAME of the asset in the file's `assets` block whose bytes draw this glyph. */
1225
+ asset?: string;
1226
+ label?: string;
1227
+ };
1228
+ interface IconsDecl {
1229
+ sets: IconSetDecl[];
1230
+ icons: IconDecl[];
1231
+ }
1232
+ type AssetKind = 'font' | 'image' | 'svg' | 'video' | 'animation';
1233
+ interface BaseAsset {
1234
+ id: string;
1235
+ name: string;
1236
+ kind: AssetKind;
1237
+ mimeType: string;
1238
+ sizeBytes: number;
1239
+ uploadedAt: string;
1240
+ url: string;
1241
+ tags: string[];
1242
+ folderId: string | null;
1243
+ }
1244
+ interface FontAsset extends BaseAsset {
1245
+ kind: 'font';
1246
+ fontFamily: string;
1247
+ fontStyle: 'normal' | 'italic';
1248
+ fontWeight: number;
1249
+ formats: Array<'woff2' | 'woff' | 'ttf' | 'otf'>;
1250
+ }
1251
+ interface ImageAsset extends BaseAsset {
1252
+ kind: 'image';
1253
+ width: number;
1254
+ height: number;
1255
+ alt: string;
1256
+ }
1257
+ interface SvgAsset extends BaseAsset {
1258
+ kind: 'svg';
1259
+ viewBox: string;
1260
+ width: number;
1261
+ height: number;
1262
+ }
1263
+ interface VideoAsset extends BaseAsset {
1264
+ kind: 'video';
1265
+ width: number;
1266
+ height: number;
1267
+ durationMs: number;
1268
+ poster?: string;
1269
+ }
1270
+ type AnimationFormat = 'lottie' | 'rive' | 'css';
1271
+ interface AnimationAsset extends BaseAsset {
1272
+ kind: 'animation';
1273
+ format: AnimationFormat;
1274
+ durationMs: number;
1275
+ loop: boolean;
1276
+ }
1277
+ type Asset = FontAsset | ImageAsset | SvgAsset | VideoAsset | AnimationAsset;
1278
+ type AssetByKind = {
1279
+ font: FontAsset;
1280
+ image: ImageAsset;
1281
+ svg: SvgAsset;
1282
+ video: VideoAsset;
1283
+ animation: AnimationAsset;
1284
+ };
1285
+ interface AssetFolder {
1286
+ id: string;
1287
+ name: string;
1288
+ parentId: string | null;
1289
+ createdAt: string;
1290
+ }
1291
+ interface AssetRegistry {
1292
+ assets: Record<string, Asset>;
1293
+ folders: Record<string, AssetFolder>;
1294
+ }
1295
+ interface Project extends MildaDocumentBase {
1296
+ kind: 'design-system';
1297
+ foundations: Foundations;
1298
+ assets: AssetRegistry;
1299
+ components: Component[];
1300
+ }
1301
+ declare const preludeV0: PreludeDocument;
1302
+ declare const atomsByName: Record<string, Atom>;
1303
+ declare const compositesByName: Record<string, CompositeBehavior>;
1304
+ declare const archetypesByName: Record<string, ArchetypeDef>;
1305
+ type ResolvedToken = {
1306
+ kind: 'value';
1307
+ type: TokenType;
1308
+ value: AnyTokenValue;
1309
+ } | {
1310
+ kind: 'escape';
1311
+ raw: string;
1312
+ note?: string;
1313
+ } |
1314
+ /**
1315
+ * A computed value (proposal 0044), reported rather than evaluated: the maths - colour
1316
+ * spaces, dp lowering - lives in the editor IR's resolver, not in this lightweight AST
1317
+ * walk. It is its own answer because neither alternative is true: `null` would say the
1318
+ * token does not resolve (it does, and a conformance check would report a hole that is not
1319
+ * there), and returning the base's value would say the token IS its base, unmodified.
1320
+ */
1321
+ {
1322
+ kind: 'computed';
1323
+ type: TokenType;
1324
+ from: string;
1325
+ } | null;
1326
+ declare function resolveToken(tokenId: string, contextIds: string | readonly string[], layers: Layer[], _depth?: number): ResolvedToken;
1327
+ declare function findToken(tokenId: string, layers: Layer[]): {
1328
+ token: Token$1;
1329
+ layerId: string;
1330
+ } | null;
1331
+ declare function allTokensOfType(type: TokenType, layers: Layer[]): Array<{
1332
+ token: Token$1;
1333
+ layerId: string;
1334
+ layerName: string;
1335
+ }>;
1336
+ interface ValidationIssue {
1337
+ severity: 'error' | 'warning';
1338
+ code: string;
1339
+ message: string;
1340
+ where?: string;
1341
+ id?: string;
1342
+ }
1343
+ declare function validate(doc: Project, prelude: PreludeDocument): ValidationIssue[];
1344
+ interface Hole {
1345
+ kind: 'facet' | 'layout' | 'behavior';
1346
+ name: string;
1347
+ where: string;
1348
+ reason: string;
1349
+ }
1350
+ interface Substitution {
1351
+ behavior: string;
1352
+ via: string;
1353
+ }
1354
+ interface ConformanceReport {
1355
+ target: string;
1356
+ complete: boolean;
1357
+ holes: Hole[];
1358
+ substitutions: Substitution[];
1359
+ }
1360
+ interface ConformanceOptions {
1361
+ target: string;
1362
+ contextIds: string[];
1363
+ layers: Layer[];
1364
+ }
1365
+ declare function conformance(comp: Component, opts: ConformanceOptions): ConformanceReport;
1366
+ interface DesignSystemDocument {
1367
+ milda: string;
1368
+ kind: 'design-system';
1369
+ prelude: string;
1370
+ meta: {
1371
+ id: string;
1372
+ name: string;
1373
+ version: string;
1374
+ description?: string;
1375
+ };
1376
+ foundations: Foundations;
1377
+ components: Component[];
1378
+ componentGroups?: ComponentGroupDecl[];
1379
+ examples?: Example[];
1380
+ docs?: DocsDecl;
1381
+ assets?: AssetsDecl;
1382
+ icons?: IconsDecl;
1383
+ }
1384
+ interface ParseIssue {
1385
+ severity: 'error' | 'warning';
1386
+ code: string;
1387
+ message: string;
1388
+ line: number;
1389
+ col: number;
1390
+ }
1391
+ interface SourcePosition {
1392
+ line: number;
1393
+ col: number;
1394
+ }
1395
+ interface SourceRange {
1396
+ start: SourcePosition;
1397
+ end: SourcePosition;
1398
+ }
1399
+ type SpanKind = 'component' | 'token' | 'contextGroup' | 'context' | 'sharedType' | 'globalProp' | 'rule' | 'part' | 'prop' | 'event';
1400
+ interface NodeSpan {
1401
+ id: string;
1402
+ kind: SpanKind;
1403
+ name: string;
1404
+ nameRange: SourceRange;
1405
+ fullRange: SourceRange;
1406
+ parentId?: string;
1407
+ }
1408
+ interface ParseResult {
1409
+ document: DesignSystemDocument;
1410
+ issues: ParseIssue[];
1411
+ spans: NodeSpan[];
1412
+ }
1413
+ interface ParseOptions {
1414
+ name?: string;
1415
+ milda?: string;
1416
+ prelude?: string;
1417
+ }
1418
+ /** Facet names accepted by `parseFacetStmt` (those with an AST home). */
1419
+ declare const FACET_NAMES: readonly string[];
1420
+ /** Token-type names accepted by `parseTokenDecl` - kebab spelling only (the camelCase
1421
+ * aliases in TYPE_MAP stay accepted, they're just not advertised, and neither are the
1422
+ * legacy spellings above). */
1423
+ declare const TOKEN_TYPE_NAMES: readonly string[];
1424
+ /** The `token … = ‹kind›` value kinds. */
1425
+ declare const TOKEN_VALUE_KINDS: readonly string[];
1426
+ /** Keys accepted inside a `layout { … }` block - keep in step with `parseLayoutBody`. `flow` and
1427
+ * `ratio` are reading aliases (0056 §3.2); `grid` is reserved (0056 §3.3). */
1428
+ declare const LAYOUT_KEYS: readonly string[];
1429
+ /** What may follow each word inside a `layout { … }` block, keyed on the word BEFORE the
1430
+ * cursor so completion can read it directly: a key's values, the edges after `pinned` /
1431
+ * `bleed`, the intents after `size` / `width` / `height`. All from the vocabulary (0056 §3.1),
1432
+ * so the parser, the printer and the LSP cannot disagree about a word. */
1433
+ declare const LAYOUT_VALUES: Readonly<Record<string, readonly string[]>>;
1434
+ /** Slot arities accepted by `slot ‹arity›` (grammar `arity`). */
1435
+ declare const SLOT_ARITIES: readonly string[];
1436
+ /** Statement keywords accepted inside a `part { … }` block, for editor completion. */
1437
+ declare const PART_KEYWORDS: readonly string[];
1438
+ /** The surface token-type names whose value MUST carry a unit (a bare number is rejected
1439
+ * with `length-unit-required`). Exported so the printer's own "emit a canonical length
1440
+ * here" set can be asserted against this one: giving `border`/`font-size`/`letter-spacing`
1441
+ * their own words widened the reader's set and left the writer's behind, so the printer
1442
+ * emitted bare numbers its own reader then refused (0041 §1.1d). */
1443
+ declare const LENGTH_TOKEN_TYPE_NAMES: readonly string[];
1444
+ /**
1445
+ * The KIND of value a token type carries. Types are grouped into families rather than compared
1446
+ * exactly, because several of them share a value shape on purpose: a `ring` or a `backdrop` IS a
1447
+ * colour, and every length type fills a length slot. Used by the alias cross-type check (below)
1448
+ * and by editor tooling, which offers the tokens that would fit a slot - one answer to "can this
1449
+ * value go there", not two that can disagree.
1450
+ */
1451
+ declare function tokenTypeFamily(type: TokenType | string): string;
1452
+ /** Every accepted spelling of a token type → the AST type it means (`dimension` → `size`,
1453
+ * `font-family` → `fontFamily`). Exported so tooling can read a DECLARED type off the source
1454
+ * and compare it with the tokens it already parsed. */
1455
+ declare const TOKEN_TYPES_BY_NAME: Readonly<Record<string, TokenType>>;
1456
+ /** The surface token-type names whose value is a COLOUR - so an editor knows that this is
1457
+ * where `hex(…)` and `oklch(…)` belong, without a second list of type names to keep in
1458
+ * step with this file's (a `ring` and a `backdrop` are colours too, and both were missed
1459
+ * by every hand-written copy of "the colour types"). */
1460
+ declare const COLOR_TOKEN_TYPE_NAMES: readonly string[];
1461
+ declare function parseMildaDocument(src: string, opts?: ParseOptions): ParseResult;
1462
+ type TokenType$1 = 'word' | 'string' | 'lbrace' | 'rbrace' | 'lparen' | 'rparen' | 'lbracket' | 'rbracket' | 'lt' | 'gt' | 'lte' | 'gte' | 'ne' | 'colon' | 'equals' | 'comma' | 'semi' | 'question' | 'arrow' | 'at' | 'newline' | 'eof';
1463
+ interface Token {
1464
+ type: TokenType$1;
1465
+ value: string;
1466
+ pos: number;
1467
+ line: number;
1468
+ col: number;
1469
+ }
1470
+ declare class LexError extends Error {
1471
+ line: number;
1472
+ col: number;
1473
+ constructor(message: string, line: number, col: number);
1474
+ }
1475
+ /** A character the lexer had to skip: not a token, not whitespace, not a comment. Collected
1476
+ * rather than thrown, so a half-typed document still lexes - but REPORTED, because silently
1477
+ * dropping a character means a typo changes the value and the author never learns. `hex(őfff)`
1478
+ * used to lex as `hex(fff)`: white, no issue, no clue (proposal 0041). */
1479
+ interface SkippedChar {
1480
+ char: string;
1481
+ line: number;
1482
+ col: number;
1483
+ }
1484
+ declare function lex(src: string, skipped?: SkippedChar[]): Token[];
1485
+ export { ASSET_BASE_KEYS, ASSET_FIELDS, ASSET_FIELD_KEYS, ASSET_KINDS, AXIS_CLAMPS, AXIS_INTENTS, type AliasTokenValue, type Align, type Anatomy, type AnatomyPart, type AnimationAsset, type AnimationFormat, type AnyTokenValue, type ArchetypeDef, type ArchetypeGroup, type ArchetypeRealize, type Asset, type AssetByKind, type AssetDecl, type AssetFolder, type AssetFolderDecl, type AssetKind, type AssetRegistry, type AssetsDecl, type Assignment, type Atom, type AtomContextVar, type AtomEvent, type AtomParam, type AtomStateNode, type AxisIntent, type AxisIntentKind, type AxisSize, type AxisSizeValue, BEHAVIOR_FIELDS, BEHAVIOR_KINDS, type BlurValue, type BorderFacetStyle, type BorderFacetValue, type BorderStyle, type BorderValue, type BorderWidth, type BrowseRealize, CELL_MODIFIERS, COLOR_KEYWORDS, COLOR_LITERAL_ALIASES, COLOR_LITERAL_FNS, COLOR_LITERAL_SPELLINGS, COLOR_TOKEN_TYPE_NAMES, CONTROL_REALIZATIONS, type Capability, type CapabilityDef, type ColorOrRef, type ColorSpace, type ColorValue, type CommitRealize, type CompareOp, type Component, type ComponentGroupDecl, type CompositeBehavior, type Composition, type ComputeOp, type ComputeSpace, type ComputeTokenValue, type ConfigFieldSpec, type ConfigSurface, type ConformanceOptions, type ConformanceReport, type ContentCategory, type Context, type ContextGroup, type Contract, type CoordEntry, DEMO_ACTION_OPS, DOCS_FOOTER_KEYWORDS, DOCS_KEYWORDS, DOCS_SITE_KEYS, DOC_BLOCK_KEYWORDS, DOC_PROSE_KINDS, DOC_TRANSCLUSIONS, type DemoVariable, type DesignSystemDocument, type DimensionOrRef, type DimensionUnit, type DimensionValue, type Distribute, type DocBlockDecl, type DocPageDecl, type DocsDecl, type DocsFooterDecl, type DocsFooterLinkDecl, type DocsSiteDecl, type DocumentKind, type DocumentMeta, type DocumentMeta as ProjectMeta, type Token as DslToken, type DurationValue, EXAMPLE_KEYWORDS, type Emit, type EscapeTokenValue, type EventDef, type Example, type Expose, FACET_NAMES, type FacetDef, type FacetMap, type FacetName, type FacetTokenType, type FacetValue, type FieldType, type FontAsset, type FontCategory, type FontFamilyValue, type FontProvenance, type FontWeightValue, type Foundations, GROUP_REALIZATIONS, type GlobalProp, type Hole, INTERACTION_KINDS, type IconDecl, type IconSetDecl, type IconsDecl, type Id, type ImageAsset, type InsetValue, LAYOUT_ALIGNS, LAYOUT_DIRECTIONS, LAYOUT_DISTRIBUTES, LAYOUT_KEYS, LAYOUT_RECORD_KEYS, LAYOUT_VALUES, LAYOUT_WRAPS, LENGTH_LITERAL_FNS, LENGTH_TOKEN_TYPE_NAMES, LOGICAL_EDGES, type Layer, type LayoutAlign, type LayoutDirection, type LayoutDistribute, type LayoutRecordKey, type LayoutSpec, type LayoutWrap, type LengthKeyword, type LengthKeywordValue, type LengthValue, LexError, type LiteralChannel, type LiteralFnSpec, type LogicalEdge, MEDIA_TYPES, MILDA_SURFACE_VERSION, type Metadata, type MildaDocumentBase, NODE_KINDS, NODE_ORIGINS, type NodeSpan, type NoneValue, type ObjectField, type OpacityValue, PART_CONFIGS, PART_CONFIG_NAMES, PART_CONFIG_WORDS, PART_KEYWORDS, PHYSICAL_EDGE_ALIASES, POSITION_KINDS, PRELUDE_VERSION, PRESENTATION_KINDS, type ParamBinding, type ParseIssue, type ParseOptions, type ParseResult, type Part, type PartA11y, type PartAction, type PartBehavior, type PartCell, type PartConfigs, type PartContent, type PartContentRule, type PartEmit, type PartForeign, type PartInstance, type PartMediaSample, type PartMediaSource, type PartMotionTransition, type PartRepeat, type PartRepeatSource, type PartRole, type PartSlot, type PartSlotAccepts, type PartSlotArity, type PartSlotSample, type PartState, type PartStateBinding, type PartValue, type PartVariant, type Position, type PositionKind, type Predicate, type PredicateRef, type PreludeDocument, type PresentationRealize, type PrimitiveTokenType, type Project, type ProjectMetadataEntry, type PropConstraint, type PropDef, type PropValue, type RawTokenValue, type Realization, type RealizeCond, type RequiresClause, type ResolvedToken, type RuleSubject, SLOT_ARITIES, SLOT_MODIFIERS, SLOT_ROLES, type ShadowLayer, type ShadowValue, type SharedType, type SkippedChar, type SourcePosition, type SourceRange, type SpanKind, type StackAxis, type StateDef, type StateName, type Substitution, type SvgAsset, TOKEN_TYPES_BY_NAME, TOKEN_TYPE_NAMES, TOKEN_VALUE_KIND, TOKEN_VALUE_KINDS, type TaxonomyNote, type Token$1 as Token, type TokenRef, type TokenType, type TokenValue, type TokenValueSchemaByType, type TonalValue, type Transition, type TransitionTarget, type TypeExpr, type TypeRef, type TypographyValue, type UsageRule, type UsesClause, VALUE_LITERAL_FNS, type ValidationIssue, type VideoAsset, type Wire, allTokensOfType, archetypesByName, atomsByName, camelField, compositesByName, conformance, findToken, kebab as kebabField, lex, parseMildaDocument, preludeV0, resolveToken, tokenTypeFamily, validate };