@signal9/era-ui 32.0.0 → 33.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 (145) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/dev/audit-overlay.svelte +2 -2
  3. package/dist/era-ui.css +1 -1
  4. package/dist/generated-docs/utilities.json +99 -99
  5. package/dist/os/pane.svelte +3 -13
  6. package/dist/styles/index.css +2 -956
  7. package/dist/styles/typography.css +1 -1
  8. package/dist/styles/utilities/geometry.css +188 -0
  9. package/dist/styles/utilities/interaction.css +334 -0
  10. package/dist/styles/utilities/materials.css +39 -0
  11. package/dist/styles/utilities/public.css +391 -0
  12. package/dist/styles/utilities.css +5 -0
  13. package/dist/ui/card/card.svelte +2 -52
  14. package/dist/ui/card/card.svelte.d.ts +0 -43
  15. package/dist/ui/card/variants.d.ts +44 -0
  16. package/dist/ui/card/variants.js +20 -0
  17. package/dist/ui/context-menu/context-menu-checkbox-item.svelte +2 -4
  18. package/dist/ui/context-menu/context-menu-group-heading.svelte +2 -5
  19. package/dist/ui/context-menu/context-menu-item.svelte +2 -8
  20. package/dist/ui/context-menu/context-menu-radio-item.svelte +2 -8
  21. package/dist/ui/context-menu/context-menu-separator.svelte +2 -5
  22. package/dist/ui/context-menu/context-menu-sub-trigger.svelte +2 -8
  23. package/dist/ui/dialog/dialog-header.svelte +1 -1
  24. package/dist/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +2 -4
  25. package/dist/ui/dropdown-menu/dropdown-menu-group-heading.svelte +2 -5
  26. package/dist/ui/dropdown-menu/dropdown-menu-item.svelte +2 -8
  27. package/dist/ui/dropdown-menu/dropdown-menu-radio-item.svelte +2 -8
  28. package/dist/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -5
  29. package/dist/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -8
  30. package/dist/ui/menu-recipes.d.ts +6 -0
  31. package/dist/ui/menu-recipes.js +6 -0
  32. package/dist/ui/menubar/menubar-checkbox-item.svelte +2 -9
  33. package/dist/ui/menubar/menubar-group-heading.svelte +2 -5
  34. package/dist/ui/menubar/menubar-item.svelte +2 -8
  35. package/dist/ui/menubar/menubar-radio-item.svelte +2 -8
  36. package/dist/ui/menubar/menubar-separator.svelte +2 -5
  37. package/dist/ui/menubar/menubar-sub-trigger.svelte +2 -8
  38. package/dist/ui/pane/pane-close.svelte +7 -26
  39. package/dist/ui/video-player/video-player.svelte +8 -8
  40. package/package.json +48 -12
  41. package/dist/docs/badge.md +0 -18
  42. package/dist/docs/bits-ui-audit.md +0 -58
  43. package/dist/docs/button.md +0 -19
  44. package/dist/docs/chip.md +0 -20
  45. package/dist/docs/component-docs-core.d.ts +0 -8
  46. package/dist/docs/component-docs-core.js +0 -73
  47. package/dist/docs/component-docs.d.ts +0 -2
  48. package/dist/docs/component-docs.js +0 -25
  49. package/dist/docs/component-source-scanners.d.ts +0 -18
  50. package/dist/docs/component-source-scanners.js +0 -46
  51. package/dist/docs/consumer-import.d.ts +0 -65
  52. package/dist/docs/consumer-import.js +0 -70
  53. package/dist/docs/css-utilities.d.ts +0 -58
  54. package/dist/docs/css-utilities.js +0 -317
  55. package/dist/docs/extract-props.d.ts +0 -13
  56. package/dist/docs/extract-props.js +0 -324
  57. package/dist/docs/generated-docs.d.ts +0 -6
  58. package/dist/docs/generated-docs.js +0 -30
  59. package/dist/docs/index.d.ts +0 -5
  60. package/dist/docs/index.js +0 -66
  61. package/dist/docs/notes.md +0 -83
  62. package/dist/docs/scroll-area.md +0 -7
  63. package/dist/docs/separator.md +0 -20
  64. package/dist/docs/table.md +0 -35
  65. package/dist/docs/utilities.d.ts +0 -4
  66. package/dist/docs/utilities.js +0 -15
  67. package/dist/generated-docs/accordion.md +0 -57
  68. package/dist/generated-docs/alert-dialog.md +0 -91
  69. package/dist/generated-docs/aspect-ratio.md +0 -17
  70. package/dist/generated-docs/avatar.md +0 -39
  71. package/dist/generated-docs/badge.md +0 -41
  72. package/dist/generated-docs/bar.md +0 -41
  73. package/dist/generated-docs/button-group.md +0 -19
  74. package/dist/generated-docs/button.md +0 -117
  75. package/dist/generated-docs/calendar.md +0 -126
  76. package/dist/generated-docs/card.md +0 -58
  77. package/dist/generated-docs/checkbox.md +0 -42
  78. package/dist/generated-docs/chip.md +0 -61
  79. package/dist/generated-docs/code-block.md +0 -20
  80. package/dist/generated-docs/collapsible.md +0 -30
  81. package/dist/generated-docs/combobox.md +0 -74
  82. package/dist/generated-docs/command-bar.md +0 -3
  83. package/dist/generated-docs/command.md +0 -126
  84. package/dist/generated-docs/context-menu.md +0 -104
  85. package/dist/generated-docs/copy-button.md +0 -29
  86. package/dist/generated-docs/cycle.md +0 -29
  87. package/dist/generated-docs/date-field.md +0 -49
  88. package/dist/generated-docs/date-picker.md +0 -180
  89. package/dist/generated-docs/date-range-field.md +0 -50
  90. package/dist/generated-docs/date-range-picker.md +0 -180
  91. package/dist/generated-docs/dialog.md +0 -94
  92. package/dist/generated-docs/draggable.md +0 -3
  93. package/dist/generated-docs/dropdown-menu.md +0 -104
  94. package/dist/generated-docs/file-upload.md +0 -18
  95. package/dist/generated-docs/getting-started.md +0 -3
  96. package/dist/generated-docs/input.md +0 -23
  97. package/dist/generated-docs/kv.md +0 -20
  98. package/dist/generated-docs/label.md +0 -17
  99. package/dist/generated-docs/link-preview.md +0 -40
  100. package/dist/generated-docs/llm-shell.md +0 -3
  101. package/dist/generated-docs/llms-full.txt +0 -5201
  102. package/dist/generated-docs/llms.txt +0 -138
  103. package/dist/generated-docs/logo.md +0 -24
  104. package/dist/generated-docs/manifest.json +0 -1685
  105. package/dist/generated-docs/measurements.md +0 -3
  106. package/dist/generated-docs/menu.md +0 -11
  107. package/dist/generated-docs/menubar.md +0 -104
  108. package/dist/generated-docs/meter.md +0 -101
  109. package/dist/generated-docs/mode.md +0 -24
  110. package/dist/generated-docs/nav.md +0 -73
  111. package/dist/generated-docs/navigation-menu.md +0 -11
  112. package/dist/generated-docs/notes.md +0 -87
  113. package/dist/generated-docs/os.md +0 -3
  114. package/dist/generated-docs/pagination.md +0 -55
  115. package/dist/generated-docs/pane.md +0 -34
  116. package/dist/generated-docs/pin-input.md +0 -31
  117. package/dist/generated-docs/popover.md +0 -43
  118. package/dist/generated-docs/progress.md +0 -17
  119. package/dist/generated-docs/radio-group.md +0 -31
  120. package/dist/generated-docs/range-calendar.md +0 -11
  121. package/dist/generated-docs/rating-group.md +0 -31
  122. package/dist/generated-docs/scroll-area.md +0 -65
  123. package/dist/generated-docs/select.md +0 -67
  124. package/dist/generated-docs/separator.md +0 -57
  125. package/dist/generated-docs/sheet.md +0 -11
  126. package/dist/generated-docs/skeleton.md +0 -18
  127. package/dist/generated-docs/slider.md +0 -71
  128. package/dist/generated-docs/spacing.md +0 -3
  129. package/dist/generated-docs/step.md +0 -51
  130. package/dist/generated-docs/surfaces.md +0 -3
  131. package/dist/generated-docs/switch.md +0 -18
  132. package/dist/generated-docs/table.md +0 -113
  133. package/dist/generated-docs/tabs.md +0 -48
  134. package/dist/generated-docs/text.md +0 -3
  135. package/dist/generated-docs/time-field.md +0 -49
  136. package/dist/generated-docs/time-range-field.md +0 -50
  137. package/dist/generated-docs/timeline.md +0 -32
  138. package/dist/generated-docs/todo.md +0 -3
  139. package/dist/generated-docs/toggle-group.md +0 -31
  140. package/dist/generated-docs/toggle.md +0 -20
  141. package/dist/generated-docs/toolbar.md +0 -11
  142. package/dist/generated-docs/tooltip.md +0 -40
  143. package/dist/generated-docs/tree.md +0 -36
  144. package/dist/generated-docs/utilities.md +0 -1236
  145. package/dist/generated-docs/video-player.md +0 -73
@@ -2,6 +2,7 @@
2
2
  import { ContextMenu } from 'bits-ui';
3
3
  import ChevronRight from '@lucide/svelte/icons/chevron-right';
4
4
  import { cn, type OwnedPartProps } from '../../utils/index.js';
5
+ import { menuSubTrigger } from '../menu-recipes.js';
5
6
 
6
7
  let {
7
8
  ref = $bindable(null),
@@ -11,14 +12,7 @@
11
12
  }: OwnedPartProps<ContextMenu.SubTriggerProps> = $props();
12
13
  </script>
13
14
 
14
- <ContextMenu.SubTrigger
15
- bind:ref
16
- class={cn(
17
- 'flex h-control cursor-pointer items-center justify-between gap-icon-inset-chip rounded-menu-item px-inset-control text-body text-fg data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[state=open]:bg-hover',
18
- className
19
- )}
20
- {...restProps}
21
- >
15
+ <ContextMenu.SubTrigger bind:ref class={cn(menuSubTrigger, className)} {...restProps}>
22
16
  {@render children?.()}
23
17
  <ChevronRight class="size-icon text-muted" />
24
18
  </ContextMenu.SubTrigger>
@@ -24,7 +24,7 @@
24
24
  · the leading side at --era-inset-control: a title has no corner to nest, so
25
25
  it takes the text inset, the same asymmetry the pane and the
26
26
  Conversations row document
27
- · the × is the dismiss family's: an xxs `Dialog.Close` whose tier
27
+ · the × is the dismiss family's: a pill-tier `Dialog.Close` whose tier
28
28
  default IS the 12px ink, destructive like Pane.Close
29
29
 
30
30
  Rendered flush by Dialog.Content / Sheet.Content when passed as their
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuChoiceItem } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -13,9 +14,6 @@
13
14
  <DropdownMenu.CheckboxItem
14
15
  bind:ref
15
16
  bind:checked
16
- class={cn(
17
- 'flex h-control cursor-pointer items-center rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight',
18
- className
19
- )}
17
+ class={cn(menuChoiceItem, className)}
20
18
  {...restProps}
21
19
  />
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuGroupHeading } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -9,8 +10,4 @@
9
10
  }: DropdownMenu.GroupHeadingProps = $props();
10
11
  </script>
11
12
 
12
- <DropdownMenu.GroupHeading
13
- bind:ref
14
- class={cn('flex h-control items-center px-inset-control text-body text-muted', className)}
15
- {...restProps}
16
- />
13
+ <DropdownMenu.GroupHeading bind:ref class={cn(menuGroupHeading, className)} {...restProps} />
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import { cn, type PartProps } from '../../utils/index.js';
4
+ import { menuItem } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -10,13 +11,6 @@
10
11
  }: PartProps<DropdownMenu.ItemProps> = $props();
11
12
  </script>
12
13
 
13
- <DropdownMenu.Item
14
- bind:ref
15
- class={cn(
16
- 'flex h-control cursor-pointer items-center gap-gutter rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight',
17
- className
18
- )}
19
- {...restProps}
20
- >
14
+ <DropdownMenu.Item bind:ref class={cn(menuItem, className)} {...restProps}>
21
15
  {@render children?.()}
22
16
  </DropdownMenu.Item>
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuChoiceItem } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -9,11 +10,4 @@
9
10
  }: DropdownMenu.RadioItemProps = $props();
10
11
  </script>
11
12
 
12
- <DropdownMenu.RadioItem
13
- bind:ref
14
- class={cn(
15
- 'flex h-control cursor-pointer items-center rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight',
16
- className
17
- )}
18
- {...restProps}
19
- />
13
+ <DropdownMenu.RadioItem bind:ref class={cn(menuChoiceItem, className)} {...restProps} />
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuSeparator } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -9,8 +10,4 @@
9
10
  }: DropdownMenu.SeparatorProps = $props();
10
11
  </script>
11
12
 
12
- <DropdownMenu.Separator
13
- bind:ref
14
- class={cn('my-[calc(var(--era-gap)/2)] h-px bg-divider-faded', className)}
15
- {...restProps}
16
- />
13
+ <DropdownMenu.Separator bind:ref class={cn(menuSeparator, className)} {...restProps} />
@@ -2,6 +2,7 @@
2
2
  import { DropdownMenu } from 'bits-ui';
3
3
  import ChevronRight from '@lucide/svelte/icons/chevron-right';
4
4
  import { cn, type OwnedPartProps } from '../../utils/index.js';
5
+ import { menuSubTrigger } from '../menu-recipes.js';
5
6
 
6
7
  let {
7
8
  ref = $bindable(null),
@@ -11,14 +12,7 @@
11
12
  }: OwnedPartProps<DropdownMenu.SubTriggerProps> = $props();
12
13
  </script>
13
14
 
14
- <DropdownMenu.SubTrigger
15
- bind:ref
16
- class={cn(
17
- 'flex h-control cursor-pointer items-center justify-between gap-icon-inset-chip rounded-menu-item px-inset-control text-body text-fg data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[state=open]:bg-hover',
18
- className
19
- )}
20
- {...restProps}
21
- >
15
+ <DropdownMenu.SubTrigger bind:ref class={cn(menuSubTrigger, className)} {...restProps}>
22
16
  {@render children?.()}
23
17
  <ChevronRight class="size-icon text-muted" />
24
18
  </DropdownMenu.SubTrigger>
@@ -0,0 +1,6 @@
1
+ /** Shared semantics for the three Bits UI menu families. */
2
+ export declare const menuItem = "flex h-control cursor-pointer items-center gap-gutter rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight";
3
+ export declare const menuChoiceItem = "flex h-control cursor-pointer items-center rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight";
4
+ export declare const menuSubTrigger = "flex h-control cursor-pointer items-center justify-between gap-icon-inset-chip rounded-menu-item px-inset-control text-body text-fg data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[state=open]:bg-hover";
5
+ export declare const menuSeparator = "my-[calc(var(--era-gap)/2)] h-px bg-divider-faded";
6
+ export declare const menuGroupHeading = "flex h-control items-center px-inset-control text-body text-muted";
@@ -0,0 +1,6 @@
1
+ /** Shared semantics for the three Bits UI menu families. */
2
+ export const menuItem = 'flex h-control cursor-pointer items-center gap-gutter rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight';
3
+ export const menuChoiceItem = 'flex h-control cursor-pointer items-center rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight';
4
+ export const menuSubTrigger = 'flex h-control cursor-pointer items-center justify-between gap-icon-inset-chip rounded-menu-item px-inset-control text-body text-fg data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[state=open]:bg-hover';
5
+ export const menuSeparator = 'my-[calc(var(--era-gap)/2)] h-px bg-divider-faded';
6
+ export const menuGroupHeading = 'flex h-control items-center px-inset-control text-body text-muted';
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { Menubar } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuChoiceItem } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -10,12 +11,4 @@
10
11
  }: Menubar.CheckboxItemProps = $props();
11
12
  </script>
12
13
 
13
- <Menubar.CheckboxItem
14
- bind:ref
15
- bind:checked
16
- class={cn(
17
- 'flex h-control cursor-pointer items-center rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight',
18
- className
19
- )}
20
- {...restProps}
21
- />
14
+ <Menubar.CheckboxItem bind:ref bind:checked class={cn(menuChoiceItem, className)} {...restProps} />
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { Menubar } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuGroupHeading } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -9,8 +10,4 @@
9
10
  }: Menubar.GroupHeadingProps = $props();
10
11
  </script>
11
12
 
12
- <Menubar.GroupHeading
13
- bind:ref
14
- class={cn('flex h-control items-center px-inset-control text-body text-muted', className)}
15
- {...restProps}
16
- />
13
+ <Menubar.GroupHeading bind:ref class={cn(menuGroupHeading, className)} {...restProps} />
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import { Menubar } from 'bits-ui';
3
3
  import { cn, type PartProps } from '../../utils/index.js';
4
+ import { menuItem } from '../menu-recipes.js';
4
5
 
5
6
  let {
6
7
  ref = $bindable(null),
@@ -10,13 +11,6 @@
10
11
  }: PartProps<Menubar.ItemProps> = $props();
11
12
  </script>
12
13
 
13
- <Menubar.Item
14
- bind:ref
15
- class={cn(
16
- 'flex h-control cursor-pointer items-center gap-gutter rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight',
17
- className
18
- )}
19
- {...restProps}
20
- >
14
+ <Menubar.Item bind:ref class={cn(menuItem, className)} {...restProps}>
21
15
  {@render children?.()}
22
16
  </Menubar.Item>
@@ -1,15 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { Menubar } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuChoiceItem } from '../menu-recipes.js';
4
5
 
5
6
  let { ref = $bindable(null), class: className, ...restProps }: Menubar.RadioItemProps = $props();
6
7
  </script>
7
8
 
8
- <Menubar.RadioItem
9
- bind:ref
10
- class={cn(
11
- 'flex h-control cursor-pointer items-center rounded-menu-item px-inset-control text-body text-fg data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight',
12
- className
13
- )}
14
- {...restProps}
15
- />
9
+ <Menubar.RadioItem bind:ref class={cn(menuChoiceItem, className)} {...restProps} />
@@ -1,12 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { Menubar } from 'bits-ui';
3
3
  import { cn } from '../../utils/index.js';
4
+ import { menuSeparator } from '../menu-recipes.js';
4
5
 
5
6
  let { ref = $bindable(null), class: className, ...restProps }: Menubar.SeparatorProps = $props();
6
7
  </script>
7
8
 
8
- <Menubar.Separator
9
- bind:ref
10
- class={cn('my-[calc(var(--era-gap)/2)] h-px bg-divider-faded', className)}
11
- {...restProps}
12
- />
9
+ <Menubar.Separator bind:ref class={cn(menuSeparator, className)} {...restProps} />
@@ -2,6 +2,7 @@
2
2
  import { Menubar } from 'bits-ui';
3
3
  import ChevronRight from '@lucide/svelte/icons/chevron-right';
4
4
  import { cn, type OwnedPartProps } from '../../utils/index.js';
5
+ import { menuSubTrigger } from '../menu-recipes.js';
5
6
 
6
7
  let {
7
8
  ref = $bindable(null),
@@ -11,14 +12,7 @@
11
12
  }: OwnedPartProps<Menubar.SubTriggerProps> = $props();
12
13
  </script>
13
14
 
14
- <Menubar.SubTrigger
15
- bind:ref
16
- class={cn(
17
- 'flex h-control cursor-pointer items-center justify-between gap-icon-inset-chip rounded-menu-item px-inset-control text-body text-fg data-[highlighted]:bg-highlight data-[highlighted]:shadow-highlight data-[state=open]:bg-hover',
18
- className
19
- )}
20
- {...restProps}
21
- >
15
+ <Menubar.SubTrigger bind:ref class={cn(menuSubTrigger, className)} {...restProps}>
22
16
  {@render children?.()}
23
17
  <ChevronRight class="size-icon text-muted" />
24
18
  </Menubar.SubTrigger>
@@ -2,7 +2,6 @@
2
2
  import type { HTMLButtonAttributes } from 'svelte/elements';
3
3
  import { Button } from '../button';
4
4
  import X from '@lucide/svelte/icons/x';
5
- import { cn } from '../../utils/index.js';
6
5
 
7
6
  let {
8
7
  ref = $bindable(null),
@@ -13,42 +12,24 @@
13
12
  } = $props();
14
13
  </script>
15
14
 
16
- <!-- A raw icon Button (size="pill" = h-pill, rd-xxs), a tight SQUARE. No
15
+ <!-- A raw icon Button (size="pill" = h-pill), a tight SQUARE. No
17
16
  data-pane-control: it stays in the drag zone, so a press-and-drag moves the
18
17
  pane while a clean click still closes (neodrag starts a drag only on
19
18
  movement and suppresses the trailing click after a real drag). Its natural
20
- rd-xxs is what the PANE's corner radius conforms to (rd-md — see Pane.Root),
19
+ pill radius is what the PANE's corner radius conforms to (see Pane.Root),
21
20
  not the other way round.
22
21
 
23
- xxs rather than the tighter `icon` size, which is what the handle's tier
24
- asks for. The GLYPH is deliberately OFF the sub-tier ladder: sp+5, where the
25
- ladder offers sp+4 (12px at dense, the xxs sub-tier) and the h-icon floor
26
- (14px). Both were tried and both are wrong here by a pixel — 12 reads
27
- visibly lighter than the reference terminal app's close button, 14 reads
28
- heavier — and a close button is the one control in the chrome you must be
29
- able to hit and read at a glance, so a pixel of it is worth an exception.
30
-
31
- sp+5 is 13/15/17/21, matching that app's 13px at dense, and the pad it
32
- leaves is a constant 2.5px at EVERY mode, so the exception is uniform rather
33
- than one hand-picked number.
34
-
35
- The pad being fractional costs nothing for this glyph in particular: an ×
36
- is two DIAGONAL strokes, which the rasteriser antialiases wherever the box
37
- lands, so pixel alignment buys no crispness (it would for the minimize −,
38
- which is axis-aligned — that one stays on the ladder). If a second component
39
- ever wants this size, it graduates from a calc here to a token in
40
- density.css.
41
-
42
- Written as [&_svg]: because that is the selector Button's icon variant uses —
43
- a bare size-* on the <X> loses to it, which is why an earlier class there had
44
- no effect at all. -->
22
+ The Button's pill glyph tier is exactly 6px smaller than its pill box:
23
+ 18px around 12px at dense, and the same difference at every density. That
24
+ leaves a whole-pixel 3px inset on all four sides without a pane-specific
25
+ size exception. -->
45
26
  <Button
46
27
  bind:ref
47
28
  icon
48
29
  size="pill"
49
30
  tone="destructive"
50
31
  aria-label="Close"
51
- class={cn('[&_svg]:size-[calc(var(--era-sp)+0.3125rem)]', className)}
32
+ class={className}
52
33
  {...restProps}
53
34
  >
54
35
  <X />
@@ -1,7 +1,7 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
3
  import { untrack } from 'svelte';
4
- import { browser } from '$app/environment';
4
+ import { BROWSER } from 'esm-env';
5
5
  import {
6
6
  ContextMenu as BitsContextMenu,
7
7
  DropdownMenu as BitsDropdownMenu,
@@ -41,8 +41,8 @@
41
41
  // or default stylesheet — every control is built from this library.
42
42
  // Wait for both custom elements to be defined before wiring remote control
43
43
  // and subscriptions; otherwise, mount can race and leave controls inert.
44
- let elementsDefined = $state(!browser);
45
- if (browser) {
44
+ let elementsDefined = $state(!BROWSER);
45
+ if (BROWSER) {
46
46
  void Promise.all([
47
47
  import('vidstack/define/media-player'),
48
48
  import('vidstack/define/media-outlet'),
@@ -313,7 +313,7 @@
313
313
  // and `new` throws. Templates only invoke `remote` from event handlers, so
314
314
  // it never runs during server render.
315
315
  let remote!: MediaRemoteControl;
316
- if (browser) remote = new MediaRemoteControl();
316
+ if (BROWSER) remote = new MediaRemoteControl();
317
317
 
318
318
  $effect(() => {
319
319
  if (!elementsDefined) return;
@@ -375,7 +375,7 @@
375
375
  // vidstack would still flip idle on `pause → play` if left long enough — so
376
376
  // we tell the controller to pause idle tracking and resume on cleanup.
377
377
  $effect(() => {
378
- if (!browser || !elementsDefined || !playerEl) return;
378
+ if (!BROWSER || !elementsDefined || !playerEl) return;
379
379
  if (autoHide) return;
380
380
  remote.pauseUserIdle();
381
381
  return () => remote.resumeUserIdle();
@@ -386,7 +386,7 @@
386
386
  // true and the consumer has opted in via `idleWhilePaused`. Reset on any
387
387
  // pointer or keyboard activity inside the player element.
388
388
  $effect(() => {
389
- if (!browser || !elementsDefined || !playerEl) return;
389
+ if (!BROWSER || !elementsDefined || !playerEl) return;
390
390
  if (!autoHide || !idleWhilePaused || !paused) {
391
391
  pausedIdle = false;
392
392
  return;
@@ -415,7 +415,7 @@
415
415
  });
416
416
 
417
417
  function downloadVideo() {
418
- if (!browser) return;
418
+ if (!BROWSER) return;
419
419
  const link = document.createElement('a');
420
420
  link.href = src;
421
421
  // Same-origin sources honor the download attribute and save the file.
@@ -625,7 +625,7 @@
625
625
  }
626
626
 
627
627
  $effect(() => {
628
- if (!browser) return;
628
+ if (!BROWSER) return;
629
629
  const src = chapterTrack?.src;
630
630
  if (!src) {
631
631
  chapterCues = [];
package/package.json CHANGED
@@ -1,33 +1,49 @@
1
1
  {
2
2
  "name": "@signal9/era-ui",
3
- "version": "32.0.0",
3
+ "version": "33.0.0",
4
+ "packageManager": "npm@11.19.0",
5
+ "engines": {
6
+ "node": ">=24 <27",
7
+ "npm": ">=11 <13"
8
+ },
4
9
  "scripts": {
10
+ "predev": "npm run build:llm-docs",
5
11
  "dev": "vite dev --host",
6
- "build": "vite build && npm run prepack",
12
+ "build": "npm run build:llm-docs && vite build && npm run package:build",
7
13
  "test:visual": "playwright test",
14
+ "test:browser:ci": "playwright test --grep @release --grep-invert @snapshot",
8
15
  "test:visual:deep": "ERA_TEST_DEPTH=deep playwright test",
16
+ "test:unit": "node --test tests/unit/*.test.mjs",
9
17
  "deploy": "npm run build && npx --yes wrangler@latest deploy",
10
18
  "preview": "wrangler dev .svelte-kit/cloudflare/_worker.js --port 4173",
11
19
  "prepare": "git config core.hooksPath .githooks 2>/dev/null || true; svelte-kit sync || echo ''",
12
- "prepack": "svelte-kit sync && svelte-package && node scripts/build-styles.js && publint",
20
+ "package:build": "svelte-kit sync && svelte-package && node scripts/build-styles.js && node scripts/run-publint.mjs",
21
+ "prepack": "npm run build:llm-docs && npm run package:build",
13
22
  "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
14
- "check:mode-verbatim": "npm run prepack && svelte-check --tsconfig tests/smoke/mode-verbatim/tsconfig.json",
23
+ "check:mode-verbatim": "npm run package:build && svelte-check --tsconfig tests/smoke/mode-verbatim/tsconfig.json",
15
24
  "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
16
- "lint": "eslint .",
25
+ "lint": "node scripts/lint.mjs",
26
+ "lint:changed": "node scripts/lint.mjs --changed",
17
27
  "format": "prettier --write .",
18
28
  "format:check": "prettier --check .",
19
29
  "gen": "wrangler types",
20
30
  "check:surfaces": "node --experimental-strip-types scripts/check-surfaces.ts",
21
31
  "check:tokens": "node --experimental-strip-types scripts/check-tokens.ts",
22
- "check:routes": "node --experimental-strip-types scripts/check-routes.ts",
32
+ "check:routes": "jiti scripts/check-routes.ts",
23
33
  "check:canonical": "node --experimental-strip-types scripts/check-canonical.ts",
24
34
  "check:layers": "node --experimental-strip-types scripts/check-layers.ts",
35
+ "check:boundaries": "node --experimental-strip-types scripts/check-boundaries.ts",
36
+ "check:agent-guidance": "node --experimental-strip-types scripts/check-agent-guidance.ts",
37
+ "check:api": "node --experimental-strip-types scripts/check-api-report.ts",
38
+ "api:update": "node --experimental-strip-types scripts/check-api-report.ts --update",
39
+ "check:package-consumer": "node scripts/check-package-consumer.mjs",
25
40
  "check:themes": "node --experimental-strip-types scripts/check-themes.ts",
26
41
  "check:classes": "node --experimental-strip-types scripts/check-classes.ts",
27
42
  "check:twmerge": "node --experimental-strip-types scripts/check-twmerge.ts",
28
- "build:llm-docs": "node --experimental-strip-types scripts/build-llm-docs.ts",
29
- "prebuild": "npm run check:surfaces && npm run check:tokens && npm run check:routes && npm run check:canonical && npm run check:layers && npm run check:themes && npm run check:classes && npm run check:twmerge && npm run check:doc-tokens && npm run check:audit-controls && npm run check:specimen-coverage && npm run check:eslint-rules && npm run check:install && npm run check:reachable && npm run check:double-edge && npm run check:geometry && npm run build:llm-docs",
30
- "validate": "npm run check && npm run lint && npm run format:check && npm run check:surfaces && npm run check:tokens && npm run check:routes && npm run check:canonical && npm run check:layers && npm run check:themes && npm run check:classes && npm run check:twmerge && npm run check:doc-tokens && npm run check:audit-controls && npm run check:specimen-coverage && npm run check:eslint-rules && npm run check:install && npm run check:reachable && npm run check:double-edge && npm run check:geometry",
43
+ "build:llm-docs": "jiti scripts/build-llm-docs.ts",
44
+ "verify": "node scripts/verify.mjs --mode=changed",
45
+ "verify:full": "node scripts/verify.mjs --mode=full",
46
+ "validate": "node scripts/verify.mjs --mode=validate",
31
47
  "test": "npm run test:visual",
32
48
  "check:doc-tokens": "node --experimental-strip-types scripts/check-doc-tokens.ts",
33
49
  "check:audit-controls": "node --experimental-strip-types scripts/check-audit-controls.ts",
@@ -37,14 +53,33 @@
37
53
  "check:reachable": "node --experimental-strip-types scripts/check-reachable.ts",
38
54
  "check:double-edge": "node --experimental-strip-types scripts/check-double-edge.ts",
39
55
  "check:geometry": "node --experimental-strip-types scripts/check-geometry.ts",
40
- "verify:published": "node scripts/verify-published.mjs"
56
+ "check:toolchain": "node scripts/check-toolchain.mjs",
57
+ "check:contracts-generated": "node scripts/generate-contracts.mjs --check",
58
+ "check:generated-docs": "jiti scripts/check-generated-docs.ts",
59
+ "check:visual-language": "node --experimental-strip-types scripts/check-visual-language.ts",
60
+ "check:consumer-lab": "node scripts/check-consumer-lab.mjs",
61
+ "contracts:update": "node scripts/generate-contracts.mjs",
62
+ "docs:update": "jiti scripts/check-generated-docs.ts --update",
63
+ "component:create": "node scripts/create-component.mjs",
64
+ "inspect": "node scripts/inspect.mjs",
65
+ "verify:published": "node scripts/verify-published.mjs",
66
+ "verify:registries": "node scripts/verify-registries.mjs",
67
+ "verify:release": "node scripts/verify.mjs --mode=release"
41
68
  },
42
69
  "files": [
43
70
  "dist",
44
71
  "skill",
45
72
  "CHANGELOG.md",
46
73
  "!dist/**/*.test.*",
47
- "!dist/**/*.spec.*"
74
+ "!dist/**/*.spec.*",
75
+ "!dist/**/AGENTS.md",
76
+ "!dist/docs/**",
77
+ "!dist/ui/*/contract.*",
78
+ "!dist/ui/contracts.*",
79
+ "!dist/ui/component-contract.*",
80
+ "!dist/generated-docs/*.md",
81
+ "!dist/generated-docs/*.txt",
82
+ "!dist/generated-docs/manifest.json"
48
83
  ],
49
84
  "sideEffects": [
50
85
  "**/*.css"
@@ -132,7 +167,6 @@
132
167
  "@playwright/test": "^1.62.1",
133
168
  "@semantic-release/changelog": "^7.0.0",
134
169
  "@semantic-release/exec": "^7.1.0",
135
- "@semantic-release/git": "^11.0.1",
136
170
  "@sveltejs/adapter-cloudflare": "^7.2.9",
137
171
  "@sveltejs/kit": "^2.70.2",
138
172
  "@sveltejs/package": "^2.5.8",
@@ -165,6 +199,7 @@
165
199
  "eslint-plugin-better-tailwindcss": "^4.7.0",
166
200
  "eslint-plugin-svelte": "^3.22.0",
167
201
  "globals": "^17.9.0",
202
+ "jiti": "^2.7.0",
168
203
  "lowlight": "^3.3.0",
169
204
  "marked": "^18.0.9",
170
205
  "prettier": "^3.9.6",
@@ -199,6 +234,7 @@
199
234
  "@lucide/svelte": "^1.30.0",
200
235
  "bits-ui": "^2.18.1",
201
236
  "clsx": "^2.1.1",
237
+ "esm-env": "^1.2.2",
202
238
  "tailwind-merge": "^3.6.0",
203
239
  "tailwind-variants": "^3.3.1"
204
240
  },
@@ -1,18 +0,0 @@
1
- ## Usage
2
-
3
- ```svelte
4
- <script>
5
- import { Badge } from '@signal9/era-ui/badge';
6
- </script>
7
-
8
- <Badge>draft</Badge>
9
- <Badge tone="accent">new</Badge>
10
- <Badge tone="success">passing</Badge>
11
- <Badge tone="destructive">failing</Badge>
12
- ```
13
-
14
- ## Notes
15
-
16
- - Non-interactive. For dismissible tokens use `Chip`. For labelled pairs use `KV`.
17
- - Uses the `xxs` tier tokens (height, radius, inset).
18
- - Inter-icon gap tightens to `--era-inset-pill` when an SVG is present.
@@ -1,58 +0,0 @@
1
- # Bits UI leverage audit
2
-
3
- _Date: 2026-04-22_
4
-
5
- ## High-level status
6
-
7
- Era UI already wraps most of the major Bits UI primitives (accordion, dialog, menus, date/time fields, calendar/date pickers, command, select/combobox, etc.).
8
-
9
- ## Components that are **custom-only** today
10
-
11
- These directories currently do not import `bits-ui` and are intentionally custom presentation components:
12
-
13
- - `badge`
14
- - `bar`
15
- - `button-group`
16
- - `card`
17
- - `chip`
18
- - `code-block`
19
- - `file-upload`
20
- - `input`
21
- - `kv`
22
- - `mode`
23
- - `skeleton`
24
- - `table`
25
-
26
- ### Which of these are likely fine as custom components
27
-
28
- No direct Bits UI primitive exists for these semantic/presentational pieces:
29
-
30
- - `badge`, `bar`, `button-group`, `card`, `chip`, `code-block`, `kv`, `mode`, `skeleton`, `table`
31
-
32
- ### One likely improvement area
33
-
34
- - `input` can stay native for simple text input, but if you want richer semantics and stronger consistency with the rest of the library, consider introducing wrappers around Bits UI field-family components (`DateField`, `TimeField`, etc.) as your recommended form surface. This is more of a product/design-system choice than a correctness gap.
35
-
36
- - `file-upload` has no first-class Bits UI file-upload primitive, so your custom drag/drop implementation is expected.
37
-
38
- ## Bits UI primitives available but not wrapped yet
39
-
40
- Bits UI currently exposes additional primitives that are not represented in `src/lib/ui` yet:
41
-
42
- - `avatar`
43
- - `collapsible`
44
- - `link-preview`
45
- - `menu`
46
- - `navigation-menu`
47
- - `range-calendar`
48
- - `rating-group`
49
- - `toggle-group`
50
- - `toolbar`
51
-
52
- If your design system roadmap includes any of those UX patterns, adding wrappers would be the main way to “take fuller advantage” of Bits UI from where the repo is today.
53
-
54
- ## Practical recommendations
55
-
56
- 1. **Prioritize wrappers with immediate UX value**: `avatar`, `collapsible`, `toggle-group`, `toolbar`.
57
- 2. **Document intentional non-Bits components** (`card`, `badge`, `table`, `skeleton`) so contributors know these are design primitives, not missing migrations.
58
- 3. **Keep custom `file-upload`** unless Bits UI adds a dedicated primitive later.
@@ -1,19 +0,0 @@
1
- ## Usage
2
-
3
- ```svelte
4
- <script>
5
- import { Button } from '@signal9/era-ui/button';
6
- </script>
7
-
8
- <Button onclick={() => console.log('clicked')}>Save</Button>
9
- <Button tone="accent" size="chip">Confirm</Button>
10
- <Button tone="destructive" variant="link">Delete</Button>
11
- <Button icon size="icon" aria-label="Close"><X /></Button>
12
- ```
13
-
14
- ## Notes
15
-
16
- - Heights, radii, paddings, and gaps come from density tokens — never hard-code px.
17
- - `link` variant intentionally does not change color on hover (underline only) so it reads as static prose until confirmed interactive.
18
- - `variant="link"` is for a _control_ that should look like a link (a button that reveals a panel, a destructive action in a row). For a link in body copy or prose, use the `era-link` CSS utility on an `<a>` instead — see [Utilities](/utilities.md).
19
- - For a segmented row of buttons, use `ButtonGroup`.