@signal9/era-ui 21.0.0 → 23.0.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 (103) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/dist/dev/audit/audits/off-tier-height.js +16 -2
  3. package/dist/dev/audit/audits/wall-is-isotropic.js +15 -10
  4. package/dist/era-ui.css +1 -1
  5. package/dist/index.d.ts +1 -1
  6. package/dist/styles/typography.css +48 -9
  7. package/dist/ui/accordion/accordion-trigger.svelte +2 -2
  8. package/dist/ui/accordion/accordion-trigger.svelte.d.ts +2 -2
  9. package/dist/ui/alert-dialog/alert-dialog-content.svelte +6 -2
  10. package/dist/ui/alert-dialog/alert-dialog-content.svelte.d.ts +2 -2
  11. package/dist/ui/alert-dialog/alert-dialog-root.svelte +33 -0
  12. package/dist/ui/alert-dialog/alert-dialog-root.svelte.d.ts +8 -0
  13. package/dist/ui/alert-dialog/alert-dialog-trigger.svelte +8 -0
  14. package/dist/ui/alert-dialog/index.d.ts +1 -1
  15. package/dist/ui/alert-dialog/index.js +1 -1
  16. package/dist/ui/card/card.svelte +3 -0
  17. package/dist/ui/combobox/combobox-trigger.svelte +2 -2
  18. package/dist/ui/combobox/combobox-trigger.svelte.d.ts +2 -2
  19. package/dist/ui/context-menu/context-menu-content.svelte +6 -2
  20. package/dist/ui/context-menu/context-menu-content.svelte.d.ts +2 -2
  21. package/dist/ui/context-menu/context-menu-root.svelte +33 -0
  22. package/dist/ui/context-menu/context-menu-root.svelte.d.ts +8 -0
  23. package/dist/ui/context-menu/context-menu-sub-content.svelte +6 -2
  24. package/dist/ui/context-menu/context-menu-sub-content.svelte.d.ts +2 -2
  25. package/dist/ui/context-menu/context-menu-sub-trigger.svelte +2 -2
  26. package/dist/ui/context-menu/context-menu-sub-trigger.svelte.d.ts +2 -2
  27. package/dist/ui/context-menu/context-menu-trigger.svelte +8 -0
  28. package/dist/ui/context-menu/index.d.ts +1 -1
  29. package/dist/ui/context-menu/index.js +1 -1
  30. package/dist/ui/date-field/date-field-input.svelte +9 -0
  31. package/dist/ui/date-picker/date-picker-trigger.svelte +2 -2
  32. package/dist/ui/date-picker/date-picker-trigger.svelte.d.ts +2 -2
  33. package/dist/ui/date-range-field/date-range-field-input.svelte +9 -0
  34. package/dist/ui/date-range-picker/date-range-picker-trigger.svelte +2 -2
  35. package/dist/ui/date-range-picker/date-range-picker-trigger.svelte.d.ts +2 -2
  36. package/dist/ui/dialog/dialog-content.svelte +16 -2
  37. package/dist/ui/dialog/dialog-content.svelte.d.ts +2 -2
  38. package/dist/ui/dialog/dialog-root.svelte +43 -0
  39. package/dist/ui/dialog/dialog-root.svelte.d.ts +8 -0
  40. package/dist/ui/dialog/dialog-trigger.svelte +10 -0
  41. package/dist/ui/dialog/index.d.ts +1 -1
  42. package/dist/ui/dialog/index.js +1 -1
  43. package/dist/ui/dropdown-menu/dropdown-menu-content.svelte +6 -2
  44. package/dist/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +2 -2
  45. package/dist/ui/dropdown-menu/dropdown-menu-root.svelte +33 -0
  46. package/dist/ui/dropdown-menu/dropdown-menu-root.svelte.d.ts +8 -0
  47. package/dist/ui/dropdown-menu/dropdown-menu-sub-content.svelte +6 -2
  48. package/dist/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +2 -2
  49. package/dist/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -2
  50. package/dist/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +2 -2
  51. package/dist/ui/dropdown-menu/dropdown-menu-trigger.svelte +10 -2
  52. package/dist/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +2 -2
  53. package/dist/ui/dropdown-menu/index.d.ts +1 -1
  54. package/dist/ui/dropdown-menu/index.js +1 -1
  55. package/dist/ui/index.d.ts +1 -0
  56. package/dist/ui/index.js +1 -0
  57. package/dist/ui/link-preview/index.d.ts +1 -1
  58. package/dist/ui/link-preview/index.js +1 -1
  59. package/dist/ui/link-preview/link-preview-content.svelte +6 -2
  60. package/dist/ui/link-preview/link-preview-content.svelte.d.ts +2 -2
  61. package/dist/ui/link-preview/link-preview-root.svelte +33 -0
  62. package/dist/ui/link-preview/link-preview-root.svelte.d.ts +8 -0
  63. package/dist/ui/link-preview/link-preview-trigger.svelte +8 -0
  64. package/dist/ui/menubar/menubar-content.svelte +6 -2
  65. package/dist/ui/menubar/menubar-content.svelte.d.ts +2 -2
  66. package/dist/ui/menubar/menubar-root.svelte +26 -1
  67. package/dist/ui/menubar/menubar-root.svelte.d.ts +1 -1
  68. package/dist/ui/menubar/menubar-sub-content.svelte +6 -2
  69. package/dist/ui/menubar/menubar-sub-content.svelte.d.ts +2 -2
  70. package/dist/ui/menubar/menubar-sub-trigger.svelte +2 -2
  71. package/dist/ui/menubar/menubar-sub-trigger.svelte.d.ts +2 -2
  72. package/dist/ui/meter/meter.svelte +50 -2
  73. package/dist/ui/meter/meter.svelte.d.ts +38 -1
  74. package/dist/ui/nav/index.d.ts +2 -0
  75. package/dist/ui/nav/index.js +2 -0
  76. package/dist/ui/nav/nav-bar.svelte +51 -0
  77. package/dist/ui/nav/nav-bar.svelte.d.ts +21 -0
  78. package/dist/ui/nav/nav-item.svelte +79 -0
  79. package/dist/ui/nav/nav-item.svelte.d.ts +29 -0
  80. package/dist/ui/provider/axes.d.ts +14 -1
  81. package/dist/ui/provider/axis-relay.svelte.d.ts +34 -0
  82. package/dist/ui/provider/axis-relay.svelte.js +109 -0
  83. package/dist/ui/select/select-content.svelte +2 -2
  84. package/dist/ui/select/select-content.svelte.d.ts +2 -2
  85. package/dist/ui/select/select-trigger.svelte +2 -2
  86. package/dist/ui/select/select-trigger.svelte.d.ts +2 -2
  87. package/dist/ui/sheet/sheet-content.svelte +8 -2
  88. package/dist/ui/sheet/sheet-content.svelte.d.ts +2 -2
  89. package/dist/ui/step/step-content.svelte +2 -2
  90. package/dist/ui/step/step-content.svelte.d.ts +2 -2
  91. package/dist/ui/step/step-summary.svelte +2 -2
  92. package/dist/ui/step/step-summary.svelte.d.ts +2 -2
  93. package/dist/ui/time-field/time-field-input.svelte +9 -0
  94. package/dist/ui/time-range-field/time-range-field-input.svelte +9 -0
  95. package/dist/ui/tooltip/index.d.ts +1 -1
  96. package/dist/ui/tooltip/index.js +1 -1
  97. package/dist/ui/tooltip/tooltip-content.svelte +6 -2
  98. package/dist/ui/tooltip/tooltip-content.svelte.d.ts +2 -2
  99. package/dist/ui/tooltip/tooltip-root.svelte +33 -0
  100. package/dist/ui/tooltip/tooltip-root.svelte.d.ts +8 -0
  101. package/dist/ui/tooltip/tooltip-trigger.svelte +8 -0
  102. package/dist/utils/index.d.ts +36 -3
  103. package/package.json +6 -4
package/CHANGELOG.md CHANGED
@@ -1,3 +1,48 @@
1
+ ## [23.0.0](https://github.com/sig-nine/era-ui/compare/v22.0.0...v23.0.0) (2026-08-09)
2
+
3
+ ### ⚠ BREAKING CHANGES
4
+
5
+ * **portal:** era owns `Root` for alert-dialog, context-menu, dialog,
6
+ dropdown-menu, link-preview, menubar, sheet and tooltip, where seven of them
7
+ previously re-exported bits-ui's. Behaviour and props are unchanged and `open`
8
+ stays bindable, but anyone importing `Root` for its bits-ui identity — a type
9
+ cast, an `instanceof`-style comparison — is now getting era's wrapper. Content
10
+ opened inside a scoped subtree also now RENDERS with that subtree's axes rather
11
+ than the document's, which is the point, and is a visible change anywhere a
12
+ scope existed and was being silently ignored.
13
+ * **types:** `PartProps<T>` no longer strips `child`. Anything relying on it
14
+ to produce a child-free prop type should use `OwnedPartProps<T>`, which is the
15
+ old definition under a name that says why.
16
+
17
+ ### Features
18
+
19
+ * **nav:** a navigation landmark whose current item announces itself ([9ffb1f2](https://github.com/sig-nine/era-ui/commit/9ffb1f2519b15aa312e6a545eb2462bdf4d9d6a0))
20
+ * **portal:** the five axes cross the portal ([de1b2ba](https://github.com/sig-nine/era-ui/commit/de1b2ba066a87bbe331df600edd78ef716ae935e))
21
+ * **types:** restore bits-ui's `child` on the parts era only restyles ([7659a36](https://github.com/sig-nine/era-ui/commit/7659a3643b466ac915c25a7578b94cf6e680d40a))
22
+
23
+ ## [22.0.0](https://github.com/sig-nine/era-ui/compare/v21.0.0...v22.0.0) (2026-08-09)
24
+
25
+ ### ⚠ BREAKING CHANGES
26
+
27
+ * **font:** a stack is read AT the element carrying `data-font`, so
28
+ `--era-font-mono` / `-sans` / `-serif` must be re-pointed at or above that
29
+ element. Setting one on a descendant of the axis host now does nothing, where
30
+ before it applied to that subtree. /audit was doing exactly this — it re-pointed
31
+ the stacks on its own <main> while the axis lived on <html>, so the harness had
32
+ been measuring the docs' pinned `monospace` while reporting the shipped stack —
33
+ and now sets them on :root. Nesting `data-font` also genuinely works, which for
34
+ anyone relying on the old source-order behaviour is a visible change.
35
+
36
+ Closes the test.fixme in axis-nesting.spec.ts; the suite now has no skips.
37
+
38
+ ### Features
39
+
40
+ * **meter:** a meter can say which band its reading is in ([9119e38](https://github.com/sig-nine/era-ui/commit/9119e38425ca511c0ff9f31a52efdf9f80dd390f))
41
+
42
+ ### Bug Fixes
43
+
44
+ * **font:** the font axis resolves by depth, like every other axis ([a1041bd](https://github.com/sig-nine/era-ui/commit/a1041bdc59a41b9829e5dad42bf727f434e67f7f))
45
+
1
46
  ## [21.0.0](https://github.com/sig-nine/era-ui/compare/v20.0.0...v21.0.0) (2026-08-09)
2
47
 
3
48
  ### ⚠ BREAKING CHANGES
@@ -2,12 +2,12 @@ import { TOL, tiers } from './_helpers.js';
2
2
  /*
3
3
  * Every chrome-bearing control must land on a tier.
4
4
  *
5
- * The tier ladder (xs / xxs / sm / md / lg) is the whole basis of the even-gap and
5
+ * The tier ladder (icon / pill / chip / control / bar) is the whole basis of the even-gap and
6
6
  * concentricity laws: those laws are stated in terms of (h_outer − h_inner)/2, so
7
7
  * a control that sits BETWEEN tiers can never nest concentrically in anything —
8
8
  * it silently poisons every gap around it. That is exactly how the date segments
9
9
  * broke: 21px tall, which is no tier at all, so their 1.5px gap could not match any
10
- * radius step. Putting them on the sm tier (22px) is what let the identity close.
10
+ * radius step. Putting them on the chip tier (22px) is what let the identity close.
11
11
  *
12
12
  * A grep cannot see this. `h-[21px]` would be caught by the hardcoded-px rule, but
13
13
  * these segments had NO height class at all — 21px was whatever the line box
@@ -21,6 +21,20 @@ export const offTierHeight = {
21
21
  severity: 'warn',
22
22
  selector: 'button, input, [role="switch"], [role="checkbox"], [role="radio"], [data-segment]',
23
23
  check(el) {
24
+ // AN UNBOUNDED CONTAINER IS NOT A TIER OBJECT. era has one place where a
25
+ // <button> is a container rather than a control: an interactive Card, which
26
+ // renders as <button> or <a> and whose height is its content's. Holding it
27
+ // to a tier would be asking a card to be 32px tall, and the geometric/optical
28
+ // padding split in density.css exists precisely because unbounded containers
29
+ // are NOT sized from the ladder.
30
+ //
31
+ // Marked, not inferred. The tempting test — "does its padding match an
32
+ // optical pad token?" — collides: --era-pad-panel is 5.6px at balanced and
33
+ // --era-inset-chip is 6px, inside this audit's own 0.5px tolerance. That
34
+ // would silently exempt a real control from the audit that catches poisoned
35
+ // gaps, which is the worst direction for this rule to be wrong in.
36
+ if (el.dataset?.eraUnbounded !== undefined)
37
+ return null;
24
38
  const s = getComputedStyle(el);
25
39
  // Chromeless controls (Button's `link` variant is tinted text, no box) have
26
40
  // no tier to be on — their height is their line box, by design.
@@ -31,11 +31,13 @@ import { TOL, flexChildren, isHorizontalFlex, paintsChrome, tiers } from './_hel
31
31
  * compare against, and an unbounded container's padding is optical rather than
32
32
  * geometric (see the geometric/optical split in density.css).
33
33
  *
34
- * DELIBERATE ASYMMETRY. Some era chrome is legitimately not isotropic: a pane
35
- * handle sits its leading side at the text inset while the trailing side keeps
36
- * the concentric wall. Those opt out with data-era-anisotropic, which is a claim
37
- * a reviewer can check rather than a silence — the same shape as
38
- * data-era-continuous on surface/invisible-box.
34
+ * DELIBERATE ASYMMETRY. Some era chrome is legitimately not isotropic, and it
35
+ * opts out with data-era-anisotropic rather than by being a shape this rule
36
+ * happens not to match the same claim-over-silence design as
37
+ * data-era-continuous on surface/invisible-box. The date/time field inputs carry
38
+ * it: --era-field-px is the room where typed TEXT starts, purpose-named and
39
+ * floored in density.css, so 8px at the sides against a 1px concentric gap is
40
+ * the intended reading and says so at the call site.
39
41
  */
40
42
  export const wallIsIsotropic = {
41
43
  id: 'layout/wall-is-isotropic',
@@ -105,13 +107,16 @@ export const wallIsIsotropic = {
105
107
  // match when an icon is present. Measuring those against the icon
106
108
  // reports 6-vs-5 on rows that are following the house rule.
107
109
  //
108
- // A TEXT FIELD (date/time field and their ranges) walls by
109
- // --era-field-px, which density.css names and floors on purpose: it is
110
- // the room where typed text starts, and it is not the segment box's
111
- // concentric gap. Measuring those reports 8-vs-1 on a deliberate choice.
112
- //
113
110
  // What is left is the case the law is actually about — chrome holding
114
111
  // controls — and it is where both shipped bugs were.
112
+ //
113
+ // The OTHER standing exception, a text field walling by --era-field-px,
114
+ // is not handled here: those four components carry data-era-anisotropic
115
+ // and are turned away at the top of this function. Verified load-bearing
116
+ // by disabling this heuristic and confirming they stay silent, which is
117
+ // the point of declaring it — the exemption survives a change to the
118
+ // scope rule, and it is a claim at the call site rather than a shape
119
+ // this function happens not to match.
115
120
  const CONTROL = 'button, a[href], input, select, textarea, [role="button"], [role="switch"],' +
116
121
  ' [role="checkbox"], [role="radio"], [role="combobox"], [role="tab"], [role="menuitem"]';
117
122
  const tallestKid = kids.find((k) => Math.abs(k.getBoundingClientRect().height - tallest) <= TOL);