@stacksjs/components 0.2.92 → 0.2.94

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 (188) hide show
  1. package/dist/{Sidebar-yb115a2w.stx → Sidebar-4hn7vw4n.stx} +18 -0
  2. package/dist/index.js +5 -5
  3. package/package.json +5 -6
  4. package/src/components/CodeBlock.stx +0 -54
  5. package/src/components/Footer.stx +0 -66
  6. package/src/components/Hero.stx +0 -25
  7. package/src/components/Installation.stx +0 -37
  8. package/src/components/index.ts +0 -4
  9. package/src/composables/index.ts +0 -4
  10. package/src/composables/useCopyCode.ts +0 -73
  11. package/src/composables/useDarkMode.ts +0 -100
  12. package/src/composables/useSEO.ts +0 -230
  13. package/src/composables/utilities/index.ts +0 -7
  14. package/src/composables/utilities/useClickOutside.ts +0 -72
  15. package/src/composables/utilities/useFocusTrap.ts +0 -159
  16. package/src/composables/utilities/useKeyboard.ts +0 -124
  17. package/src/composables/utilities/useLocalStorage.ts +0 -132
  18. package/src/composables/utilities/useMediaQuery.ts +0 -118
  19. package/src/index.ts +0 -99
  20. package/src/stx.d.ts +0 -4
  21. package/src/ui/accordion/Accordion.stx +0 -146
  22. package/src/ui/accordion/AccordionItem.stx +0 -37
  23. package/src/ui/accordion/index.ts +0 -47
  24. package/src/ui/audio/Audio.stx +0 -50
  25. package/src/ui/audio/README.md +0 -41
  26. package/src/ui/audio/index.ts +0 -13
  27. package/src/ui/auth/Login.stx +0 -161
  28. package/src/ui/auth/README.md +0 -142
  29. package/src/ui/auth/Signup.stx +0 -159
  30. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  31. package/src/ui/auth/index.ts +0 -32
  32. package/src/ui/avatar/Avatar.stx +0 -77
  33. package/src/ui/avatar/index.ts +0 -12
  34. package/src/ui/badge/Badge.stx +0 -62
  35. package/src/ui/badge/index.ts +0 -10
  36. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  37. package/src/ui/breadcrumb/index.ts +0 -15
  38. package/src/ui/button/Button.stx +0 -74
  39. package/src/ui/button/README.md +0 -80
  40. package/src/ui/button/index.ts +0 -85
  41. package/src/ui/calendar/Calendar.stx +0 -189
  42. package/src/ui/calendar/README.md +0 -254
  43. package/src/ui/calendar/index.ts +0 -14
  44. package/src/ui/card/Card.stx +0 -68
  45. package/src/ui/card/index.ts +0 -13
  46. package/src/ui/checkbox/Checkbox.stx +0 -86
  47. package/src/ui/checkbox/index.ts +0 -16
  48. package/src/ui/combobox/Combobox.stx +0 -96
  49. package/src/ui/combobox/ComboboxButton.stx +0 -25
  50. package/src/ui/combobox/ComboboxInput.stx +0 -32
  51. package/src/ui/combobox/ComboboxOption.stx +0 -49
  52. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  53. package/src/ui/combobox/README.md +0 -150
  54. package/src/ui/combobox/index.ts +0 -40
  55. package/src/ui/command-palette/CommandPalette.stx +0 -81
  56. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  57. package/src/ui/command-palette/README.md +0 -42
  58. package/src/ui/command-palette/index.ts +0 -15
  59. package/src/ui/dialog/Dialog.stx +0 -41
  60. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  61. package/src/ui/dialog/DialogDescription.stx +0 -11
  62. package/src/ui/dialog/DialogPanel.stx +0 -16
  63. package/src/ui/dialog/DialogTitle.stx +0 -11
  64. package/src/ui/dialog/README.md +0 -121
  65. package/src/ui/dialog/index.ts +0 -32
  66. package/src/ui/drawer/Drawer.stx +0 -120
  67. package/src/ui/drawer/README.md +0 -90
  68. package/src/ui/drawer/index.ts +0 -9
  69. package/src/ui/dropdown/Dropdown.stx +0 -82
  70. package/src/ui/dropdown/DropdownButton.stx +0 -29
  71. package/src/ui/dropdown/DropdownItem.stx +0 -35
  72. package/src/ui/dropdown/DropdownItems.stx +0 -18
  73. package/src/ui/dropdown/README.md +0 -114
  74. package/src/ui/dropdown/index.ts +0 -29
  75. package/src/ui/form/Form.stx +0 -95
  76. package/src/ui/form/index.ts +0 -67
  77. package/src/ui/heatmap/Heatmap.stx +0 -294
  78. package/src/ui/image/Image.stx +0 -165
  79. package/src/ui/image/README.md +0 -164
  80. package/src/ui/image/index.ts +0 -22
  81. package/src/ui/input/EmailInput.stx +0 -30
  82. package/src/ui/input/NumberInput.stx +0 -126
  83. package/src/ui/input/PasswordInput.stx +0 -143
  84. package/src/ui/input/SearchInput.stx +0 -44
  85. package/src/ui/input/TextInput.stx +0 -132
  86. package/src/ui/input/index.ts +0 -180
  87. package/src/ui/listbox/Listbox.stx +0 -101
  88. package/src/ui/listbox/ListboxButton.stx +0 -28
  89. package/src/ui/listbox/ListboxLabel.stx +0 -11
  90. package/src/ui/listbox/ListboxOption.stx +0 -49
  91. package/src/ui/listbox/ListboxOptions.stx +0 -16
  92. package/src/ui/listbox/README.md +0 -135
  93. package/src/ui/listbox/index.ts +0 -39
  94. package/src/ui/navigator/Navigator.stx +0 -113
  95. package/src/ui/navigator/README.md +0 -352
  96. package/src/ui/navigator/index.ts +0 -20
  97. package/src/ui/notification/Notification.stx +0 -117
  98. package/src/ui/notification/README.md +0 -114
  99. package/src/ui/notification/index.ts +0 -12
  100. package/src/ui/pagination/Pagination.stx +0 -150
  101. package/src/ui/pagination/index.ts +0 -11
  102. package/src/ui/payment/Checkout.stx +0 -31
  103. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  104. package/src/ui/payment/PaymentMethods.stx +0 -104
  105. package/src/ui/payment/README.md +0 -345
  106. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  107. package/src/ui/payment/index.ts +0 -59
  108. package/src/ui/popover/Popover.stx +0 -60
  109. package/src/ui/popover/PopoverButton.stx +0 -29
  110. package/src/ui/popover/PopoverPanel.stx +0 -23
  111. package/src/ui/popover/README.md +0 -91
  112. package/src/ui/popover/index.ts +0 -22
  113. package/src/ui/portal/Portal.stx +0 -57
  114. package/src/ui/portal/index.ts +0 -6
  115. package/src/ui/progress/Progress.stx +0 -131
  116. package/src/ui/progress/index.ts +0 -12
  117. package/src/ui/radio/Radio.stx +0 -77
  118. package/src/ui/radio/index.ts +0 -15
  119. package/src/ui/radio-group/README.md +0 -139
  120. package/src/ui/radio-group/RadioGroup.stx +0 -60
  121. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  123. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  124. package/src/ui/radio-group/index.ts +0 -30
  125. package/src/ui/select/README.md +0 -180
  126. package/src/ui/select/Select.stx +0 -82
  127. package/src/ui/select/index.ts +0 -21
  128. package/src/ui/sidebar/Sidebar.stx +0 -458
  129. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  130. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  131. package/src/ui/sidebar/SidebarItem.stx +0 -86
  132. package/src/ui/sidebar/SidebarSection.stx +0 -83
  133. package/src/ui/sidebar/index.ts +0 -153
  134. package/src/ui/sidebar/themes.ts +0 -240
  135. package/src/ui/skeleton/Skeleton.stx +0 -48
  136. package/src/ui/skeleton/index.ts +0 -11
  137. package/src/ui/spinner/Spinner.stx +0 -109
  138. package/src/ui/spinner/index.ts +0 -9
  139. package/src/ui/stepper/README.md +0 -36
  140. package/src/ui/stepper/Stepper.stx +0 -17
  141. package/src/ui/stepper/StepperStep.stx +0 -57
  142. package/src/ui/stepper/index.ts +0 -19
  143. package/src/ui/storage/README.md +0 -193
  144. package/src/ui/storage/index.ts +0 -347
  145. package/src/ui/switch/README.md +0 -114
  146. package/src/ui/switch/Switch.stx +0 -72
  147. package/src/ui/switch/index.ts +0 -10
  148. package/src/ui/table/README.md +0 -39
  149. package/src/ui/table/Table.stx +0 -14
  150. package/src/ui/table/TableBody.stx +0 -10
  151. package/src/ui/table/TableCell.stx +0 -10
  152. package/src/ui/table/TableHead.stx +0 -10
  153. package/src/ui/table/TableHeader.stx +0 -20
  154. package/src/ui/table/TableRow.stx +0 -11
  155. package/src/ui/table/index.ts +0 -35
  156. package/src/ui/tabs/TabPanel.stx +0 -25
  157. package/src/ui/tabs/Tabs.stx +0 -202
  158. package/src/ui/tabs/index.ts +0 -50
  159. package/src/ui/teleport/Teleport.stx +0 -65
  160. package/src/ui/teleport/index.ts +0 -7
  161. package/src/ui/textarea/Textarea.stx +0 -108
  162. package/src/ui/textarea/index.ts +0 -20
  163. package/src/ui/tooltip/Tooltip.stx +0 -71
  164. package/src/ui/tooltip/index.ts +0 -10
  165. package/src/ui/transition/README.md +0 -30
  166. package/src/ui/transition/Transition.stx +0 -102
  167. package/src/ui/transition/index.ts +0 -25
  168. package/src/ui/video/README.md +0 -47
  169. package/src/ui/video/Video.stx +0 -45
  170. package/src/ui/video/index.ts +0 -16
  171. package/src/ui/virtual-list/VirtualList.stx +0 -67
  172. package/src/ui/virtual-list/index.ts +0 -10
  173. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  174. package/src/ui/virtual-table/index.ts +0 -21
  175. package/src/utils/PROP_VALIDATION.md +0 -458
  176. package/src/utils/THEME_SYSTEM.md +0 -702
  177. package/src/utils/accessibility.ts +0 -841
  178. package/src/utils/animation/easing.ts +0 -368
  179. package/src/utils/animation/helpers.ts +0 -223
  180. package/src/utils/animation/index.ts +0 -5
  181. package/src/utils/animation/keyframes.ts +0 -230
  182. package/src/utils/error-handling.ts +0 -475
  183. package/src/utils/highlighter.ts +0 -93
  184. package/src/utils/i18n.ts +0 -634
  185. package/src/utils/keep-alive.ts +0 -819
  186. package/src/utils/lazy-loading.ts +0 -530
  187. package/src/utils/prop-validation.ts +0 -478
  188. package/src/utils/theme.ts +0 -626
@@ -1,102 +0,0 @@
1
- <script server>
2
- export const show = $props.show !== false
3
- export const enter = $props.enter || 'transition-opacity duration-300'
4
- export const enterFrom = $props.enterFrom || 'opacity-0'
5
- export const enterTo = $props.enterTo || 'opacity-100'
6
- export const leave = $props.leave || 'transition-opacity duration-200'
7
- export const leaveFrom = $props.leaveFrom || 'opacity-100'
8
- export const leaveTo = $props.leaveTo || 'opacity-0'
9
- export const appear = $props.appear || false
10
- export const duration = $props.duration || 300
11
- export const delay = $props.delay || 0
12
- export const preset = $props.preset || ''
13
- export const className = $props.className || ''
14
-
15
- const presets = {
16
- fade: { enter: 'transition-opacity', enterFrom: 'opacity-0', enterTo: 'opacity-100', leave: 'transition-opacity', leaveFrom: 'opacity-100', leaveTo: 'opacity-0' },
17
- slide: { enter: 'transition-transform', enterFrom: 'translate-y-2', enterTo: 'translate-y-0', leave: 'transition-transform', leaveFrom: 'translate-y-0', leaveTo: 'translate-y-2' },
18
- slideLeft: { enter: 'transition-transform', enterFrom: 'translate-x-full', enterTo: 'translate-x-0', leave: 'transition-transform', leaveFrom: 'translate-x-0', leaveTo: '-translate-x-full' },
19
- slideRight: { enter: 'transition-transform', enterFrom: '-translate-x-full', enterTo: 'translate-x-0', leave: 'transition-transform', leaveFrom: 'translate-x-0', leaveTo: 'translate-x-full' },
20
- scale: { enter: 'transition-transform', enterFrom: 'scale-95', enterTo: 'scale-100', leave: 'transition-transform', leaveFrom: 'scale-100', leaveTo: 'scale-95' },
21
- rotate: { enter: 'transition-transform', enterFrom: 'rotate-12 scale-95', enterTo: 'rotate-0 scale-100', leave: 'transition-transform', leaveFrom: 'rotate-0 scale-100', leaveTo: '-rotate-12 scale-95' },
22
- zoom: { enter: 'transition-all', enterFrom: 'scale-0 opacity-0', enterTo: 'scale-100 opacity-100', leave: 'transition-all', leaveFrom: 'scale-100 opacity-100', leaveTo: 'scale-0 opacity-0' },
23
- }
24
-
25
- const p = preset && presets[preset] ? presets[preset] : {}
26
- export const enterClass = p.enter || enter
27
- export const enterFromClass = p.enterFrom || enterFrom
28
- export const enterToClass = p.enterTo || enterTo
29
- export const leaveClass = p.leave || leave
30
- export const leaveFromClass = p.leaveFrom || leaveFrom
31
- export const leaveToClass = p.leaveTo || leaveTo
32
-
33
- export const durationStyle = `transition-duration: ${duration}ms; transition-delay: ${delay}ms;`
34
- export const extraClass = className
35
- </script>
36
-
37
- <script client>
38
- const emit = defineEmits()
39
- const showProp = {{ show }}
40
- const appear = {{ appear }}
41
- const duration = {{ duration }}
42
- const delay = {{ delay }}
43
- const enterClass = {{ enterClass }}
44
- const enterFromClass = {{ enterFromClass }}
45
- const enterToClass = {{ enterToClass }}
46
- const leaveClass = {{ leaveClass }}
47
- const leaveFromClass = {{ leaveFromClass }}
48
- const leaveToClass = {{ leaveToClass }}
49
- const extraClass = {{ extraClass }}
50
-
51
- const visible = state(showProp)
52
- const isEntering = state(appear && showProp)
53
- const isLeaving = state(false)
54
- const shouldRender = state(showProp)
55
-
56
- const transitionClass = derived(() => {
57
- if (visible()) {
58
- return isEntering() ? `${enterClass} ${enterFromClass}` : enterToClass
59
- }
60
- return isLeaving() ? `${leaveClass} ${leaveFromClass}` : leaveToClass
61
- })
62
-
63
- const componentClass = derived(() => `${transitionClass()} ${extraClass}`.trim())
64
-
65
- function setShow(next) {
66
- if (next === visible()) return
67
- if (next) {
68
- emit('beforeEnter')
69
- shouldRender.set(true)
70
- visible.set(true)
71
- isEntering.set(true)
72
- setTimeout(() => emit('enter'), delay)
73
- setTimeout(() => {
74
- isEntering.set(false)
75
- emit('afterEnter')
76
- }, duration + delay)
77
- }
78
- else {
79
- emit('beforeLeave')
80
- visible.set(false)
81
- isLeaving.set(true)
82
- setTimeout(() => emit('leave'), delay)
83
- setTimeout(() => {
84
- isLeaving.set(false)
85
- shouldRender.set(false)
86
- emit('afterLeave')
87
- }, duration + delay)
88
- }
89
- }
90
-
91
- onMount(() => {
92
- if (appear && showProp) {
93
- setTimeout(() => isEntering.set(false), duration + delay)
94
- }
95
- })
96
-
97
- defineExpose({ visible, setShow })
98
- </script>
99
-
100
- <div :show="shouldRender()" :class="componentClass()" style="{{ durationStyle }}">
101
- <slot />
102
- </div>
@@ -1,25 +0,0 @@
1
- export { default as Transition } from './Transition.stx'
2
-
3
- export interface TransitionProps {
4
- show?: boolean
5
- enter?: string
6
- enterFrom?: string
7
- enterTo?: string
8
- leave?: string
9
- leaveFrom?: string
10
- leaveTo?: string
11
- appear?: boolean
12
- appearFrom?: string
13
- appearTo?: string
14
- mode?: 'in-out' | 'out-in' | 'default'
15
- duration?: number
16
- delay?: number
17
- preset?: 'fade' | 'slide' | 'slideLeft' | 'slideRight' | 'scale' | 'rotate' | 'zoom' | ''
18
- onBeforeEnter?: () => void
19
- onEnter?: () => void
20
- onAfterEnter?: () => void
21
- onBeforeLeave?: () => void
22
- onLeave?: () => void
23
- onAfterLeave?: () => void
24
- className?: string
25
- }
@@ -1,47 +0,0 @@
1
- # Video Component
2
-
3
- A responsive video player with aspect ratio support and poster images.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <Video
15
- src="/videos/demo.mp4"
16
- poster="/images/video-thumbnail.jpg"
17
- title="Product Demo"
18
- aspectRatio="16/9"
19
- controls
20
- />
21
- ```
22
-
23
- ## Props
24
-
25
- | Prop | Type | Default | Description |
26
- |------|------|---------|-------------|
27
- | `src` | `string` | - | Video file URL (required) |
28
- | `poster` | `string` | `''` | Poster image URL |
29
- | `autoplay` | `boolean` | `false` | Auto-play on load |
30
- | `loop` | `boolean` | `false` | Loop playback |
31
- | `muted` | `boolean` | `false` | Start muted |
32
- | `controls` | `boolean` | `true` | Show native controls |
33
- | `preload` | `'none' \| 'metadata' \| 'auto'` | `'metadata'` | Preload strategy |
34
- | `width` | `number \| string` | - | Video width |
35
- | `height` | `number \| string` | - | Video height |
36
- | `aspectRatio` | `'16/9' \| '4/3' \| '1/1' \| string` | `'16/9'` | Aspect ratio |
37
- | `className` | `string` | `''` | Additional CSS classes |
38
- | `title` | `string` | `''` | Optional title above player |
39
-
40
- ## Features
41
-
42
- - **Aspect ratios** - 16:9, 4:3, 1:1 built-in
43
- - **Poster images** - Show thumbnail before play
44
- - **Native controls** - Uses browser's native video controls
45
- - **Dark mode** - Styled for dark mode
46
- - **Responsive** - Full-width with aspect ratio
47
- - **Accessible** - Proper fallback text
@@ -1,45 +0,0 @@
1
- <script server>
2
- export const src = $props.src || ''
3
- export const poster = $props.poster || ''
4
- export const autoplay = $props.autoplay || false
5
- export const loop = $props.loop || false
6
- export const muted = $props.muted || false
7
- export const controls = $props.controls ?? true
8
- export const preload = $props.preload || 'metadata'
9
- export const width = $props.width
10
- export const height = $props.height
11
- export const aspectRatio = $props.aspectRatio || '16/9'
12
- export const className = $props.className || ''
13
- export const title = $props.title || ''
14
-
15
- export const containerClasses = `relative w-full overflow-hidden rounded-lg ${className}`.trim()
16
- export const videoClasses = 'w-full h-full object-cover bg-gray-900 dark:bg-gray-950'
17
- export const aspectRatioClass = aspectRatio === '16/9' ? 'aspect-video' : aspectRatio === '4/3' ? 'aspect-[4/3]' : aspectRatio === '1/1' ? 'aspect-square' : ''
18
- </script>
19
-
20
- <div class="{{ containerClasses }}">
21
- @if(title)
22
- <div class="mb-2 px-1">
23
- <h3 class="text-sm font-medium text-gray-900 dark:text-gray-100">
24
- {{ title }}
25
- </h3>
26
- </div>
27
- @endif
28
-
29
- <div class="{{ aspectRatioClass }}">
30
- <video
31
- class="{{ videoClasses }}"
32
- src="{{ src }}"
33
- poster="{{ poster }}"
34
- @if(controls)controls@endif
35
- @if(autoplay)autoplay@endif
36
- @if(loop)loop@endif
37
- @if(muted)muted@endif
38
- preload="{{ preload }}"
39
- width="{{ width }}"
40
- height="{{ height }}"
41
- >
42
- Your browser does not support the video element.
43
- </video>
44
- </div>
45
- </div>
@@ -1,16 +0,0 @@
1
- export { default as Video } from './Video.stx'
2
-
3
- export interface VideoProps {
4
- src: string
5
- poster?: string
6
- autoplay?: boolean
7
- loop?: boolean
8
- muted?: boolean
9
- controls?: boolean
10
- preload?: 'none' | 'metadata' | 'auto'
11
- width?: number | string
12
- height?: number | string
13
- aspectRatio?: '16/9' | '4/3' | '1/1' | string
14
- className?: string
15
- title?: string
16
- }
@@ -1,67 +0,0 @@
1
- <script server>
2
- export const items = $props.items || []
3
- export const itemHeight = $props.itemHeight || 50
4
- export const height = $props.height || 400
5
- export const overscan = $props.overscan || 3
6
- export const className = $props.className || ''
7
-
8
- export const totalHeight = items.length * itemHeight
9
- export const containerClasses = `overflow-auto ${className}`.trim()
10
- </script>
11
-
12
- <script client>
13
- const items = {{ items }}
14
- const itemHeight = {{ itemHeight }}
15
- const height = {{ height }}
16
- const overscan = {{ overscan }}
17
-
18
- const scrollTop = state(0)
19
-
20
- const visibleRange = derived(() => {
21
- const top = scrollTop()
22
- const startIndex = Math.max(0, Math.floor(top / itemHeight) - overscan)
23
- const endIndex = Math.min(items.length - 1, Math.floor((top + height) / itemHeight) + overscan)
24
- return { startIndex, endIndex }
25
- })
26
-
27
- const visibleItems = derived(() => {
28
- const { startIndex, endIndex } = visibleRange()
29
- return items.slice(startIndex, endIndex + 1).map((item, i) => ({
30
- item,
31
- index: startIndex + i,
32
- top: (startIndex + i) * itemHeight,
33
- }))
34
- })
35
-
36
- let ticking = false
37
- function onScroll(event) {
38
- const target = event.target
39
- if (!ticking) {
40
- requestAnimationFrame(() => {
41
- scrollTop.set(target.scrollTop)
42
- ticking = false
43
- })
44
- ticking = true
45
- }
46
- }
47
-
48
- defineExpose({ scrollTop, scrollTo: (top) => scrollTop.set(top) })
49
- </script>
50
-
51
- <div
52
- class="{{ containerClasses }}"
53
- style="height: {{ height }}px"
54
- @scroll="onScroll($event)"
55
- >
56
- <div class="relative" style="height: {{ totalHeight }}px">
57
- <div
58
- :for="entry in visibleItems()"
59
- :key="entry.index"
60
- class="absolute left-0 right-0"
61
- :style="`top: ${entry.top}px; height: {{ itemHeight }}px`"
62
- :data-index="entry.index"
63
- >
64
- <slot :item="entry.item" :index="entry.index" />
65
- </div>
66
- </div>
67
- </div>
@@ -1,10 +0,0 @@
1
- export { default as VirtualList } from './VirtualList.stx'
2
-
3
- export interface VirtualListProps<T = any> {
4
- items: T[]
5
- itemHeight: number
6
- height: number
7
- overscan?: number
8
- renderItem?: (item: T, index: number) => string
9
- className?: string
10
- }
@@ -1,103 +0,0 @@
1
- <script server>
2
- export const columns = $props.columns || []
3
- export const data = $props.data || []
4
- export const rowHeight = $props.rowHeight || 48
5
- export const height = $props.height || 600
6
- export const headerHeight = $props.headerHeight || 56
7
- export const overscan = $props.overscan || 5
8
- export const striped = $props.striped || false
9
- export const hoverable = $props.hoverable ?? true
10
- export const className = $props.className || ''
11
-
12
- export const totalHeight = data.length * rowHeight
13
- export const containerClasses = `border border-gray-200 dark:border-gray-700 rounded-lg overflow-hidden ${className}`.trim()
14
- export const headerClasses = `bg-gray-50 dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 flex`.trim()
15
- export const headerCellClasses = `px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider`.trim()
16
- export const bodyClasses = `overflow-auto bg-white dark:bg-gray-900`.trim()
17
- export const rowClasses = `absolute left-0 right-0 flex border-b border-gray-200 dark:border-gray-700 ${hoverable ? 'hover:bg-gray-50 dark:hover:bg-gray-800' : ''}`.trim()
18
- export const cellClasses = `px-6 py-4 text-sm text-gray-900 dark:text-gray-100`.trim()
19
- </script>
20
-
21
- <script client>
22
- const data = {{ data }}
23
- const columns = {{ columns }}
24
- const rowHeight = {{ rowHeight }}
25
- const height = {{ height }}
26
- const headerHeight = {{ headerHeight }}
27
- const overscan = {{ overscan }}
28
- const striped = {{ striped }}
29
-
30
- const scrollTop = state(0)
31
-
32
- const visibleRows = derived(() => {
33
- const top = scrollTop()
34
- const startIndex = Math.max(0, Math.floor(top / rowHeight) - overscan)
35
- const endIndex = Math.min(data.length - 1, Math.floor((top + height - headerHeight) / rowHeight) + overscan)
36
- const out = []
37
- for (let i = startIndex; i <= endIndex; i++) {
38
- out.push({
39
- row: data[i],
40
- index: i,
41
- top: i * rowHeight,
42
- striped: striped && (i % 2 === 1),
43
- })
44
- }
45
- return out
46
- })
47
-
48
- function getCellValue(row, column) {
49
- if (column.render) return column.render(row[column.key], row)
50
- return row[column.key]
51
- }
52
-
53
- let ticking = false
54
- function onScroll(event) {
55
- const target = event.target
56
- if (!ticking) {
57
- requestAnimationFrame(() => {
58
- scrollTop.set(target.scrollTop)
59
- ticking = false
60
- })
61
- ticking = true
62
- }
63
- }
64
-
65
- defineExpose({ scrollTop })
66
- </script>
67
-
68
- <div class="{{ containerClasses }}">
69
- <div class="{{ headerClasses }}" style="height: {{ headerHeight }}px">
70
- @foreach(column in columns)
71
- <div
72
- class="{{ headerCellClasses }}"
73
- style="flex: {{ column.width || 1 }}; min-width: {{ column.minWidth || 'auto' }}"
74
- >
75
- {{ column.label || column.key }}
76
- </div>
77
- @endforeach
78
- </div>
79
-
80
- <div
81
- class="{{ bodyClasses }}"
82
- style="height: {{ height - headerHeight }}px"
83
- @scroll="onScroll($event)"
84
- >
85
- <div class="relative" style="height: {{ totalHeight }}px">
86
- <div
87
- :for="entry in visibleRows()"
88
- :key="entry.index"
89
- :class="entry.striped ? '{{ rowClasses }} bg-gray-50 dark:bg-gray-800' : '{{ rowClasses }}'"
90
- :style="`top: ${entry.top}px; height: {{ rowHeight }}px`"
91
- :data-index="entry.index"
92
- >
93
- <div
94
- :for="column in columns"
95
- :key="column.key"
96
- class="{{ cellClasses }}"
97
- :style="`flex: ${column.width || 1}; min-width: ${column.minWidth || 'auto'}`"
98
- x-html="getCellValue(entry.row, column)"
99
- ></div>
100
- </div>
101
- </div>
102
- </div>
103
- </div>
@@ -1,21 +0,0 @@
1
- export { default as VirtualTable } from './VirtualTable.stx'
2
-
3
- export interface VirtualTableColumn<T = any> {
4
- key: string
5
- label?: string
6
- width?: number
7
- minWidth?: string
8
- render?: (value: any, row: T) => string
9
- }
10
-
11
- export interface VirtualTableProps<T = any> {
12
- columns: VirtualTableColumn<T>[]
13
- data: T[]
14
- rowHeight?: number
15
- height?: number
16
- headerHeight?: number
17
- overscan?: number
18
- striped?: boolean
19
- hoverable?: boolean
20
- className?: string
21
- }