@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,59 +0,0 @@
1
- export { default as Checkout } from './Checkout.stx'
2
- export { default as DefaultPaymentMethod } from './DefaultPaymentMethod.stx'
3
- export { default as PaymentMethods } from './PaymentMethods.stx'
4
- export { default as SubscriptionCheckout } from './SubscriptionCheckout.stx'
5
-
6
- export interface PaymentMethod {
7
- id: string | number
8
- brand: string
9
- last_four: string
10
- exp_month: number
11
- exp_year: number
12
- is_default?: boolean
13
- }
14
-
15
- export interface PaymentMethodsProps {
16
- paymentMethods: PaymentMethod[]
17
- onDeletePaymentMethod?: (id: string | number) => void
18
- onMakeDefault?: (id: string | number) => void
19
- isLoading?: boolean
20
- className?: string
21
- }
22
-
23
- export interface DefaultPaymentMethodProps {
24
- paymentMethod: PaymentMethod | null
25
- isLoading?: boolean
26
- className?: string
27
- }
28
-
29
- export interface Product {
30
- id: string | number
31
- name: string
32
- price: number // in cents
33
- images?: string
34
- quantity?: number
35
- }
36
-
37
- export interface SubscriptionCheckoutProps {
38
- products: Product[]
39
- stripePublicKey: string
40
- apiUrl: string
41
- onSubmit?: (result: { success: boolean }) => void
42
- onRemoveProduct?: (id: string | number) => void
43
- shipping?: number
44
- taxes?: number
45
- className?: string
46
- }
47
-
48
- export interface CheckoutProps {
49
- products: Product[]
50
- redirectUrl: string
51
- mode: 'one-time' | 'subscription'
52
- stripePublicKey: string
53
- apiUrl: string
54
- onSubmit?: (result: { success: boolean }) => void
55
- onRemoveProduct?: (id: string | number) => void
56
- shipping?: number
57
- taxes?: number
58
- className?: string
59
- }
@@ -1,60 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
-
5
- const baseClasses = 'relative'
6
- export const popoverClasses = `${baseClasses} ${className}`.trim()
7
- export const popoverInstanceId = `stx-pop-${Math.random().toString(36).slice(2, 11)}`
8
- </script>
9
-
10
- <script client>
11
- const emit = defineEmits()
12
- const popoverInstanceId = {{ popoverInstanceId }}
13
- const isOpen = state(false)
14
- let rootEl = null
15
- let outsideHandler = null
16
-
17
- function open() { if (!isOpen()) { isOpen.set(true); emit('change', true) } }
18
- function close() { if (isOpen()) { isOpen.set(false); emit('change', false) } }
19
- function toggle() { isOpen() ? close() : open() }
20
-
21
- function onToggle(event) { event.stopPropagation(); toggle() }
22
- function onClose(event) { event.stopPropagation(); close() }
23
- function onOpen(event) { event.stopPropagation(); open() }
24
-
25
- onMount(() => {
26
- rootEl = document.querySelector(`[data-popover-id="${popoverInstanceId}"]`)
27
- outsideHandler = (event) => {
28
- if (!isOpen()) return
29
- if (rootEl && !rootEl.contains(event.target)) close()
30
- }
31
- document.addEventListener('click', outsideHandler, true)
32
- })
33
-
34
- onDestroy(() => {
35
- if (outsideHandler) document.removeEventListener('click', outsideHandler, true)
36
- })
37
-
38
- const dataState = derived(() => isOpen() ? 'open' : 'closed')
39
-
40
- defineExpose({ isOpen, toggle, open, close })
41
- </script>
42
-
43
- <component
44
- :is="{{ as }}"
45
- class="{{ popoverClasses }}"
46
- data-stx-popover
47
- data-popover-id="{{ popoverInstanceId }}"
48
- :data-state="dataState()"
49
- @stx:popover-toggle="onToggle($event)"
50
- @stx:popover-open="onOpen($event)"
51
- @stx:popover-close="onClose($event)"
52
- >
53
- <slot />
54
- </component>
55
-
56
- <style>
57
- [data-stx-popover][data-state="closed"] [data-stx-popover-panel] {
58
- display: none;
59
- }
60
- </style>
@@ -1,29 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'button'
4
- export const disabled = $props.disabled || false
5
-
6
- const baseClasses = 'inline-flex items-center gap-2 focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75'
7
- export const buttonClasses = `${baseClasses} ${className}`.trim()
8
- </script>
9
-
10
- <script client>
11
- const emit = defineEmits()
12
- const isDisabled = {{ disabled }}
13
-
14
- function onClick(event) {
15
- if (isDisabled) return
16
- emit('click', event)
17
- event.currentTarget.dispatchEvent(new CustomEvent('stx:popover-toggle', { bubbles: true }))
18
- }
19
- </script>
20
-
21
- <component
22
- :is="{{ as }}"
23
- class="{{ buttonClasses }}"
24
- data-stx-popover-button
25
- @if(disabled)disabled aria-disabled="true"@endif
26
- @click="onClick($event)"
27
- >
28
- <slot />
29
- </component>
@@ -1,23 +0,0 @@
1
- <script server>
2
- export const className = $props.className || ''
3
- export const as = $props.as || 'div'
4
- export const position = $props.position || 'bottom'
5
-
6
- const positionClasses = {
7
- top: 'bottom-full mb-2',
8
- bottom: 'top-full mt-2',
9
- left: 'right-full mr-2',
10
- right: 'left-full ml-2',
11
- }
12
-
13
- const baseClasses = 'absolute z-10 rounded-lg bg-white dark:bg-neutral-800 p-4 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none'
14
- export const panelClasses = `${baseClasses} ${positionClasses[position]} ${className}`.trim()
15
- </script>
16
-
17
- <component
18
- :is="{{ as }}"
19
- class="{{ panelClasses }}"
20
- data-stx-popover-panel
21
- >
22
- <slot />
23
- </component>
@@ -1,91 +0,0 @@
1
- # Popover Component
2
-
3
- A floating panel that displays rich content anchored to a button or element.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- bun add @stacksjs/components
9
- ```
10
-
11
- ## Usage
12
-
13
- ```stx
14
- <Popover>
15
- <PopoverButton className="px-4 py-2 bg-blue-500 text-white rounded">
16
- Solutions
17
- </PopoverButton>
18
-
19
- <PopoverPanel className="w-64">
20
- <div class="grid gap-4">
21
- <a href="/analytics">Analytics</a>
22
- <a href="/engagement">Engagement</a>
23
- <a href="/security">Security</a>
24
- </div>
25
- </PopoverPanel>
26
- </Popover>
27
- ```
28
-
29
- ## Props
30
-
31
- ### Popover
32
- | Prop | Type | Default | Description |
33
- |------|------|---------|-------------|
34
- | `className` | `string` | `''` | Additional CSS classes |
35
- | `as` | `string` | `'div'` | HTML element to render |
36
-
37
- ### PopoverButton
38
- | Prop | Type | Default | Description |
39
- |------|------|---------|-------------|
40
- | `className` | `string` | `''` | Additional CSS classes |
41
- | `as` | `string` | `'button'` | HTML element to render |
42
- | `disabled` | `boolean` | `false` | Disable the button |
43
- | `onClick` | `(e: Event) => void` | - | Click handler |
44
-
45
- ### PopoverPanel
46
- | Prop | Type | Default | Description |
47
- |------|------|---------|-------------|
48
- | `className` | `string` | `''` | Additional CSS classes |
49
- | `as` | `string` | `'div'` | HTML element to render |
50
- | `static` | `boolean` | `false` | Keep visible regardless of state |
51
- | `position` | `'top' \| 'bottom' \| 'left' \| 'right'` | `'bottom'` | Panel position |
52
-
53
- ## Examples
54
-
55
- ### Solutions Menu
56
-
57
- ```stx
58
- <PopoverPanel className="w-80">
59
- <div class="grid gap-8">
60
- <a href="/analytics" class="flex items-start gap-4 group">
61
- <div class="shrink-0 text-blue-500">
62
- <svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
63
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
64
- </svg>
65
- </div>
66
- <div>
67
- <p class="font-semibold text-neutral-900 dark:text-white group-hover:text-blue-500">Analytics</p>
68
- <p class="text-sm text-neutral-500 dark:text-neutral-400">Get a better understanding of your traffic</p>
69
- </div>
70
- </a>
71
- </div>
72
- </PopoverPanel>
73
- ```
74
-
75
- ### Different Positions
76
-
77
- ```stx
78
- <PopoverPanel position="top">Content appears above</PopoverPanel>
79
-
80
- <PopoverPanel position="left">Content appears to the left</PopoverPanel>
81
- ```
82
-
83
- ## Features
84
-
85
- - Multiple positioning options
86
- - Auto-positioning
87
- - Dark mode support
88
- - Accessible (WAI-ARIA)
89
- - Keyboard support
90
- - Focus management
91
- - Customizable styling
@@ -1,22 +0,0 @@
1
- export { default as Popover } from './Popover.stx'
2
- export { default as PopoverButton } from './PopoverButton.stx'
3
- export { default as PopoverPanel } from './PopoverPanel.stx'
4
-
5
- export interface PopoverProps {
6
- className?: string
7
- as?: string
8
- }
9
-
10
- export interface PopoverButtonProps {
11
- className?: string
12
- as?: string
13
- disabled?: boolean
14
- onClick?: (e: Event) => void
15
- }
16
-
17
- export interface PopoverPanelProps {
18
- className?: string
19
- as?: string
20
- static?: boolean
21
- position?: 'top' | 'bottom' | 'left' | 'right'
22
- }
@@ -1,57 +0,0 @@
1
- <script server>
2
- export const target = $props.target || 'body'
3
- export const disabled = $props.disabled || false
4
-
5
- export const portalId = `portal-content-${Math.random().toString(36).slice(2, 11)}`
6
- </script>
7
-
8
- <script client>
9
- const target = {{ target }}
10
- const isDisabled = {{ disabled }}
11
- const portalId = {{ portalId }}
12
-
13
- let portalContainer = null
14
-
15
- function createPortal() {
16
- if (isDisabled) return
17
- const targetElement = typeof target === 'string' ? document.querySelector(target) : target
18
- if (!targetElement) {
19
- console.warn(`Portal target "${target}" not found`)
20
- return
21
- }
22
- portalContainer = document.createElement('div')
23
- portalContainer.setAttribute('data-portal', 'true')
24
- const portalContent = document.getElementById(portalId)
25
- if (portalContent) {
26
- while (portalContent.firstChild) {
27
- portalContainer.appendChild(portalContent.firstChild)
28
- }
29
- }
30
- targetElement.appendChild(portalContainer)
31
- }
32
-
33
- function cleanupPortal() {
34
- if (portalContainer && portalContainer.parentNode) {
35
- portalContainer.parentNode.removeChild(portalContainer)
36
- portalContainer = null
37
- }
38
- }
39
-
40
- onMount(() => {
41
- setTimeout(createPortal, 0)
42
- window.addEventListener('beforeunload', cleanupPortal)
43
- })
44
-
45
- onDestroy(() => {
46
- cleanupPortal()
47
- window.removeEventListener('beforeunload', cleanupPortal)
48
- })
49
- </script>
50
-
51
- @if(disabled)
52
- <slot />
53
- @else
54
- <div id="{{ portalId }}" style="display: none;">
55
- <slot />
56
- </div>
57
- @endif
@@ -1,6 +0,0 @@
1
- export { default as Portal } from './Portal.stx'
2
-
3
- export interface PortalProps {
4
- target?: string | HTMLElement
5
- disabled?: boolean
6
- }
@@ -1,131 +0,0 @@
1
- <script server>
2
- export const value = $props.value || 0
3
- export const max = $props.max || 100
4
- export const variant = $props.variant || 'linear'
5
- export const size = $props.size || 'md'
6
- export const color = $props.color || 'primary'
7
- export const showLabel = $props.showLabel ?? false
8
- export const indeterminate = $props.indeterminate || false
9
- export const className = $props.className || ''
10
-
11
- const linearSizeClasses = { sm: 'h-1', md: 'h-2', lg: 'h-3' }
12
- const circularSizeClasses = { sm: 'w-12 h-12', md: 'w-16 h-16', lg: 'w-24 h-24' }
13
- const colorClasses = {
14
- primary: 'bg-blue-600 dark:bg-blue-500',
15
- secondary: 'bg-purple-600 dark:bg-purple-500',
16
- success: 'bg-green-600 dark:bg-green-500',
17
- warning: 'bg-yellow-600 dark:bg-yellow-500',
18
- danger: 'bg-red-600 dark:bg-red-500',
19
- info: 'bg-cyan-600 dark:bg-cyan-500',
20
- }
21
-
22
- export const circularSize = size === 'sm' ? 48 : size === 'md' ? 64 : 96
23
- export const strokeWidth = size === 'sm' ? 4 : size === 'md' ? 6 : 8
24
- export const radius = (circularSize - strokeWidth) / 2
25
- export const circumference = 2 * Math.PI * radius
26
-
27
- export const containerClasses = variant === 'linear'
28
- ? `w-full ${className}`.trim()
29
- : `inline-flex items-center justify-center ${className}`.trim()
30
-
31
- export const linearTrackClasses = `w-full ${linearSizeClasses[size]} bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden`.trim()
32
- export const linearBarClasses = `h-full ${colorClasses[color]} transition-all duration-300 ease-in-out ${indeterminate ? 'animate-progress-indeterminate' : ''}`.trim()
33
- export const circularSizeClass = circularSizeClasses[size]
34
- export const labelClasses = `text-sm font-medium text-gray-700 dark:text-gray-300 mb-2`.trim()
35
- export const circularTrackColor = 'stroke-gray-200 dark:stroke-gray-700'
36
- export const circularBarColor = color === 'primary' ? 'stroke-blue-600 dark:stroke-blue-500'
37
- : color === 'secondary' ? 'stroke-purple-600 dark:stroke-purple-500'
38
- : color === 'success' ? 'stroke-green-600 dark:stroke-green-500'
39
- : color === 'warning' ? 'stroke-yellow-600 dark:stroke-yellow-500'
40
- : color === 'danger' ? 'stroke-red-600 dark:stroke-red-500'
41
- : 'stroke-cyan-600 dark:stroke-cyan-500'
42
- </script>
43
-
44
- <script client>
45
- const max = {{ max }}
46
- const indeterminate = {{ indeterminate }}
47
- const circumference = {{ circumference }}
48
- // Reactive prop binding — parent can drive `value` via signals. See #1704.
49
- const value = useReactiveProp('value', {{ value }})
50
-
51
- const percentage = derived(() => Math.min(Math.max((value() / max) * 100, 0), 100))
52
- const percentLabel = derived(() => `${Math.round(percentage())}%`)
53
- const linearWidth = derived(() => indeterminate ? '30%' : `${percentage()}%`)
54
- const dashOffset = derived(() => indeterminate ? 0 : circumference - (percentage() / 100) * circumference)
55
-
56
- defineExpose({ value, setValue: (v) => value.set(v) })
57
- </script>
58
-
59
- @if(variant === 'linear')
60
- <div class="{{ containerClasses }}">
61
- @if(showLabel)
62
- <div class="flex items-center justify-between mb-2">
63
- <span class="{{ labelClasses }}" x-text="percentLabel()"></span>
64
- </div>
65
- @endif
66
-
67
- <div
68
- class="{{ linearTrackClasses }}"
69
- role="progressbar"
70
- :aria-valuenow="value()"
71
- aria-valuemin="0"
72
- aria-valuemax="{{ max }}"
73
- >
74
- <div
75
- class="{{ linearBarClasses }}"
76
- :style="`width: ${linearWidth()}`"
77
- ></div>
78
- </div>
79
- </div>
80
- @else
81
- <div class="{{ containerClasses }}">
82
- <div class="{{ circularSizeClass }} relative">
83
- <svg
84
- class="transform -rotate-90"
85
- width="{{ circularSize }}"
86
- height="{{ circularSize }}"
87
- role="progressbar"
88
- :aria-valuenow="value()"
89
- aria-valuemin="0"
90
- aria-valuemax="{{ max }}"
91
- >
92
- <circle
93
- class="{{ circularTrackColor }}"
94
- cx="{{ circularSize / 2 }}"
95
- cy="{{ circularSize / 2 }}"
96
- r="{{ radius }}"
97
- stroke-width="{{ strokeWidth }}"
98
- fill="none"
99
- />
100
- <circle
101
- class="{{ circularBarColor }} transition-all duration-300 ease-in-out {{ indeterminate ? 'animate-spin' : '' }}"
102
- cx="{{ circularSize / 2 }}"
103
- cy="{{ circularSize / 2 }}"
104
- r="{{ radius }}"
105
- stroke-width="{{ strokeWidth }}"
106
- fill="none"
107
- stroke-dasharray="{{ circumference }}"
108
- :stroke-dashoffset="dashOffset()"
109
- stroke-linecap="round"
110
- />
111
- </svg>
112
-
113
- @if(showLabel)
114
- <div class="absolute inset-0 flex items-center justify-center">
115
- <span class="text-sm font-semibold text-gray-700 dark:text-gray-300" x-text="percentLabel()"></span>
116
- </div>
117
- @endif
118
- </div>
119
- </div>
120
- @endif
121
-
122
- <style>
123
- @keyframes progress-indeterminate {
124
- 0% { transform: translateX(-100%); }
125
- 100% { transform: translateX(400%); }
126
- }
127
-
128
- .animate-progress-indeterminate {
129
- animation: progress-indeterminate 1.5s ease-in-out infinite;
130
- }
131
- </style>
@@ -1,12 +0,0 @@
1
- export { default as Progress } from './Progress.stx'
2
-
3
- export interface ProgressProps {
4
- value?: number
5
- max?: number
6
- variant?: 'linear' | 'circular'
7
- size?: 'sm' | 'md' | 'lg'
8
- color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'
9
- showLabel?: boolean
10
- indeterminate?: boolean
11
- className?: string
12
- }
@@ -1,77 +0,0 @@
1
- <script server>
2
- export const checked = $props.checked || false
3
- export const disabled = $props.disabled || false
4
- export const size = $props.size || 'md'
5
- export const label = $props.label || ''
6
- export const description = $props.description || ''
7
- export const error = $props.error || false
8
- export const required = $props.required || false
9
- export const value = $props.value || ''
10
- export const name = $props.name || ''
11
- export const className = $props.className || ''
12
-
13
- const sizeClasses = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6' }
14
- const baseClasses = 'border-gray-300 dark:border-gray-600 text-indigo-600 dark:text-indigo-500 focus:ring-indigo-600 dark:focus:ring-indigo-500 focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-900 transition-colors'
15
- const stateClasses = error ? 'border-red-300 dark:border-red-600 text-red-600 dark:text-red-500 focus:ring-red-500 dark:focus:ring-red-400' : ''
16
- const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'
17
-
18
- export const radioClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses}`.trim()
19
- export const labelClasses = `text-sm font-medium ${error ? 'text-red-600 dark:text-red-400' : 'text-gray-900 dark:text-gray-100'} ${disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer'}`.trim()
20
- export const descriptionClasses = `text-sm ${error ? 'text-red-500 dark:text-red-400' : 'text-gray-500 dark:text-gray-400'}`.trim()
21
- export const inputId = `radio-${value || label}`
22
- </script>
23
-
24
- <script client>
25
- const emit = defineEmits()
26
- const isDisabled = {{ disabled }}
27
- const radioValue = {{ value }}
28
- // Reactive prop binding — parent can drive `checked` via signals. See #1704.
29
- const isChecked = useReactiveProp('checked', {{ checked }})
30
-
31
- function onInputChange(event) {
32
- if (isDisabled) {
33
- event.target.checked = isChecked()
34
- return
35
- }
36
- isChecked.set(event.target.checked)
37
- emit('change', { value: radioValue, checked: isChecked() })
38
- }
39
-
40
- defineExpose({ isChecked })
41
- </script>
42
-
43
- <div class="relative flex items-start {{ className }}">
44
- <div class="flex h-6 items-center">
45
- <input
46
- id="{{ inputId }}"
47
- type="radio"
48
- name="{{ name }}"
49
- value="{{ value }}"
50
- :checked="isChecked()"
51
- @if(disabled)disabled@endif
52
- @if(required)required@endif
53
- class="{{ radioClasses }}"
54
- @change="onInputChange($event)"
55
- :aria-invalid="{{ error ? 'true' : 'false' }}"
56
- @if(description)aria-describedby="radio-description"@endif
57
- />
58
- </div>
59
-
60
- @if(label || description)
61
- <div class="ml-3 text-sm leading-6">
62
- @if(label)
63
- <label for="{{ inputId }}" class="{{ labelClasses }}">
64
- {{ label }}
65
- @if(required)
66
- <span class="text-red-500 ml-1">*</span>
67
- @endif
68
- </label>
69
- @endif
70
- @if(description)
71
- <p id="radio-description" class="{{ descriptionClasses }}">
72
- {{ description }}
73
- </p>
74
- @endif
75
- </div>
76
- @endif
77
- </div>
@@ -1,15 +0,0 @@
1
- export { default as Radio } from './Radio.stx'
2
-
3
- export interface RadioProps {
4
- checked?: boolean
5
- onChange?: (value: string, checked: boolean) => void
6
- disabled?: boolean
7
- size?: 'sm' | 'md' | 'lg'
8
- label?: string
9
- description?: string
10
- error?: boolean
11
- required?: boolean
12
- value?: string
13
- name?: string
14
- className?: string
15
- }