tera-system-ui 0.0.23 → 0.0.25
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/components/avatar/Avatar.svelte +43 -43
- package/dist/components/brand-logo/BrandLogo.svelte +31 -31
- package/dist/components/button/Button.svelte +49 -49
- package/dist/components/combobox/Combobox.svelte +8 -8
- package/dist/components/command/command.scss +72 -72
- package/dist/components/command/components/Command.svelte +120 -120
- package/dist/components/command/components/Command.svelte.d.ts +1 -1
- package/dist/components/command/components/CommandEmpty.svelte +30 -30
- package/dist/components/command/components/CommandEmpty.svelte.d.ts +1 -1
- package/dist/components/command/components/CommandGroup.svelte +110 -110
- package/dist/components/command/components/CommandGroup.svelte.d.ts +1 -1
- package/dist/components/command/components/CommandInput.svelte +92 -92
- package/dist/components/command/components/CommandInput.svelte.d.ts +1 -1
- package/dist/components/command/components/CommandItem.svelte +110 -110
- package/dist/components/command/components/CommandItem.svelte.d.ts +1 -1
- package/dist/components/command/components/CommandList.svelte +56 -56
- package/dist/components/command/components/CommandLoading.svelte +28 -28
- package/dist/components/command/components/CommandLoading.svelte.d.ts +1 -1
- package/dist/components/command/components/CommandSeparator.svelte +21 -21
- package/dist/components/command/components/CommandSeparator.svelte.d.ts +1 -1
- package/dist/components/dialog/Dialog.astro +64 -64
- package/dist/components/dialog/Dialog.svelte +109 -109
- package/dist/components/dialog/dialog.scss +115 -115
- package/dist/components/dropdown-menu/components/DropdownMenu.svelte +33 -33
- package/dist/components/dropdown-menu/components/DropdownMenuGroup.svelte +11 -11
- package/dist/components/dropdown-menu/components/DropdownMenuHeader.svelte +11 -11
- package/dist/components/dropdown-menu/components/DropdownMenuItem.svelte +30 -30
- package/dist/components/dropdown-menu/components/DropdownMenuSeparator.svelte +10 -10
- package/dist/components/header/Header.svelte +36 -36
- package/dist/components/header/header.scss +19 -19
- package/dist/components/icons/IconArrowBigRightFilled.svelte +10 -10
- package/dist/components/icons/IconBook.svelte +10 -10
- package/dist/components/icons/IconBookmarkPlus.svelte +10 -10
- package/dist/components/icons/IconCalculator.svelte +10 -10
- package/dist/components/icons/IconCheck.svelte +10 -10
- package/dist/components/icons/IconChevronDown.svelte +10 -10
- package/dist/components/icons/IconCopy.svelte +10 -10
- package/dist/components/icons/IconCopyCheckFilled.svelte +10 -10
- package/dist/components/icons/IconHamburger.svelte +10 -10
- package/dist/components/icons/IconLanguage.svelte +10 -10
- package/dist/components/icons/IconLoader2.svelte +10 -10
- package/dist/components/icons/IconLogout.svelte +10 -10
- package/dist/components/icons/IconMoon.svelte +10 -10
- package/dist/components/icons/IconPointFilled.svelte +10 -10
- package/dist/components/icons/IconSearch.svelte +10 -10
- package/dist/components/icons/IconSettings.svelte +10 -10
- package/dist/components/icons/IconSun.svelte +10 -10
- package/dist/components/icons/IconSwitchHorizontal.svelte +10 -10
- package/dist/components/icons/IconSwitchVertical.svelte +10 -10
- package/dist/components/icons/IconTransform.svelte +10 -10
- package/dist/components/icons/IconX.svelte +10 -10
- package/dist/components/input/Input.svelte +24 -24
- package/dist/components/language-picker-button/LanguagePickerButton.svelte +109 -109
- package/dist/components/light-dark-toggle/LightDarkToggle.svelte +36 -36
- package/dist/components/popover/Popover.svelte +159 -159
- package/dist/components/popover-responsive/PopoverResponsive.svelte +87 -87
- package/dist/components/side-navigation/SideNavigation.svelte +114 -114
- package/dist/components/side-navigation/SideNavigationItem.svelte +17 -17
- package/dist/components/side-navigation/SideNavigationLayout.svelte +19 -19
- package/dist/components/side-navigation/sidenav.scss +149 -149
- package/dist/components/slider/Slider.svelte +181 -181
- package/dist/components/star-rating/StarRating.d.ts +10 -0
- package/dist/components/star-rating/StarRating.js +7 -0
- package/dist/components/star-rating/StarRating.svelte +88 -0
- package/dist/components/star-rating/StarRating.svelte.d.ts +3 -0
- package/dist/components/star-rating/index.d.ts +1 -0
- package/dist/components/star-rating/index.js +1 -0
- package/dist/components/tabs/components/Tabs.svelte +47 -47
- package/dist/components/tabs/components/TabsContent.svelte +34 -34
- package/dist/components/tabs/components/TabsItem.svelte +29 -29
- package/dist/components/tabs/components/TabsList.svelte +41 -41
- package/dist/components/tera-ui-context/TeraUiContext.svelte +28 -28
- package/dist/components/text-area/TextArea.svelte +88 -88
- package/dist/components/user-avatar-with-menu/UserAvatarWithMenu.svelte +67 -67
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/themes/scrollbar.scss +37 -37
- package/dist/themes/tera-ui-base.css +208 -210
- package/dist/themes/tw-preset.cjs +153 -153
- package/package.json +98 -98
- package/scripts/add-component-template.js +120 -120
- package/scripts/generate-ts-index.js +138 -138
|
@@ -1,183 +1,183 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {type SliderProps} from "./Slider";
|
|
3
|
-
|
|
4
|
-
let {
|
|
5
|
-
children,
|
|
6
|
-
min = 0,
|
|
7
|
-
max = 100,
|
|
8
|
-
step = 1,
|
|
9
|
-
value = $bindable(),
|
|
10
|
-
showTicks = false,
|
|
11
|
-
onchange,
|
|
12
|
-
...props
|
|
13
|
-
}: SliderProps = $props();
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
let slider = $state<HTMLElement>()
|
|
17
|
-
let sliderHandle = $state<HTMLElement>()
|
|
18
|
-
let sliderTrack = $state<HTMLElement>()
|
|
19
|
-
let sliderRail = $state<HTMLElement>()
|
|
20
|
-
let sliderTooltip = $state<HTMLElement>()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
$effect(() => {
|
|
24
|
-
if (!slider || !sliderHandle || !sliderTrack || !sliderRail) return
|
|
25
|
-
slider.addEventListener('pointerdown', (e) => {
|
|
26
|
-
sliderHandle.setAttribute('data-state', 'dragging');
|
|
27
|
-
onDrag(e)
|
|
28
|
-
document.addEventListener('pointermove', onDrag);
|
|
29
|
-
document.addEventListener('pointerup', () => {
|
|
30
|
-
document.removeEventListener('pointermove', onDrag);
|
|
31
|
-
sliderHandle.removeAttribute('data-state');
|
|
32
|
-
toggleToolTip(false)
|
|
33
|
-
|
|
34
|
-
}, {once: true});
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// For touch support
|
|
38
|
-
slider.addEventListener('touchstart', (e) => {
|
|
39
|
-
sliderHandle.setAttribute('data-state', 'dragging');
|
|
40
|
-
onDrag(e)
|
|
41
|
-
document.addEventListener('touchmove', onDrag);
|
|
42
|
-
document.addEventListener('touchend', () => {
|
|
43
|
-
document.removeEventListener('touchmove', onDrag);
|
|
44
|
-
toggleToolTip(false)
|
|
45
|
-
sliderHandle.removeAttribute('data-state');
|
|
46
|
-
}, {once: true});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
sliderHandle.addEventListener('pointerenter', (e) => {
|
|
50
|
-
toggleToolTip(true)
|
|
51
|
-
sliderHandle.addEventListener('pointerleave', (e) => {
|
|
52
|
-
toggleToolTip(false)
|
|
53
|
-
}, {once: true});
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
let tooltipInterval
|
|
59
|
-
|
|
60
|
-
function toggleToolTip(open) {
|
|
61
|
-
if (tooltipInterval) clearInterval(tooltipInterval)
|
|
62
|
-
|
|
63
|
-
if (open) {
|
|
64
|
-
sliderTooltip.classList.add('show');
|
|
65
|
-
} else {
|
|
66
|
-
tooltipInterval = setTimeout(() => {
|
|
67
|
-
sliderTooltip.classList.remove('show');
|
|
68
|
-
}, 300)
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const calculateValue = (position) => {
|
|
74
|
-
const sliderWidth = sliderRail.offsetWidth;
|
|
75
|
-
|
|
76
|
-
// calculate step size in px
|
|
77
|
-
const stepSize = sliderWidth / ((max - min) / step)
|
|
78
|
-
|
|
79
|
-
// Clamp position within the slider width
|
|
80
|
-
const clampedPosition = Math.max(0, Math.min(position, sliderWidth));
|
|
81
|
-
// Calculate nearest step position
|
|
82
|
-
const stepCount = Math.round(clampedPosition / stepSize);
|
|
83
|
-
|
|
84
|
-
console.log(stepCount)
|
|
85
|
-
return min + stepCount
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const onDrag = (event) => {
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
event.stopPropagation();
|
|
91
|
-
toggleToolTip(true)
|
|
92
|
-
|
|
93
|
-
let position
|
|
94
|
-
|
|
95
|
-
if (event.type.startsWith('touch')) {
|
|
96
|
-
const touch = event.touches[0];
|
|
97
|
-
position = touch.clientX - slider.getBoundingClientRect().left;
|
|
98
|
-
} else {
|
|
99
|
-
position = event.clientX - slider.getBoundingClientRect().left;
|
|
100
|
-
}
|
|
101
|
-
let newValue = calculateValue(position);
|
|
102
|
-
|
|
103
|
-
if (newValue !== value) {
|
|
104
|
-
value = newValue;
|
|
105
|
-
onchange?.(value);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
updateSliderByValue(newValue)
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
$effect(() => {
|
|
113
|
-
if (value == undefined) {
|
|
114
|
-
value = min
|
|
115
|
-
}
|
|
116
|
-
updateSliderByValue(value)
|
|
117
|
-
})
|
|
118
|
-
|
|
119
|
-
function updateSliderByValue(v: number) {
|
|
120
|
-
const percentage = ((value - min) / (max - min)) * 100
|
|
121
|
-
|
|
122
|
-
// Update the position of the handle and track width
|
|
123
|
-
sliderHandle.style.left = `${percentage}%`;
|
|
124
|
-
sliderTooltip.style.left = `${percentage}%`;
|
|
125
|
-
sliderTrack.style.width = `${percentage}%`;
|
|
126
|
-
}
|
|
127
|
-
</script>
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
<div bind:this={slider} class="cursor-pointer w-full relative mx-1 py-2.5">
|
|
131
|
-
<div data-slider-rail bind:this={sliderRail} class="w-full h-1.5 bg-neutral-token-4 rounded-full overflow-hidden">
|
|
132
|
-
<div data-slider-track bind:this={sliderTrack} class="rounded-full w-full h-full bg-primary-token-4"></div>
|
|
133
|
-
</div>
|
|
134
|
-
|
|
135
|
-
<div
|
|
136
|
-
bind:this={sliderHandle}
|
|
137
|
-
data-slider-handle
|
|
138
|
-
tabindex="0"
|
|
139
|
-
role="slider"
|
|
140
|
-
aria-valuemin={`${(min ?? 0)}`}
|
|
141
|
-
aria-valuemax={`${(max ?? 0)}`}
|
|
142
|
-
aria-valuenow={`${(value ?? 0)}`}
|
|
143
|
-
aria-orientation="horizontal"
|
|
144
|
-
class="slider-handle -translate-x-1/2 absolute top-1/2 -translate-y-1/2 rounded-full bg-neutral-token-1 border-[3px] border-primary-token-5 size-4"
|
|
145
|
-
>
|
|
146
|
-
|
|
147
|
-
</div>
|
|
148
|
-
|
|
149
|
-
<div bind:this={sliderTooltip} data-slider-tooltip class="">
|
|
150
|
-
<span class="z-10 relative">
|
|
151
|
-
{value}
|
|
152
|
-
</span>
|
|
153
|
-
</div>
|
|
154
|
-
|
|
155
|
-
<!-- <input-->
|
|
156
|
-
<!-- type="range"-->
|
|
157
|
-
<!-- min={min}-->
|
|
158
|
-
<!-- max={max}-->
|
|
159
|
-
<!-- step={step}-->
|
|
160
|
-
<!-- oninput={(event) => {-->
|
|
161
|
-
<!-- value = event.target.value;-->
|
|
162
|
-
<!-- handleChange(event);-->
|
|
163
|
-
<!-- }}-->
|
|
164
|
-
<!-- class="w-full appearance-none bg-gray-300 rounded-lg h-2 focus:outline-none focus:ring-2 focus:ring-blue-500 transition"-->
|
|
165
|
-
<!-- />-->
|
|
166
|
-
|
|
167
|
-
<!-- {#if showTicks}-->
|
|
168
|
-
<!-- <div class="relative mt-2 flex justify-between text-xs text-gray-500">-->
|
|
169
|
-
<!-- {#each ticks as tick}-->
|
|
170
|
-
<!-- <div class="flex-1">-->
|
|
171
|
-
<!-- <div-->
|
|
172
|
-
<!-- class="h-2 w-0.5 bg-gray-400 mx-auto"-->
|
|
173
|
-
<!-- style="transform: translateX(-50%);"-->
|
|
174
|
-
<!-- ></div>-->
|
|
175
|
-
<!-- </div>-->
|
|
176
|
-
<!-- {/each}-->
|
|
177
|
-
<!-- </div>-->
|
|
178
|
-
<!-- {/if}-->
|
|
179
|
-
</div>
|
|
180
|
-
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {type SliderProps} from "./Slider";
|
|
3
|
+
|
|
4
|
+
let {
|
|
5
|
+
children,
|
|
6
|
+
min = 0,
|
|
7
|
+
max = 100,
|
|
8
|
+
step = 1,
|
|
9
|
+
value = $bindable(),
|
|
10
|
+
showTicks = false,
|
|
11
|
+
onchange,
|
|
12
|
+
...props
|
|
13
|
+
}: SliderProps = $props();
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
let slider = $state<HTMLElement>()
|
|
17
|
+
let sliderHandle = $state<HTMLElement>()
|
|
18
|
+
let sliderTrack = $state<HTMLElement>()
|
|
19
|
+
let sliderRail = $state<HTMLElement>()
|
|
20
|
+
let sliderTooltip = $state<HTMLElement>()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
$effect(() => {
|
|
24
|
+
if (!slider || !sliderHandle || !sliderTrack || !sliderRail) return
|
|
25
|
+
slider.addEventListener('pointerdown', (e) => {
|
|
26
|
+
sliderHandle.setAttribute('data-state', 'dragging');
|
|
27
|
+
onDrag(e)
|
|
28
|
+
document.addEventListener('pointermove', onDrag);
|
|
29
|
+
document.addEventListener('pointerup', () => {
|
|
30
|
+
document.removeEventListener('pointermove', onDrag);
|
|
31
|
+
sliderHandle.removeAttribute('data-state');
|
|
32
|
+
toggleToolTip(false)
|
|
33
|
+
|
|
34
|
+
}, {once: true});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// For touch support
|
|
38
|
+
slider.addEventListener('touchstart', (e) => {
|
|
39
|
+
sliderHandle.setAttribute('data-state', 'dragging');
|
|
40
|
+
onDrag(e)
|
|
41
|
+
document.addEventListener('touchmove', onDrag);
|
|
42
|
+
document.addEventListener('touchend', () => {
|
|
43
|
+
document.removeEventListener('touchmove', onDrag);
|
|
44
|
+
toggleToolTip(false)
|
|
45
|
+
sliderHandle.removeAttribute('data-state');
|
|
46
|
+
}, {once: true});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
sliderHandle.addEventListener('pointerenter', (e) => {
|
|
50
|
+
toggleToolTip(true)
|
|
51
|
+
sliderHandle.addEventListener('pointerleave', (e) => {
|
|
52
|
+
toggleToolTip(false)
|
|
53
|
+
}, {once: true});
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
let tooltipInterval
|
|
59
|
+
|
|
60
|
+
function toggleToolTip(open) {
|
|
61
|
+
if (tooltipInterval) clearInterval(tooltipInterval)
|
|
62
|
+
|
|
63
|
+
if (open) {
|
|
64
|
+
sliderTooltip.classList.add('show');
|
|
65
|
+
} else {
|
|
66
|
+
tooltipInterval = setTimeout(() => {
|
|
67
|
+
sliderTooltip.classList.remove('show');
|
|
68
|
+
}, 300)
|
|
69
|
+
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const calculateValue = (position) => {
|
|
74
|
+
const sliderWidth = sliderRail.offsetWidth;
|
|
75
|
+
|
|
76
|
+
// calculate step size in px
|
|
77
|
+
const stepSize = sliderWidth / ((max - min) / step)
|
|
78
|
+
|
|
79
|
+
// Clamp position within the slider width
|
|
80
|
+
const clampedPosition = Math.max(0, Math.min(position, sliderWidth));
|
|
81
|
+
// Calculate nearest step position
|
|
82
|
+
const stepCount = Math.round(clampedPosition / stepSize);
|
|
83
|
+
|
|
84
|
+
console.log(stepCount)
|
|
85
|
+
return min + stepCount
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const onDrag = (event) => {
|
|
89
|
+
event.preventDefault();
|
|
90
|
+
event.stopPropagation();
|
|
91
|
+
toggleToolTip(true)
|
|
92
|
+
|
|
93
|
+
let position
|
|
94
|
+
|
|
95
|
+
if (event.type.startsWith('touch')) {
|
|
96
|
+
const touch = event.touches[0];
|
|
97
|
+
position = touch.clientX - slider.getBoundingClientRect().left;
|
|
98
|
+
} else {
|
|
99
|
+
position = event.clientX - slider.getBoundingClientRect().left;
|
|
100
|
+
}
|
|
101
|
+
let newValue = calculateValue(position);
|
|
102
|
+
|
|
103
|
+
if (newValue !== value) {
|
|
104
|
+
value = newValue;
|
|
105
|
+
onchange?.(value);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
updateSliderByValue(newValue)
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
$effect(() => {
|
|
113
|
+
if (value == undefined) {
|
|
114
|
+
value = min
|
|
115
|
+
}
|
|
116
|
+
updateSliderByValue(value)
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
function updateSliderByValue(v: number) {
|
|
120
|
+
const percentage = ((value - min) / (max - min)) * 100
|
|
121
|
+
|
|
122
|
+
// Update the position of the handle and track width
|
|
123
|
+
sliderHandle.style.left = `${percentage}%`;
|
|
124
|
+
sliderTooltip.style.left = `${percentage}%`;
|
|
125
|
+
sliderTrack.style.width = `${percentage}%`;
|
|
126
|
+
}
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
<div bind:this={slider} class="cursor-pointer w-full relative mx-1 py-2.5">
|
|
131
|
+
<div data-slider-rail bind:this={sliderRail} class="w-full h-1.5 bg-neutral-token-4 rounded-full overflow-hidden">
|
|
132
|
+
<div data-slider-track bind:this={sliderTrack} class="rounded-full w-full h-full bg-primary-token-4"></div>
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<div
|
|
136
|
+
bind:this={sliderHandle}
|
|
137
|
+
data-slider-handle
|
|
138
|
+
tabindex="0"
|
|
139
|
+
role="slider"
|
|
140
|
+
aria-valuemin={`${(min ?? 0)}`}
|
|
141
|
+
aria-valuemax={`${(max ?? 0)}`}
|
|
142
|
+
aria-valuenow={`${(value ?? 0)}`}
|
|
143
|
+
aria-orientation="horizontal"
|
|
144
|
+
class="slider-handle -translate-x-1/2 absolute top-1/2 -translate-y-1/2 rounded-full bg-neutral-token-1 border-[3px] border-primary-token-5 size-4"
|
|
145
|
+
>
|
|
146
|
+
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div bind:this={sliderTooltip} data-slider-tooltip class="">
|
|
150
|
+
<span class="z-10 relative">
|
|
151
|
+
{value}
|
|
152
|
+
</span>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
<!-- <input-->
|
|
156
|
+
<!-- type="range"-->
|
|
157
|
+
<!-- min={min}-->
|
|
158
|
+
<!-- max={max}-->
|
|
159
|
+
<!-- step={step}-->
|
|
160
|
+
<!-- oninput={(event) => {-->
|
|
161
|
+
<!-- value = event.target.value;-->
|
|
162
|
+
<!-- handleChange(event);-->
|
|
163
|
+
<!-- }}-->
|
|
164
|
+
<!-- class="w-full appearance-none bg-gray-300 rounded-lg h-2 focus:outline-none focus:ring-2 focus:ring-blue-500 transition"-->
|
|
165
|
+
<!-- />-->
|
|
166
|
+
|
|
167
|
+
<!-- {#if showTicks}-->
|
|
168
|
+
<!-- <div class="relative mt-2 flex justify-between text-xs text-gray-500">-->
|
|
169
|
+
<!-- {#each ticks as tick}-->
|
|
170
|
+
<!-- <div class="flex-1">-->
|
|
171
|
+
<!-- <div-->
|
|
172
|
+
<!-- class="h-2 w-0.5 bg-gray-400 mx-auto"-->
|
|
173
|
+
<!-- style="transform: translateX(-50%);"-->
|
|
174
|
+
<!-- ></div>-->
|
|
175
|
+
<!-- </div>-->
|
|
176
|
+
<!-- {/each}-->
|
|
177
|
+
<!-- </div>-->
|
|
178
|
+
<!-- {/if}-->
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
181
|
<style>.slider-handle {
|
|
182
182
|
transition: all 0.2s ease-in-out, left 0s;
|
|
183
183
|
}
|
|
@@ -225,4 +225,4 @@
|
|
|
225
225
|
[data-slider-tooltip]:global(.show) {
|
|
226
226
|
opacity: 1;
|
|
227
227
|
transform: translateY(-3.5rem) translateX(-50%) scale(1);
|
|
228
|
-
}</style>
|
|
228
|
+
}</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type VariantProps } from "tailwind-variants";
|
|
2
|
+
export declare const styles: import("tailwind-variants").TVReturnType<{}, undefined, "", import("tailwind-variants/dist/config").TVConfig<{}, {}>, {}, undefined, import("tailwind-variants").TVReturnType<{}, undefined, "", import("tailwind-variants/dist/config").TVConfig<{}, {}>, unknown, unknown, undefined>>;
|
|
3
|
+
type StarRatingVariants = VariantProps<typeof styles>;
|
|
4
|
+
export interface StarRatingProps extends StarRatingVariants {
|
|
5
|
+
children?: any;
|
|
6
|
+
class?: string;
|
|
7
|
+
value?: number;
|
|
8
|
+
onchange?: (value: number) => void;
|
|
9
|
+
}
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {type StarRatingProps, styles} from "./StarRating";
|
|
3
|
+
import {cn} from "../../utils/utils";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
children,
|
|
7
|
+
value = $bindable(),
|
|
8
|
+
onchange,
|
|
9
|
+
...props
|
|
10
|
+
}: StarRatingProps = $props();
|
|
11
|
+
|
|
12
|
+
let hoverRating = $state(0);
|
|
13
|
+
|
|
14
|
+
// Descriptive texts for each star rating
|
|
15
|
+
const descriptions = [
|
|
16
|
+
'Very Bad',
|
|
17
|
+
'Bad',
|
|
18
|
+
'Okay',
|
|
19
|
+
'Good',
|
|
20
|
+
'Excellent'
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
// Sets the rating when a star is clicked
|
|
24
|
+
function setRating(v, e) {
|
|
25
|
+
if (value != v) {
|
|
26
|
+
value = v;
|
|
27
|
+
} else {
|
|
28
|
+
value = undefined
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
onchange?.(v)
|
|
32
|
+
console.log('setRating', e.type)
|
|
33
|
+
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Updates hover state when hovering over a star
|
|
37
|
+
function setHover(v, e) {
|
|
38
|
+
hoverRating = v;
|
|
39
|
+
console.log('setHover', v, e.type)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Resets hover state when leaving the star area
|
|
43
|
+
function resetHover(e) {
|
|
44
|
+
|
|
45
|
+
hoverRating = 0;
|
|
46
|
+
console.log('resetHover', e.type)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
</script>
|
|
50
|
+
|
|
51
|
+
<div class="inline-flex items-center">
|
|
52
|
+
{#each Array(5) as _, index (index)}
|
|
53
|
+
<button
|
|
54
|
+
data-rating-icon
|
|
55
|
+
data-highlight={(hoverRating || value) > index}
|
|
56
|
+
data-hovering={hoverRating === (index + 1)}
|
|
57
|
+
aria-label=""
|
|
58
|
+
onpointerenter={(e) => setHover(index + 1, e)}
|
|
59
|
+
onpointerleave={resetHover}
|
|
60
|
+
ontouchendcapture={resetHover}
|
|
61
|
+
onclick={(e) => setRating(index + 1, e)}
|
|
62
|
+
class={cn(" h-6 px-1 ")}>
|
|
63
|
+
<svg
|
|
64
|
+
viewBox="64 64 896 896" focusable="true" data-icon="star" width="1em" height="1em"
|
|
65
|
+
fill="currentColor"
|
|
66
|
+
class="h-full w-full fill-inherit"
|
|
67
|
+
aria-hidden="true">
|
|
68
|
+
<path d="M908.1 353.1l-253.9-36.9L540.7 86.1c-3.1-6.3-8.2-11.4-14.5-14.5-15.8-7.8-35-1.3-42.9 14.5L369.8 316.2l-253.9 36.9c-7 1-13.4 4.3-18.3 9.3a32.05 32.05 0 00.6 45.3l183.7 179.1-43.4 252.9a31.95 31.95 0 0046.4 33.7L512 754l227.1 119.4c6.2 3.3 13.4 4.4 20.3 3.2 17.4-3 29.1-19.5 26.1-36.9l-43.4-252.9 183.7-179.1c5-4.9 8.3-11.3 9.3-18.3 2.7-17.5-9.5-33.7-27-36.3z"></path>
|
|
69
|
+
</svg>
|
|
70
|
+
</button>
|
|
71
|
+
{/each}
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
<style global>[data-rating-icon] {
|
|
76
|
+
fill: hsl(var(--tw---token-color-neutral-token-5));
|
|
77
|
+
transition-property: all;
|
|
78
|
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
79
|
+
transition-duration: 300ms
|
|
80
|
+
}
|
|
81
|
+
[data-rating-icon][data-highlight=true] {
|
|
82
|
+
fill: #facc15
|
|
83
|
+
}
|
|
84
|
+
[data-rating-icon][data-hovering=true] {
|
|
85
|
+
--tw-scale-x: 1.1;
|
|
86
|
+
--tw-scale-y: 1.1;
|
|
87
|
+
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
|
|
88
|
+
}</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as StarRating } from './StarRating.svelte';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as StarRating } from './StarRating.svelte';
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {setCtx, type TabsProps} from "../Tabs";
|
|
3
|
-
import {cn} from "../../../utils/utils";
|
|
4
|
-
import {createTabs} from "../tabs.svelte";
|
|
5
|
-
import {untrack} from "svelte";
|
|
6
|
-
|
|
7
|
-
let {
|
|
8
|
-
children,
|
|
9
|
-
value = $bindable(),
|
|
10
|
-
class: className,
|
|
11
|
-
...props
|
|
12
|
-
}: TabsProps = $props();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
function setValue(v: string) {
|
|
16
|
-
console.log('Change value', v)
|
|
17
|
-
value = v
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
function getValue() {
|
|
21
|
-
return value
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let tabsState = createTabs(value)
|
|
25
|
-
|
|
26
|
-
setCtx({
|
|
27
|
-
setValue: setValue,
|
|
28
|
-
getValue: getValue,
|
|
29
|
-
currentTab: value,
|
|
30
|
-
state: tabsState
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
$effect(() => {
|
|
34
|
-
value = tabsState.currentTab
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
$effect(() => {
|
|
38
|
-
tabsState.currentTab = value
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
let tabs = $state()
|
|
42
|
-
</script>
|
|
43
|
-
|
|
44
|
-
<div bind:this={tabs}
|
|
45
|
-
data-tabs-root
|
|
46
|
-
class={cn("grid grid-rows-[auto_1fr] max-h-full gap-2", className)}>
|
|
47
|
-
{@render children?.()}
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {setCtx, type TabsProps} from "../Tabs";
|
|
3
|
+
import {cn} from "../../../utils/utils";
|
|
4
|
+
import {createTabs} from "../tabs.svelte";
|
|
5
|
+
import {untrack} from "svelte";
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
children,
|
|
9
|
+
value = $bindable(),
|
|
10
|
+
class: className,
|
|
11
|
+
...props
|
|
12
|
+
}: TabsProps = $props();
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
function setValue(v: string) {
|
|
16
|
+
console.log('Change value', v)
|
|
17
|
+
value = v
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getValue() {
|
|
21
|
+
return value
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let tabsState = createTabs(value)
|
|
25
|
+
|
|
26
|
+
setCtx({
|
|
27
|
+
setValue: setValue,
|
|
28
|
+
getValue: getValue,
|
|
29
|
+
currentTab: value,
|
|
30
|
+
state: tabsState
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
$effect(() => {
|
|
34
|
+
value = tabsState.currentTab
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
$effect(() => {
|
|
38
|
+
tabsState.currentTab = value
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
let tabs = $state()
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<div bind:this={tabs}
|
|
45
|
+
data-tabs-root
|
|
46
|
+
class={cn("grid grid-rows-[auto_1fr] max-h-full gap-2", className)}>
|
|
47
|
+
{@render children?.()}
|
|
48
48
|
</div>
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import {getCtx} from "../Tabs";
|
|
3
|
-
import {cn} from "../../../utils/utils";
|
|
4
|
-
|
|
5
|
-
let {
|
|
6
|
-
children,
|
|
7
|
-
class: className,
|
|
8
|
-
value,
|
|
9
|
-
...props
|
|
10
|
-
} = $props();
|
|
11
|
-
|
|
12
|
-
let context = getCtx()
|
|
13
|
-
|
|
14
|
-
$effect(() => {
|
|
15
|
-
// console.log(context.state.currentTab)
|
|
16
|
-
})
|
|
17
|
-
</script>
|
|
18
|
-
|
|
19
|
-
<div
|
|
20
|
-
role="tabpanel"
|
|
21
|
-
data-value={value}
|
|
22
|
-
data-state={context.state.currentTab === value ? 'active' : 'inactive'}
|
|
23
|
-
class={cn("bg-neutral-token-1 overflow-auto", className)}>
|
|
24
|
-
{@render children?.()}
|
|
25
|
-
</div>
|
|
26
|
-
|
|
27
|
-
<style>
|
|
28
|
-
[data-state="active"] {
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import {getCtx} from "../Tabs";
|
|
3
|
+
import {cn} from "../../../utils/utils";
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
children,
|
|
7
|
+
class: className,
|
|
8
|
+
value,
|
|
9
|
+
...props
|
|
10
|
+
} = $props();
|
|
11
|
+
|
|
12
|
+
let context = getCtx()
|
|
13
|
+
|
|
14
|
+
$effect(() => {
|
|
15
|
+
// console.log(context.state.currentTab)
|
|
16
|
+
})
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div
|
|
20
|
+
role="tabpanel"
|
|
21
|
+
data-value={value}
|
|
22
|
+
data-state={context.state.currentTab === value ? 'active' : 'inactive'}
|
|
23
|
+
class={cn("bg-neutral-token-1 overflow-auto", className)}>
|
|
24
|
+
{@render children?.()}
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<style>
|
|
28
|
+
[data-state="active"] {
|
|
29
29
|
display: block
|
|
30
|
-
}
|
|
31
|
-
[data-state="inactive"] {
|
|
30
|
+
}
|
|
31
|
+
[data-state="inactive"] {
|
|
32
32
|
display: none
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
</style>
|
|
36
|
-
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
</style>
|
|
36
|
+
|