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,207 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Textarea - A styled textarea component for multi-line text input.
|
|
4
|
+
Provides consistent styling, accessibility features, and integration with the Form component.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<Textarea
|
|
9
|
+
name="description"
|
|
10
|
+
placeholder="Enter description"
|
|
11
|
+
rows={4}
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<FormField label="Message">
|
|
15
|
+
<Textarea name="message" required />
|
|
16
|
+
</FormField>
|
|
17
|
+
```
|
|
18
|
+
-->
|
|
19
|
+
<script>
|
|
20
|
+
import { getContext } from "svelte"
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
/** @type {string} - Additional CSS classes */
|
|
24
|
+
class: className = "",
|
|
25
|
+
|
|
26
|
+
/** @type {string} - HTML id for accessibility */
|
|
27
|
+
id,
|
|
28
|
+
|
|
29
|
+
/** @type {string} - Textarea name */
|
|
30
|
+
name,
|
|
31
|
+
|
|
32
|
+
/** @type {string} - Textarea placeholder */
|
|
33
|
+
placeholder = "",
|
|
34
|
+
|
|
35
|
+
/** @type {string} - Textarea value */
|
|
36
|
+
value = "",
|
|
37
|
+
|
|
38
|
+
/** @type {number} - Number of rows */
|
|
39
|
+
rows = 3,
|
|
40
|
+
|
|
41
|
+
/** @type {boolean} - Whether the textarea is required */
|
|
42
|
+
required = false,
|
|
43
|
+
|
|
44
|
+
/** @type {boolean} - Whether the textarea is disabled */
|
|
45
|
+
disabled = false,
|
|
46
|
+
|
|
47
|
+
/** @type {boolean} - Whether the textarea is readonly */
|
|
48
|
+
readonly = false,
|
|
49
|
+
|
|
50
|
+
/** @type {string} - Minimum length */
|
|
51
|
+
minlength,
|
|
52
|
+
|
|
53
|
+
/** @type {string} - Maximum length */
|
|
54
|
+
maxlength,
|
|
55
|
+
|
|
56
|
+
/** @type {string} - Autocomplete attribute */
|
|
57
|
+
autocomplete,
|
|
58
|
+
|
|
59
|
+
/** @type {boolean} - Whether to auto-resize based on content */
|
|
60
|
+
autoResize = false,
|
|
61
|
+
|
|
62
|
+
/** @type {string} - ARIA label for accessibility */
|
|
63
|
+
ariaLabel,
|
|
64
|
+
/** @type {(event: CustomEvent) => void} - Input event handler */
|
|
65
|
+
oninput,
|
|
66
|
+
/** @type {(event: CustomEvent) => void} - Change event handler */
|
|
67
|
+
onchange,
|
|
68
|
+
/** @type {(event: Event) => void} - Focus event handler */
|
|
69
|
+
onfocus,
|
|
70
|
+
/** @type {(event: Event) => void} - Blur event handler */
|
|
71
|
+
onblur,
|
|
72
|
+
/** @type {object} - Additional props to pass to the input element */
|
|
73
|
+
...restProps
|
|
74
|
+
} = $props()
|
|
75
|
+
|
|
76
|
+
// Get form context if available
|
|
77
|
+
const formContext = getContext("form")
|
|
78
|
+
|
|
79
|
+
// Generate unique ID if not provided
|
|
80
|
+
const textareaId = id || `textarea-${crypto.randomUUID()}`
|
|
81
|
+
|
|
82
|
+
// Textarea state
|
|
83
|
+
let textareaValue = $state(value)
|
|
84
|
+
let isFocused = $state(false)
|
|
85
|
+
let textareaEl = $state()
|
|
86
|
+
let fieldApi = $state()
|
|
87
|
+
|
|
88
|
+
// Register with form if available
|
|
89
|
+
$effect(() => {
|
|
90
|
+
if (formContext && name) {
|
|
91
|
+
fieldApi = formContext.registerField(name, value)
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
// Update value when form field changes
|
|
96
|
+
$effect(() => {
|
|
97
|
+
if (fieldApi) {
|
|
98
|
+
const formValue = fieldApi.getValue()
|
|
99
|
+
if (formValue !== undefined && formValue !== textareaValue) {
|
|
100
|
+
textareaValue = formValue
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
// Update textarea value when prop changes
|
|
106
|
+
$effect(() => {
|
|
107
|
+
textareaValue = value
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Handles textarea input
|
|
112
|
+
* @param {Event} event - Input event
|
|
113
|
+
*/
|
|
114
|
+
function handleInput(event) {
|
|
115
|
+
const newValue = event.target.value
|
|
116
|
+
textareaValue = newValue
|
|
117
|
+
|
|
118
|
+
// Update form field if available
|
|
119
|
+
if (fieldApi) {
|
|
120
|
+
fieldApi.setValue(newValue)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Auto-resize if enabled
|
|
124
|
+
if (autoResize && textareaEl) {
|
|
125
|
+
resizeTextarea()
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
oninput?.(new CustomEvent("input", { detail: { value: newValue } }))
|
|
129
|
+
onchange?.(new CustomEvent("change", { detail: { value: newValue } }))
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Handles focus events
|
|
134
|
+
*/
|
|
135
|
+
function handleFocus(event) {
|
|
136
|
+
isFocused = true
|
|
137
|
+
onfocus?.(event)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Handles blur events
|
|
142
|
+
*/
|
|
143
|
+
function handleBlur(event) {
|
|
144
|
+
isFocused = false
|
|
145
|
+
onblur?.(event)
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Resizes the textarea based on content
|
|
150
|
+
*/
|
|
151
|
+
function resizeTextarea() {
|
|
152
|
+
if (!textareaEl) return
|
|
153
|
+
|
|
154
|
+
// Reset height to calculate scroll height
|
|
155
|
+
textareaEl.style.height = "auto"
|
|
156
|
+
|
|
157
|
+
// Set height to scroll height
|
|
158
|
+
textareaEl.style.height = `${textareaEl.scrollHeight}px`
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Initialize auto-resize
|
|
162
|
+
$effect(() => {
|
|
163
|
+
if (autoResize && textareaEl) {
|
|
164
|
+
// Use setTimeout to ensure content is rendered
|
|
165
|
+
setTimeout(resizeTextarea, 0)
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
</script>
|
|
169
|
+
|
|
170
|
+
<div class="textarea-wrapper {className}">
|
|
171
|
+
<textarea
|
|
172
|
+
id={textareaId}
|
|
173
|
+
{name}
|
|
174
|
+
{placeholder}
|
|
175
|
+
value={textareaValue}
|
|
176
|
+
{rows}
|
|
177
|
+
{required}
|
|
178
|
+
disabled={disabled || (fieldApi && fieldApi.isDisabled())}
|
|
179
|
+
{readonly}
|
|
180
|
+
{minlength}
|
|
181
|
+
{maxlength}
|
|
182
|
+
{autocomplete}
|
|
183
|
+
aria-label={ariaLabel}
|
|
184
|
+
class="textarea {isFocused ? 'is-focused' : ''}"
|
|
185
|
+
oninput={handleInput}
|
|
186
|
+
onfocus={handleFocus}
|
|
187
|
+
onblur={handleBlur}
|
|
188
|
+
bind:this={textareaEl}
|
|
189
|
+
{...restProps}
|
|
190
|
+
></textarea>
|
|
191
|
+
</div>
|
|
192
|
+
|
|
193
|
+
<style>
|
|
194
|
+
@reference "../../twintrinsic.css";
|
|
195
|
+
|
|
196
|
+
.textarea-wrapper {
|
|
197
|
+
@apply w-full;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.textarea {
|
|
201
|
+
@apply w-full rounded-md border-border dark:border-border bg-background dark:bg-background text-text dark:text-text;
|
|
202
|
+
@apply border focus:outline-none focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400 focus:border-primary-500 dark:focus:border-primary-400;
|
|
203
|
+
@apply disabled:opacity-50 disabled:cursor-not-allowed disabled:bg-surface dark:disabled:bg-surface;
|
|
204
|
+
@apply placeholder:text-muted dark:placeholder:text-muted;
|
|
205
|
+
@apply p-3 resize-y;
|
|
206
|
+
}
|
|
207
|
+
</style>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export default Textarea;
|
|
2
|
+
type Textarea = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Textarea - A styled textarea component for multi-line text input.
|
|
8
|
+
* Provides consistent styling, accessibility features, and integration with the Form component.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Textarea
|
|
13
|
+
* name="description"
|
|
14
|
+
* placeholder="Enter description"
|
|
15
|
+
* rows={4}
|
|
16
|
+
* />
|
|
17
|
+
*
|
|
18
|
+
* <FormField label="Message">
|
|
19
|
+
* <Textarea name="message" required />
|
|
20
|
+
* </FormField>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare const Textarea: import("svelte").Component<{
|
|
24
|
+
class?: string;
|
|
25
|
+
id: any;
|
|
26
|
+
name: any;
|
|
27
|
+
placeholder?: string;
|
|
28
|
+
value?: string;
|
|
29
|
+
rows?: number;
|
|
30
|
+
required?: boolean;
|
|
31
|
+
disabled?: boolean;
|
|
32
|
+
readonly?: boolean;
|
|
33
|
+
minlength: any;
|
|
34
|
+
maxlength: any;
|
|
35
|
+
autocomplete: any;
|
|
36
|
+
autoResize?: boolean;
|
|
37
|
+
ariaLabel: any;
|
|
38
|
+
oninput: any;
|
|
39
|
+
onchange: any;
|
|
40
|
+
onfocus: any;
|
|
41
|
+
onblur: any;
|
|
42
|
+
} & Record<string, any>, {}, "">;
|
|
43
|
+
type $$ComponentProps = {
|
|
44
|
+
class?: string;
|
|
45
|
+
id: any;
|
|
46
|
+
name: any;
|
|
47
|
+
placeholder?: string;
|
|
48
|
+
value?: string;
|
|
49
|
+
rows?: number;
|
|
50
|
+
required?: boolean;
|
|
51
|
+
disabled?: boolean;
|
|
52
|
+
readonly?: boolean;
|
|
53
|
+
minlength: any;
|
|
54
|
+
maxlength: any;
|
|
55
|
+
autocomplete: any;
|
|
56
|
+
autoResize?: boolean;
|
|
57
|
+
ariaLabel: any;
|
|
58
|
+
oninput: any;
|
|
59
|
+
onchange: any;
|
|
60
|
+
onfocus: any;
|
|
61
|
+
onblur: any;
|
|
62
|
+
} & Record<string, any>;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Icon - A component for displaying SVG icons with consistent styling.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
```svelte
|
|
7
|
+
<Icon name="check" />
|
|
8
|
+
<Icon name="arrow-right" size="lg" />
|
|
9
|
+
<Icon name="close" class="text-error" />
|
|
10
|
+
```
|
|
11
|
+
-->
|
|
12
|
+
<script>
|
|
13
|
+
const {
|
|
14
|
+
/** @type {string} - Name of the icon to display */
|
|
15
|
+
name = "",
|
|
16
|
+
/** @type {'sm' | 'md' | 'lg' | 'xl'} - Size of the icon */
|
|
17
|
+
size = "md",
|
|
18
|
+
/** @type {string} - Additional CSS classes */
|
|
19
|
+
class: className = "",
|
|
20
|
+
} = $props()
|
|
21
|
+
|
|
22
|
+
// Icon size mappings
|
|
23
|
+
const sizes = {
|
|
24
|
+
sm: 16,
|
|
25
|
+
md: 20,
|
|
26
|
+
lg: 24,
|
|
27
|
+
xl: 32,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Icon paths mapping
|
|
31
|
+
const icons = {
|
|
32
|
+
// Interface
|
|
33
|
+
check: "M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z",
|
|
34
|
+
close:
|
|
35
|
+
"M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z",
|
|
36
|
+
plus: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z",
|
|
37
|
+
minus: "M19 13H5v-2h14v2z",
|
|
38
|
+
search:
|
|
39
|
+
"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z",
|
|
40
|
+
settings:
|
|
41
|
+
"M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.05.3-.09.63-.09.94s.02.64.07.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z",
|
|
42
|
+
menu: "M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z",
|
|
43
|
+
more: "M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z",
|
|
44
|
+
|
|
45
|
+
// Navigation
|
|
46
|
+
"arrow-left": "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z",
|
|
47
|
+
"arrow-right": "M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z",
|
|
48
|
+
"arrow-up": "M4 12l1.41 1.41L11 7.83V20h2V7.83l5.58 5.59L20 12l-8-8z",
|
|
49
|
+
"arrow-down": "M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8z",
|
|
50
|
+
"chevron-left": "M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z",
|
|
51
|
+
"chevron-right": "M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z",
|
|
52
|
+
"chevron-up": "M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z",
|
|
53
|
+
"chevron-down": "M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z",
|
|
54
|
+
|
|
55
|
+
// Actions
|
|
56
|
+
edit: "M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z",
|
|
57
|
+
delete: "M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z",
|
|
58
|
+
save: "M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z",
|
|
59
|
+
refresh:
|
|
60
|
+
"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z",
|
|
61
|
+
download: "M19 9h-4V3H9v6H5l7 7 7-7zM5 18v2h14v-2H5z",
|
|
62
|
+
upload: "M9 16h6v-6h4l-7-7-7 7h4zm-4 2h14v2H5z",
|
|
63
|
+
copy: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z",
|
|
64
|
+
|
|
65
|
+
// Forms
|
|
66
|
+
calendar:
|
|
67
|
+
"M20 3h-1V1h-2v2H7V1H5v2H4c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 18H4V8h16v13z",
|
|
68
|
+
eye: "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z",
|
|
69
|
+
"eye-off":
|
|
70
|
+
"M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z",
|
|
71
|
+
lock: "M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z",
|
|
72
|
+
unlock:
|
|
73
|
+
"M12 17c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm6-9h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6h1.9c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm0 12H6V10h12v10z",
|
|
74
|
+
|
|
75
|
+
// Media
|
|
76
|
+
play: "M8 5v14l11-7z",
|
|
77
|
+
pause: "M6 19h4V5H6v14zm8-14v14h4V5h-4z",
|
|
78
|
+
stop: "M6 6h12v12H6z",
|
|
79
|
+
"volume-up":
|
|
80
|
+
"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z",
|
|
81
|
+
"volume-down":
|
|
82
|
+
"M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z",
|
|
83
|
+
"volume-mute": "M7 9v6h4l5 5V4l-5 5H7z",
|
|
84
|
+
"volume-off":
|
|
85
|
+
"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z",
|
|
86
|
+
|
|
87
|
+
// Status
|
|
88
|
+
info: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-6h2v6zm0-8h-2V7h2v2z",
|
|
89
|
+
warning: "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z",
|
|
90
|
+
error:
|
|
91
|
+
"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z",
|
|
92
|
+
success:
|
|
93
|
+
"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z",
|
|
94
|
+
help: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 17h-2v-2h2v2zm2.07-7.75l-.9.92C13.45 12.9 13 13.5 13 15h-2v-.5c0-1.1.45-2.1 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41 0-1.1-.9-2-2-2s-2 .9-2 2H8c0-2.21 1.79-4 4-4s4 1.79 4 4c0 .88-.36 1.68-.93 2.25z",
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Get icon path
|
|
98
|
+
const path = $derived(icons[name] || "")
|
|
99
|
+
const pixelSize = $derived(sizes[size] || sizes.md)
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
<svg
|
|
103
|
+
class="icon {className}"
|
|
104
|
+
class:icon-sm={size === 'sm'}
|
|
105
|
+
class:icon-md={size === 'md'}
|
|
106
|
+
class:icon-lg={size === 'lg'}
|
|
107
|
+
class:icon-xl={size === 'xl'}
|
|
108
|
+
viewBox="0 0 24 24"
|
|
109
|
+
width={pixelSize}
|
|
110
|
+
height={pixelSize}
|
|
111
|
+
fill="currentColor"
|
|
112
|
+
aria-hidden="true"
|
|
113
|
+
>
|
|
114
|
+
<path d={path} />
|
|
115
|
+
</svg>
|
|
116
|
+
|
|
117
|
+
<style>
|
|
118
|
+
@reference '../../twintrinsic.css';
|
|
119
|
+
|
|
120
|
+
.icon {
|
|
121
|
+
@apply inline-block align-middle;
|
|
122
|
+
@apply transition-colors duration-150;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.icon-sm {
|
|
126
|
+
@apply w-4 h-4;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.icon-md {
|
|
130
|
+
@apply w-5 h-5;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.icon-lg {
|
|
134
|
+
@apply w-6 h-6;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.icon-xl {
|
|
138
|
+
@apply w-8 h-8;
|
|
139
|
+
}
|
|
140
|
+
</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export default Icon;
|
|
2
|
+
type Icon = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Icon - A component for displaying SVG icons with consistent styling.
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```svelte
|
|
11
|
+
* <Icon name="check" />
|
|
12
|
+
* <Icon name="arrow-right" size="lg" />
|
|
13
|
+
* <Icon name="close" class="text-error" />
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
declare const Icon: import("svelte").Component<{
|
|
17
|
+
name?: string;
|
|
18
|
+
size?: string;
|
|
19
|
+
class?: string;
|
|
20
|
+
}, {}, "">;
|
|
21
|
+
type $$ComponentProps = {
|
|
22
|
+
name?: string;
|
|
23
|
+
size?: string;
|
|
24
|
+
class?: string;
|
|
25
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Icon } from "./Icon.svelte";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Icon } from "./Icon.svelte";
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Lazy - A component that renders its content only when it becomes visible in the viewport.
|
|
4
|
+
Useful for performance optimization by deferring the rendering of off-screen content.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<Lazy>
|
|
9
|
+
<div>This content will only be rendered when visible</div>
|
|
10
|
+
</Lazy>
|
|
11
|
+
|
|
12
|
+
<Lazy placeholder={<div>Loading...</div>}>
|
|
13
|
+
<HeavyComponent />
|
|
14
|
+
</Lazy>
|
|
15
|
+
```
|
|
16
|
+
-->
|
|
17
|
+
<script>
|
|
18
|
+
import { onMount } from "svelte"
|
|
19
|
+
|
|
20
|
+
const {
|
|
21
|
+
/** @type {string} - Additional CSS classes */
|
|
22
|
+
class: className = "",
|
|
23
|
+
|
|
24
|
+
/** @type {string} - HTML id for accessibility */
|
|
25
|
+
id = crypto.randomUUID(),
|
|
26
|
+
|
|
27
|
+
/** @type {number} - Threshold for intersection (0-1), where 1 means fully visible */
|
|
28
|
+
threshold = 0.1,
|
|
29
|
+
|
|
30
|
+
/** @type {string} - Margin around the root element for intersection detection */
|
|
31
|
+
rootMargin = "0px",
|
|
32
|
+
|
|
33
|
+
/** @type {boolean} - Whether to keep content rendered after it's been visible once */
|
|
34
|
+
keepRendered = true,
|
|
35
|
+
|
|
36
|
+
/** @type {boolean} - Whether to show a loading indicator while content is loading */
|
|
37
|
+
showLoading = false,
|
|
38
|
+
|
|
39
|
+
/** @type {number} - Delay in ms before showing content after it becomes visible */
|
|
40
|
+
delay = 0,
|
|
41
|
+
|
|
42
|
+
children,
|
|
43
|
+
placeholder,
|
|
44
|
+
} = $props()
|
|
45
|
+
|
|
46
|
+
// State
|
|
47
|
+
let isVisible = $state(false)
|
|
48
|
+
let hasBeenVisible = $state(false)
|
|
49
|
+
let shouldRender = $state(false)
|
|
50
|
+
let element
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Handles intersection changes
|
|
54
|
+
* @param {IntersectionObserverEntry[]} entries - Intersection entries
|
|
55
|
+
*/
|
|
56
|
+
function handleIntersection(entries) {
|
|
57
|
+
const [entry] = entries
|
|
58
|
+
|
|
59
|
+
if (entry.isIntersecting) {
|
|
60
|
+
isVisible = true
|
|
61
|
+
hasBeenVisible = true
|
|
62
|
+
|
|
63
|
+
if (delay > 0) {
|
|
64
|
+
setTimeout(() => {
|
|
65
|
+
shouldRender = true
|
|
66
|
+
}, delay)
|
|
67
|
+
} else {
|
|
68
|
+
shouldRender = true
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// If we only need to detect visibility once, disconnect the observer
|
|
72
|
+
if (keepRendered) {
|
|
73
|
+
observer?.disconnect()
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
isVisible = false
|
|
77
|
+
|
|
78
|
+
// If we're not keeping rendered content, unrender when not visible
|
|
79
|
+
if (!keepRendered) {
|
|
80
|
+
shouldRender = false
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let observer
|
|
86
|
+
|
|
87
|
+
onMount(() => {
|
|
88
|
+
// Check if IntersectionObserver is available
|
|
89
|
+
if ("IntersectionObserver" in window) {
|
|
90
|
+
observer = new IntersectionObserver(handleIntersection, {
|
|
91
|
+
root: null, // viewport
|
|
92
|
+
rootMargin,
|
|
93
|
+
threshold,
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
if (element) {
|
|
97
|
+
observer.observe(element)
|
|
98
|
+
}
|
|
99
|
+
} else {
|
|
100
|
+
// Fallback for browsers that don't support IntersectionObserver
|
|
101
|
+
shouldRender = true
|
|
102
|
+
isVisible = true
|
|
103
|
+
hasBeenVisible = true
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return () => {
|
|
107
|
+
observer?.disconnect()
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
</script>
|
|
111
|
+
|
|
112
|
+
<div
|
|
113
|
+
{id}
|
|
114
|
+
class="lazy-container {className}"
|
|
115
|
+
bind:this={element}
|
|
116
|
+
>
|
|
117
|
+
{#if shouldRender}
|
|
118
|
+
<div class="lazy-content">
|
|
119
|
+
{@render children?.()}
|
|
120
|
+
</div>
|
|
121
|
+
{:else if placeholder}
|
|
122
|
+
<div class="lazy-placeholder">
|
|
123
|
+
{@render placeholder()}
|
|
124
|
+
</div>
|
|
125
|
+
{:else if showLoading && hasBeenVisible}
|
|
126
|
+
<div class="lazy-loading" aria-live="polite" aria-busy="true">
|
|
127
|
+
<div class="loading-spinner" aria-hidden="true"></div>
|
|
128
|
+
<span class="sr-only">Loading content</span>
|
|
129
|
+
</div>
|
|
130
|
+
{/if}
|
|
131
|
+
</div>
|
|
132
|
+
|
|
133
|
+
<style>
|
|
134
|
+
@reference "../../twintrinsic.css";
|
|
135
|
+
|
|
136
|
+
.lazy-container {
|
|
137
|
+
@apply min-h-[20px];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.lazy-loading {
|
|
141
|
+
@apply flex items-center justify-center p-4;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.loading-spinner {
|
|
145
|
+
@apply w-8 h-8 rounded-full border-4 border-primary-200 dark:border-primary-800;
|
|
146
|
+
@apply border-t-primary-500 dark:border-t-primary-400;
|
|
147
|
+
animation: spin 1s linear infinite;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
@keyframes spin {
|
|
151
|
+
from {
|
|
152
|
+
transform: rotate(0deg);
|
|
153
|
+
}
|
|
154
|
+
to {
|
|
155
|
+
transform: rotate(360deg);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export default Lazy;
|
|
2
|
+
type Lazy = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Lazy - A component that renders its content only when it becomes visible in the viewport.
|
|
8
|
+
* Useful for performance optimization by deferring the rendering of off-screen content.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Lazy>
|
|
13
|
+
* <div>This content will only be rendered when visible</div>
|
|
14
|
+
* </Lazy>
|
|
15
|
+
*
|
|
16
|
+
* <Lazy placeholder={<div>Loading...</div>}>
|
|
17
|
+
* <HeavyComponent />
|
|
18
|
+
* </Lazy>
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
declare const Lazy: import("svelte").Component<{
|
|
22
|
+
class?: string;
|
|
23
|
+
id?: any;
|
|
24
|
+
threshold?: number;
|
|
25
|
+
rootMargin?: string;
|
|
26
|
+
keepRendered?: boolean;
|
|
27
|
+
showLoading?: boolean;
|
|
28
|
+
delay?: number;
|
|
29
|
+
children: any;
|
|
30
|
+
placeholder: any;
|
|
31
|
+
}, {}, "">;
|
|
32
|
+
type $$ComponentProps = {
|
|
33
|
+
class?: string;
|
|
34
|
+
id?: any;
|
|
35
|
+
threshold?: number;
|
|
36
|
+
rootMargin?: string;
|
|
37
|
+
keepRendered?: boolean;
|
|
38
|
+
showLoading?: boolean;
|
|
39
|
+
delay?: number;
|
|
40
|
+
children: any;
|
|
41
|
+
placeholder: any;
|
|
42
|
+
};
|