@signal9/era-ui 32.0.1 → 33.0.1

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 (142) hide show
  1. package/CHANGELOG.md +6 -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/styles/index.css +2 -956
  6. package/dist/styles/typography.css +1 -1
  7. package/dist/styles/utilities/geometry.css +188 -0
  8. package/dist/styles/utilities/interaction.css +334 -0
  9. package/dist/styles/utilities/materials.css +39 -0
  10. package/dist/styles/utilities/public.css +391 -0
  11. package/dist/styles/utilities.css +5 -0
  12. package/dist/ui/card/card.svelte +2 -52
  13. package/dist/ui/card/card.svelte.d.ts +0 -43
  14. package/dist/ui/card/variants.d.ts +44 -0
  15. package/dist/ui/card/variants.js +20 -0
  16. package/dist/ui/context-menu/context-menu-checkbox-item.svelte +2 -4
  17. package/dist/ui/context-menu/context-menu-group-heading.svelte +2 -5
  18. package/dist/ui/context-menu/context-menu-item.svelte +2 -8
  19. package/dist/ui/context-menu/context-menu-radio-item.svelte +2 -8
  20. package/dist/ui/context-menu/context-menu-separator.svelte +2 -5
  21. package/dist/ui/context-menu/context-menu-sub-trigger.svelte +2 -8
  22. package/dist/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +2 -4
  23. package/dist/ui/dropdown-menu/dropdown-menu-group-heading.svelte +2 -5
  24. package/dist/ui/dropdown-menu/dropdown-menu-item.svelte +2 -8
  25. package/dist/ui/dropdown-menu/dropdown-menu-radio-item.svelte +2 -8
  26. package/dist/ui/dropdown-menu/dropdown-menu-separator.svelte +2 -5
  27. package/dist/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +2 -8
  28. package/dist/ui/menu-recipes.d.ts +6 -0
  29. package/dist/ui/menu-recipes.js +6 -0
  30. package/dist/ui/menubar/menubar-checkbox-item.svelte +2 -9
  31. package/dist/ui/menubar/menubar-group-heading.svelte +2 -5
  32. package/dist/ui/menubar/menubar-item.svelte +2 -8
  33. package/dist/ui/menubar/menubar-radio-item.svelte +2 -8
  34. package/dist/ui/menubar/menubar-separator.svelte +2 -5
  35. package/dist/ui/menubar/menubar-sub-trigger.svelte +2 -8
  36. package/dist/ui/video-player/video-player.svelte +8 -8
  37. package/package.json +48 -12
  38. package/dist/docs/badge.md +0 -18
  39. package/dist/docs/bits-ui-audit.md +0 -58
  40. package/dist/docs/button.md +0 -19
  41. package/dist/docs/chip.md +0 -20
  42. package/dist/docs/component-docs-core.d.ts +0 -8
  43. package/dist/docs/component-docs-core.js +0 -73
  44. package/dist/docs/component-docs.d.ts +0 -2
  45. package/dist/docs/component-docs.js +0 -25
  46. package/dist/docs/component-source-scanners.d.ts +0 -18
  47. package/dist/docs/component-source-scanners.js +0 -46
  48. package/dist/docs/consumer-import.d.ts +0 -65
  49. package/dist/docs/consumer-import.js +0 -70
  50. package/dist/docs/css-utilities.d.ts +0 -58
  51. package/dist/docs/css-utilities.js +0 -317
  52. package/dist/docs/extract-props.d.ts +0 -13
  53. package/dist/docs/extract-props.js +0 -324
  54. package/dist/docs/generated-docs.d.ts +0 -6
  55. package/dist/docs/generated-docs.js +0 -30
  56. package/dist/docs/index.d.ts +0 -5
  57. package/dist/docs/index.js +0 -66
  58. package/dist/docs/notes.md +0 -83
  59. package/dist/docs/scroll-area.md +0 -7
  60. package/dist/docs/separator.md +0 -20
  61. package/dist/docs/table.md +0 -35
  62. package/dist/docs/utilities.d.ts +0 -4
  63. package/dist/docs/utilities.js +0 -15
  64. package/dist/generated-docs/accordion.md +0 -57
  65. package/dist/generated-docs/alert-dialog.md +0 -91
  66. package/dist/generated-docs/aspect-ratio.md +0 -17
  67. package/dist/generated-docs/avatar.md +0 -39
  68. package/dist/generated-docs/badge.md +0 -41
  69. package/dist/generated-docs/bar.md +0 -41
  70. package/dist/generated-docs/button-group.md +0 -19
  71. package/dist/generated-docs/button.md +0 -117
  72. package/dist/generated-docs/calendar.md +0 -126
  73. package/dist/generated-docs/card.md +0 -58
  74. package/dist/generated-docs/checkbox.md +0 -42
  75. package/dist/generated-docs/chip.md +0 -61
  76. package/dist/generated-docs/code-block.md +0 -20
  77. package/dist/generated-docs/collapsible.md +0 -30
  78. package/dist/generated-docs/combobox.md +0 -74
  79. package/dist/generated-docs/command-bar.md +0 -3
  80. package/dist/generated-docs/command.md +0 -126
  81. package/dist/generated-docs/context-menu.md +0 -104
  82. package/dist/generated-docs/copy-button.md +0 -29
  83. package/dist/generated-docs/cycle.md +0 -29
  84. package/dist/generated-docs/date-field.md +0 -49
  85. package/dist/generated-docs/date-picker.md +0 -180
  86. package/dist/generated-docs/date-range-field.md +0 -50
  87. package/dist/generated-docs/date-range-picker.md +0 -180
  88. package/dist/generated-docs/dialog.md +0 -94
  89. package/dist/generated-docs/draggable.md +0 -3
  90. package/dist/generated-docs/dropdown-menu.md +0 -104
  91. package/dist/generated-docs/file-upload.md +0 -18
  92. package/dist/generated-docs/getting-started.md +0 -3
  93. package/dist/generated-docs/input.md +0 -23
  94. package/dist/generated-docs/kv.md +0 -20
  95. package/dist/generated-docs/label.md +0 -17
  96. package/dist/generated-docs/link-preview.md +0 -40
  97. package/dist/generated-docs/llm-shell.md +0 -3
  98. package/dist/generated-docs/llms-full.txt +0 -5201
  99. package/dist/generated-docs/llms.txt +0 -138
  100. package/dist/generated-docs/logo.md +0 -24
  101. package/dist/generated-docs/manifest.json +0 -1685
  102. package/dist/generated-docs/measurements.md +0 -3
  103. package/dist/generated-docs/menu.md +0 -11
  104. package/dist/generated-docs/menubar.md +0 -104
  105. package/dist/generated-docs/meter.md +0 -101
  106. package/dist/generated-docs/mode.md +0 -24
  107. package/dist/generated-docs/nav.md +0 -73
  108. package/dist/generated-docs/navigation-menu.md +0 -11
  109. package/dist/generated-docs/notes.md +0 -87
  110. package/dist/generated-docs/os.md +0 -3
  111. package/dist/generated-docs/pagination.md +0 -55
  112. package/dist/generated-docs/pane.md +0 -34
  113. package/dist/generated-docs/pin-input.md +0 -31
  114. package/dist/generated-docs/popover.md +0 -43
  115. package/dist/generated-docs/progress.md +0 -17
  116. package/dist/generated-docs/radio-group.md +0 -31
  117. package/dist/generated-docs/range-calendar.md +0 -11
  118. package/dist/generated-docs/rating-group.md +0 -31
  119. package/dist/generated-docs/scroll-area.md +0 -65
  120. package/dist/generated-docs/select.md +0 -67
  121. package/dist/generated-docs/separator.md +0 -57
  122. package/dist/generated-docs/sheet.md +0 -11
  123. package/dist/generated-docs/skeleton.md +0 -18
  124. package/dist/generated-docs/slider.md +0 -71
  125. package/dist/generated-docs/spacing.md +0 -3
  126. package/dist/generated-docs/step.md +0 -51
  127. package/dist/generated-docs/surfaces.md +0 -3
  128. package/dist/generated-docs/switch.md +0 -18
  129. package/dist/generated-docs/table.md +0 -113
  130. package/dist/generated-docs/tabs.md +0 -48
  131. package/dist/generated-docs/text.md +0 -3
  132. package/dist/generated-docs/time-field.md +0 -49
  133. package/dist/generated-docs/time-range-field.md +0 -50
  134. package/dist/generated-docs/timeline.md +0 -32
  135. package/dist/generated-docs/todo.md +0 -3
  136. package/dist/generated-docs/toggle-group.md +0 -31
  137. package/dist/generated-docs/toggle.md +0 -20
  138. package/dist/generated-docs/toolbar.md +0 -11
  139. package/dist/generated-docs/tooltip.md +0 -40
  140. package/dist/generated-docs/tree.md +0 -36
  141. package/dist/generated-docs/utilities.md +0 -1236
  142. 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>
@@ -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>
@@ -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.1",
3
+ "version": "33.0.1",
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`.
package/dist/docs/chip.md DELETED
@@ -1,20 +0,0 @@
1
- ## Usage
2
-
3
- ```svelte
4
- <script>
5
- import { Chip } from '@signal9/era-ui/chip';
6
-
7
- let tags = $state(['alpha', 'beta', 'gamma']);
8
- </script>
9
-
10
- {#each tags as tag}
11
- <Chip ondismiss={() => (tags = tags.filter((t) => t !== tag))}>
12
- {tag}
13
- </Chip>
14
- {/each}
15
- ```
16
-
17
- ## Notes
18
-
19
- - Internal pointerdown/up events on the dismiss button are stopped from bubbling — this prevents accidental toggling when a Chip is nested inside a Select/Popover trigger.
20
- - Uses the `xxs` tier tokens (height, radius, inset). Part of the Badge/Chip/KV "tag" family.
@@ -1,8 +0,0 @@
1
- import type { ComponentEntry } from '../../routes/registry.js';
2
- import type { RootExport, SubExport } from './component-source-scanners.js';
3
- export interface ComponentDocSources {
4
- rootExports: Record<string, RootExport>;
5
- subExportsBySlug: Record<string, SubExport[]>;
6
- svelteBySlug: Record<string, Record<string, string>>;
7
- }
8
- export declare function buildComponentDocFromSources(entry: ComponentEntry, sources: ComponentDocSources, appendix?: string): string;