sv5ui 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +6 -0
  2. package/dist/Alert/Alert.svelte +33 -22
  3. package/dist/Alert/Alert.svelte.d.ts +1 -1
  4. package/dist/Alert/alert.types.d.ts +4 -0
  5. package/dist/Avatar/Avatar.svelte +72 -46
  6. package/dist/Avatar/avatar.types.d.ts +36 -3
  7. package/dist/Avatar/avatar.variants.d.ts +138 -0
  8. package/dist/Avatar/avatar.variants.js +23 -12
  9. package/dist/Avatar/index.d.ts +1 -1
  10. package/dist/AvatarGroup/AvatarGroup.svelte +11 -6
  11. package/dist/AvatarGroup/AvatarGroup.svelte.d.ts +1 -1
  12. package/dist/AvatarGroup/avatar-group.types.d.ts +18 -3
  13. package/dist/AvatarGroup/avatar-group.variants.d.ts +85 -0
  14. package/dist/AvatarGroup/avatar-group.variants.js +19 -29
  15. package/dist/Badge/Badge.svelte +4 -3
  16. package/dist/Badge/Badge.svelte.d.ts +1 -1
  17. package/dist/Badge/badge.types.d.ts +9 -0
  18. package/dist/Breadcrumb/Breadcrumb.svelte +20 -7
  19. package/dist/Breadcrumb/Breadcrumb.svelte.d.ts +1 -1
  20. package/dist/Breadcrumb/breadcrumb.types.d.ts +5 -1
  21. package/dist/Breadcrumb/breadcrumb.variants.d.ts +15 -5
  22. package/dist/Breadcrumb/breadcrumb.variants.js +7 -3
  23. package/dist/Button/Button.svelte +71 -16
  24. package/dist/Button/Button.svelte.d.ts +0 -1
  25. package/dist/Button/button.types.d.ts +61 -2
  26. package/dist/Calendar/Calendar.svelte +4 -0
  27. package/dist/Calendar/Calendar.svelte.d.ts +1 -1
  28. package/dist/Calendar/calendar.types.d.ts +4 -0
  29. package/dist/Card/Card.svelte +5 -4
  30. package/dist/Card/Card.svelte.d.ts +1 -1
  31. package/dist/Card/card.types.d.ts +5 -1
  32. package/dist/Checkbox/Checkbox.svelte +37 -11
  33. package/dist/Checkbox/Checkbox.svelte.d.ts +1 -1
  34. package/dist/Checkbox/checkbox.types.d.ts +16 -1
  35. package/dist/Checkbox/checkbox.variants.d.ts +90 -0
  36. package/dist/Checkbox/checkbox.variants.js +73 -4
  37. package/dist/Chip/Chip.svelte +3 -2
  38. package/dist/Chip/Chip.svelte.d.ts +1 -1
  39. package/dist/Chip/chip.types.d.ts +5 -1
  40. package/dist/Chip/chip.variants.d.ts +135 -45
  41. package/dist/Chip/chip.variants.js +9 -9
  42. package/dist/ContextMenu/ContextMenu.svelte +87 -77
  43. package/dist/ContextMenu/ContextMenu.svelte.d.ts +1 -1
  44. package/dist/ContextMenu/context-menu.types.d.ts +9 -3
  45. package/dist/ContextMenu/context-menu.types.js +1 -1
  46. package/dist/ContextMenu/context-menu.variants.d.ts +74 -160
  47. package/dist/ContextMenu/context-menu.variants.js +63 -95
  48. package/dist/DropdownMenu/DropdownMenu.svelte +37 -43
  49. package/dist/DropdownMenu/DropdownMenu.svelte.d.ts +1 -1
  50. package/dist/DropdownMenu/dropdown-menu.types.d.ts +9 -3
  51. package/dist/DropdownMenu/dropdown-menu.types.js +1 -1
  52. package/dist/DropdownMenu/dropdown-menu.variants.d.ts +79 -230
  53. package/dist/DropdownMenu/dropdown-menu.variants.js +68 -111
  54. package/dist/DropdownMenu/index.d.ts +1 -1
  55. package/dist/Empty/Empty.svelte +68 -33
  56. package/dist/Empty/Empty.svelte.d.ts +1 -1
  57. package/dist/Empty/empty.types.d.ts +26 -9
  58. package/dist/Empty/empty.variants.d.ts +150 -130
  59. package/dist/Empty/empty.variants.js +33 -324
  60. package/dist/FieldGroup/FieldGroup.svelte +11 -6
  61. package/dist/FieldGroup/FieldGroup.svelte.d.ts +1 -1
  62. package/dist/FieldGroup/field-group.types.d.ts +4 -0
  63. package/dist/FormField/FormField.svelte +17 -18
  64. package/dist/FormField/FormField.svelte.d.ts +1 -1
  65. package/dist/FormField/form-field.types.d.ts +4 -0
  66. package/dist/Icon/Icon.svelte +13 -7
  67. package/dist/Icon/icon.types.d.ts +18 -9
  68. package/dist/Input/Input.svelte +30 -29
  69. package/dist/Kbd/Kbd.svelte +13 -3
  70. package/dist/Kbd/Kbd.svelte.d.ts +1 -1
  71. package/dist/Kbd/index.d.ts +1 -1
  72. package/dist/Kbd/kbd.types.d.ts +15 -1
  73. package/dist/Kbd/kbd.variants.d.ts +92 -30
  74. package/dist/Kbd/kbd.variants.js +55 -35
  75. package/dist/Kbd/useKbd.svelte.d.ts +2 -2
  76. package/dist/Kbd/useKbd.svelte.js +34 -41
  77. package/dist/Link/Link.svelte +69 -24
  78. package/dist/Link/Link.svelte.d.ts +1 -1
  79. package/dist/Link/link.types.d.ts +26 -8
  80. package/dist/Link/link.variants.d.ts +35 -60
  81. package/dist/Link/link.variants.js +8 -110
  82. package/dist/Modal/Modal.svelte +9 -1
  83. package/dist/Modal/modal.types.d.ts +5 -0
  84. package/dist/Modal/modal.variants.d.ts +5 -0
  85. package/dist/Modal/modal.variants.js +1 -0
  86. package/dist/Pagination/Pagination.svelte +143 -94
  87. package/dist/Pagination/Pagination.svelte.d.ts +1 -1
  88. package/dist/Pagination/index.d.ts +1 -1
  89. package/dist/Pagination/pagination.types.d.ts +21 -2
  90. package/dist/Pagination/pagination.variants.d.ts +21 -387
  91. package/dist/Pagination/pagination.variants.js +63 -59
  92. package/dist/Popover/Popover.svelte +9 -12
  93. package/dist/Popover/Popover.svelte.d.ts +1 -1
  94. package/dist/Popover/popover.types.d.ts +4 -0
  95. package/dist/Popover/popover.variants.d.ts +5 -75
  96. package/dist/Popover/popover.variants.js +6 -16
  97. package/dist/Progress/Progress.svelte +58 -30
  98. package/dist/Progress/progress.types.d.ts +9 -1
  99. package/dist/Progress/progress.variants.d.ts +55 -25
  100. package/dist/Progress/progress.variants.js +34 -28
  101. package/dist/RadioGroup/RadioGroup.svelte +105 -61
  102. package/dist/RadioGroup/RadioGroup.svelte.d.ts +1 -1
  103. package/dist/RadioGroup/radio-group.types.d.ts +16 -1
  104. package/dist/RadioGroup/radio-group.variants.d.ts +90 -0
  105. package/dist/RadioGroup/radio-group.variants.js +73 -4
  106. package/dist/Select/Select.svelte +9 -6
  107. package/dist/Select/Select.svelte.d.ts +1 -1
  108. package/dist/Select/select.types.d.ts +4 -0
  109. package/dist/SelectMenu/SelectMenu.svelte +436 -0
  110. package/dist/SelectMenu/SelectMenu.svelte.d.ts +5 -0
  111. package/dist/SelectMenu/index.d.ts +2 -0
  112. package/dist/SelectMenu/index.js +1 -0
  113. package/dist/SelectMenu/select-menu.types.d.ts +262 -0
  114. package/dist/SelectMenu/select-menu.types.js +1 -0
  115. package/dist/SelectMenu/select-menu.variants.d.ts +759 -0
  116. package/dist/SelectMenu/select-menu.variants.js +33 -0
  117. package/dist/Separator/Separator.svelte +1 -2
  118. package/dist/Separator/separator.variants.d.ts +1 -5
  119. package/dist/Separator/separator.variants.js +2 -2
  120. package/dist/Skeleton/Skeleton.svelte +18 -2
  121. package/dist/Skeleton/Skeleton.svelte.d.ts +1 -1
  122. package/dist/Skeleton/skeleton.types.d.ts +10 -1
  123. package/dist/Slideover/Slideover.svelte +9 -1
  124. package/dist/Slideover/slideover.types.d.ts +5 -0
  125. package/dist/Slideover/slideover.variants.d.ts +20 -5
  126. package/dist/Slideover/slideover.variants.js +4 -29
  127. package/dist/Switch/Switch.svelte +32 -31
  128. package/dist/Switch/Switch.svelte.d.ts +1 -1
  129. package/dist/Switch/switch.types.d.ts +6 -1
  130. package/dist/Switch/switch.variants.js +6 -6
  131. package/dist/Tabs/Tabs.svelte +6 -9
  132. package/dist/Tabs/Tabs.svelte.d.ts +1 -1
  133. package/dist/Tabs/tabs.types.d.ts +4 -0
  134. package/dist/Tabs/tabs.variants.js +2 -0
  135. package/dist/Textarea/Textarea.svelte +26 -25
  136. package/dist/ThemeModeButton/theme-mode-button.types.d.ts +7 -2
  137. package/dist/Timeline/Timeline.svelte +62 -19
  138. package/dist/Timeline/Timeline.svelte.d.ts +1 -1
  139. package/dist/Timeline/index.d.ts +1 -1
  140. package/dist/Timeline/timeline.types.d.ts +8 -0
  141. package/dist/Tooltip/Tooltip.svelte +12 -10
  142. package/dist/Tooltip/Tooltip.svelte.d.ts +1 -1
  143. package/dist/Tooltip/tooltip.types.d.ts +8 -4
  144. package/dist/Tooltip/tooltip.variants.d.ts +10 -75
  145. package/dist/Tooltip/tooltip.variants.js +8 -17
  146. package/dist/User/User.svelte +13 -9
  147. package/dist/User/User.svelte.d.ts +1 -1
  148. package/dist/User/user.types.d.ts +4 -0
  149. package/dist/User/user.variants.d.ts +60 -0
  150. package/dist/User/user.variants.js +13 -1
  151. package/dist/config.d.ts +4 -0
  152. package/dist/config.js +4 -0
  153. package/dist/index.d.ts +1 -1
  154. package/dist/index.js +1 -1
  155. package/package.json +2 -2
@@ -91,15 +91,16 @@
91
91
  loading && isTrailing ? loadingIcon : trailingIcon || (trailing ? icon : undefined)
92
92
  )
93
93
 
94
- const ariaDescribedBy = $derived.by(() => {
95
- if (!formFieldContext) return undefined
96
- const id = formFieldContext.ariaId
97
- if (hasError) return `${id}-error`
98
- return `${id}-description ${id}-help`
99
- })
94
+ const ariaDescribedBy = $derived(
95
+ !formFieldContext
96
+ ? undefined
97
+ : hasError
98
+ ? `${formFieldContext.ariaId}-error`
99
+ : `${formFieldContext.ariaId}-description ${formFieldContext.ariaId}-help`
100
+ )
100
101
 
101
- const classes = $derived.by(() => {
102
- const slots = textareaVariants({
102
+ const variantSlots = $derived(
103
+ textareaVariants({
103
104
  variant,
104
105
  color: resolvedColor,
105
106
  size: resolvedSize,
@@ -109,22 +110,22 @@
109
110
  highlight: resolvedHighlight,
110
111
  autoresize
111
112
  })
112
- return {
113
- root: slots.root({
114
- class: [config.slots.root, fieldGroupClass?.root, className, ui?.root]
115
- }),
116
- base: slots.base({
117
- class: [config.slots.base, fieldGroupClass?.base, ui?.base]
118
- }),
119
- leading: slots.leading({ class: [config.slots.leading, ui?.leading] }),
120
- leadingIcon: slots.leadingIcon({
121
- class: [config.slots.leadingIcon, ui?.leadingIcon]
122
- }),
123
- trailing: slots.trailing({ class: [config.slots.trailing, ui?.trailing] }),
124
- trailingIcon: slots.trailingIcon({
125
- class: [config.slots.trailingIcon, ui?.trailingIcon]
126
- })
127
- }
113
+ )
114
+ const classes = $derived({
115
+ root: variantSlots.root({
116
+ class: [config.slots.root, fieldGroupClass?.root, className, ui?.root]
117
+ }),
118
+ base: variantSlots.base({
119
+ class: [config.slots.base, fieldGroupClass?.base, ui?.base]
120
+ }),
121
+ leading: variantSlots.leading({ class: [config.slots.leading, ui?.leading] }),
122
+ leadingIcon: variantSlots.leadingIcon({
123
+ class: [config.slots.leadingIcon, ui?.leadingIcon]
124
+ }),
125
+ trailing: variantSlots.trailing({ class: [config.slots.trailing, ui?.trailing] }),
126
+ trailingIcon: variantSlots.trailingIcon({
127
+ class: [config.slots.trailingIcon, ui?.trailingIcon]
128
+ })
128
129
  })
129
130
 
130
131
  let cachedMaxHeight = $state(0)
@@ -172,6 +173,7 @@
172
173
  {/if}
173
174
 
174
175
  <textarea
176
+ {...restProps}
175
177
  bind:this={ref}
176
178
  bind:value
177
179
  {rows}
@@ -181,7 +183,6 @@
181
183
  aria-describedby={ariaDescribedBy}
182
184
  aria-invalid={resolvedHighlight ? true : undefined}
183
185
  class={classes.base}
184
- {...restProps}
185
186
  ></textarea>
186
187
 
187
188
  {#if trailingSlot}
@@ -1,9 +1,9 @@
1
1
  import type { Snippet } from 'svelte';
2
- import type { HTMLButtonAttributes } from 'svelte/elements';
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
3
  import type { ClassNameValue } from 'tailwind-merge';
4
4
  import type { ButtonVariantProps } from '../Button/button.variants.js';
5
5
  import type { ThemeModeButtonSlots } from './theme-mode-button.variants.js';
6
- export type ThemeModeButtonProps = Omit<HTMLButtonAttributes, 'children'> & {
6
+ export type ThemeModeButtonProps = Omit<HTMLAttributes<HTMLElement>, 'class' | 'children'> & {
7
7
  /**
8
8
  * Controls the visual style of the button.
9
9
  * @default 'ghost'
@@ -36,6 +36,11 @@ export type ThemeModeButtonProps = Omit<HTMLButtonAttributes, 'children'> & {
36
36
  * @default false
37
37
  */
38
38
  loading?: boolean;
39
+ /**
40
+ * Disables the button and prevents interaction.
41
+ * @default false
42
+ */
43
+ disabled?: boolean;
39
44
  /**
40
45
  * Forces equal width and height, ideal for icon-only buttons.
41
46
  * @default true
@@ -5,6 +5,7 @@
5
5
  </script>
6
6
 
7
7
  <script lang="ts">
8
+ import type { ClassNameValue } from 'tailwind-merge'
8
9
  import { timelineVariants, timelineDefaults } from './timeline.variants.js'
9
10
  import type { TimelineItemState } from './timeline.types.js'
10
11
  import { getComponentConfig } from '../config.js'
@@ -14,6 +15,7 @@
14
15
  const config = getComponentConfig('timeline', timelineDefaults)
15
16
 
16
17
  let {
18
+ ref = $bindable(null),
17
19
  as = 'div',
18
20
  items = [],
19
21
  size = config.defaultVariants.size,
@@ -31,19 +33,54 @@
31
33
  ...restProps
32
34
  }: Props = $props()
33
35
 
34
- // Pre-compute shared slot classes outside the loop (these don't vary per item)
36
+ type ItemUi = Partial<Record<string, ClassNameValue>>
37
+
35
38
  const classes = $derived.by(() => {
36
39
  const slots = timelineVariants({ orientation, color, size, reverse })
40
+ const c = config.slots
41
+
42
+ // Pre-compute defaults — reused for all items without per-item ui
43
+ const _item = slots.item({ class: [c.item, ui?.item] })
44
+ const _container = slots.container({ class: [c.container, ui?.container] })
45
+ const _indicator = slots.indicator({ class: [c.indicator, ui?.indicator] })
46
+ const _separator = slots.separator({ class: [c.separator, ui?.separator] })
47
+ const _wrapper = slots.wrapper({ class: [c.wrapper, ui?.wrapper] })
48
+ const _date = slots.date({ class: [c.date, ui?.date] })
49
+ const _title = slots.title({ class: [c.title, ui?.title] })
50
+ const _description = slots.description({ class: [c.description, ui?.description] })
51
+
37
52
  return {
38
- root: slots.root({ class: [config.slots.root, className, ui?.root] }),
39
- item: slots.item({ class: [config.slots.item, ui?.item] }),
40
- container: slots.container({ class: [config.slots.container, ui?.container] }),
41
- indicator: slots.indicator({ class: [config.slots.indicator, ui?.indicator] }),
42
- separator: slots.separator({ class: [config.slots.separator, ui?.separator] }),
43
- wrapper: slots.wrapper({ class: [config.slots.wrapper, ui?.wrapper] }),
44
- date: slots.date({ class: [config.slots.date, ui?.date] }),
45
- title: slots.title({ class: [config.slots.title, ui?.title] }),
46
- description: slots.description({ class: [config.slots.description, ui?.description] })
53
+ root: slots.root({ class: [c.root, className, ui?.root] }),
54
+ item: (itemClass?: ClassNameValue, itemUi?: ItemUi) =>
55
+ itemClass || itemUi
56
+ ? slots.item({ class: [c.item, ui?.item, itemUi?.item, itemClass] })
57
+ : _item,
58
+ container: (itemUi?: ItemUi) =>
59
+ itemUi
60
+ ? slots.container({ class: [c.container, ui?.container, itemUi.container] })
61
+ : _container,
62
+ indicator: (itemUi?: ItemUi) =>
63
+ itemUi
64
+ ? slots.indicator({ class: [c.indicator, ui?.indicator, itemUi.indicator] })
65
+ : _indicator,
66
+ separator: (itemUi?: ItemUi) =>
67
+ itemUi
68
+ ? slots.separator({ class: [c.separator, ui?.separator, itemUi.separator] })
69
+ : _separator,
70
+ wrapper: (itemUi?: ItemUi) =>
71
+ itemUi
72
+ ? slots.wrapper({ class: [c.wrapper, ui?.wrapper, itemUi.wrapper] })
73
+ : _wrapper,
74
+ date: (itemUi?: ItemUi) =>
75
+ itemUi?.date ? slots.date({ class: [c.date, ui?.date, itemUi.date] }) : _date,
76
+ title: (itemUi?: ItemUi) =>
77
+ itemUi?.title ? slots.title({ class: [c.title, ui?.title, itemUi.title] }) : _title,
78
+ description: (itemUi?: ItemUi) =>
79
+ itemUi?.description
80
+ ? slots.description({
81
+ class: [c.description, ui?.description, itemUi.description]
82
+ })
83
+ : _description
47
84
  }
48
85
  })
49
86
 
@@ -58,15 +95,21 @@
58
95
  }
59
96
  </script>
60
97
 
61
- <svelte:element this={as} class={classes.root} {...restProps}>
98
+ <svelte:element
99
+ this={as}
100
+ bind:this={ref}
101
+ class={classes.root}
102
+ data-orientation={orientation}
103
+ {...restProps}
104
+ >
62
105
  {#each items as item, index (item.value ?? index)}
63
106
  {@const state = getState(index)}
64
- <div class={item.class ? `${classes.item} ${item.class}` : classes.item} data-state={state}>
65
- <div class={classes.container}>
107
+ <div class={classes.item(item.class, item.ui)} data-state={state}>
108
+ <div class={classes.container(item.ui)}>
66
109
  {#if indicator}
67
110
  {@render indicator({ item, index, state })}
68
111
  {:else}
69
- <div class={classes.indicator}>
112
+ <div class={classes.indicator(item.ui)}>
70
113
  {#if item.avatar}
71
114
  <Avatar {...item.avatar} {size} />
72
115
  {:else if item.icon}
@@ -76,27 +119,27 @@
76
119
  {/if}
77
120
 
78
121
  {#if reverse ? index > 0 : index < items.length - 1}
79
- <div class={classes.separator}></div>
122
+ <div class={classes.separator(item.ui)}></div>
80
123
  {/if}
81
124
  </div>
82
125
 
83
- <div class={classes.wrapper}>
126
+ <div class={classes.wrapper(item.ui)}>
84
127
  {#if dateSlot}
85
128
  {@render dateSlot({ item, index, state })}
86
129
  {:else if item.date}
87
- <div class={classes.date}>{item.date}</div>
130
+ <div class={classes.date(item.ui)}>{item.date}</div>
88
131
  {/if}
89
132
 
90
133
  {#if titleSlot}
91
134
  {@render titleSlot({ item, index, state })}
92
135
  {:else if item.title}
93
- <div class={classes.title}>{item.title}</div>
136
+ <div class={classes.title(item.ui)}>{item.title}</div>
94
137
  {/if}
95
138
 
96
139
  {#if descriptionSlot}
97
140
  {@render descriptionSlot({ item, index, state })}
98
141
  {:else if item.description}
99
- <div class={classes.description}>{item.description}</div>
142
+ <div class={classes.description(item.ui)}>{item.description}</div>
100
143
  {/if}
101
144
 
102
145
  {#if content}
@@ -1,5 +1,5 @@
1
1
  import type { TimelineProps } from './timeline.types.js';
2
2
  export type Props = TimelineProps;
3
- declare const Timeline: import("svelte").Component<TimelineProps, {}, "">;
3
+ declare const Timeline: import("svelte").Component<TimelineProps, {}, "ref">;
4
4
  type Timeline = ReturnType<typeof Timeline>;
5
5
  export default Timeline;
@@ -1,2 +1,2 @@
1
1
  export { default as Timeline } from './Timeline.svelte';
2
- export type { TimelineProps, TimelineItem } from './timeline.types.js';
2
+ export type { TimelineProps, TimelineItem, TimelineItemState } from './timeline.types.js';
@@ -38,8 +38,16 @@ export type TimelineItem = {
38
38
  * Additional CSS classes for this item.
39
39
  */
40
40
  class?: ClassNameValue;
41
+ /**
42
+ * Per-item slot class overrides.
43
+ */
44
+ ui?: Partial<Record<'item' | 'container' | 'indicator' | 'separator' | 'wrapper' | 'date' | 'title' | 'description', ClassNameValue>>;
41
45
  };
42
46
  export type TimelineProps = Omit<HTMLAttributes<HTMLElement>, 'class'> & {
47
+ /**
48
+ * Bindable reference to the root DOM element.
49
+ */
50
+ ref?: HTMLElement | null;
43
51
  /**
44
52
  * The HTML element to render as.
45
53
  * @default 'div'
@@ -13,6 +13,7 @@
13
13
  const config = getComponentConfig('tooltip', tooltipDefaults)
14
14
 
15
15
  let {
16
+ ref = $bindable(null),
16
17
  open = $bindable(false),
17
18
  onOpenChange,
18
19
  delayDuration,
@@ -20,7 +21,7 @@
20
21
  disableCloseOnTriggerClick,
21
22
  ignoreNonKeyboardFocus,
22
23
  disabled = false,
23
- side = config.defaultVariants.side ?? 'bottom',
24
+ side = 'bottom',
24
25
  sideOffset = 8,
25
26
  align = 'center',
26
27
  alignOffset = 0,
@@ -39,17 +40,18 @@
39
40
  ui,
40
41
  class: className,
41
42
  children,
42
- content: contentSlot
43
+ content: contentSlot,
44
+ ...restProps
43
45
  }: Props = $props()
44
46
 
45
47
  // Pre-compute booleans
46
48
  const hasText = $derived(!!text)
47
49
  const hasKbds = $derived(!!kbds?.length)
48
50
  const hasContent = $derived(hasText || hasKbds || !!contentSlot)
49
- const showArrow = $derived(!!arrow)
50
51
 
51
52
  // Compute variant classes
52
- const variantSlots = $derived(tooltipVariants({ side, transition }))
53
+ const variantSlots = $derived(tooltipVariants({ transition }))
54
+ const kbdsSize = (config.slots.kbdsSize ?? 'sm') as 'sm' | 'md' | 'lg'
53
55
  const classes = $derived({
54
56
  content: variantSlots.content({ class: [config.slots.content, ui?.content] }),
55
57
  arrow: variantSlots.arrow({ class: [config.slots.arrow, ui?.arrow] }),
@@ -57,7 +59,7 @@
57
59
  kbds: variantSlots.kbds({ class: [config.slots.kbds, ui?.kbds] })
58
60
  })
59
61
 
60
- // Arrow props - default size matches tooltip height for proper pointing
62
+ // Arrow props
61
63
  const arrowProps = $derived.by(() => {
62
64
  if (typeof arrow === 'object') {
63
65
  return { width: 12, height: 6, ...arrow }
@@ -81,9 +83,9 @@
81
83
  <span class="mx-0.5 text-inverse-on-surface/60">·</span>
82
84
  {/if}
83
85
  {#if typeof kbd === 'string'}
84
- <Kbd value={kbd} size="sm" variant="soft" color="surface" />
86
+ <Kbd value={kbd} size={kbdsSize} variant="soft" color="surface" />
85
87
  {:else}
86
- <Kbd size="sm" variant="soft" color="surface" {...kbd} />
88
+ <Kbd size={kbdsSize} variant="soft" color="surface" {...kbd} />
87
89
  {/if}
88
90
  {/each}
89
91
  </span>
@@ -93,6 +95,7 @@
93
95
 
94
96
  {#snippet tooltipContentEl()}
95
97
  <Tooltip.Content
98
+ bind:ref
96
99
  {side}
97
100
  {sideOffset}
98
101
  {align}
@@ -105,10 +108,11 @@
105
108
  {onEscapeKeydown}
106
109
  {forceMount}
107
110
  class={classes.content}
111
+ {...restProps}
108
112
  >
109
113
  {@render tooltipContent()}
110
114
 
111
- {#if showArrow}
115
+ {#if arrow}
112
116
  <Tooltip.Arrow
113
117
  width={arrowProps.width}
114
118
  height={arrowProps.height}
@@ -122,8 +126,6 @@
122
126
  <Tooltip.Root
123
127
  bind:open
124
128
  {onOpenChange}
125
- {delayDuration}
126
- {disableHoverableContent}
127
129
  {disableCloseOnTriggerClick}
128
130
  {ignoreNonKeyboardFocus}
129
131
  disabled={disabled || !hasContent}
@@ -1,6 +1,6 @@
1
1
  import type { TooltipProps } from './tooltip.types.js';
2
2
  export type Props = TooltipProps;
3
3
  import { Tooltip } from 'bits-ui';
4
- declare const Tooltip: import("svelte").Component<TooltipProps, {}, "open">;
4
+ declare const Tooltip: import("svelte").Component<TooltipProps, {}, "ref" | "open">;
5
5
  type Tooltip = ReturnType<typeof Tooltip>;
6
6
  export default Tooltip;
@@ -1,13 +1,17 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  import type { ClassNameValue } from 'tailwind-merge';
3
3
  import type { TooltipSlots, TooltipVariantProps } from './tooltip.variants.js';
4
- import type { TooltipRootPropsWithoutHTML, TooltipContentPropsWithoutHTML, TooltipArrowPropsWithoutHTML } from 'bits-ui';
4
+ import type { TooltipRootPropsWithoutHTML, TooltipContentPropsWithoutHTML, TooltipArrowPropsWithoutHTML, TooltipProviderPropsWithoutHTML } from 'bits-ui';
5
5
  import type { KbdProps } from '../Kbd/kbd.types.js';
6
- export type TooltipSide = 'top' | 'right' | 'bottom' | 'left';
7
6
  export type TooltipAlign = 'start' | 'center' | 'end';
8
- type RootProps = Pick<TooltipRootPropsWithoutHTML, 'open' | 'onOpenChange' | 'delayDuration' | 'disableHoverableContent' | 'disableCloseOnTriggerClick' | 'ignoreNonKeyboardFocus' | 'disabled'>;
7
+ type ProviderProps = Pick<TooltipProviderPropsWithoutHTML, 'delayDuration' | 'disableHoverableContent'>;
8
+ type RootProps = Pick<TooltipRootPropsWithoutHTML, 'open' | 'onOpenChange' | 'disableCloseOnTriggerClick' | 'ignoreNonKeyboardFocus' | 'disabled'>;
9
9
  type ContentProps = Pick<TooltipContentPropsWithoutHTML, 'side' | 'sideOffset' | 'align' | 'alignOffset' | 'avoidCollisions' | 'collisionBoundary' | 'collisionPadding' | 'sticky' | 'hideWhenDetached' | 'onEscapeKeydown' | 'forceMount'>;
10
- export interface TooltipProps extends RootProps, ContentProps {
10
+ export interface TooltipProps extends ProviderProps, RootProps, ContentProps {
11
+ /**
12
+ * Bindable reference to the content DOM element.
13
+ */
14
+ ref?: HTMLElement | null;
11
15
  /**
12
16
  * The text content of the tooltip.
13
17
  */
@@ -1,22 +1,8 @@
1
1
  import { type VariantProps } from 'tailwind-variants';
2
2
  export declare const tooltipVariants: import("tailwind-variants").TVReturnType<{
3
- side: {
4
- top: {
5
- content: string;
6
- };
7
- right: {
8
- content: string;
9
- };
10
- bottom: {
11
- content: string;
12
- };
13
- left: {
14
- content: string;
15
- };
16
- };
17
3
  transition: {
18
4
  true: {
19
- content: string;
5
+ content: string[];
20
6
  };
21
7
  };
22
8
  }, {
@@ -24,24 +10,11 @@ export declare const tooltipVariants: import("tailwind-variants").TVReturnType<{
24
10
  arrow: string;
25
11
  text: string;
26
12
  kbds: string;
13
+ kbdsSize: string;
27
14
  }, undefined, {
28
- side: {
29
- top: {
30
- content: string;
31
- };
32
- right: {
33
- content: string;
34
- };
35
- bottom: {
36
- content: string;
37
- };
38
- left: {
39
- content: string;
40
- };
41
- };
42
15
  transition: {
43
16
  true: {
44
- content: string;
17
+ content: string[];
45
18
  };
46
19
  };
47
20
  }, {
@@ -49,24 +22,11 @@ export declare const tooltipVariants: import("tailwind-variants").TVReturnType<{
49
22
  arrow: string;
50
23
  text: string;
51
24
  kbds: string;
25
+ kbdsSize: string;
52
26
  }, import("tailwind-variants").TVReturnType<{
53
- side: {
54
- top: {
55
- content: string;
56
- };
57
- right: {
58
- content: string;
59
- };
60
- bottom: {
61
- content: string;
62
- };
63
- left: {
64
- content: string;
65
- };
66
- };
67
27
  transition: {
68
28
  true: {
69
- content: string;
29
+ content: string[];
70
30
  };
71
31
  };
72
32
  }, {
@@ -74,28 +34,15 @@ export declare const tooltipVariants: import("tailwind-variants").TVReturnType<{
74
34
  arrow: string;
75
35
  text: string;
76
36
  kbds: string;
37
+ kbdsSize: string;
77
38
  }, undefined, unknown, unknown, undefined>>;
78
39
  export type TooltipVariantProps = VariantProps<typeof tooltipVariants>;
79
40
  export type TooltipSlots = keyof ReturnType<typeof tooltipVariants>;
80
41
  export declare const tooltipDefaults: {
81
42
  defaultVariants: import("tailwind-variants").TVDefaultVariants<{
82
- side: {
83
- top: {
84
- content: string;
85
- };
86
- right: {
87
- content: string;
88
- };
89
- bottom: {
90
- content: string;
91
- };
92
- left: {
93
- content: string;
94
- };
95
- };
96
43
  transition: {
97
44
  true: {
98
- content: string;
45
+ content: string[];
99
46
  };
100
47
  };
101
48
  }, {
@@ -103,24 +50,11 @@ export declare const tooltipDefaults: {
103
50
  arrow: string;
104
51
  text: string;
105
52
  kbds: string;
53
+ kbdsSize: string;
106
54
  }, {
107
- side: {
108
- top: {
109
- content: string;
110
- };
111
- right: {
112
- content: string;
113
- };
114
- bottom: {
115
- content: string;
116
- };
117
- left: {
118
- content: string;
119
- };
120
- };
121
55
  transition: {
122
56
  true: {
123
- content: string;
57
+ content: string[];
124
58
  };
125
59
  };
126
60
  }, {
@@ -128,6 +62,7 @@ export declare const tooltipDefaults: {
128
62
  arrow: string;
129
63
  text: string;
130
64
  kbds: string;
65
+ kbdsSize: string;
131
66
  }>;
132
67
  slots: Partial<Record<TooltipSlots, string>>;
133
68
  };
@@ -10,31 +10,22 @@ export const tooltipVariants = tv({
10
10
  ],
11
11
  arrow: 'fill-inverse-surface text-inverse-surface',
12
12
  text: 'truncate',
13
- kbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5'
13
+ kbds: 'hidden lg:inline-flex items-center shrink-0 gap-0.5',
14
+ kbdsSize: 'sm'
14
15
  },
15
16
  variants: {
16
- side: {
17
- top: {
18
- content: 'data-[state=delayed-open]:animate-[slide-in-from-bottom_150ms_ease-out] data-[state=closed]:animate-[slide-in-from-top_100ms_ease-in_reverse]'
19
- },
20
- right: {
21
- content: 'data-[state=delayed-open]:animate-[slide-in-from-left_150ms_ease-out] data-[state=closed]:animate-[slide-in-from-right_100ms_ease-in_reverse]'
22
- },
23
- bottom: {
24
- content: 'data-[state=delayed-open]:animate-[slide-in-from-top_150ms_ease-out] data-[state=closed]:animate-[slide-in-from-bottom_100ms_ease-in_reverse]'
25
- },
26
- left: {
27
- content: 'data-[state=delayed-open]:animate-[slide-in-from-right_150ms_ease-out] data-[state=closed]:animate-[slide-in-from-left_100ms_ease-in_reverse]'
28
- }
29
- },
30
17
  transition: {
31
18
  true: {
32
- content: 'data-[state=delayed-open]:animate-[fade-in_150ms_ease-out,zoom-in_150ms_ease-out] data-[state=closed]:animate-[fade-out_100ms_ease-in,zoom-out_100ms_ease-in]'
19
+ content: [
20
+ 'data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95',
21
+ 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
22
+ 'data-[side=top]:slide-in-from-bottom-2 data-[side=right]:slide-in-from-left-2',
23
+ 'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2'
24
+ ]
33
25
  }
34
26
  }
35
27
  },
36
28
  defaultVariants: {
37
- side: 'bottom',
38
29
  transition: true
39
30
  }
40
31
  });
@@ -14,6 +14,7 @@
14
14
  const config = getComponentConfig('user', userDefaults)
15
15
 
16
16
  let {
17
+ ref = $bindable(null),
17
18
  as = 'div',
18
19
  ui,
19
20
  name,
@@ -44,13 +45,10 @@
44
45
  })
45
46
 
46
47
  const mergedAvatarProps = $derived(
47
- avatar ? { size: size as typeof avatar.size, ...avatar } : undefined
48
+ avatar ? { alt: name, size: size as typeof avatar.size, ...avatar } : undefined
48
49
  )
49
50
 
50
- const chipProps = $derived.by(() => {
51
- if (!chip || !avatar) return null
52
- return chip === true ? {} : chip
53
- })
51
+ const chipProps = $derived(chip && avatar ? (chip === true ? {} : chip) : null)
54
52
  </script>
55
53
 
56
54
  {#snippet userContent()}
@@ -71,24 +69,30 @@
71
69
  {#if nameSlot}
72
70
  {@render nameSlot()}
73
71
  {:else if name}
74
- <div class={classes.name}>{name}</div>
72
+ <p class={classes.name}>{name}</p>
75
73
  {/if}
76
74
 
77
75
  {#if descriptionSlot}
78
76
  {@render descriptionSlot()}
79
77
  {:else if description}
80
- <div class={classes.description}>{description}</div>
78
+ <p class={classes.description}>{description}</p>
81
79
  {/if}
82
80
  </div>
83
81
  {/if}
84
82
  {/snippet}
85
83
 
86
84
  {#if href}
87
- <Link {href} raw class={classes.root}>
85
+ <Link bind:ref {href} raw class={classes.root} data-orientation={orientation} {...restProps}>
88
86
  {@render userContent()}
89
87
  </Link>
90
88
  {:else}
91
- <svelte:element this={as} class={classes.root} {...restProps}>
89
+ <svelte:element
90
+ this={as}
91
+ bind:this={ref}
92
+ class={classes.root}
93
+ data-orientation={orientation}
94
+ {...restProps}
95
+ >
92
96
  {@render userContent()}
93
97
  </svelte:element>
94
98
  {/if}
@@ -1,5 +1,5 @@
1
1
  import type { UserProps } from './user.types.js';
2
2
  export type Props = UserProps;
3
- declare const User: import("svelte").Component<UserProps, {}, "">;
3
+ declare const User: import("svelte").Component<UserProps, {}, "ref">;
4
4
  type User = ReturnType<typeof User>;
5
5
  export default User;
@@ -6,6 +6,10 @@ import type { AvatarProps } from '../Avatar/avatar.types.js';
6
6
  import type { ChipProps } from '../Chip/chip.types.js';
7
7
  import type { LinkProps } from '../Link/link.types.js';
8
8
  export type UserProps = Omit<HTMLAttributes<HTMLElement>, 'class'> & {
9
+ /**
10
+ * Bindable reference to the root DOM element.
11
+ */
12
+ ref?: HTMLElement | null;
9
13
  /**
10
14
  * Sets the HTML element type to render.
11
15
  * Ignored when `href` is provided.