twintrinsic 0.0.1
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/LICENSE +674 -0
- package/README.md +150 -0
- package/dist/App/App.svelte +54 -0
- package/dist/App/App.svelte.d.ts +65 -0
- package/dist/Section.svelte +25 -0
- package/dist/Section.svelte.d.ts +34 -0
- package/dist/actions/clickOutside.d.ts +9 -0
- package/dist/actions/clickOutside.js +19 -0
- package/dist/actions/index.d.ts +1 -0
- package/dist/actions/index.js +1 -0
- package/dist/components/Accordion/Accordion.svelte +75 -0
- package/dist/components/Accordion/Accordion.svelte.d.ts +39 -0
- package/dist/components/Accordion/AccordionItem.svelte +150 -0
- package/dist/components/Accordion/AccordionItem.svelte.d.ts +30 -0
- package/dist/components/App/App.story.md +8 -0
- package/dist/components/App/App.story.svelte +170 -0
- package/dist/components/App/App.story.svelte.d.ts +22 -0
- package/dist/components/App/App.svelte +77 -0
- package/dist/components/App/App.svelte.d.ts +66 -0
- package/dist/components/App/Split.svelte +346 -0
- package/dist/components/App/Split.svelte.d.ts +54 -0
- package/dist/components/App/index.d.ts +2 -0
- package/dist/components/App/index.js +3 -0
- package/dist/components/AppHeader/AppHeader.svelte +439 -0
- package/dist/components/AppHeader/AppHeader.svelte.d.ts +24 -0
- package/dist/components/Avatar/Avatar.svelte +300 -0
- package/dist/components/Avatar/Avatar.svelte.d.ts +48 -0
- package/dist/components/Avatar/AvatarGroup.svelte +185 -0
- package/dist/components/Avatar/AvatarGroup.svelte.d.ts +46 -0
- package/dist/components/Badge/Badge.svelte +186 -0
- package/dist/components/Badge/Badge.svelte.d.ts +51 -0
- package/dist/components/BottomBar/BottomBar.svelte +146 -0
- package/dist/components/BottomBar/BottomBar.svelte.d.ts +38 -0
- package/dist/components/Breadcrumb/Breadcrumb.svelte +77 -0
- package/dist/components/Breadcrumb/Breadcrumb.svelte.d.ts +42 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.svelte +171 -0
- package/dist/components/Breadcrumb/BreadcrumbItem.svelte.d.ts +38 -0
- package/dist/components/Button/Button.svelte +252 -0
- package/dist/components/Button/Button.svelte.d.ts +80 -0
- package/dist/components/Button/ButtonGroup.svelte +127 -0
- package/dist/components/Button/ButtonGroup.svelte.d.ts +44 -0
- package/dist/components/Card/Card.svelte +152 -0
- package/dist/components/Card/Card.svelte.d.ts +55 -0
- package/dist/components/Carousel/Carousel.svelte +461 -0
- package/dist/components/Carousel/Carousel.svelte.d.ts +79 -0
- package/dist/components/Carousel/CarouselItem.svelte +149 -0
- package/dist/components/Carousel/CarouselItem.svelte.d.ts +35 -0
- package/dist/components/Chip/Chip.svelte +288 -0
- package/dist/components/Chip/Chip.svelte.d.ts +71 -0
- package/dist/components/Chip/ChipGroup.svelte +190 -0
- package/dist/components/Chip/ChipGroup.svelte.d.ts +71 -0
- package/dist/components/CodeBlock/CodeBlock.svelte +356 -0
- package/dist/components/CodeBlock/CodeBlock.svelte.d.ts +44 -0
- package/dist/components/CodeBlock/index.d.ts +1 -0
- package/dist/components/CodeBlock/index.js +1 -0
- package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte +145 -0
- package/dist/components/CodeBlockSpeed/CodeBlockSpeed.svelte.d.ts +44 -0
- package/dist/components/CodeEditor/CodeEditor.svelte +229 -0
- package/dist/components/CodeEditor/CodeEditor.svelte.d.ts +23 -0
- package/dist/components/Combobox/Combobox.svelte +279 -0
- package/dist/components/Combobox/Combobox.svelte.d.ts +34 -0
- package/dist/components/Container/Container.svelte +45 -0
- package/dist/components/Container/Container.svelte.d.ts +36 -0
- package/dist/components/DataTable/DataTable.svelte +879 -0
- package/dist/components/DataTable/DataTable.svelte.d.ts +102 -0
- package/dist/components/Form/AutoComplete.svelte +357 -0
- package/dist/components/Form/AutoComplete.svelte.d.ts +73 -0
- package/dist/components/Form/Calendar.svelte +429 -0
- package/dist/components/Form/Calendar.svelte.d.ts +53 -0
- package/dist/components/Form/Checkbox.svelte +196 -0
- package/dist/components/Form/Checkbox.svelte.d.ts +50 -0
- package/dist/components/Form/ColorPicker.svelte +396 -0
- package/dist/components/Form/ColorPicker.svelte.d.ts +43 -0
- package/dist/components/Form/Combobox.svelte +645 -0
- package/dist/components/Form/Combobox.svelte.d.ts +93 -0
- package/dist/components/Form/Dropdown.svelte +773 -0
- package/dist/components/Form/Dropdown.svelte.d.ts +81 -0
- package/dist/components/Form/FileUpload.svelte +796 -0
- package/dist/components/Form/FileUpload.svelte.d.ts +78 -0
- package/dist/components/Form/FloatLabel.svelte +245 -0
- package/dist/components/Form/FloatLabel.svelte.d.ts +44 -0
- package/dist/components/Form/Form.svelte +281 -0
- package/dist/components/Form/Form.svelte.d.ts +54 -0
- package/dist/components/Form/FormField.svelte +218 -0
- package/dist/components/Form/FormField.svelte.d.ts +47 -0
- package/dist/components/Form/Input.svelte +340 -0
- package/dist/components/Form/Input.svelte.d.ts +79 -0
- package/dist/components/Form/InputSwitch.svelte +189 -0
- package/dist/components/Form/InputSwitch.svelte.d.ts +46 -0
- package/dist/components/Form/InvalidState.svelte +97 -0
- package/dist/components/Form/InvalidState.svelte.d.ts +37 -0
- package/dist/components/Form/Knob.svelte +537 -0
- package/dist/components/Form/Knob.svelte.d.ts +78 -0
- package/dist/components/Form/ListInput.svelte +469 -0
- package/dist/components/Form/ListInput.svelte.d.ts +70 -0
- package/dist/components/Form/Listbox.svelte +513 -0
- package/dist/components/Form/Listbox.svelte.d.ts +74 -0
- package/dist/components/Form/NumberInput.svelte +452 -0
- package/dist/components/Form/NumberInput.svelte.d.ts +82 -0
- package/dist/components/Form/Radio.svelte +192 -0
- package/dist/components/Form/Radio.svelte.d.ts +53 -0
- package/dist/components/Form/RadioGroup.svelte +155 -0
- package/dist/components/Form/RadioGroup.svelte.d.ts +48 -0
- package/dist/components/Form/Rating.svelte +380 -0
- package/dist/components/Form/Rating.svelte.d.ts +64 -0
- package/dist/components/Form/Select.svelte +436 -0
- package/dist/components/Form/Select.svelte.d.ts +49 -0
- package/dist/components/Form/SelectGroup.svelte +34 -0
- package/dist/components/Form/SelectGroup.svelte.d.ts +33 -0
- package/dist/components/Form/Slider.svelte +622 -0
- package/dist/components/Form/Slider.svelte.d.ts +73 -0
- package/dist/components/Form/Switch.svelte +192 -0
- package/dist/components/Form/Switch.svelte.d.ts +46 -0
- package/dist/components/Form/TextInput.svelte +274 -0
- package/dist/components/Form/TextInput.svelte.d.ts +74 -0
- package/dist/components/Form/Textarea.svelte +207 -0
- package/dist/components/Form/Textarea.svelte.d.ts +62 -0
- package/dist/components/Icon/Icon.svelte +140 -0
- package/dist/components/Icon/Icon.svelte.d.ts +25 -0
- package/dist/components/Icon/index.d.ts +1 -0
- package/dist/components/Icon/index.js +1 -0
- package/dist/components/Lazy/Lazy.svelte +158 -0
- package/dist/components/Lazy/Lazy.svelte.d.ts +42 -0
- package/dist/components/Masonry/Masonry.svelte +299 -0
- package/dist/components/Masonry/Masonry.svelte.d.ts +55 -0
- package/dist/components/Menu/Menu/Menu.svelte +65 -0
- package/dist/components/Menu/Menu/Menu.svelte.d.ts +17 -0
- package/dist/components/Menu/Menu/MenuItem.svelte +90 -0
- package/dist/components/Menu/Menu/MenuItem.svelte.d.ts +27 -0
- package/dist/components/Modal/Modal.svelte +334 -0
- package/dist/components/Modal/Modal.svelte.d.ts +55 -0
- package/dist/components/Panel/Card.svelte +141 -0
- package/dist/components/Panel/Card.svelte.d.ts +52 -0
- package/dist/components/Panel/Hero/Hero.story.md +9 -0
- package/dist/components/Panel/Hero/Hero.story.svelte +49 -0
- package/dist/components/Panel/Hero/Hero.story.svelte.d.ts +21 -0
- package/dist/components/Panel/Hero/Hero.svelte +24 -0
- package/dist/components/Panel/Hero/Hero.svelte.d.ts +32 -0
- package/dist/components/Panel/LazyPanel.svelte +110 -0
- package/dist/components/Panel/LazyPanel.svelte.d.ts +46 -0
- package/dist/components/Panel/Panel.svelte +205 -0
- package/dist/components/Panel/Panel.svelte.d.ts +23 -0
- package/dist/components/Progress/Progress.svelte +220 -0
- package/dist/components/Progress/Progress.svelte.d.ts +61 -0
- package/dist/components/Separator/Separator.svelte +109 -0
- package/dist/components/Separator/Separator.svelte.d.ts +35 -0
- package/dist/components/Sidebar/Sidebar.svelte +213 -0
- package/dist/components/Sidebar/Sidebar.svelte.d.ts +60 -0
- package/dist/components/Skeleton/Skeleton.svelte +170 -0
- package/dist/components/Skeleton/Skeleton.svelte.d.ts +48 -0
- package/dist/components/Stepper/Stepper.svelte +111 -0
- package/dist/components/Stepper/Stepper.svelte.d.ts +54 -0
- package/dist/components/Stepper/StepperStep.svelte +369 -0
- package/dist/components/Stepper/StepperStep.svelte.d.ts +63 -0
- package/dist/components/Table/Table.svelte +167 -0
- package/dist/components/Table/Table.svelte.d.ts +56 -0
- package/dist/components/Table/TableBody.svelte +41 -0
- package/dist/components/Table/TableBody.svelte.d.ts +33 -0
- package/dist/components/Table/TableCell.svelte +76 -0
- package/dist/components/Table/TableCell.svelte.d.ts +36 -0
- package/dist/components/Table/TableHead.svelte +41 -0
- package/dist/components/Table/TableHead.svelte.d.ts +32 -0
- package/dist/components/Table/TableHeader.svelte +148 -0
- package/dist/components/Table/TableHeader.svelte.d.ts +42 -0
- package/dist/components/Table/TableRow.svelte +99 -0
- package/dist/components/Table/TableRow.svelte.d.ts +40 -0
- package/dist/components/Tabs/Tab.svelte +145 -0
- package/dist/components/Tabs/Tab.svelte.d.ts +36 -0
- package/dist/components/Tabs/TabList.svelte +60 -0
- package/dist/components/Tabs/TabList.svelte.d.ts +32 -0
- package/dist/components/Tabs/TabPanel.svelte +118 -0
- package/dist/components/Tabs/TabPanel.svelte.d.ts +38 -0
- package/dist/components/Tabs/Tabs.svelte +287 -0
- package/dist/components/Tabs/Tabs.svelte.d.ts +50 -0
- package/dist/components/Tag/Tag.svelte +260 -0
- package/dist/components/Tag/Tag.svelte.d.ts +54 -0
- package/dist/components/Tag/TagGroup.svelte +147 -0
- package/dist/components/Tag/TagGroup.svelte.d.ts +62 -0
- package/dist/components/ThemeToggle/ThemeToggle.svelte +93 -0
- package/dist/components/ThemeToggle/ThemeToggle.svelte.d.ts +12 -0
- package/dist/components/Timeline/Timeline.svelte +144 -0
- package/dist/components/Timeline/Timeline.svelte.d.ts +48 -0
- package/dist/components/Timeline/TimelineItem.svelte +391 -0
- package/dist/components/Timeline/TimelineItem.svelte.d.ts +63 -0
- package/dist/components/Toast/Toast.svelte +313 -0
- package/dist/components/Toast/Toast.svelte.d.ts +44 -0
- package/dist/components/Toast/toastStore.d.ts +40 -0
- package/dist/components/Toast/toastStore.js +293 -0
- package/dist/components/Tooltip/Tooltip.svelte +282 -0
- package/dist/components/Tooltip/Tooltip.svelte.d.ts +55 -0
- package/dist/components/Tree/Tree.svelte +129 -0
- package/dist/components/Tree/Tree.svelte.d.ts +61 -0
- package/dist/components/Tree/TreeNode.svelte +332 -0
- package/dist/components/Tree/TreeNode.svelte.d.ts +55 -0
- package/dist/components/icons/TwintrinsicLogo.svelte +73 -0
- package/dist/components/icons/TwintrinsicLogo.svelte.d.ts +17 -0
- package/dist/components/icons/twintrinsic-source.svg +73 -0
- package/dist/components/icons/twintrinsic.svg +38 -0
- package/dist/docs/EventsTable.svelte +86 -0
- package/dist/docs/EventsTable.svelte.d.ts +27 -0
- package/dist/docs/PropsTable.svelte +103 -0
- package/dist/docs/PropsTable.svelte.d.ts +28 -0
- package/dist/docs/index.d.ts +2 -0
- package/dist/docs/index.js +2 -0
- package/dist/helpers/detectLanguage.d.ts +6 -0
- package/dist/helpers/detectLanguage.js +60 -0
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.js +1 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +94 -0
- package/dist/twintrinsic.css +347 -0
- package/package.json +98 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export default Radio;
|
|
2
|
+
type Radio = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Radio - A styled radio button component.
|
|
8
|
+
* Provides consistent styling, accessibility features, and integration with the Form component.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Radio
|
|
13
|
+
* name="theme"
|
|
14
|
+
* value="light"
|
|
15
|
+
* label="Light theme"
|
|
16
|
+
* checked={theme === 'light'}
|
|
17
|
+
* />
|
|
18
|
+
*
|
|
19
|
+
* <FormField label="Select theme">
|
|
20
|
+
* <div class="flex gap-4">
|
|
21
|
+
* <Radio name="theme" value="light" label="Light" />
|
|
22
|
+
* <Radio name="theme" value="dark" label="Dark" />
|
|
23
|
+
* <Radio name="theme" value="system" label="System" />
|
|
24
|
+
* </div>
|
|
25
|
+
* </FormField>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
declare const Radio: import("svelte").Component<{
|
|
29
|
+
class?: string;
|
|
30
|
+
id?: any;
|
|
31
|
+
name: any;
|
|
32
|
+
value: any;
|
|
33
|
+
label: any;
|
|
34
|
+
checked?: boolean;
|
|
35
|
+
required?: boolean;
|
|
36
|
+
disabled?: boolean;
|
|
37
|
+
size?: string;
|
|
38
|
+
ariaLabel: any;
|
|
39
|
+
onchange: any;
|
|
40
|
+
} & Record<string, any>, {}, "">;
|
|
41
|
+
type $$ComponentProps = {
|
|
42
|
+
class?: string;
|
|
43
|
+
id?: any;
|
|
44
|
+
name: any;
|
|
45
|
+
value: any;
|
|
46
|
+
label: any;
|
|
47
|
+
checked?: boolean;
|
|
48
|
+
required?: boolean;
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
size?: string;
|
|
51
|
+
ariaLabel: any;
|
|
52
|
+
onchange: any;
|
|
53
|
+
} & Record<string, any>;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
RadioGroup - A component for grouping related radio buttons.
|
|
4
|
+
Provides consistent styling, accessibility features, and integration with the Form component.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<RadioGroup
|
|
9
|
+
name="theme"
|
|
10
|
+
value="light"
|
|
11
|
+
legend="Select theme"
|
|
12
|
+
>
|
|
13
|
+
<Radio value="light" label="Light" />
|
|
14
|
+
<Radio value="dark" label="Dark" />
|
|
15
|
+
<Radio value="system" label="System" />
|
|
16
|
+
</RadioGroup>
|
|
17
|
+
```
|
|
18
|
+
-->
|
|
19
|
+
<script>
|
|
20
|
+
import { getContext, setContext } from "svelte"
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
/** @type {string} - Additional CSS classes */
|
|
24
|
+
class: className = "",
|
|
25
|
+
|
|
26
|
+
/** @type {string} - HTML id for accessibility */
|
|
27
|
+
id = crypto.randomUUID(),
|
|
28
|
+
|
|
29
|
+
/** @type {string} - Radio group name */
|
|
30
|
+
name,
|
|
31
|
+
|
|
32
|
+
/** @type {string} - Currently selected value */
|
|
33
|
+
value = "",
|
|
34
|
+
|
|
35
|
+
/** @type {string} - Legend text for the fieldset */
|
|
36
|
+
legend,
|
|
37
|
+
|
|
38
|
+
/** @type {boolean} - Whether the radio group is required */
|
|
39
|
+
required = false,
|
|
40
|
+
|
|
41
|
+
/** @type {boolean} - Whether the radio group is disabled */
|
|
42
|
+
disabled = false,
|
|
43
|
+
|
|
44
|
+
/** @type {string} - Layout direction (horizontal or vertical) */
|
|
45
|
+
layout = "vertical",
|
|
46
|
+
|
|
47
|
+
/** @type {string} - Size of the radio buttons (sm, md, lg) */
|
|
48
|
+
size = "md",
|
|
49
|
+
|
|
50
|
+
/** @type {(event: CustomEvent) => void} - Change event handler */
|
|
51
|
+
onchange,
|
|
52
|
+
|
|
53
|
+
children,
|
|
54
|
+
} = $props()
|
|
55
|
+
|
|
56
|
+
// Get form context if available
|
|
57
|
+
const formContext = getContext("form")
|
|
58
|
+
|
|
59
|
+
// Radio group state
|
|
60
|
+
let selectedValue = $state(value)
|
|
61
|
+
|
|
62
|
+
// Update selected value when prop changes
|
|
63
|
+
$effect(() => {
|
|
64
|
+
selectedValue = value
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
// Register with form if available
|
|
68
|
+
let fieldApi = $state()
|
|
69
|
+
|
|
70
|
+
$effect(() => {
|
|
71
|
+
if (formContext && name) {
|
|
72
|
+
fieldApi = formContext.registerField(name, value)
|
|
73
|
+
}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// Update value when form field changes
|
|
77
|
+
$effect(() => {
|
|
78
|
+
if (fieldApi) {
|
|
79
|
+
const formValue = fieldApi.getValue()
|
|
80
|
+
if (formValue !== undefined && formValue !== selectedValue) {
|
|
81
|
+
selectedValue = formValue
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Handles radio selection
|
|
88
|
+
* @param {CustomEvent} event - Change event from Radio component
|
|
89
|
+
*/
|
|
90
|
+
function handleRadioChange(event) {
|
|
91
|
+
const { value: radioValue } = event.detail
|
|
92
|
+
selectedValue = radioValue
|
|
93
|
+
|
|
94
|
+
// Update form field if available
|
|
95
|
+
if (fieldApi) {
|
|
96
|
+
fieldApi.setValue(radioValue)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
onchange?.(new CustomEvent("change", { detail: { value: radioValue } }))
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Provide context for child Radio components
|
|
103
|
+
$effect(() => {
|
|
104
|
+
setContext("radioGroup", {
|
|
105
|
+
name,
|
|
106
|
+
selectedValue: () => selectedValue,
|
|
107
|
+
required,
|
|
108
|
+
disabled: () => disabled || (fieldApi && fieldApi.isDisabled()),
|
|
109
|
+
size,
|
|
110
|
+
onChange: handleRadioChange,
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
</script>
|
|
114
|
+
|
|
115
|
+
<fieldset
|
|
116
|
+
{id}
|
|
117
|
+
class="radio-group {layout === 'horizontal' ? 'radio-group-horizontal' : 'radio-group-vertical'} {className}"
|
|
118
|
+
{disabled}
|
|
119
|
+
>
|
|
120
|
+
{#if legend}
|
|
121
|
+
<legend class="radio-group-legend">{legend}</legend>
|
|
122
|
+
{/if}
|
|
123
|
+
|
|
124
|
+
<div class="radio-group-items">
|
|
125
|
+
{@render children?.()}
|
|
126
|
+
</div>
|
|
127
|
+
</fieldset>
|
|
128
|
+
|
|
129
|
+
<style>
|
|
130
|
+
@reference "../../twintrinsic.css";
|
|
131
|
+
|
|
132
|
+
.radio-group {
|
|
133
|
+
@apply border-0 p-0 m-0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.radio-group-legend {
|
|
137
|
+
@apply text-sm font-medium text-text dark:text-text mb-2;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.radio-group-items {
|
|
141
|
+
@apply flex;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.radio-group-vertical .radio-group-items {
|
|
145
|
+
@apply flex-col gap-2;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.radio-group-horizontal .radio-group-items {
|
|
149
|
+
@apply flex-row flex-wrap gap-4;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.radio-group[disabled] {
|
|
153
|
+
@apply opacity-50 cursor-not-allowed;
|
|
154
|
+
}
|
|
155
|
+
</style>
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export default RadioGroup;
|
|
2
|
+
type RadioGroup = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* RadioGroup - A component for grouping related radio buttons.
|
|
8
|
+
* Provides consistent styling, accessibility features, and integration with the Form component.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <RadioGroup
|
|
13
|
+
* name="theme"
|
|
14
|
+
* value="light"
|
|
15
|
+
* legend="Select theme"
|
|
16
|
+
* >
|
|
17
|
+
* <Radio value="light" label="Light" />
|
|
18
|
+
* <Radio value="dark" label="Dark" />
|
|
19
|
+
* <Radio value="system" label="System" />
|
|
20
|
+
* </RadioGroup>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare const RadioGroup: import("svelte").Component<{
|
|
24
|
+
class?: string;
|
|
25
|
+
id?: any;
|
|
26
|
+
name: any;
|
|
27
|
+
value?: string;
|
|
28
|
+
legend: any;
|
|
29
|
+
required?: boolean;
|
|
30
|
+
disabled?: boolean;
|
|
31
|
+
layout?: string;
|
|
32
|
+
size?: string;
|
|
33
|
+
onchange: any;
|
|
34
|
+
children: any;
|
|
35
|
+
}, {}, "">;
|
|
36
|
+
type $$ComponentProps = {
|
|
37
|
+
class?: string;
|
|
38
|
+
id?: any;
|
|
39
|
+
name: any;
|
|
40
|
+
value?: string;
|
|
41
|
+
legend: any;
|
|
42
|
+
required?: boolean;
|
|
43
|
+
disabled?: boolean;
|
|
44
|
+
layout?: string;
|
|
45
|
+
size?: string;
|
|
46
|
+
onchange: any;
|
|
47
|
+
children: any;
|
|
48
|
+
};
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Rating - A component for collecting user ratings through stars or other symbols.
|
|
4
|
+
Provides consistent styling, accessibility features, and interactive options.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<Rating value={3} />
|
|
9
|
+
|
|
10
|
+
<Rating
|
|
11
|
+
value={4.5}
|
|
12
|
+
max={5}
|
|
13
|
+
precision={0.5}
|
|
14
|
+
size="lg"
|
|
15
|
+
readonly={false}
|
|
16
|
+
onchange={(e) => console.log(e.detail.value)}
|
|
17
|
+
/>
|
|
18
|
+
|
|
19
|
+
<Rating
|
|
20
|
+
value={2}
|
|
21
|
+
icon="<svg>...</svg>"
|
|
22
|
+
emptyIcon="<svg>...</svg>"
|
|
23
|
+
variant="warning"
|
|
24
|
+
/>
|
|
25
|
+
```
|
|
26
|
+
-->
|
|
27
|
+
<script>
|
|
28
|
+
const {
|
|
29
|
+
/** @type {string} - Additional CSS classes */
|
|
30
|
+
class: className = "",
|
|
31
|
+
|
|
32
|
+
/** @type {string} - HTML id for accessibility */
|
|
33
|
+
id = crypto.randomUUID(),
|
|
34
|
+
|
|
35
|
+
/** @type {number} - Current rating value */
|
|
36
|
+
value = 0,
|
|
37
|
+
|
|
38
|
+
/** @type {number} - Maximum rating value */
|
|
39
|
+
max = 5,
|
|
40
|
+
|
|
41
|
+
/** @type {number} - Step size for ratings (0.5 for half stars, 1 for whole stars) */
|
|
42
|
+
precision = 1,
|
|
43
|
+
|
|
44
|
+
/** @type {string} - Size of the rating icons (sm, md, lg) */
|
|
45
|
+
size = "md",
|
|
46
|
+
|
|
47
|
+
/** @type {string} - Visual style variant */
|
|
48
|
+
variant = "warning",
|
|
49
|
+
|
|
50
|
+
/** @type {boolean} - Whether the rating is readonly */
|
|
51
|
+
readonly = false,
|
|
52
|
+
|
|
53
|
+
/** @type {boolean} - Whether the rating is disabled */
|
|
54
|
+
disabled = false,
|
|
55
|
+
|
|
56
|
+
/** @type {boolean} - Whether to show the numeric value */
|
|
57
|
+
showValue = false,
|
|
58
|
+
|
|
59
|
+
/** @type {string} - Custom icon for filled state (HTML or SVG string) */
|
|
60
|
+
icon,
|
|
61
|
+
|
|
62
|
+
/** @type {string} - Custom icon for empty state (HTML or SVG string) */
|
|
63
|
+
emptyIcon,
|
|
64
|
+
|
|
65
|
+
/** @type {string} - Name attribute for form submission */
|
|
66
|
+
name,
|
|
67
|
+
|
|
68
|
+
/** @type {string} - ARIA label for accessibility */
|
|
69
|
+
ariaLabel = "Rating",
|
|
70
|
+
|
|
71
|
+
/** @type {(event: CustomEvent) => void} - Change event handler */
|
|
72
|
+
onchange,
|
|
73
|
+
} = $props()
|
|
74
|
+
|
|
75
|
+
// Component state
|
|
76
|
+
let currentValue = $state(value)
|
|
77
|
+
let hoverValue = $state(-1)
|
|
78
|
+
let isDragging = $state(false)
|
|
79
|
+
let ratingElement = $state()
|
|
80
|
+
|
|
81
|
+
// Update internal value when prop changes
|
|
82
|
+
$effect(() => {
|
|
83
|
+
currentValue = value
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
// Computed values
|
|
87
|
+
const displayValue = $derived(hoverValue >= 0 ? hoverValue : currentValue)
|
|
88
|
+
const isInteractive = $derived(!readonly && !disabled)
|
|
89
|
+
|
|
90
|
+
// Determine size classes
|
|
91
|
+
const sizeClasses = $derived(
|
|
92
|
+
{
|
|
93
|
+
sm: "text-sm gap-0.5",
|
|
94
|
+
md: "text-base gap-1",
|
|
95
|
+
lg: "text-lg gap-1.5",
|
|
96
|
+
}[size] || "text-base gap-1"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// Determine icon size classes
|
|
100
|
+
const iconSizeClasses = $derived(
|
|
101
|
+
{
|
|
102
|
+
sm: "w-4 h-4",
|
|
103
|
+
md: "w-5 h-5",
|
|
104
|
+
lg: "w-6 h-6",
|
|
105
|
+
}[size] || "w-5 h-5"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
// Determine variant classes
|
|
109
|
+
const variantClasses = $derived(
|
|
110
|
+
{
|
|
111
|
+
default: "text-muted dark:text-muted",
|
|
112
|
+
primary: "text-primary-500 dark:text-primary-500",
|
|
113
|
+
secondary: "text-secondary-500 dark:text-secondary-500",
|
|
114
|
+
success: "text-success-500 dark:text-success-500",
|
|
115
|
+
warning: "text-warning-500 dark:text-warning-500",
|
|
116
|
+
error: "text-error-500 dark:text-error-500",
|
|
117
|
+
info: "text-info-500 dark:text-info-500",
|
|
118
|
+
}[variant] || "text-warning-500 dark:text-warning-500"
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
// Generate items array based on max and precision
|
|
122
|
+
const items = $derived(Array.from({ length: max / precision }, (_, i) => (i + 1) * precision))
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Calculates the value based on mouse position
|
|
126
|
+
* @param {MouseEvent|TouchEvent} event - Mouse or touch event
|
|
127
|
+
* @returns {number} - Calculated value
|
|
128
|
+
*/
|
|
129
|
+
function calculateValue(event) {
|
|
130
|
+
if (!ratingElement) return 0
|
|
131
|
+
|
|
132
|
+
const rect = ratingElement.getBoundingClientRect()
|
|
133
|
+
const clientX = event.type.startsWith("touch") ? event.touches[0].clientX : event.clientX
|
|
134
|
+
|
|
135
|
+
// Calculate percentage of width
|
|
136
|
+
const percent = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width))
|
|
137
|
+
|
|
138
|
+
// Calculate value based on percentage, max, and precision
|
|
139
|
+
const rawValue = percent * max
|
|
140
|
+
|
|
141
|
+
// Round to nearest precision step
|
|
142
|
+
return Math.max(precision, Math.round(rawValue / precision) * precision)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Handles mouse move or touch move events
|
|
147
|
+
* @param {MouseEvent|TouchEvent} event - Mouse or touch event
|
|
148
|
+
*/
|
|
149
|
+
function handleMove(event) {
|
|
150
|
+
if (!isInteractive) return
|
|
151
|
+
|
|
152
|
+
if (isDragging || event.type === "mousemove") {
|
|
153
|
+
hoverValue = calculateValue(event)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Handles mouse down or touch start events
|
|
159
|
+
* @param {MouseEvent|TouchEvent} event - Mouse or touch event
|
|
160
|
+
*/
|
|
161
|
+
function handleStart(event) {
|
|
162
|
+
if (!isInteractive) return
|
|
163
|
+
|
|
164
|
+
isDragging = true
|
|
165
|
+
hoverValue = calculateValue(event)
|
|
166
|
+
|
|
167
|
+
// Add document event listeners for drag
|
|
168
|
+
if (event.type === "mousedown") {
|
|
169
|
+
document.addEventListener("mousemove", handleMove)
|
|
170
|
+
document.addEventListener("mouseup", handleEnd)
|
|
171
|
+
} else if (event.type === "touchstart") {
|
|
172
|
+
document.addEventListener("touchmove", handleMove, { passive: true })
|
|
173
|
+
document.addEventListener("touchend", handleEnd)
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Handles mouse up or touch end events
|
|
179
|
+
*/
|
|
180
|
+
function handleEnd() {
|
|
181
|
+
if (!isInteractive || !isDragging) return
|
|
182
|
+
|
|
183
|
+
// Update value and dispatch change event
|
|
184
|
+
if (hoverValue >= 0) {
|
|
185
|
+
currentValue = hoverValue
|
|
186
|
+
onchange?.(new CustomEvent("change", { detail: { value: currentValue } }))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
isDragging = false
|
|
190
|
+
|
|
191
|
+
// Remove document event listeners
|
|
192
|
+
document.removeEventListener("mousemove", handleMove)
|
|
193
|
+
document.removeEventListener("mouseup", handleEnd)
|
|
194
|
+
document.removeEventListener("touchmove", handleMove)
|
|
195
|
+
document.removeEventListener("touchend", handleEnd)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Handles mouse enter events
|
|
200
|
+
*/
|
|
201
|
+
function handleEnter() {
|
|
202
|
+
if (!isInteractive) return
|
|
203
|
+
hoverValue = currentValue
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Handles mouse leave events
|
|
208
|
+
*/
|
|
209
|
+
function handleLeave() {
|
|
210
|
+
if (!isInteractive || isDragging) return
|
|
211
|
+
hoverValue = -1
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Handles click events on individual items
|
|
216
|
+
* @param {number} itemValue - Value of the clicked item
|
|
217
|
+
*/
|
|
218
|
+
function handleItemClick(itemValue) {
|
|
219
|
+
if (!isInteractive) return
|
|
220
|
+
|
|
221
|
+
// Toggle off if clicking the same value
|
|
222
|
+
if (currentValue === itemValue && precision === 1) {
|
|
223
|
+
currentValue = 0
|
|
224
|
+
} else {
|
|
225
|
+
currentValue = itemValue
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
hoverValue = currentValue
|
|
229
|
+
onchange?.(new CustomEvent("change", { detail: { value: currentValue } }))
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Handles keyboard navigation
|
|
234
|
+
* @param {KeyboardEvent} event - Keydown event
|
|
235
|
+
*/
|
|
236
|
+
function handleKeydown(event) {
|
|
237
|
+
if (!isInteractive) return
|
|
238
|
+
|
|
239
|
+
let newValue = currentValue
|
|
240
|
+
|
|
241
|
+
switch (event.key) {
|
|
242
|
+
case "ArrowRight":
|
|
243
|
+
case "ArrowUp":
|
|
244
|
+
newValue = Math.min(max, currentValue + precision)
|
|
245
|
+
break
|
|
246
|
+
case "ArrowLeft":
|
|
247
|
+
case "ArrowDown":
|
|
248
|
+
newValue = Math.max(0, currentValue - precision)
|
|
249
|
+
break
|
|
250
|
+
case "Home":
|
|
251
|
+
newValue = precision
|
|
252
|
+
break
|
|
253
|
+
case "End":
|
|
254
|
+
newValue = max
|
|
255
|
+
break
|
|
256
|
+
default:
|
|
257
|
+
return
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (newValue !== currentValue) {
|
|
261
|
+
currentValue = newValue
|
|
262
|
+
hoverValue = newValue
|
|
263
|
+
dispatch("change", { value: currentValue })
|
|
264
|
+
event.preventDefault()
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
</script>
|
|
268
|
+
|
|
269
|
+
<div
|
|
270
|
+
{id}
|
|
271
|
+
class="
|
|
272
|
+
rating
|
|
273
|
+
{sizeClasses}
|
|
274
|
+
{isInteractive ? 'rating-interactive' : ''}
|
|
275
|
+
{disabled ? 'rating-disabled' : ''}
|
|
276
|
+
{className}
|
|
277
|
+
"
|
|
278
|
+
role={isInteractive ? 'slider' : 'img'}
|
|
279
|
+
aria-label={ariaLabel}
|
|
280
|
+
aria-valuemin={isInteractive ? 0 : undefined}
|
|
281
|
+
aria-valuemax={isInteractive ? max : undefined}
|
|
282
|
+
aria-valuenow={isInteractive ? currentValue : undefined}
|
|
283
|
+
aria-valuetext={isInteractive ? `${currentValue} out of ${max}` : undefined}
|
|
284
|
+
aria-readonly={readonly ? true : undefined}
|
|
285
|
+
aria-disabled={disabled ? true : undefined}
|
|
286
|
+
tabindex={isInteractive ? 0 : undefined}
|
|
287
|
+
onmousedown={handleStart}
|
|
288
|
+
ontouchstart={handleStart}
|
|
289
|
+
onmouseenter={handleEnter}
|
|
290
|
+
onmouseleave={handleLeave}
|
|
291
|
+
onkeydown={handleKeydown}
|
|
292
|
+
bind:this={ratingElement}
|
|
293
|
+
>
|
|
294
|
+
{#if name && isInteractive}
|
|
295
|
+
<input type="hidden" {name} value={currentValue} />
|
|
296
|
+
{/if}
|
|
297
|
+
|
|
298
|
+
<div class="rating-items">
|
|
299
|
+
{#each items as item}
|
|
300
|
+
<span
|
|
301
|
+
class="
|
|
302
|
+
rating-item
|
|
303
|
+
{item <= displayValue ? 'rating-item-filled' : 'rating-item-empty'}
|
|
304
|
+
{variantClasses}
|
|
305
|
+
"
|
|
306
|
+
role={isInteractive ? 'presentation' : undefined}
|
|
307
|
+
onclick={() => handleItemClick(item)}
|
|
308
|
+
>
|
|
309
|
+
{#if item <= displayValue}
|
|
310
|
+
{#if icon}
|
|
311
|
+
<span class="rating-icon {iconSizeClasses}">
|
|
312
|
+
{@html icon}
|
|
313
|
+
</span>
|
|
314
|
+
{:else}
|
|
315
|
+
<svg class="{iconSizeClasses}" fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
316
|
+
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path>
|
|
317
|
+
</svg>
|
|
318
|
+
{/if}
|
|
319
|
+
{:else}
|
|
320
|
+
{#if emptyIcon}
|
|
321
|
+
<span class="rating-icon {iconSizeClasses}">
|
|
322
|
+
{@html emptyIcon}
|
|
323
|
+
</span>
|
|
324
|
+
{:else}
|
|
325
|
+
<svg class="{iconSizeClasses}" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
326
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path>
|
|
327
|
+
</svg>
|
|
328
|
+
{/if}
|
|
329
|
+
{/if}
|
|
330
|
+
</span>
|
|
331
|
+
{/each}
|
|
332
|
+
</div>
|
|
333
|
+
|
|
334
|
+
{#if showValue}
|
|
335
|
+
<span class="rating-value">
|
|
336
|
+
{currentValue}
|
|
337
|
+
</span>
|
|
338
|
+
{/if}
|
|
339
|
+
</div>
|
|
340
|
+
|
|
341
|
+
<style>
|
|
342
|
+
@reference "../../twintrinsic.css";
|
|
343
|
+
|
|
344
|
+
.rating {
|
|
345
|
+
@apply inline-flex items-center;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
.rating-interactive {
|
|
349
|
+
@apply cursor-pointer;
|
|
350
|
+
@apply focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400 focus:ring-offset-2 rounded;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
.rating-disabled {
|
|
354
|
+
@apply opacity-50 cursor-not-allowed;
|
|
355
|
+
@apply pointer-events-none;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.rating-items {
|
|
359
|
+
@apply inline-flex;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
.rating-item {
|
|
363
|
+
@apply inline-flex items-center justify-center;
|
|
364
|
+
@apply transition-colors duration-150;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.rating-item-empty {
|
|
368
|
+
@apply text-muted/30 dark:text-muted/30;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.rating-interactive .rating-item {
|
|
372
|
+
@apply hover:scale-110;
|
|
373
|
+
@apply transition-transform duration-150;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.rating-value {
|
|
377
|
+
@apply ml-2 font-medium;
|
|
378
|
+
@apply text-text dark:text-text;
|
|
379
|
+
}
|
|
380
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export default Rating;
|
|
2
|
+
type Rating = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Rating - A component for collecting user ratings through stars or other symbols.
|
|
8
|
+
* Provides consistent styling, accessibility features, and interactive options.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Rating value={3} />
|
|
13
|
+
*
|
|
14
|
+
* <Rating
|
|
15
|
+
* value={4.5}
|
|
16
|
+
* max={5}
|
|
17
|
+
* precision={0.5}
|
|
18
|
+
* size="lg"
|
|
19
|
+
* readonly={false}
|
|
20
|
+
* onchange={(e) => console.log(e.detail.value)}
|
|
21
|
+
* />
|
|
22
|
+
*
|
|
23
|
+
* <Rating
|
|
24
|
+
* value={2}
|
|
25
|
+
* icon="<svg>...</svg>"
|
|
26
|
+
* emptyIcon="<svg>...</svg>"
|
|
27
|
+
* variant="warning"
|
|
28
|
+
* />
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare const Rating: import("svelte").Component<{
|
|
32
|
+
class?: string;
|
|
33
|
+
id?: any;
|
|
34
|
+
value?: number;
|
|
35
|
+
max?: number;
|
|
36
|
+
precision?: number;
|
|
37
|
+
size?: string;
|
|
38
|
+
variant?: string;
|
|
39
|
+
readonly?: boolean;
|
|
40
|
+
disabled?: boolean;
|
|
41
|
+
showValue?: boolean;
|
|
42
|
+
icon: any;
|
|
43
|
+
emptyIcon: any;
|
|
44
|
+
name: any;
|
|
45
|
+
ariaLabel?: string;
|
|
46
|
+
onchange: any;
|
|
47
|
+
}, {}, "">;
|
|
48
|
+
type $$ComponentProps = {
|
|
49
|
+
class?: string;
|
|
50
|
+
id?: any;
|
|
51
|
+
value?: number;
|
|
52
|
+
max?: number;
|
|
53
|
+
precision?: number;
|
|
54
|
+
size?: string;
|
|
55
|
+
variant?: string;
|
|
56
|
+
readonly?: boolean;
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
showValue?: boolean;
|
|
59
|
+
icon: any;
|
|
60
|
+
emptyIcon: any;
|
|
61
|
+
name: any;
|
|
62
|
+
ariaLabel?: string;
|
|
63
|
+
onchange: any;
|
|
64
|
+
};
|