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,299 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
Masonry - A component for creating Pinterest-style grid layouts.
|
|
4
|
+
Provides responsive, dynamic layouts for items of varying heights.
|
|
5
|
+
|
|
6
|
+
Usage:
|
|
7
|
+
```svelte
|
|
8
|
+
<Masonry columns={3} gap={16}>
|
|
9
|
+
<div>Item 1 with some content</div>
|
|
10
|
+
<div>Item 2 with more content that might be taller</div>
|
|
11
|
+
<div>Item 3 with less content</div>
|
|
12
|
+
<div>Item 4 with a different height</div>
|
|
13
|
+
</Masonry>
|
|
14
|
+
|
|
15
|
+
<Masonry
|
|
16
|
+
columns={{ default: 1, sm: 2, md: 3, lg: 4, xl: 5 }}
|
|
17
|
+
gap={20}
|
|
18
|
+
columnWidth="300px"
|
|
19
|
+
>
|
|
20
|
+
{#each items as item}
|
|
21
|
+
<div>{item.content}</div>
|
|
22
|
+
{/each}
|
|
23
|
+
</Masonry>
|
|
24
|
+
```
|
|
25
|
+
-->
|
|
26
|
+
<script>
|
|
27
|
+
import { onMount, onDestroy } from "svelte"
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
/** @type {string} - Additional CSS classes */
|
|
31
|
+
class: className = "",
|
|
32
|
+
|
|
33
|
+
/** @type {string} - HTML id for accessibility */
|
|
34
|
+
id = crypto.randomUUID(),
|
|
35
|
+
|
|
36
|
+
/** @type {number|Object} - Number of columns or responsive breakpoints object */
|
|
37
|
+
columns = 3,
|
|
38
|
+
|
|
39
|
+
/** @type {number} - Gap between items in pixels */
|
|
40
|
+
gap = 16,
|
|
41
|
+
|
|
42
|
+
/** @type {string} - Fixed column width (overrides columns) */
|
|
43
|
+
columnWidth,
|
|
44
|
+
|
|
45
|
+
/** @type {boolean} - Whether to center the grid */
|
|
46
|
+
centered = false,
|
|
47
|
+
|
|
48
|
+
/** @type {boolean} - Whether to animate item positions */
|
|
49
|
+
animated = true,
|
|
50
|
+
|
|
51
|
+
/** @type {number} - Animation duration in milliseconds */
|
|
52
|
+
animationDuration = 300,
|
|
53
|
+
|
|
54
|
+
/** @type {string} - Animation easing function */
|
|
55
|
+
animationEasing = "ease-out",
|
|
56
|
+
|
|
57
|
+
/** @type {string} - ARIA label for the grid */
|
|
58
|
+
ariaLabel = "Masonry grid",
|
|
59
|
+
|
|
60
|
+
children,
|
|
61
|
+
} = $props()
|
|
62
|
+
|
|
63
|
+
// Component state
|
|
64
|
+
let containerElement = $state()
|
|
65
|
+
let items = $state([])
|
|
66
|
+
let columnCount = $state(3)
|
|
67
|
+
let columnHeights = $state([])
|
|
68
|
+
let resizeObserver = $state()
|
|
69
|
+
let mutationObserver = $state()
|
|
70
|
+
let itemObservers = $state([])
|
|
71
|
+
|
|
72
|
+
// Initialize column count based on columns prop
|
|
73
|
+
$effect(() => {
|
|
74
|
+
columnCount = typeof columns === "number" ? columns : 3
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Initializes the masonry layout
|
|
79
|
+
*/
|
|
80
|
+
function initLayout() {
|
|
81
|
+
if (!containerElement) return
|
|
82
|
+
|
|
83
|
+
// Determine column count based on container width and breakpoints
|
|
84
|
+
if (typeof columns === "object") {
|
|
85
|
+
const containerWidth = containerElement.offsetWidth
|
|
86
|
+
const breakpoints = {
|
|
87
|
+
default: 1,
|
|
88
|
+
sm: 640,
|
|
89
|
+
md: 768,
|
|
90
|
+
lg: 1024,
|
|
91
|
+
xl: 1280,
|
|
92
|
+
"2xl": 1536,
|
|
93
|
+
...columns,
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Sort breakpoints by size (descending)
|
|
97
|
+
const sortedBreakpoints = Object.entries(breakpoints)
|
|
98
|
+
.filter(([key]) => key !== "default")
|
|
99
|
+
.sort((a, b) => b[1] - a[1])
|
|
100
|
+
|
|
101
|
+
// Find the first breakpoint that matches
|
|
102
|
+
let matchedColumns = breakpoints.default
|
|
103
|
+
for (const [key, width] of sortedBreakpoints) {
|
|
104
|
+
if (containerWidth >= width) {
|
|
105
|
+
matchedColumns = columns[key]
|
|
106
|
+
break
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
columnCount = matchedColumns
|
|
111
|
+
} else if (columnWidth) {
|
|
112
|
+
// Calculate column count based on fixed column width
|
|
113
|
+
const containerWidth = containerElement.offsetWidth
|
|
114
|
+
columnCount = Math.max(1, Math.floor(containerWidth / parseInt(columnWidth)))
|
|
115
|
+
} else {
|
|
116
|
+
columnCount = columns
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Initialize column heights
|
|
120
|
+
columnHeights = Array(columnCount).fill(0)
|
|
121
|
+
|
|
122
|
+
// Position items
|
|
123
|
+
positionItems()
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Positions items in the masonry layout
|
|
128
|
+
*/
|
|
129
|
+
function positionItems() {
|
|
130
|
+
if (!containerElement || !items.length) return
|
|
131
|
+
|
|
132
|
+
// Reset column heights
|
|
133
|
+
columnHeights = Array(columnCount).fill(0)
|
|
134
|
+
|
|
135
|
+
// Calculate column width
|
|
136
|
+
const containerWidth = containerElement.offsetWidth
|
|
137
|
+
const colWidth = (containerWidth - gap * (columnCount - 1)) / columnCount
|
|
138
|
+
|
|
139
|
+
// Position each item
|
|
140
|
+
items.forEach((item, index) => {
|
|
141
|
+
// Find the shortest column
|
|
142
|
+
const shortestCol = columnHeights.indexOf(Math.min(...columnHeights))
|
|
143
|
+
|
|
144
|
+
// Calculate position
|
|
145
|
+
const left = shortestCol * (colWidth + gap)
|
|
146
|
+
const top = columnHeights[shortestCol]
|
|
147
|
+
|
|
148
|
+
// Update item style
|
|
149
|
+
const itemStyle = item.style
|
|
150
|
+
itemStyle.width = `${colWidth}px`
|
|
151
|
+
itemStyle.left = `${left}px`
|
|
152
|
+
itemStyle.top = `${top}px`
|
|
153
|
+
|
|
154
|
+
// Add transition if animated
|
|
155
|
+
if (animated) {
|
|
156
|
+
itemStyle.transition = `transform ${animationDuration}ms ${animationEasing}, opacity ${animationDuration}ms ${animationEasing}`
|
|
157
|
+
itemStyle.transform = "translate3d(0, 0, 0)"
|
|
158
|
+
itemStyle.opacity = "1"
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Update column height
|
|
162
|
+
columnHeights[shortestCol] += item.offsetHeight + gap
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Update container height
|
|
166
|
+
const maxHeight = Math.max(...columnHeights) - gap
|
|
167
|
+
containerElement.style.height = `${maxHeight}px`
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Observes changes to item dimensions
|
|
172
|
+
*/
|
|
173
|
+
function observeItems() {
|
|
174
|
+
// Clean up existing observers
|
|
175
|
+
itemObservers.forEach((observer) => observer.disconnect())
|
|
176
|
+
itemObservers = []
|
|
177
|
+
|
|
178
|
+
// Create new observers for each item
|
|
179
|
+
items.forEach((item) => {
|
|
180
|
+
const observer = new ResizeObserver(() => {
|
|
181
|
+
// Reposition items when an item's size changes
|
|
182
|
+
positionItems()
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
observer.observe(item)
|
|
186
|
+
itemObservers.push(observer)
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Initialize layout on mount
|
|
191
|
+
onMount(() => {
|
|
192
|
+
if (containerElement) {
|
|
193
|
+
// Get all immediate children
|
|
194
|
+
items = Array.from(containerElement.children)
|
|
195
|
+
|
|
196
|
+
// Set initial styles
|
|
197
|
+
items.forEach((item) => {
|
|
198
|
+
item.style.position = "absolute"
|
|
199
|
+
if (animated) {
|
|
200
|
+
item.style.opacity = "0"
|
|
201
|
+
item.style.transform = "translate3d(0, 20px, 0)"
|
|
202
|
+
}
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
// Initialize layout
|
|
206
|
+
initLayout()
|
|
207
|
+
|
|
208
|
+
// Observe container resize
|
|
209
|
+
resizeObserver = new ResizeObserver(() => {
|
|
210
|
+
initLayout()
|
|
211
|
+
})
|
|
212
|
+
resizeObserver.observe(containerElement)
|
|
213
|
+
|
|
214
|
+
// Observe DOM changes (added/removed items)
|
|
215
|
+
mutationObserver = new MutationObserver((mutations) => {
|
|
216
|
+
let needsUpdate = false
|
|
217
|
+
|
|
218
|
+
mutations.forEach((mutation) => {
|
|
219
|
+
if (mutation.type === "childList") {
|
|
220
|
+
if (mutation.addedNodes.length || mutation.removedNodes.length) {
|
|
221
|
+
needsUpdate = true
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
if (needsUpdate) {
|
|
227
|
+
items = Array.from(containerElement.children)
|
|
228
|
+
|
|
229
|
+
// Set styles for new items
|
|
230
|
+
items.forEach((item) => {
|
|
231
|
+
if (!item.style.position) {
|
|
232
|
+
item.style.position = "absolute"
|
|
233
|
+
if (animated) {
|
|
234
|
+
item.style.opacity = "0"
|
|
235
|
+
item.style.transform = "translate3d(0, 20px, 0)"
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
initLayout()
|
|
241
|
+
observeItems()
|
|
242
|
+
}
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
mutationObserver.observe(containerElement, {
|
|
246
|
+
childList: true,
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
// Observe item size changes
|
|
250
|
+
observeItems()
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return () => {
|
|
254
|
+
// Clean up observers on destroy
|
|
255
|
+
if (resizeObserver) {
|
|
256
|
+
resizeObserver.disconnect()
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (mutationObserver) {
|
|
260
|
+
mutationObserver.disconnect()
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
itemObservers.forEach((observer) => observer.disconnect())
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
</script>
|
|
267
|
+
|
|
268
|
+
<div
|
|
269
|
+
{id}
|
|
270
|
+
class="
|
|
271
|
+
masonry
|
|
272
|
+
{centered ? 'masonry-centered' : ''}
|
|
273
|
+
{className}
|
|
274
|
+
"
|
|
275
|
+
style="--masonry-gap: {gap}px;"
|
|
276
|
+
role="grid"
|
|
277
|
+
aria-label={ariaLabel}
|
|
278
|
+
bind:this={containerElement}
|
|
279
|
+
>
|
|
280
|
+
{@render children?.()}
|
|
281
|
+
</div>
|
|
282
|
+
|
|
283
|
+
<style>
|
|
284
|
+
@reference "../../twintrinsic.css";
|
|
285
|
+
|
|
286
|
+
.masonry {
|
|
287
|
+
@apply relative w-full;
|
|
288
|
+
min-height: 100px;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.masonry-centered {
|
|
292
|
+
@apply mx-auto;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.masonry > :global(*) {
|
|
296
|
+
@apply box-border;
|
|
297
|
+
margin-bottom: var(--masonry-gap);
|
|
298
|
+
}
|
|
299
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export default Masonry;
|
|
2
|
+
type Masonry = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Masonry - A component for creating Pinterest-style grid layouts.
|
|
8
|
+
* Provides responsive, dynamic layouts for items of varying heights.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* ```svelte
|
|
12
|
+
* <Masonry columns={3} gap={16}>
|
|
13
|
+
* <div>Item 1 with some content</div>
|
|
14
|
+
* <div>Item 2 with more content that might be taller</div>
|
|
15
|
+
* <div>Item 3 with less content</div>
|
|
16
|
+
* <div>Item 4 with a different height</div>
|
|
17
|
+
* </Masonry>
|
|
18
|
+
*
|
|
19
|
+
* <Masonry
|
|
20
|
+
* columns={{ default: 1, sm: 2, md: 3, lg: 4, xl: 5 }}
|
|
21
|
+
* gap={20}
|
|
22
|
+
* columnWidth="300px"
|
|
23
|
+
* >
|
|
24
|
+
* {#each items as item}
|
|
25
|
+
* <div>{item.content}</div>
|
|
26
|
+
* {/each}
|
|
27
|
+
* </Masonry>
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
declare const Masonry: import("svelte").Component<{
|
|
31
|
+
class?: string;
|
|
32
|
+
id?: any;
|
|
33
|
+
columns?: number;
|
|
34
|
+
gap?: number;
|
|
35
|
+
columnWidth: any;
|
|
36
|
+
centered?: boolean;
|
|
37
|
+
animated?: boolean;
|
|
38
|
+
animationDuration?: number;
|
|
39
|
+
animationEasing?: string;
|
|
40
|
+
ariaLabel?: string;
|
|
41
|
+
children: any;
|
|
42
|
+
}, {}, "">;
|
|
43
|
+
type $$ComponentProps = {
|
|
44
|
+
class?: string;
|
|
45
|
+
id?: any;
|
|
46
|
+
columns?: number;
|
|
47
|
+
gap?: number;
|
|
48
|
+
columnWidth: any;
|
|
49
|
+
centered?: boolean;
|
|
50
|
+
animated?: boolean;
|
|
51
|
+
animationDuration?: number;
|
|
52
|
+
animationEasing?: string;
|
|
53
|
+
ariaLabel?: string;
|
|
54
|
+
children: any;
|
|
55
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
const {
|
|
3
|
+
/** @type {string} - Additional CSS classes */
|
|
4
|
+
class: className = "",
|
|
5
|
+
|
|
6
|
+
/** @type {string} - HTML id for accessibility */
|
|
7
|
+
id = crypto.randomUUID(),
|
|
8
|
+
|
|
9
|
+
/** @type {string} - ARIA label */
|
|
10
|
+
ariaLabel = "Menu",
|
|
11
|
+
children,
|
|
12
|
+
} = $props()
|
|
13
|
+
|
|
14
|
+
let isOpen = $state(false)
|
|
15
|
+
|
|
16
|
+
function toggleMenu() {
|
|
17
|
+
isOpen = !isOpen
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="menu {className}" {id}>
|
|
22
|
+
<button
|
|
23
|
+
type="button"
|
|
24
|
+
class="menu-trigger"
|
|
25
|
+
{id}
|
|
26
|
+
aria-haspopup="true"
|
|
27
|
+
aria-expanded={isOpen}
|
|
28
|
+
aria-label={ariaLabel}
|
|
29
|
+
onclick={toggleMenu}
|
|
30
|
+
>
|
|
31
|
+
{@render children?.('trigger')}
|
|
32
|
+
</button>
|
|
33
|
+
|
|
34
|
+
{#if isOpen}
|
|
35
|
+
<div
|
|
36
|
+
class="menu-content"
|
|
37
|
+
role="menu"
|
|
38
|
+
aria-orientation="vertical"
|
|
39
|
+
aria-labelledby={id}
|
|
40
|
+
>
|
|
41
|
+
{@render children?.('content')}
|
|
42
|
+
</div>
|
|
43
|
+
{/if}
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<style>
|
|
47
|
+
@reference "../../../twintrinsic.css";
|
|
48
|
+
|
|
49
|
+
.menu {
|
|
50
|
+
@apply relative inline-block;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.menu-trigger {
|
|
54
|
+
@apply inline-flex items-center justify-center rounded-md;
|
|
55
|
+
@apply px-4 py-2 text-sm font-medium;
|
|
56
|
+
@apply bg-background border border-border;
|
|
57
|
+
@apply hover:bg-hover focus:outline-none focus:ring-2 focus:ring-primary-500;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.menu-content {
|
|
61
|
+
@apply absolute right-0 mt-2 w-56;
|
|
62
|
+
@apply bg-background border border-border rounded-md shadow-lg;
|
|
63
|
+
@apply origin-top-right;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export default Menu;
|
|
2
|
+
type Menu = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const Menu: import("svelte").Component<{
|
|
7
|
+
class?: string;
|
|
8
|
+
id?: any;
|
|
9
|
+
ariaLabel?: string;
|
|
10
|
+
children: any;
|
|
11
|
+
}, {}, "">;
|
|
12
|
+
type $$ComponentProps = {
|
|
13
|
+
class?: string;
|
|
14
|
+
id?: any;
|
|
15
|
+
ariaLabel?: string;
|
|
16
|
+
children: any;
|
|
17
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
const {
|
|
3
|
+
/** @type {string} - Additional CSS classes */
|
|
4
|
+
class: className = "",
|
|
5
|
+
|
|
6
|
+
/** @type {string} - HTML id for accessibility */
|
|
7
|
+
id = crypto.randomUUID(),
|
|
8
|
+
|
|
9
|
+
/** @type {string} - ARIA label */
|
|
10
|
+
ariaLabel,
|
|
11
|
+
|
|
12
|
+
/** @type {string} - Link href */
|
|
13
|
+
href = "#",
|
|
14
|
+
|
|
15
|
+
/** @type {boolean} - Whether the item is active */
|
|
16
|
+
active = false,
|
|
17
|
+
|
|
18
|
+
/** @type {boolean} - Whether the item is disabled */
|
|
19
|
+
disabled = false,
|
|
20
|
+
|
|
21
|
+
/** @type {boolean} - Whether the submenu is initially open */
|
|
22
|
+
initialOpen = false,
|
|
23
|
+
|
|
24
|
+
/** @type {any} - Value associated with this menu item */
|
|
25
|
+
value = {},
|
|
26
|
+
|
|
27
|
+
children,
|
|
28
|
+
} = $props()
|
|
29
|
+
|
|
30
|
+
// Use $state for values that need to be modified
|
|
31
|
+
let isOpen = $state(false)
|
|
32
|
+
|
|
33
|
+
// Sync isOpen when initialOpen changes
|
|
34
|
+
$effect(() => {
|
|
35
|
+
isOpen = initialOpen
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
const toggleMenu = () => {
|
|
39
|
+
isOpen = !isOpen
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<svelte:element
|
|
44
|
+
this={href ? 'a' : 'button'}
|
|
45
|
+
{href}
|
|
46
|
+
{id}
|
|
47
|
+
class="menu-item {className}"
|
|
48
|
+
class:active
|
|
49
|
+
class:disabled
|
|
50
|
+
role="menuitem"
|
|
51
|
+
aria-label={ariaLabel}
|
|
52
|
+
aria-disabled={disabled}
|
|
53
|
+
onclick={!disabled && toggleMenu}
|
|
54
|
+
>
|
|
55
|
+
{@render children?.()}
|
|
56
|
+
{#if value?.children}
|
|
57
|
+
<ul class="menu-item-submenu" class:hidden={!isOpen}>
|
|
58
|
+
{#each value.children as child}
|
|
59
|
+
<MenuItem value={child}/>
|
|
60
|
+
{/each}
|
|
61
|
+
</ul>
|
|
62
|
+
{/if}
|
|
63
|
+
</svelte:element>
|
|
64
|
+
|
|
65
|
+
<style>
|
|
66
|
+
@reference "../../../twintrinsic.css";
|
|
67
|
+
|
|
68
|
+
.menu-item {
|
|
69
|
+
@apply block w-full text-left;
|
|
70
|
+
@apply px-4 py-2 text-sm;
|
|
71
|
+
@apply hover:bg-hover focus:outline-none focus:bg-hover;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.menu-item.active {
|
|
75
|
+
@apply bg-primary-500 text-white;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.menu-item.disabled {
|
|
79
|
+
@apply opacity-50 cursor-not-allowed;
|
|
80
|
+
@apply hover:bg-transparent;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.menu-item-submenu {
|
|
84
|
+
@apply pl-4;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.hidden {
|
|
88
|
+
@apply hidden;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export default MenuItem;
|
|
2
|
+
type MenuItem = {
|
|
3
|
+
$on?(type: string, callback: (e: any) => void): () => void;
|
|
4
|
+
$set?(props: Partial<$$ComponentProps>): void;
|
|
5
|
+
};
|
|
6
|
+
declare const MenuItem: import("svelte").Component<{
|
|
7
|
+
class?: string;
|
|
8
|
+
id?: any;
|
|
9
|
+
ariaLabel: any;
|
|
10
|
+
href?: string;
|
|
11
|
+
active?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
initialOpen?: boolean;
|
|
14
|
+
value?: Record<string, any>;
|
|
15
|
+
children: any;
|
|
16
|
+
}, {}, "">;
|
|
17
|
+
type $$ComponentProps = {
|
|
18
|
+
class?: string;
|
|
19
|
+
id?: any;
|
|
20
|
+
ariaLabel: any;
|
|
21
|
+
href?: string;
|
|
22
|
+
active?: boolean;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
initialOpen?: boolean;
|
|
25
|
+
value?: Record<string, any>;
|
|
26
|
+
children: any;
|
|
27
|
+
};
|