@stacksjs/components 0.2.93 → 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 (187) hide show
  1. package/dist/index.js +4 -4
  2. package/package.json +5 -6
  3. package/src/components/CodeBlock.stx +0 -54
  4. package/src/components/Footer.stx +0 -66
  5. package/src/components/Hero.stx +0 -25
  6. package/src/components/Installation.stx +0 -37
  7. package/src/components/index.ts +0 -4
  8. package/src/composables/index.ts +0 -4
  9. package/src/composables/useCopyCode.ts +0 -73
  10. package/src/composables/useDarkMode.ts +0 -100
  11. package/src/composables/useSEO.ts +0 -230
  12. package/src/composables/utilities/index.ts +0 -7
  13. package/src/composables/utilities/useClickOutside.ts +0 -72
  14. package/src/composables/utilities/useFocusTrap.ts +0 -159
  15. package/src/composables/utilities/useKeyboard.ts +0 -124
  16. package/src/composables/utilities/useLocalStorage.ts +0 -132
  17. package/src/composables/utilities/useMediaQuery.ts +0 -118
  18. package/src/index.ts +0 -99
  19. package/src/stx.d.ts +0 -4
  20. package/src/ui/accordion/Accordion.stx +0 -146
  21. package/src/ui/accordion/AccordionItem.stx +0 -37
  22. package/src/ui/accordion/index.ts +0 -47
  23. package/src/ui/audio/Audio.stx +0 -50
  24. package/src/ui/audio/README.md +0 -41
  25. package/src/ui/audio/index.ts +0 -13
  26. package/src/ui/auth/Login.stx +0 -161
  27. package/src/ui/auth/README.md +0 -142
  28. package/src/ui/auth/Signup.stx +0 -159
  29. package/src/ui/auth/TwoFactorChallenge.stx +0 -111
  30. package/src/ui/auth/index.ts +0 -32
  31. package/src/ui/avatar/Avatar.stx +0 -77
  32. package/src/ui/avatar/index.ts +0 -12
  33. package/src/ui/badge/Badge.stx +0 -62
  34. package/src/ui/badge/index.ts +0 -10
  35. package/src/ui/breadcrumb/Breadcrumb.stx +0 -79
  36. package/src/ui/breadcrumb/index.ts +0 -15
  37. package/src/ui/button/Button.stx +0 -74
  38. package/src/ui/button/README.md +0 -80
  39. package/src/ui/button/index.ts +0 -85
  40. package/src/ui/calendar/Calendar.stx +0 -189
  41. package/src/ui/calendar/README.md +0 -254
  42. package/src/ui/calendar/index.ts +0 -14
  43. package/src/ui/card/Card.stx +0 -68
  44. package/src/ui/card/index.ts +0 -13
  45. package/src/ui/checkbox/Checkbox.stx +0 -86
  46. package/src/ui/checkbox/index.ts +0 -16
  47. package/src/ui/combobox/Combobox.stx +0 -96
  48. package/src/ui/combobox/ComboboxButton.stx +0 -25
  49. package/src/ui/combobox/ComboboxInput.stx +0 -32
  50. package/src/ui/combobox/ComboboxOption.stx +0 -49
  51. package/src/ui/combobox/ComboboxOptions.stx +0 -16
  52. package/src/ui/combobox/README.md +0 -150
  53. package/src/ui/combobox/index.ts +0 -40
  54. package/src/ui/command-palette/CommandPalette.stx +0 -81
  55. package/src/ui/command-palette/CommandPaletteItem.stx +0 -27
  56. package/src/ui/command-palette/README.md +0 -42
  57. package/src/ui/command-palette/index.ts +0 -15
  58. package/src/ui/dialog/Dialog.stx +0 -41
  59. package/src/ui/dialog/DialogBackdrop.stx +0 -9
  60. package/src/ui/dialog/DialogDescription.stx +0 -11
  61. package/src/ui/dialog/DialogPanel.stx +0 -16
  62. package/src/ui/dialog/DialogTitle.stx +0 -11
  63. package/src/ui/dialog/README.md +0 -121
  64. package/src/ui/dialog/index.ts +0 -32
  65. package/src/ui/drawer/Drawer.stx +0 -120
  66. package/src/ui/drawer/README.md +0 -90
  67. package/src/ui/drawer/index.ts +0 -9
  68. package/src/ui/dropdown/Dropdown.stx +0 -82
  69. package/src/ui/dropdown/DropdownButton.stx +0 -29
  70. package/src/ui/dropdown/DropdownItem.stx +0 -35
  71. package/src/ui/dropdown/DropdownItems.stx +0 -18
  72. package/src/ui/dropdown/README.md +0 -114
  73. package/src/ui/dropdown/index.ts +0 -29
  74. package/src/ui/form/Form.stx +0 -95
  75. package/src/ui/form/index.ts +0 -67
  76. package/src/ui/heatmap/Heatmap.stx +0 -294
  77. package/src/ui/image/Image.stx +0 -165
  78. package/src/ui/image/README.md +0 -164
  79. package/src/ui/image/index.ts +0 -22
  80. package/src/ui/input/EmailInput.stx +0 -30
  81. package/src/ui/input/NumberInput.stx +0 -126
  82. package/src/ui/input/PasswordInput.stx +0 -143
  83. package/src/ui/input/SearchInput.stx +0 -44
  84. package/src/ui/input/TextInput.stx +0 -132
  85. package/src/ui/input/index.ts +0 -180
  86. package/src/ui/listbox/Listbox.stx +0 -101
  87. package/src/ui/listbox/ListboxButton.stx +0 -28
  88. package/src/ui/listbox/ListboxLabel.stx +0 -11
  89. package/src/ui/listbox/ListboxOption.stx +0 -49
  90. package/src/ui/listbox/ListboxOptions.stx +0 -16
  91. package/src/ui/listbox/README.md +0 -135
  92. package/src/ui/listbox/index.ts +0 -39
  93. package/src/ui/navigator/Navigator.stx +0 -113
  94. package/src/ui/navigator/README.md +0 -352
  95. package/src/ui/navigator/index.ts +0 -20
  96. package/src/ui/notification/Notification.stx +0 -117
  97. package/src/ui/notification/README.md +0 -114
  98. package/src/ui/notification/index.ts +0 -12
  99. package/src/ui/pagination/Pagination.stx +0 -150
  100. package/src/ui/pagination/index.ts +0 -11
  101. package/src/ui/payment/Checkout.stx +0 -31
  102. package/src/ui/payment/DefaultPaymentMethod.stx +0 -62
  103. package/src/ui/payment/PaymentMethods.stx +0 -104
  104. package/src/ui/payment/README.md +0 -345
  105. package/src/ui/payment/SubscriptionCheckout.stx +0 -323
  106. package/src/ui/payment/index.ts +0 -59
  107. package/src/ui/popover/Popover.stx +0 -60
  108. package/src/ui/popover/PopoverButton.stx +0 -29
  109. package/src/ui/popover/PopoverPanel.stx +0 -23
  110. package/src/ui/popover/README.md +0 -91
  111. package/src/ui/popover/index.ts +0 -22
  112. package/src/ui/portal/Portal.stx +0 -57
  113. package/src/ui/portal/index.ts +0 -6
  114. package/src/ui/progress/Progress.stx +0 -131
  115. package/src/ui/progress/index.ts +0 -12
  116. package/src/ui/radio/Radio.stx +0 -77
  117. package/src/ui/radio/index.ts +0 -15
  118. package/src/ui/radio-group/README.md +0 -139
  119. package/src/ui/radio-group/RadioGroup.stx +0 -60
  120. package/src/ui/radio-group/RadioGroupDescription.stx +0 -11
  121. package/src/ui/radio-group/RadioGroupLabel.stx +0 -11
  122. package/src/ui/radio-group/RadioGroupOption.stx +0 -58
  123. package/src/ui/radio-group/index.ts +0 -30
  124. package/src/ui/select/README.md +0 -180
  125. package/src/ui/select/Select.stx +0 -82
  126. package/src/ui/select/index.ts +0 -21
  127. package/src/ui/sidebar/Sidebar.stx +0 -476
  128. package/src/ui/sidebar/SidebarFooter.stx +0 -71
  129. package/src/ui/sidebar/SidebarHeader.stx +0 -103
  130. package/src/ui/sidebar/SidebarItem.stx +0 -86
  131. package/src/ui/sidebar/SidebarSection.stx +0 -83
  132. package/src/ui/sidebar/index.ts +0 -153
  133. package/src/ui/sidebar/themes.ts +0 -240
  134. package/src/ui/skeleton/Skeleton.stx +0 -48
  135. package/src/ui/skeleton/index.ts +0 -11
  136. package/src/ui/spinner/Spinner.stx +0 -109
  137. package/src/ui/spinner/index.ts +0 -9
  138. package/src/ui/stepper/README.md +0 -36
  139. package/src/ui/stepper/Stepper.stx +0 -17
  140. package/src/ui/stepper/StepperStep.stx +0 -57
  141. package/src/ui/stepper/index.ts +0 -19
  142. package/src/ui/storage/README.md +0 -193
  143. package/src/ui/storage/index.ts +0 -347
  144. package/src/ui/switch/README.md +0 -114
  145. package/src/ui/switch/Switch.stx +0 -72
  146. package/src/ui/switch/index.ts +0 -10
  147. package/src/ui/table/README.md +0 -39
  148. package/src/ui/table/Table.stx +0 -14
  149. package/src/ui/table/TableBody.stx +0 -10
  150. package/src/ui/table/TableCell.stx +0 -10
  151. package/src/ui/table/TableHead.stx +0 -10
  152. package/src/ui/table/TableHeader.stx +0 -20
  153. package/src/ui/table/TableRow.stx +0 -11
  154. package/src/ui/table/index.ts +0 -35
  155. package/src/ui/tabs/TabPanel.stx +0 -25
  156. package/src/ui/tabs/Tabs.stx +0 -202
  157. package/src/ui/tabs/index.ts +0 -50
  158. package/src/ui/teleport/Teleport.stx +0 -65
  159. package/src/ui/teleport/index.ts +0 -7
  160. package/src/ui/textarea/Textarea.stx +0 -108
  161. package/src/ui/textarea/index.ts +0 -20
  162. package/src/ui/tooltip/Tooltip.stx +0 -71
  163. package/src/ui/tooltip/index.ts +0 -10
  164. package/src/ui/transition/README.md +0 -30
  165. package/src/ui/transition/Transition.stx +0 -102
  166. package/src/ui/transition/index.ts +0 -25
  167. package/src/ui/video/README.md +0 -47
  168. package/src/ui/video/Video.stx +0 -45
  169. package/src/ui/video/index.ts +0 -16
  170. package/src/ui/virtual-list/VirtualList.stx +0 -67
  171. package/src/ui/virtual-list/index.ts +0 -10
  172. package/src/ui/virtual-table/VirtualTable.stx +0 -103
  173. package/src/ui/virtual-table/index.ts +0 -21
  174. package/src/utils/PROP_VALIDATION.md +0 -458
  175. package/src/utils/THEME_SYSTEM.md +0 -702
  176. package/src/utils/accessibility.ts +0 -841
  177. package/src/utils/animation/easing.ts +0 -368
  178. package/src/utils/animation/helpers.ts +0 -223
  179. package/src/utils/animation/index.ts +0 -5
  180. package/src/utils/animation/keyframes.ts +0 -230
  181. package/src/utils/error-handling.ts +0 -475
  182. package/src/utils/highlighter.ts +0 -93
  183. package/src/utils/i18n.ts +0 -634
  184. package/src/utils/keep-alive.ts +0 -819
  185. package/src/utils/lazy-loading.ts +0 -530
  186. package/src/utils/prop-validation.ts +0 -478
  187. 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
- }