@stacksjs/components 0.2.176 → 0.2.178
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.
- package/dist/{Accordion-pt8j917s.stx → Accordion-8tv78bh9.stx} +4 -4
- package/dist/{AccordionItem-hbhzx63p.stx → AccordionItem-7bd3ga36.stx} +3 -3
- package/dist/{Audio-hjywk3qc.stx → Audio-y0sgq50z.stx} +3 -3
- package/dist/{Avatar-h3jmwcq0.stx → Avatar-rjvwnskf.stx} +2 -2
- package/dist/{Badge-k8dy3d53.stx → Badge-k52qmxcm.stx} +1 -1
- package/dist/{Breadcrumb-7f7s4d02.stx → Breadcrumb-sy5taqsn.stx} +7 -7
- package/dist/{Button-1vknasy3.stx → Button-wrwmnfpf.stx} +2 -2
- package/dist/{Calendar-reny0et7.stx → Calendar-gjjhhfnt.stx} +8 -8
- package/dist/{Card-c1g1fd1w.stx → Card-473a02fy.stx} +3 -3
- package/dist/{Checkbox-aqmq4cqv.stx → Checkbox-2s2a7n4h.stx} +4 -4
- package/dist/{Checkout-agt0ngpw.stx → Checkout-22wh3s22.stx} +1 -1
- package/dist/{ComboboxOption-hmxt3gte.stx → ComboboxOption-6yh7xk7q.stx} +2 -2
- package/dist/{CommandPaletteItem-mvk6q7a2.stx → CommandPaletteItem-chdw0070.stx} +1 -1
- package/dist/{DefaultPaymentMethod-shhf6aap.stx → DefaultPaymentMethod-6qrem3sg.stx} +8 -8
- package/dist/{DialogDescription-76prd1m2.stx → DialogDescription-gth4c2kx.stx} +1 -1
- package/dist/{Drawer-hrz7qcyp.stx → Drawer-jgepqr9j.stx} +1 -1
- package/dist/{DropdownItem-c7rz08e5.stx → DropdownItem-d8ht2bp5.stx} +1 -1
- package/dist/{Form-bpnpbymb.stx → Form-vbag14t1.stx} +1 -1
- package/dist/{ListboxOption-e0dtv1gc.stx → ListboxOption-4j070101.stx} +2 -2
- package/dist/{Login-gepemsth.stx → Login-2cp65d41.stx} +40 -22
- package/dist/{Navigator-rk2a5wvk.stx → Navigator-smpa7my4.stx} +12 -12
- package/dist/{NumberInput-g41gmd2c.stx → NumberInput-j9p5bm5y.stx} +7 -7
- package/dist/{Pagination-wtgxmzey.stx → Pagination-jbcjrfcs.stx} +3 -3
- package/dist/{PasswordInput-4rsq1gwb.stx → PasswordInput-4qykq1dz.stx} +8 -8
- package/dist/{PaymentMethods-x4vrx9yb.stx → PaymentMethods-2xy66bwk.stx} +11 -11
- package/dist/{Progress-9dhakbh4.stx → Progress-4h7dytq5.stx} +9 -9
- package/dist/{Radio-djtb5dpc.stx → Radio-ccm07b2m.stx} +4 -4
- package/dist/RadioGroup-eerw9gq7.stx +138 -0
- package/dist/{RadioGroupDescription-yej78fak.stx → RadioGroupDescription-z34r9avr.stx} +1 -1
- package/dist/{RadioGroupOption-s1d6r221.stx → RadioGroupOption-7pq7rw84.stx} +1 -1
- package/dist/{Select-1vnd0brz.stx → Select-zt72gg1e.stx} +4 -4
- package/dist/{SidebarItem-2a6n0be3.stx → SidebarItem-5v8atp7p.stx} +2 -2
- package/dist/{SidebarPinned-tvj28bm0.stx → SidebarPinned-rq05nrtd.stx} +3 -3
- package/dist/{Signup-hxm5hwkr.stx → Signup-cbncrtvd.stx} +29 -19
- package/dist/{Skeleton-v1pwa8nr.stx → Skeleton-wtwb97xd.stx} +1 -1
- package/dist/{Spinner-7dahavkd.stx → Spinner-ypya5tt2.stx} +8 -8
- package/dist/{StepperStep-wxgembat.stx → StepperStep-3ahq4d9m.stx} +3 -3
- package/dist/{SubscriptionCheckout-zy2ycrmw.stx → SubscriptionCheckout-7fdkwf04.stx} +40 -34
- package/dist/{Switch-p1bcr9ks.stx → Switch-hdta55a8.stx} +1 -1
- package/dist/{Table-6cx8az9h.stx → Table-0mc3fdek.stx} +1 -1
- package/dist/{TableBody-wf6t13j9.stx → TableBody-drxyz5jh.stx} +1 -1
- package/dist/{TableCell-ntx0edbn.stx → TableCell-8swtcq8s.stx} +1 -1
- package/dist/{TableHead-3k4hnm2k.stx → TableHead-e9xvjx2j.stx} +1 -1
- package/dist/{TableHeader-0eyzbqpz.stx → TableHeader-sxc77b4d.stx} +2 -2
- package/dist/{TableRow-z09p2ebf.stx → TableRow-xd542nvb.stx} +1 -1
- package/dist/{Tabs-79brys99.stx → Tabs-b4xsba1w.stx} +6 -6
- package/dist/{TextInput-g0vaz0pe.stx → TextInput-cefyyprt.stx} +9 -9
- package/dist/{Textarea-96kawv5c.stx → Textarea-xcdym703.stx} +6 -6
- package/dist/{TwoFactorChallenge-y5m3nk79.stx → TwoFactorChallenge-y7n4yrk9.stx} +8 -8
- package/dist/{Video-84j4pv6h.stx → Video-a0aeyexv.stx} +1 -1
- package/dist/{VirtualTable-f9crbfjr.stx → VirtualTable-jvm1784g.stx} +6 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +89 -55
- package/dist/theme/index.d.ts +92 -0
- package/package.json +3 -3
- package/src/index.ts +2 -0
- package/src/theme/index.ts +130 -0
- package/src/ui/accordion/Accordion.stx +4 -4
- package/src/ui/accordion/AccordionItem.stx +3 -3
- package/src/ui/audio/Audio.stx +3 -3
- package/src/ui/auth/Login.stx +40 -22
- package/src/ui/auth/Signup.stx +29 -19
- package/src/ui/auth/TwoFactorChallenge.stx +8 -8
- package/src/ui/avatar/Avatar.stx +2 -2
- package/src/ui/badge/Badge.stx +1 -1
- package/src/ui/breadcrumb/Breadcrumb.stx +7 -7
- package/src/ui/button/Button.stx +2 -2
- package/src/ui/calendar/Calendar.stx +8 -8
- package/src/ui/card/Card.stx +3 -3
- package/src/ui/checkbox/Checkbox.stx +4 -4
- package/src/ui/combobox/ComboboxOption.stx +2 -2
- package/src/ui/command-palette/CommandPaletteItem.stx +1 -1
- package/src/ui/dialog/DialogDescription.stx +1 -1
- package/src/ui/drawer/Drawer.stx +1 -1
- package/src/ui/dropdown/DropdownItem.stx +1 -1
- package/src/ui/form/Form.stx +1 -1
- package/src/ui/input/NumberInput.stx +7 -7
- package/src/ui/input/PasswordInput.stx +8 -8
- package/src/ui/input/TextInput.stx +9 -9
- package/src/ui/listbox/ListboxOption.stx +2 -2
- package/src/ui/navigator/Navigator.stx +12 -12
- package/src/ui/pagination/Pagination.stx +3 -3
- package/src/ui/payment/Checkout.stx +1 -1
- package/src/ui/payment/DefaultPaymentMethod.stx +8 -8
- package/src/ui/payment/PaymentMethods.stx +11 -11
- package/src/ui/payment/SubscriptionCheckout.stx +40 -34
- package/src/ui/progress/Progress.stx +9 -9
- package/src/ui/radio/Radio.stx +4 -4
- package/src/ui/radio-group/RadioGroup.stx +79 -1
- package/src/ui/radio-group/RadioGroupDescription.stx +1 -1
- package/src/ui/radio-group/RadioGroupOption.stx +1 -1
- package/src/ui/select/Select.stx +4 -4
- package/src/ui/sidebar/SidebarItem.stx +2 -2
- package/src/ui/sidebar/SidebarPinned.stx +3 -3
- package/src/ui/skeleton/Skeleton.stx +1 -1
- package/src/ui/spinner/Spinner.stx +8 -8
- package/src/ui/stepper/StepperStep.stx +3 -3
- package/src/ui/switch/Switch.stx +1 -1
- package/src/ui/table/Table.stx +1 -1
- package/src/ui/table/TableBody.stx +1 -1
- package/src/ui/table/TableCell.stx +1 -1
- package/src/ui/table/TableHead.stx +1 -1
- package/src/ui/table/TableHeader.stx +2 -2
- package/src/ui/table/TableRow.stx +1 -1
- package/src/ui/tabs/Tabs.stx +6 -6
- package/src/ui/textarea/Textarea.stx +6 -6
- package/src/ui/video/Video.stx +1 -1
- package/src/ui/virtual-table/VirtualTable.stx +6 -6
- package/dist/RadioGroup-qxmnm3xm.stx +0 -60
|
@@ -3,6 +3,30 @@ export const value = $props.value
|
|
|
3
3
|
export const className = $props.className || ''
|
|
4
4
|
export const as = $props.as || 'div'
|
|
5
5
|
|
|
6
|
+
/*
|
|
7
|
+
* Prop-array mode, alongside the slot API (stacksjs/stx#1930).
|
|
8
|
+
*
|
|
9
|
+
* `<RadioGroup :options="[{ label: 'A', value: 'a' }]" />` used to emit a
|
|
10
|
+
* hydration shell and nothing else: the labels reached the page only inside
|
|
11
|
+
* `data-stx-props`, so the choices were invisible without JavaScript and to a
|
|
12
|
+
* crawler. Every comparable component here — Tabs, Accordion, Select, Navigator,
|
|
13
|
+
* Breadcrumb — server-renders its content from a prop array, so this was the
|
|
14
|
+
* odd one out rather than a deliberate choice.
|
|
15
|
+
*
|
|
16
|
+
* The options are rendered here rather than delegated to <RadioGroupOption>
|
|
17
|
+
* because a loop variable cannot cross a component boundary as a `:` binding.
|
|
18
|
+
* Interpolating it would stringify the value — `1` and `"1"` would stop being
|
|
19
|
+
* distinguishable — and the group compares values by identity. Emitting the
|
|
20
|
+
* option markup directly keeps `data-option-value` exact JSON, which is what
|
|
21
|
+
* `syncOptionStates` already reads.
|
|
22
|
+
*/
|
|
23
|
+
export const options = Array.isArray($props.options) ? $props.options : []
|
|
24
|
+
export const hasPropOptions = options.length > 0
|
|
25
|
+
|
|
26
|
+
const optionBaseClasses = 'relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none transition-all bg-white dark:bg-neutral-800 text-fg focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-60 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300 dark:focus-visible:ring-offset-blue-700'
|
|
27
|
+
export const optionClasses = optionBaseClasses
|
|
28
|
+
export const optionDisabledClasses = `${optionBaseClasses} opacity-50 cursor-not-allowed`
|
|
29
|
+
|
|
6
30
|
const baseClasses = 'w-full'
|
|
7
31
|
export const groupClasses = `${baseClasses} ${className}`.trim()
|
|
8
32
|
export const radioGroupInstanceId = `stx-rg-${Math.random().toString(36).slice(2, 11)}`
|
|
@@ -40,11 +64,42 @@ function onSelect(event) {
|
|
|
40
64
|
selectValue(event.detail)
|
|
41
65
|
}
|
|
42
66
|
|
|
67
|
+
// Options rendered from the `options` prop have no <RadioGroupOption> behind
|
|
68
|
+
// them to dispatch stx:radio-select, so the group claims them by delegation.
|
|
69
|
+
// One listener on the root rather than a handler per option, which also means
|
|
70
|
+
// options added later are picked up with no re-binding.
|
|
71
|
+
function optionValueOf(el) {
|
|
72
|
+
try { return JSON.parse(el.dataset.optionValue ?? 'null') }
|
|
73
|
+
catch { return el.dataset.optionValue }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function onDelegatedActivate(event) {
|
|
77
|
+
const option = event.target.closest?.('[data-stx-radio-option]')
|
|
78
|
+
if (!option || !rootEl || !rootEl.contains(option)) return
|
|
79
|
+
if (option.getAttribute('aria-disabled') === 'true') return
|
|
80
|
+
// A <RadioGroupOption> dispatches its own event; claiming its click too would
|
|
81
|
+
// select twice and emit two change events.
|
|
82
|
+
if (option.dataset.stxRadioDelegated !== 'true') return
|
|
83
|
+
if (event.type === 'keydown' && event.key !== ' ' && event.key !== 'Enter') return
|
|
84
|
+
event.preventDefault()
|
|
85
|
+
selectValue(optionValueOf(option))
|
|
86
|
+
}
|
|
87
|
+
|
|
43
88
|
onMount(() => {
|
|
44
89
|
rootEl = document.querySelector(`[data-radio-group-id="${radioGroupInstanceId}"]`)
|
|
90
|
+
if (rootEl) {
|
|
91
|
+
rootEl.addEventListener('click', onDelegatedActivate)
|
|
92
|
+
rootEl.addEventListener('keydown', onDelegatedActivate)
|
|
93
|
+
}
|
|
45
94
|
syncOptionStates()
|
|
46
95
|
})
|
|
47
96
|
|
|
97
|
+
onDestroy(() => {
|
|
98
|
+
if (!rootEl) return
|
|
99
|
+
rootEl.removeEventListener('click', onDelegatedActivate)
|
|
100
|
+
rootEl.removeEventListener('keydown', onDelegatedActivate)
|
|
101
|
+
})
|
|
102
|
+
|
|
48
103
|
defineExpose({ selected, selectValue })
|
|
49
104
|
</script>
|
|
50
105
|
|
|
@@ -56,5 +111,28 @@ defineExpose({ selected, selectValue })
|
|
|
56
111
|
role="radiogroup"
|
|
57
112
|
@stx:radio-select="onSelect($event)"
|
|
58
113
|
>
|
|
59
|
-
|
|
114
|
+
@if(hasPropOptions)
|
|
115
|
+
@foreach(option in options)
|
|
116
|
+
<div
|
|
117
|
+
data-stx-radio-option
|
|
118
|
+
data-stx-radio-delegated="true"
|
|
119
|
+
data-option-value="{{ JSON.stringify(option.value === undefined ? null : option.value) }}"
|
|
120
|
+
role="radio"
|
|
121
|
+
aria-checked="{{ option.value === value ? 'true' : 'false' }}"
|
|
122
|
+
data-checked="{{ option.value === value ? 'true' : 'false' }}"
|
|
123
|
+
aria-disabled="{{ option.disabled ? 'true' : 'false' }}"
|
|
124
|
+
tabindex="{{ option.disabled ? '-1' : '0' }}"
|
|
125
|
+
class="{{ option.disabled ? optionDisabledClasses : optionClasses }}"
|
|
126
|
+
>
|
|
127
|
+
<span class="flex flex-col">
|
|
128
|
+
<span class="text-sm font-medium">{{ option.label }}</span>
|
|
129
|
+
@if(option.description)
|
|
130
|
+
<span class="text-sm opacity-70">{{ option.description }}</span>
|
|
131
|
+
@endif
|
|
132
|
+
</span>
|
|
133
|
+
</div>
|
|
134
|
+
@endforeach
|
|
135
|
+
@else
|
|
136
|
+
<slot />
|
|
137
|
+
@endif
|
|
60
138
|
</component>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const className = $props.className || ''
|
|
3
3
|
export const as = $props.as || 'span'
|
|
4
4
|
|
|
5
|
-
const baseClasses = 'inline text-sm text-
|
|
5
|
+
const baseClasses = 'inline text-sm text-fg-soft'
|
|
6
6
|
const descriptionClasses = `${baseClasses} ${className}`.trim()
|
|
7
7
|
</script>
|
|
8
8
|
|
|
@@ -4,7 +4,7 @@ export const disabled = $props.disabled || false
|
|
|
4
4
|
export const className = $props.className || ''
|
|
5
5
|
export const as = $props.as || 'div'
|
|
6
6
|
|
|
7
|
-
const baseClasses = 'relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none transition-all bg-white dark:bg-neutral-800 text-
|
|
7
|
+
const baseClasses = 'relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none transition-all bg-white dark:bg-neutral-800 text-fg focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-60 focus-visible:ring-offset-2 focus-visible:ring-offset-blue-300 dark:focus-visible:ring-offset-blue-700'
|
|
8
8
|
const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : ''
|
|
9
9
|
export const optionClasses = `${baseClasses} ${disabledClasses} ${className}`.trim()
|
|
10
10
|
export const valueJson = JSON.stringify(value === undefined ? null : value)
|
package/src/ui/select/Select.stx
CHANGED
|
@@ -14,14 +14,14 @@ const sizeClasses = { sm: 'px-3 py-1.5 text-sm h-8', md: 'px-4 py-2 text-base h-
|
|
|
14
14
|
const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset dark:bg-blue-gray-700 dark:text-gray-100'
|
|
15
15
|
const stateClasses = error
|
|
16
16
|
? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
17
|
-
: 'ring-
|
|
17
|
+
: 'ring-line-strong text-fg placeholder-fg-subtle focus:ring-accent'
|
|
18
18
|
const disabledClasses = disabled
|
|
19
|
-
? 'opacity-50 cursor-not-allowed bg-
|
|
19
|
+
? 'opacity-50 cursor-not-allowed bg-surface'
|
|
20
20
|
: 'bg-white dark:bg-blue-gray-700 cursor-pointer hover:ring-gray-400 dark:hover:ring-gray-500'
|
|
21
21
|
|
|
22
22
|
export const selectClasses = `${baseClasses} ${sizeClasses[size]} ${stateClasses} ${disabledClasses} ${className}`.trim()
|
|
23
|
-
export const labelClasses = `block text-sm font-medium leading-6 ${error ? 'text-
|
|
24
|
-
export const helperClasses = `mt-2 text-sm ${error ? 'text-
|
|
23
|
+
export const labelClasses = `block text-sm font-medium leading-6 ${error ? 'text-danger' : 'text-fg'}`.trim()
|
|
24
|
+
export const helperClasses = `mt-2 text-sm ${error ? 'text-danger' : 'text-fg-soft'}`.trim()
|
|
25
25
|
export const selectId = `select-${value}`
|
|
26
26
|
</script>
|
|
27
27
|
|
|
@@ -53,7 +53,7 @@ export const isLink = Boolean(href) && !disabled
|
|
|
53
53
|
@if(indentStyle)style="{{ indentStyle }}"@endif
|
|
54
54
|
>
|
|
55
55
|
@if(isLink)
|
|
56
|
-
<
|
|
56
|
+
<StxLink to="{{ href }}" data-sidebar-item data-label="{{ label }}" class="{{ rowClasses }}" :data-active="active ? 'true' : null" :aria-current="active ? 'page' : null">
|
|
57
57
|
<span class="{{ disclosureClasses }}" @if(expandable)data-sidebar-disclosure role="button" aria-label="Toggle {{ label }}"@endif>
|
|
58
58
|
@if(expandable)
|
|
59
59
|
<span data-sidebar-chevron class="{{ chevronClasses }}" aria-hidden="true"></span>
|
|
@@ -68,7 +68,7 @@ export const isLink = Boolean(href) && !disabled
|
|
|
68
68
|
@if(count !== '' && count !== null && count !== undefined)
|
|
69
69
|
<span data-sidebar-count class="{{ countClasses }}">{{ count }}</span>
|
|
70
70
|
@endif
|
|
71
|
-
</
|
|
71
|
+
</StxLink>
|
|
72
72
|
@else
|
|
73
73
|
<button type="button" data-sidebar-item data-label="{{ label }}" class="{{ rowClasses }}" @if(active)data-active="true" aria-current="page"@endif @if(disabled)data-disabled disabled aria-disabled="true"@endif>
|
|
74
74
|
<span class="{{ disclosureClasses }}" @if(expandable)data-sidebar-disclosure role="button" aria-label="Toggle {{ label }}"@endif>
|
|
@@ -51,8 +51,8 @@ function onPinnedClick(event) {
|
|
|
51
51
|
>
|
|
52
52
|
@foreach(items as item)
|
|
53
53
|
@if(item.href)
|
|
54
|
-
<
|
|
55
|
-
|
|
54
|
+
<StxLink
|
|
55
|
+
to="{{ item.href }}"
|
|
56
56
|
data-space-pinned-item
|
|
57
57
|
data-pinned-id="{{ item.id }}"
|
|
58
58
|
class="{{ tileClasses }}"
|
|
@@ -65,7 +65,7 @@ function onPinnedClick(event) {
|
|
|
65
65
|
@else
|
|
66
66
|
<span class="{{ item.icon }} h-[20px] w-[20px]" @if(item.iconStyle)style="{{ item.iconStyle }}"@endif aria-hidden="true"></span>
|
|
67
67
|
@endif
|
|
68
|
-
</
|
|
68
|
+
</StxLink>
|
|
69
69
|
@else
|
|
70
70
|
<button
|
|
71
71
|
type="button"
|
|
@@ -33,7 +33,7 @@ if (height) {
|
|
|
33
33
|
styleString += `height: ${typeof height === 'number' ? height + 'px' : height};`
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
export const skeletonClasses = `bg-
|
|
36
|
+
export const skeletonClasses = `bg-surface-sunken ${baseClasses} ${animationClasses} ${className}`.trim()
|
|
37
37
|
export const containerClasses = count > 1 ? 'space-y-3' : ''
|
|
38
38
|
</script>
|
|
39
39
|
|
|
@@ -16,19 +16,19 @@ const sizeClasses = {
|
|
|
16
16
|
|
|
17
17
|
// Color classes
|
|
18
18
|
const colorClasses = {
|
|
19
|
-
primary: 'text-
|
|
19
|
+
primary: 'text-info',
|
|
20
20
|
secondary: 'text-purple-600 dark:text-purple-500',
|
|
21
|
-
success: 'text-
|
|
21
|
+
success: 'text-success',
|
|
22
22
|
warning: 'text-yellow-600 dark:text-yellow-500',
|
|
23
|
-
danger: 'text-
|
|
23
|
+
danger: 'text-danger',
|
|
24
24
|
info: 'text-cyan-600 dark:text-cyan-500',
|
|
25
25
|
white: 'text-white',
|
|
26
|
-
gray: 'text-
|
|
26
|
+
gray: 'text-fg-muted',
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
export const containerClasses = `inline-flex flex-col items-center gap-2 ${className}`.trim()
|
|
30
30
|
export const spinnerClasses = `${sizeClasses[size]} ${colorClasses[color]} animate-spin`.trim()
|
|
31
|
-
export const labelClasses = `text-sm font-medium text-
|
|
31
|
+
export const labelClasses = `text-sm font-medium text-fg-strong`.trim()
|
|
32
32
|
|
|
33
33
|
// Dots size classes
|
|
34
34
|
const dotsSizeClasses = {
|
|
@@ -40,11 +40,11 @@ const dotsSizeClasses = {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const dotsColorClasses = {
|
|
43
|
-
primary: 'bg-
|
|
43
|
+
primary: 'bg-info-solid',
|
|
44
44
|
secondary: 'bg-purple-600 dark:bg-purple-500',
|
|
45
|
-
success: 'bg-
|
|
45
|
+
success: 'bg-success-solid',
|
|
46
46
|
warning: 'bg-yellow-600 dark:bg-yellow-500',
|
|
47
|
-
danger: 'bg-
|
|
47
|
+
danger: 'bg-danger-solid',
|
|
48
48
|
info: 'bg-cyan-600 dark:bg-cyan-500',
|
|
49
49
|
white: 'bg-white',
|
|
50
50
|
gray: 'bg-gray-600 dark:bg-gray-400',
|
|
@@ -29,7 +29,7 @@ function onClick() {
|
|
|
29
29
|
@click="onClick()"
|
|
30
30
|
class="flex items-center gap-3 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 rounded-lg p-2"
|
|
31
31
|
>
|
|
32
|
-
<div class="{{ isComplete ? 'bg-
|
|
32
|
+
<div class="{{ isComplete ? 'bg-info-solid' : isCurrent ? 'bg-info-solid ring-4 ring-blue-200 dark:ring-blue-800' : 'bg-neutral-300 dark:bg-neutral-600' }} w-10 h-10 rounded-full flex items-center justify-center text-white font-semibold transition-all">
|
|
33
33
|
@if(isComplete)
|
|
34
34
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
35
35
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7" />
|
|
@@ -41,11 +41,11 @@ function onClick() {
|
|
|
41
41
|
|
|
42
42
|
@if(label)
|
|
43
43
|
<div class="text-left">
|
|
44
|
-
<div class="text-sm font-medium {{ isCurrent ? 'text-
|
|
44
|
+
<div class="text-sm font-medium {{ isCurrent ? 'text-info' : 'text-neutral-900 dark:text-white' }}">
|
|
45
45
|
{{ label }}
|
|
46
46
|
</div>
|
|
47
47
|
@if(description)
|
|
48
|
-
<div class="text-xs text-
|
|
48
|
+
<div class="text-xs text-fg-soft">
|
|
49
49
|
{{ description }}
|
|
50
50
|
</div>
|
|
51
51
|
@endif
|
package/src/ui/switch/Switch.stx
CHANGED
|
@@ -53,7 +53,7 @@ defineExpose({ isChecked, toggle })
|
|
|
53
53
|
|
|
54
54
|
<label class="inline-flex items-center gap-3 cursor-pointer">
|
|
55
55
|
@if(label)
|
|
56
|
-
<span class="text-sm font-medium text-
|
|
56
|
+
<span class="text-sm font-medium text-fg-strong">
|
|
57
57
|
{{ label }}
|
|
58
58
|
</span>
|
|
59
59
|
@endif
|
package/src/ui/table/Table.stx
CHANGED
|
@@ -3,7 +3,7 @@ export const className = $props.className || ''
|
|
|
3
3
|
export const striped = $props.striped || false
|
|
4
4
|
export const hoverable = $props.hoverable !== false
|
|
5
5
|
|
|
6
|
-
const baseClasses = 'min-w-full divide-y divide-
|
|
6
|
+
const baseClasses = 'min-w-full divide-y divide-line'
|
|
7
7
|
const tableClasses = `${baseClasses} ${className}`.trim()
|
|
8
8
|
</script>
|
|
9
9
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script server>
|
|
2
2
|
export const className = $props.className || ''
|
|
3
3
|
|
|
4
|
-
const baseClasses = 'bg-white divide-y divide-
|
|
4
|
+
const baseClasses = 'bg-white divide-y divide-line dark:bg-neutral-900'
|
|
5
5
|
const bodyClasses = `${baseClasses} ${className}`.trim()
|
|
6
6
|
</script>
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<script server>
|
|
2
2
|
export const className = $props.className || ''
|
|
3
3
|
|
|
4
|
-
const baseClasses = 'px-6 py-4 whitespace-nowrap text-sm text-
|
|
4
|
+
const baseClasses = 'px-6 py-4 whitespace-nowrap text-sm text-fg'
|
|
5
5
|
const cellClasses = `${baseClasses} ${className}`.trim()
|
|
6
6
|
</script>
|
|
7
7
|
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
export const className = $props.className || ''
|
|
3
3
|
export const sortable = $props.sortable || false
|
|
4
4
|
|
|
5
|
-
const baseClasses = 'px-6 py-3 text-left text-xs font-medium text-
|
|
6
|
-
const sortableClasses = sortable ? 'cursor-pointer hover:text-
|
|
5
|
+
const baseClasses = 'px-6 py-3 text-left text-xs font-medium text-fg-soft uppercase tracking-wider'
|
|
6
|
+
const sortableClasses = sortable ? 'cursor-pointer hover:text-fg-strong' : ''
|
|
7
7
|
export const headerClasses = `${baseClasses} ${sortableClasses} ${className}`.trim()
|
|
8
8
|
</script>
|
|
9
9
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export const className = $props.className || ''
|
|
3
3
|
export const hoverable = $props.hoverable !== false
|
|
4
4
|
|
|
5
|
-
const hoverClasses = hoverable ? 'hover:bg-
|
|
5
|
+
const hoverClasses = hoverable ? 'hover:bg-surface' : ''
|
|
6
6
|
const rowClasses = `${hoverClasses} ${className}`.trim()
|
|
7
7
|
</script>
|
|
8
8
|
|
package/src/ui/tabs/Tabs.stx
CHANGED
|
@@ -24,9 +24,9 @@ const tabListOrientationClasses = {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const variantClasses = {
|
|
27
|
-
line: 'border-
|
|
28
|
-
pills: 'gap-2 border-0 bg-
|
|
29
|
-
enclosed: 'border-
|
|
27
|
+
line: 'border-line',
|
|
28
|
+
pills: 'gap-2 border-0 bg-surface-raised p-1 rounded-lg',
|
|
29
|
+
enclosed: 'border-line',
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
export const containerClasses = `flex ${orientationClasses[orientation]} ${className}`.trim()
|
|
@@ -97,14 +97,14 @@ function getTabClasses(index) {
|
|
|
97
97
|
const base = 'px-4 py-2 font-medium text-sm transition-colors duration-150 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 dark:focus:ring-offset-gray-900'
|
|
98
98
|
if (variant === 'line') {
|
|
99
99
|
const border = orientation === 'horizontal' ? 'border-b-2' : 'border-r-2'
|
|
100
|
-
return `${base} ${border} ${isActiveTab ? 'border-blue-500 text-
|
|
100
|
+
return `${base} ${border} ${isActiveTab ? 'border-blue-500 text-info' : 'border-transparent text-fg-muted hover:text-fg hover:border-line-strong'}`
|
|
101
101
|
}
|
|
102
102
|
if (variant === 'pills') {
|
|
103
|
-
return `${base} rounded-md ${isActiveTab ? 'bg-white dark:bg-gray-700 text-
|
|
103
|
+
return `${base} rounded-md ${isActiveTab ? 'bg-white dark:bg-gray-700 text-fg shadow-sm' : 'text-fg-muted hover:text-fg'}`
|
|
104
104
|
}
|
|
105
105
|
if (variant === 'enclosed') {
|
|
106
106
|
const borders = orientation === 'horizontal' ? 'border-t border-l border-r rounded-t-md' : 'border-t border-l border-b rounded-l-md'
|
|
107
|
-
return `${base} ${borders} ${isActiveTab ? 'bg-white dark:bg-gray-800 border-
|
|
107
|
+
return `${base} ${borders} ${isActiveTab ? 'bg-white dark:bg-gray-800 border-line -mb-px' : 'bg-surface border-transparent hover:border-line'}`
|
|
108
108
|
}
|
|
109
109
|
return base
|
|
110
110
|
}
|
|
@@ -19,16 +19,16 @@ const resizeClasses = { none: 'resize-none', vertical: 'resize-y', horizontal: '
|
|
|
19
19
|
const baseClasses = 'block w-full border-0 rounded-md shadow-sm ring-1 ring-inset transition-colors duration-200 focus:ring-2 focus:ring-inset px-4 py-2 text-base dark:bg-blue-gray-700 dark:text-gray-100'
|
|
20
20
|
const stateClasses = error
|
|
21
21
|
? 'ring-red-300 dark:ring-red-600 text-red-900 dark:text-red-300 placeholder-red-300 dark:placeholder-red-500 focus:ring-red-500 dark:focus:ring-red-400'
|
|
22
|
-
: 'ring-
|
|
22
|
+
: 'ring-line-strong text-fg placeholder-fg-subtle focus:ring-accent'
|
|
23
23
|
const disabledClasses = disabled
|
|
24
|
-
? 'opacity-50 cursor-not-allowed bg-
|
|
24
|
+
? 'opacity-50 cursor-not-allowed bg-surface'
|
|
25
25
|
: readonly
|
|
26
|
-
? 'bg-
|
|
26
|
+
? 'bg-surface cursor-default'
|
|
27
27
|
: 'bg-white dark:bg-blue-gray-700'
|
|
28
28
|
|
|
29
29
|
export const textareaClasses = `${baseClasses} ${stateClasses} ${disabledClasses} ${resizeClasses[resize]} ${className}`.trim()
|
|
30
|
-
export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ? 'text-
|
|
31
|
-
export const helperClasses = `mt-2 text-sm ${error ? 'text-
|
|
30
|
+
export const labelClasses = `block text-sm font-medium leading-6 mb-2 ${error ? 'text-danger' : 'text-fg'}`.trim()
|
|
31
|
+
export const helperClasses = `mt-2 text-sm ${error ? 'text-danger' : 'text-fg-soft'}`.trim()
|
|
32
32
|
</script>
|
|
33
33
|
|
|
34
34
|
<script client>
|
|
@@ -101,7 +101,7 @@ defineExpose({ value: inputValue })
|
|
|
101
101
|
@endif
|
|
102
102
|
|
|
103
103
|
@if(showCount && maxLength)
|
|
104
|
-
<p class="text-sm text-
|
|
104
|
+
<p class="text-sm text-fg-soft" x-text="charCount()"></p>
|
|
105
105
|
@endif
|
|
106
106
|
</div>
|
|
107
107
|
@endif
|
package/src/ui/video/Video.stx
CHANGED
|
@@ -20,7 +20,7 @@ export const aspectRatioClass = aspectRatio === '16/9' ? 'aspect-video' : aspect
|
|
|
20
20
|
<div class="{{ containerClasses }}">
|
|
21
21
|
@if(title)
|
|
22
22
|
<div class="mb-2 px-1">
|
|
23
|
-
<h3 class="text-sm font-medium text-
|
|
23
|
+
<h3 class="text-sm font-medium text-fg">
|
|
24
24
|
{{ title }}
|
|
25
25
|
</h3>
|
|
26
26
|
</div>
|
|
@@ -10,12 +10,12 @@ export const hoverable = $props.hoverable ?? true
|
|
|
10
10
|
export const className = $props.className || ''
|
|
11
11
|
|
|
12
12
|
export const totalHeight = data.length * rowHeight
|
|
13
|
-
export const containerClasses = `border border-
|
|
14
|
-
export const headerClasses = `bg-
|
|
15
|
-
export const headerCellClasses = `px-6 py-3 text-left text-xs font-medium text-
|
|
13
|
+
export const containerClasses = `border border-line rounded-lg overflow-hidden ${className}`.trim()
|
|
14
|
+
export const headerClasses = `bg-surface border-b border-line flex`.trim()
|
|
15
|
+
export const headerCellClasses = `px-6 py-3 text-left text-xs font-medium text-fg-soft uppercase tracking-wider`.trim()
|
|
16
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-
|
|
18
|
-
export const cellClasses = `px-6 py-4 text-sm text-
|
|
17
|
+
export const rowClasses = `absolute left-0 right-0 flex border-b border-line ${hoverable ? 'hover:bg-surface' : ''}`.trim()
|
|
18
|
+
export const cellClasses = `px-6 py-4 text-sm text-fg`.trim()
|
|
19
19
|
</script>
|
|
20
20
|
|
|
21
21
|
<script client>
|
|
@@ -86,7 +86,7 @@ defineExpose({ scrollTop })
|
|
|
86
86
|
<div
|
|
87
87
|
:for="entry in visibleRows()"
|
|
88
88
|
:key="entry.index"
|
|
89
|
-
:class="entry.striped ? '{{ rowClasses }} bg-
|
|
89
|
+
:class="entry.striped ? '{{ rowClasses }} bg-surface' : '{{ rowClasses }}'"
|
|
90
90
|
:style="`top: ${entry.top}px; height: {{ rowHeight }}px`"
|
|
91
91
|
:data-index="entry.index"
|
|
92
92
|
>
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
<script server>
|
|
2
|
-
export const value = $props.value
|
|
3
|
-
export const className = $props.className || ''
|
|
4
|
-
export const as = $props.as || 'div'
|
|
5
|
-
|
|
6
|
-
const baseClasses = 'w-full'
|
|
7
|
-
export const groupClasses = `${baseClasses} ${className}`.trim()
|
|
8
|
-
export const radioGroupInstanceId = `stx-rg-${Math.random().toString(36).slice(2, 11)}`
|
|
9
|
-
</script>
|
|
10
|
-
|
|
11
|
-
<script client>
|
|
12
|
-
const emit = defineEmits()
|
|
13
|
-
const radioGroupInstanceId = {{ radioGroupInstanceId }}
|
|
14
|
-
const initialValue = {{ value === undefined ? 'null' : value }}
|
|
15
|
-
const selected = state(initialValue)
|
|
16
|
-
let rootEl = null
|
|
17
|
-
|
|
18
|
-
function selectValue(v) {
|
|
19
|
-
selected.set(v)
|
|
20
|
-
syncOptionStates()
|
|
21
|
-
emit('change', v)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function syncOptionStates() {
|
|
25
|
-
if (!rootEl) return
|
|
26
|
-
const options = rootEl.querySelectorAll('[data-stx-radio-option]')
|
|
27
|
-
for (const opt of options) {
|
|
28
|
-
const raw = opt.dataset.optionValue
|
|
29
|
-
let v
|
|
30
|
-
try { v = JSON.parse(raw ?? 'null') }
|
|
31
|
-
catch { v = raw }
|
|
32
|
-
const checked = selected() === v
|
|
33
|
-
opt.setAttribute('aria-checked', checked ? 'true' : 'false')
|
|
34
|
-
opt.setAttribute('data-checked', checked ? 'true' : 'false')
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function onSelect(event) {
|
|
39
|
-
event.stopPropagation()
|
|
40
|
-
selectValue(event.detail)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
onMount(() => {
|
|
44
|
-
rootEl = document.querySelector(`[data-radio-group-id="${radioGroupInstanceId}"]`)
|
|
45
|
-
syncOptionStates()
|
|
46
|
-
})
|
|
47
|
-
|
|
48
|
-
defineExpose({ selected, selectValue })
|
|
49
|
-
</script>
|
|
50
|
-
|
|
51
|
-
<component
|
|
52
|
-
:is="{{ as }}"
|
|
53
|
-
class="{{ groupClasses }}"
|
|
54
|
-
data-stx-radio-group
|
|
55
|
-
data-radio-group-id="{{ radioGroupInstanceId }}"
|
|
56
|
-
role="radiogroup"
|
|
57
|
-
@stx:radio-select="onSelect($event)"
|
|
58
|
-
>
|
|
59
|
-
<slot />
|
|
60
|
-
</component>
|