@exponential_app/eui 0.2.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.
Files changed (69) hide show
  1. package/catalog/a11y.json +15 -1
  2. package/catalog/core.catalog.json +142 -0
  3. package/catalog/core.schema.json +198 -1
  4. package/catalog/host.json +10 -0
  5. package/catalog/macros.json +541 -1
  6. package/catalog/recipes.json +2 -2
  7. package/catalog/strings.json +5 -0
  8. package/catalog/theme.schema.json +2066 -212
  9. package/conformance/manifest.json +5 -5
  10. package/dist/chunks/{index-gtk2gwsb.js → index-4z7f2bp1.js} +160 -33
  11. package/dist/chunks/{index-gtk2gwsb.js.map → index-4z7f2bp1.js.map} +6 -5
  12. package/dist/chunks/{index-5fmaa0xq.js → index-abcjanhc.js} +629 -3
  13. package/dist/chunks/{index-5fmaa0xq.js.map → index-abcjanhc.js.map} +2 -2
  14. package/dist/chunks/{index-62yzr94z.js → index-dx45asrf.js} +99 -3
  15. package/dist/chunks/{index-62yzr94z.js.map → index-dx45asrf.js.map} +2 -2
  16. package/dist/chunks/{index-bg2jsgjq.js → index-h3zgfghf.js} +304 -6
  17. package/dist/chunks/{index-bg2jsgjq.js.map → index-h3zgfghf.js.map} +2 -2
  18. package/dist/conformance.js +7901 -614
  19. package/dist/conformance.js.map +2 -2
  20. package/dist/entries/prompt.js +2 -2
  21. package/dist/entries/schema.js +2 -2
  22. package/dist/host/index.js +20 -4
  23. package/dist/host/index.js.map +1 -1
  24. package/dist/index.js +46 -5
  25. package/dist/index.js.map +4 -3
  26. package/dist/types/src/catalog.generated.d.ts +23 -3
  27. package/dist/types/src/host/contract.d.ts +17 -0
  28. package/dist/types/src/host/exposes.d.ts +68 -0
  29. package/dist/types/src/host/index.d.ts +1 -0
  30. package/dist/types/src/host/package.d.ts +8 -0
  31. package/dist/types/src/index.d.ts +1 -0
  32. package/dist/types/src/text-clusters.d.ts +11 -0
  33. package/dist/types/src/web/primitives/carousel.d.ts +17 -0
  34. package/dist/types/src/web/primitives/index.d.ts +3 -0
  35. package/dist/types/src/web/primitives/mosaic.d.ts +30 -0
  36. package/dist/types/src/web/primitives/outline.d.ts +22 -0
  37. package/dist/web/index.js +8 -2
  38. package/dist/web/index.js.map +4 -4
  39. package/dist/web/primitives/index.js +59 -1
  40. package/dist/web/primitives/index.js.map +6 -3
  41. package/docs/components.generated.json +150 -1
  42. package/docs/package-format.md +56 -1
  43. package/docs/round-6-contract.md +108 -0
  44. package/docs/themes.generated.json +39 -2
  45. package/fixtures/bind-time.json +1464 -0
  46. package/fixtures/catalog-components.json +96 -0
  47. package/fixtures/catalog-macros.json +1159 -48
  48. package/fixtures/conformance-baseline.json +46073 -44448
  49. package/fixtures/conformance-known.json +76 -64
  50. package/fixtures/host-router.json +539 -1
  51. package/fixtures/kitchen-sink.expanded.json +614 -1
  52. package/fixtures/kitchen-sink.json +69 -1
  53. package/fixtures/primitive-specimens.json +3 -0
  54. package/fixtures/prompt-budget.json +14 -14
  55. package/fixtures/specimens.json +122 -0
  56. package/fixtures/text-clusters.json +65 -0
  57. package/fixtures/theme-recipes.json +4617 -1691
  58. package/fixtures/theme-resolved.json +1154 -2
  59. package/generated/ExponentialUICatalog.generated.kt +13 -13
  60. package/generated/ExponentialUICatalog.generated.swift +13 -13
  61. package/generated/ExponentialUIThemes.generated.kt +7 -7
  62. package/generated/ExponentialUIThemes.generated.swift +7 -7
  63. package/generated/catalog.descriptions.generated.rs +1 -1
  64. package/generated/catalog.generated.rs +18 -18
  65. package/generated/catalog.themes.generated.rs +8 -8
  66. package/generated/core.descriptions.json +96 -0
  67. package/generated/core.runtime.json +86 -0
  68. package/package.json +1 -1
  69. package/themes/neutral.theme.json +288 -0
@@ -0,0 +1,108 @@
1
+ # Exponential UI — round 6 contract (EXP-1495)
2
+
3
+ Round 6 adds the low-level pieces THE plan page (#EXP-1493,
4
+ `packages/domain-contract/fixtures/plan-page.json`) needs: an anchor list, a
5
+ wide picture group, and a counter + thumbnail strip on the Carousel. This
6
+ file is the CONTRACT half: what changed in `@exponential_app/eui` and what
7
+ each renderer implements to match. Everything here is locked by a fixture
8
+ or a test.
9
+
10
+ ## 0. What moved
11
+
12
+ | area | change | source of truth | locked by |
13
+ |---|---|---|---|
14
+ | `Outline` | NEW macro (navigation, lite): `items` (`outlineItem` {id, title, count}), `value` (the active id, bindable, two-way), `caption`; event `select {id}` | `core.catalog.json`, `macros.json`, neutral recipes | `catalog-macros.json`, `bind-time.json` |
15
+ | `Mosaic` | NEW macro (media, not lite): `pictures` (`picture` {src, alt}), `label`; event `select {index}` | same | `catalog-macros.json` |
16
+ | `Carousel` | `counter` (boolean) + `thumbnails` (array of url); parts `counter`, `thumbnails`, `thumbnail` (state `selected`), recipe prop `counter` | `core.catalog.json`, `recipes.json`, neutral recipes | `catalog-components.json`, `theme-recipes.json`, the kitchen sink |
17
+ | strings | `morePictures` (`+{count}`), `morePicturesLabel` (`{alt}, {count} more`), `outline`, `outlineRow` (`{title}, {count}`), `pageCounter` (`{page} / {total}`) | `strings.json` | generated STRING tables |
18
+ | kitchen sink | + Outline (after the Breadcrumb), Mosaic (4 pictures, after the Carousel); the Carousel gains `counter: true` + two thumbnails | `kitchen-sink.json` | `kitchen-sink.expanded.json` |
19
+ | web primitives | `OUTLINE_CLASSES`/`OUTLINE_GEOMETRY`/`outlineCountText`, `MOSAIC_CLASSES`/`MOSAIC_GEOMETRY`/`mosaicTiles`, `CAROUSEL_CLASSES`/`CAROUSEL_GEOMETRY`/`carouselCounterText` | `src/web/primitives/{outline,mosaic,carousel}.ts` | `recipes.test.ts` (no class literal in the React/Solid twins) |
20
+
21
+ Counts: 89 offered components (49 natives, 40 macros; 62 lite),
22
+ + the hidden TreeGuides and Unknown. Prompt budget 7,900 → 8,034 tokens
23
+ (a named exception: the measured total, no slack).
24
+
25
+ ## 1. Outline
26
+
27
+ THE plan page's left column (plan-page.json `layout.outlineRowHeight` 32,
28
+ `outlineActiveBar` 2). Parts: `root` (column, gap xxs; role navigation
29
+ labelled `caption`, else `$string.outline`) → `caption` (Text caption, one
30
+ line, hidden from AT; neutral: 11/16 medium, letter spacing 0.5, UPPERCASE,
31
+ muted, padded sm × xs) → per item `row` (a pressable Box, row, centred,
32
+ gap xs, `$control.rowCompact` (32) tall, padding-x sm, relative, clipping;
33
+ role link labelled `title` (+ `, count` via `$string.outlineRow`),
34
+ `current: location` on the active row; `$recipe` `active` = `item.id ==
35
+ value`; press → `select {id}`, and with a bound `value` the `$set` writes
36
+ the id back) → `bar` (only on the active row: absolute, inset-inline-start 0,
37
+ top/bottom 0, 2 px wide; neutral: foreground) → `title` (Text, one line,
38
+ flex 1; neutral: sm muted, active = foreground medium) → `count` (only when
39
+ `count` > 0: caption `· n`, muted, hidden from AT). Neutral row: radius sm,
40
+ hover = accent, active = accent. No `value` (or none matching) = no active
41
+ row. Scroll-spy stays in the HOST: it binds `value` to the section in view.
42
+
43
+ ## 2. Mosaic
44
+
45
+ THE wide picture group (plan-page.json `mosaicTiles` + `mosaic`). No
46
+ `$each`: the macro addresses `props.pictures.0/1/2` directly (the TS and Rust
47
+ `lookup` index arrays by a numeric segment). Parts: `root` (row, full width,
48
+ `aspectRatio` 1.6; role group labelled `label`; neutral gap 10) →
49
+ `lead` (picture 0: 1 picture = the whole group, 2 = a half (flex 1), 3+ =
50
+ `flexBasis` 60 %, no grow/shrink; `$recipe size` large|half) → `pair`
51
+ (picture 1, ONLY when exactly 2: flex 1, `size` half) → `side` (3+ only:
52
+ column, flex 1, neutral gap 10) → `top` (picture 1) + `bottom` (picture 2,
53
+ both flex 1, `size` small) → `more` (on `bottom` when 4+: absolute inset 0,
54
+ centred; neutral fill `#0000008c` = black 0.55) → `moreLabel` (Text
55
+ `$string.morePictures` = `+{count}`, count = n − 3; neutral white xl
56
+ semibold). Every tile = a pressable Box (relative, clipping, min 0; role
57
+ button labelled the picture's `alt`, the `+N` tile `$string.morePicturesLabel`)
58
+ holding `image` (Image `fit: cover`, absolute inset 0, 100 % × 100 %, hidden
59
+ from AT); press → `select {index}` (0, 1 or 2; the host opens its lightbox
60
+ over every picture). Neutral tile: radius lg (10), hairline border, muted
61
+ fill under the picture, hover opacity 0.92. An empty `pictures` = an empty
62
+ group box (hosts draw none).
63
+
64
+ ## 3. Carousel `counter` and `thumbnails`
65
+
66
+ Both only with TWO OR MORE pages (like the controls row).
67
+
68
+ - `counter: true` = a pill over the TRACK's top-start corner (mirrored under
69
+ RTL), inset `$spacing.sm` (8) from the top and the start edge, above the
70
+ pages, never intercepting a press or a swipe: part `counter`, text
71
+ `$string.pageCounter` {page: current + 1, total: n}, hidden from AT (each
72
+ page is already `page i of n`). Neutral: height 20, padding-x sm, radius
73
+ full, fill `#0000008c`, text `#ffffff` xs medium, tabular figures.
74
+ - `thumbnails: [url…]` = a strip under the track, BEFORE the controls row:
75
+ part `thumbnails` (row, neutral gap sm, start-aligned, scrolling sideways
76
+ when it overflows; the current thumbnail scrolled into view), one
77
+ `thumbnail` per PAGE (URLs past the page count are ignored; a missing one
78
+ = the empty muted square): a button 52 × 52 (neutral: radius md, a 2 px
79
+ border, transparent → `$color.foreground` when `selected` = the current
80
+ page, muted fill, opacity 0.7 → 1 when selected or hovered), the picture
81
+ covering it inside the border; a press goes to that page (fires `change
82
+ {page}` like a dot). A11y: each a button `$string.pageOf`, the current
83
+ one `current`/`aria-current`.
84
+
85
+ The Rust core lays both out (`layout_tree` containers: the counter is an
86
+ overlay box of the track, out of flow; the strip a row of fixed 52 × 52
87
+ items between the track and the controls), so FFI/gpui painters read the
88
+ frames; the web renderers lay out with CSS.
89
+
90
+ ## 4. Per-renderer checklist
91
+
92
+ Every renderer: replay the regenerated `catalog-components.json`,
93
+ `catalog-macros.json`, `bind-time.json`, `theme-recipes.json`,
94
+ `kitchen-sink*.json`; paint the two new specimens (`exponential-ui-outline`,
95
+ `exponential-ui-mosaic`) and the Carousel extras; re-record what the grown
96
+ kitchen sink moves (baselines, snapshots, bench node counts).
97
+
98
+ - **Macros (Outline, Mosaic)**: nothing to paint beyond Box/Text/Image;
99
+ check the Box `aspectRatio`, `position: absolute` + `inset` and
100
+ `insetInlineStart` paths, Image `fit: cover` inside a sized box.
101
+ - **React / Solid / element**: Carousel counter + strip (CSS), the
102
+ `selected` thumbnail recipe, `change` on a thumbnail press; re-record
103
+ `fixtures/conformance-baseline.json`; the primitive twins `Outline`,
104
+ `Mosaic` (+ the carousel extras) on `@exponential_app/eui/web/primitives`.
105
+ - **Rust core / FFI**: the generated catalog, the Carousel counter + strip
106
+ frames in `layout_tree`, the macro fixtures.
107
+ - **gpui / SwiftUI / Compose**: paint the counter + strip from the core's
108
+ frames and recipes; thumbnail press → `change`; snapshots re-recorded.
@@ -2694,11 +2694,33 @@
2694
2694
  "indicator",
2695
2695
  "controls",
2696
2696
  "previous",
2697
- "next"
2697
+ "next",
2698
+ "counter",
2699
+ "thumbnails",
2700
+ "thumbnail"
2698
2701
  ],
2699
2702
  "props": [
2700
2703
  "loop",
2701
- "indicators"
2704
+ "indicators",
2705
+ "counter"
2706
+ ]
2707
+ },
2708
+ {
2709
+ "name": "Mosaic",
2710
+ "kind": "macro",
2711
+ "parts": [
2712
+ "root",
2713
+ "lead",
2714
+ "image",
2715
+ "pair",
2716
+ "side",
2717
+ "top",
2718
+ "bottom",
2719
+ "more",
2720
+ "moreLabel"
2721
+ ],
2722
+ "props": [
2723
+ "size"
2702
2724
  ]
2703
2725
  },
2704
2726
  {
@@ -2842,6 +2864,21 @@
2842
2864
  "current"
2843
2865
  ]
2844
2866
  },
2867
+ {
2868
+ "name": "Outline",
2869
+ "kind": "macro",
2870
+ "parts": [
2871
+ "root",
2872
+ "caption",
2873
+ "row",
2874
+ "bar",
2875
+ "title",
2876
+ "count"
2877
+ ],
2878
+ "props": [
2879
+ "active"
2880
+ ]
2881
+ },
2845
2882
  {
2846
2883
  "name": "Stepper",
2847
2884
  "kind": "macro",