uisv 0.0.12 → 0.0.13

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.
Files changed (75) hide show
  1. package/dist/components/accordion.svelte +108 -0
  2. package/dist/components/accordion.svelte.d.ts +58 -0
  3. package/dist/components/alert.svelte +271 -0
  4. package/dist/components/alert.svelte.d.ts +23 -0
  5. package/dist/components/badge.svelte +225 -0
  6. package/dist/components/badge.svelte.d.ts +19 -0
  7. package/dist/components/banner.svelte +254 -0
  8. package/dist/components/banner.svelte.d.ts +23 -0
  9. package/dist/components/button/button.svelte +105 -0
  10. package/dist/components/button/button.svelte.d.ts +4 -0
  11. package/dist/components/button/index.d.ts +48 -0
  12. package/dist/components/button/index.js +4 -0
  13. package/dist/components/button/style.d.ts +148 -0
  14. package/dist/components/button/style.js +248 -0
  15. package/dist/components/card.svelte +70 -0
  16. package/dist/components/card.svelte.d.ts +17 -0
  17. package/dist/components/checkbox-group.svelte +258 -0
  18. package/dist/components/checkbox-group.svelte.d.ts +26 -0
  19. package/dist/components/checkbox.svelte +175 -0
  20. package/dist/components/checkbox.svelte.d.ts +27 -0
  21. package/dist/components/chip.svelte +82 -0
  22. package/dist/components/chip.svelte.d.ts +17 -0
  23. package/dist/components/color-picker.svelte +48 -0
  24. package/dist/components/color-picker.svelte.d.ts +10 -0
  25. package/dist/components/h1.svelte +15 -0
  26. package/dist/components/h1.svelte.d.ts +3 -0
  27. package/dist/components/h2.svelte +19 -0
  28. package/dist/components/h2.svelte.d.ts +3 -0
  29. package/dist/components/h3.svelte +16 -0
  30. package/dist/components/h3.svelte.d.ts +3 -0
  31. package/dist/components/h4.svelte +19 -0
  32. package/dist/components/h4.svelte.d.ts +3 -0
  33. package/dist/components/h5.svelte +19 -0
  34. package/dist/components/h5.svelte.d.ts +3 -0
  35. package/dist/components/h6.svelte +19 -0
  36. package/dist/components/h6.svelte.d.ts +3 -0
  37. package/dist/components/index.d.ts +42 -0
  38. package/dist/components/index.js +42 -0
  39. package/dist/components/input/index.d.ts +54 -0
  40. package/dist/components/input/index.js +2 -0
  41. package/dist/components/input/input.svelte +103 -0
  42. package/dist/components/input/input.svelte.d.ts +4 -0
  43. package/dist/components/input/style.d.ts +316 -0
  44. package/dist/components/input/style.js +128 -0
  45. package/dist/components/input-time/index.d.ts +375 -0
  46. package/dist/components/input-time/index.js +144 -0
  47. package/dist/components/input-time/input-time.svelte +39 -0
  48. package/dist/components/input-time/input-time.svelte.d.ts +4 -0
  49. package/dist/components/kbd.svelte +239 -0
  50. package/dist/components/kbd.svelte.d.ts +40 -0
  51. package/dist/components/p.svelte +9 -0
  52. package/dist/components/p.svelte.d.ts +3 -0
  53. package/dist/components/pin-input.svelte +162 -0
  54. package/dist/components/pin-input.svelte.d.ts +25 -0
  55. package/dist/components/placeholder.svelte +34 -0
  56. package/dist/components/placeholder.svelte.d.ts +3 -0
  57. package/dist/components/popover.svelte +151 -0
  58. package/dist/components/popover.svelte.d.ts +88 -0
  59. package/dist/components/progress.svelte +124 -0
  60. package/dist/components/progress.svelte.d.ts +21 -0
  61. package/dist/components/select.svelte +171 -0
  62. package/dist/components/select.svelte.d.ts +50 -0
  63. package/dist/components/slider.svelte +172 -0
  64. package/dist/components/slider.svelte.d.ts +44 -0
  65. package/dist/components/switch.svelte +180 -0
  66. package/dist/components/switch.svelte.d.ts +27 -0
  67. package/dist/components/tabs.svelte +246 -0
  68. package/dist/components/tabs.svelte.d.ts +34 -0
  69. package/dist/index.d.ts +4 -0
  70. package/dist/index.js +3 -0
  71. package/dist/utilities.svelte.d.ts +24 -0
  72. package/dist/utilities.svelte.js +47 -0
  73. package/dist/vite.d.ts +51 -0
  74. package/dist/vite.js +157 -0
  75. package/package.json +2 -2
@@ -0,0 +1,180 @@
1
+ <script module lang="ts">
2
+ import { type PropColor, isComponent, isSnippet } from '../index.js';
3
+ import type { Snippet } from 'svelte';
4
+ import type { ClassNameValue } from 'tailwind-merge';
5
+ import { tv } from 'tailwind-variants';
6
+ import type { Component } from 'vitest-browser-svelte';
7
+
8
+ export type SwitchProps = {
9
+ value?: boolean;
10
+ color?: PropColor;
11
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
12
+ disabled?: boolean;
13
+ loading?: boolean;
14
+ loadingicon?: string | Snippet | Component;
15
+ uncheckedicon?: string | Snippet | Component;
16
+ checkedicon?: string | Snippet | Component;
17
+ label?: string | Snippet;
18
+ description?: string | Snippet;
19
+ required?: boolean;
20
+ ui?: {
21
+ root?: ClassNameValue;
22
+ container?: ClassNameValue;
23
+ thumb?: ClassNameValue;
24
+ label?: ClassNameValue;
25
+ description?: ClassNameValue;
26
+ };
27
+ };
28
+ </script>
29
+
30
+ <script lang="ts">
31
+ let {
32
+ value = $bindable(false),
33
+ color = 'primary',
34
+ size = 'md',
35
+ disabled,
36
+ loading,
37
+ loadingicon = 'i-lucide-loader-circle',
38
+ uncheckedicon,
39
+ checkedicon,
40
+ label,
41
+ description,
42
+ required,
43
+ ui = {},
44
+ }: SwitchProps = $props();
45
+
46
+ const classes = $derived.by(() =>
47
+ tv({
48
+ slots: {
49
+ root: 'flex-inline gap-2',
50
+ container: 'rounded-full bg-neutral-200 p-0.5 relative transition',
51
+ thumb: [
52
+ 'bg-white block rounded-full absolute top-0.5 transition grid place-items-center',
53
+ value ? 'translate-x-full' : 'text-neutral-500',
54
+ ],
55
+ icon: 'pi',
56
+ label: 'text-sm',
57
+ description: 'text-sm text-neutral-500',
58
+ },
59
+ variants: {
60
+ color: {
61
+ primary: {
62
+ container: ['', value && 'bg-primary-500 text-primary-500'],
63
+ },
64
+ surface: {
65
+ container: ['', value && 'bg-neutral-900 text-neutral-900'],
66
+ },
67
+ info: {
68
+ container: ['', value && 'bg-info-500 text-info-500'],
69
+ },
70
+ success: {
71
+ container: ['', value && 'bg-success-500 text-success-500'],
72
+ },
73
+ warning: {
74
+ container: ['', value && 'bg-warning-500 text-warning-500'],
75
+ },
76
+ error: {
77
+ container: ['', value && 'bg-error-500 text-error-500'],
78
+ },
79
+ },
80
+ size: {
81
+ xs: {
82
+ container: 'w-7 min-w-7 h-4',
83
+ thumb: 'size-3',
84
+ icon: 'size-2.5',
85
+ },
86
+ sm: {
87
+ container: 'w-8 min-w-8 h-4.5',
88
+ thumb: 'size-3.5',
89
+ icon: 'size-3',
90
+ },
91
+ md: {
92
+ container: 'w-9 min-w-9 h-5',
93
+ thumb: 'size-4',
94
+ icon: 'size-3.5',
95
+ },
96
+ lg: {
97
+ container: 'w-10 min-w-10 h-5.5',
98
+ thumb: 'size-4.5',
99
+ icon: 'size-4',
100
+ },
101
+ xl: {
102
+ container: 'w-11 min-w-11 h-6',
103
+ thumb: 'size-5',
104
+ icon: 'size-4.5',
105
+ },
106
+ },
107
+ },
108
+ compoundVariants: [],
109
+ })({ color, size }),
110
+ );
111
+ </script>
112
+
113
+ <div
114
+ data-state={value ? 'checked' : 'unchecked'}
115
+ class={classes.root({
116
+ class: [(loading || disabled) && 'opacity-50', ui.thumb],
117
+ })}
118
+ >
119
+ <button
120
+ aria-label="switch"
121
+ data-state={value ? 'checked' : 'unchecked'}
122
+ class={classes.container({ class: [loading && 'cursor-not-allowed', ui.thumb] })}
123
+ onclick={() => {
124
+ console.log('click');
125
+ if (loading) return;
126
+ value = !value;
127
+ }}
128
+ >
129
+ <span data-state={value ? 'checked' : 'unchecked'} class={classes.thumb({ class: ui.thumb })}>
130
+ {@render Icon(uncheckedicon, [(loading || value) && 'opacity-0'])}
131
+ {@render Icon(checkedicon, [(loading || !value) && 'opacity-0'])}
132
+ {@render Icon(loadingicon || 'i-lucide-loader-circle', [
133
+ 'animate-spin',
134
+ !loading && 'opacity-0',
135
+ ])}
136
+ </span>
137
+ </button>
138
+
139
+ {#if label}
140
+ <span>
141
+ <div
142
+ class={classes.label({
143
+ class: [required ? 'after:content-["*"] after:text-error-500' : '', ui.thumb],
144
+ })}
145
+ >
146
+ {#if typeof label === 'string'}
147
+ {label}
148
+ {:else}
149
+ {@render label()}
150
+ {/if}
151
+ </div>
152
+
153
+ {#if description}
154
+ <div class={classes.description({ class: ui.thumb })}>
155
+ {#if typeof description === 'string'}
156
+ {description}
157
+ {:else}
158
+ {@render description()}
159
+ {/if}
160
+ </div>
161
+ {/if}
162
+ </span>
163
+ {/if}
164
+ </div>
165
+
166
+ {#snippet Icon(ico?: SwitchProps['checkedicon'], icon_class?: ClassNameValue)}
167
+ <div class={['absolute', icon_class]}>
168
+ {#if typeof ico === 'string'}
169
+ <div
170
+ data-state={value ? 'checked' : 'unchecked'}
171
+ class={classes.icon({ class: [ico] })}
172
+ ></div>
173
+ {:else if isSnippet(ico)}
174
+ {@render ico()}
175
+ {:else if isComponent(ico)}
176
+ {@const Iconn = ico}
177
+ <Iconn />
178
+ {/if}
179
+ </div>
180
+ {/snippet}
@@ -0,0 +1,27 @@
1
+ import { type PropColor } from '../index.js';
2
+ import type { Snippet } from 'svelte';
3
+ import type { ClassNameValue } from 'tailwind-merge';
4
+ import type { Component } from 'vitest-browser-svelte';
5
+ export type SwitchProps = {
6
+ value?: boolean;
7
+ color?: PropColor;
8
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
9
+ disabled?: boolean;
10
+ loading?: boolean;
11
+ loadingicon?: string | Snippet | Component;
12
+ uncheckedicon?: string | Snippet | Component;
13
+ checkedicon?: string | Snippet | Component;
14
+ label?: string | Snippet;
15
+ description?: string | Snippet;
16
+ required?: boolean;
17
+ ui?: {
18
+ root?: ClassNameValue;
19
+ container?: ClassNameValue;
20
+ thumb?: ClassNameValue;
21
+ label?: ClassNameValue;
22
+ description?: ClassNameValue;
23
+ };
24
+ };
25
+ declare const Switch: import("svelte").Component<SwitchProps, {}, "value">;
26
+ type Switch = ReturnType<typeof Switch>;
27
+ export default Switch;
@@ -0,0 +1,246 @@
1
+ <script module lang="ts">
2
+ import { Tabs } from 'bits-ui';
3
+ import { isComponent, isSnippet, useElementRects, type PropColor } from '../index.js';
4
+ import type { ClassNameValue } from 'tailwind-merge';
5
+ import { tv } from 'tailwind-variants';
6
+ import { type Component, type Snippet } from 'svelte';
7
+ import Icon from '@iconify/svelte';
8
+ import { ElementRect } from 'runed';
9
+
10
+ export type TabItem =
11
+ | string
12
+ | {
13
+ label: string;
14
+ icon?: string | Component | Snippet;
15
+ iconposition?: 'before' | 'after';
16
+ content?: string | Component;
17
+ };
18
+
19
+ export type TabsProps = {
20
+ value?: number;
21
+ items: TabItem[];
22
+ color?: PropColor;
23
+ variant?: 'link' | 'pill';
24
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
25
+ disabled?: boolean;
26
+ orientation?: 'vertical' | 'horizontal';
27
+ ui?: {
28
+ root?: ClassNameValue;
29
+ item?: ClassNameValue;
30
+ list?: ClassNameValue;
31
+ content?: ClassNameValue;
32
+ icon?: ClassNameValue;
33
+ indicator?: ClassNameValue;
34
+ };
35
+ [k: `content_${string}`]: Snippet<[{ item: TabItem; value: number }]>;
36
+ };
37
+ </script>
38
+
39
+ <script lang="ts">
40
+ let {
41
+ value = $bindable(0),
42
+ items = [],
43
+ color = 'primary',
44
+ variant = 'pill',
45
+ size = 'md',
46
+ disabled,
47
+ orientation = 'horizontal',
48
+ ui = {},
49
+ ...rest
50
+ }: TabsProps = $props();
51
+
52
+ let container_el = $state<HTMLElement | null>(null);
53
+ const container_rect = new ElementRect(() => container_el);
54
+ let item_els = $state<HTMLElement[]>([]);
55
+ const rects = useElementRects(() => item_els);
56
+ const rect = $derived.by(() => {
57
+ const result = { w: 0, h: 0, l: 0, t: 0 };
58
+
59
+ if (rects[value]) {
60
+ result.w = rects[value].width;
61
+ result.l = rects[value].left - container_rect.left;
62
+ result.h = rects[value].height;
63
+ result.t = rects[value].top - container_rect.top;
64
+ }
65
+
66
+ return result;
67
+ });
68
+
69
+ const classes = $derived.by(() =>
70
+ tv({
71
+ slots: {
72
+ root: '',
73
+ list: 'flex relative p-1',
74
+ item: 'flex items-center justify-center text-muted data-[state="inactive"]:hover:(text-highlighted) font-medium z-1 transition-all',
75
+ icon: '',
76
+ content: 'mt-2',
77
+ indicator: 'absolute z-0 transition-all duration-200 rounded-md w---width',
78
+ },
79
+ variants: {
80
+ variant: {
81
+ pill: {
82
+ list: 'bg-surface-elevated rounded-lg',
83
+ item: 'flex-1 data-[state="active"]:(text-inverted)',
84
+ trigger: 'flex-1',
85
+ indicator: 'rounded-md shadow-xs',
86
+ },
87
+ link: {
88
+ list: 'border-b border-surface-accented',
89
+ item: '',
90
+ indicator: 'rounded-full -bottom-px',
91
+ trigger: 'focus:outline-none',
92
+ },
93
+ },
94
+ color: {
95
+ primary: {
96
+ item: 'data-[variant="link"]:data-[state="active"]:text-primary-500',
97
+ indicator: 'bg-primary-500',
98
+ },
99
+ surface: {
100
+ item: 'data-[variant="link"]:data-[state="active"]:text-surface-500',
101
+ indicator: 'bg-surface-900',
102
+ },
103
+ info: {
104
+ item: 'data-[variant="link"]:data-[state="active"]:text-info-500',
105
+ indicator: 'bg-info-500',
106
+ },
107
+ success: {
108
+ item: 'data-[variant="link"]:data-[state="active"]:text-success-500',
109
+ indicator: 'bg-success-500',
110
+ },
111
+ warning: {
112
+ item: 'data-[variant="link"]:data-[state="active"]:text-warning-500',
113
+ indicator: 'bg-warning-500',
114
+ },
115
+ error: {
116
+ item: 'data-[variant="link"]:data-[state="active"]:text-error-500',
117
+ indicator: 'bg-error-500',
118
+ },
119
+ },
120
+ size: {
121
+ xs: {
122
+ list: 'text-xs',
123
+ item: 'min-h-6 gap-1 px-2',
124
+ icon: 'size-4',
125
+ },
126
+ sm: {
127
+ list: 'text-xs',
128
+ item: 'min-h-7 gap-1 px-3',
129
+ icon: 'size-4',
130
+ },
131
+ md: {
132
+ list: 'text-sm',
133
+ item: 'min-h-8 gap-2 px-4',
134
+ icon: 'size-5',
135
+ },
136
+ lg: {
137
+ list: 'text-sm',
138
+ item: 'min-h-9 gap-2 px-4',
139
+ icon: 'size-5',
140
+ },
141
+ xl: {
142
+ list: '',
143
+ item: 'min-h-10 gap-4 px-5',
144
+ icon: 'size-6',
145
+ },
146
+ },
147
+ orientation: {
148
+ horizontal: {
149
+ indicator: 'h-px left---left',
150
+ },
151
+ vertical: {
152
+ root: '',
153
+ list: 'flex-col',
154
+ indicator: 'h-(--height) top-(--top)',
155
+ },
156
+ },
157
+ },
158
+ compoundVariants: [
159
+ { size: 'xs', variant: 'pill', class: { indicator: 'h-6' } },
160
+ { size: 'sm', variant: 'pill', class: { indicator: 'h-7' } },
161
+ { size: 'md', variant: 'pill', class: { indicator: 'h-8' } },
162
+ { size: 'lg', variant: 'pill', class: { indicator: 'h-9' } },
163
+ { size: 'xl', variant: 'pill', class: { indicator: 'h-10' } },
164
+ {
165
+ size: 'xs',
166
+ variant: 'link',
167
+ orientation: 'vertical',
168
+ class: { indicator: 'h-6' },
169
+ },
170
+ { size: 'sm', variant: 'link', orientation: 'vertical', class: { indicator: 'h-7' } },
171
+ { size: 'md', variant: 'link', orientation: 'vertical', class: { indicator: 'h-8' } },
172
+ { size: 'lg', variant: 'link', orientation: 'vertical', class: { indicator: 'h-9' } },
173
+ { size: 'xl', variant: 'link', orientation: 'vertical', class: { indicator: 'h-10' } },
174
+ {
175
+ orientation: 'vertical',
176
+ variant: 'link',
177
+ class: { list: 'border-b-0 border-l', indicator: 'w-px -left-px' },
178
+ },
179
+ ],
180
+ })({ color, size, orientation, variant }),
181
+ );
182
+ </script>
183
+
184
+ <Tabs.Root
185
+ {disabled}
186
+ bind:value={() => value.toString(), (v) => (value = parseInt(v))}
187
+ class={classes.root({ class: ui.root })}
188
+ {orientation}
189
+ >
190
+ <Tabs.List bind:ref={container_el} class={classes.list({ class: ui.list })}>
191
+ {#each items as item, idx (idx)}
192
+ {@const label = typeof item === 'string' ? item : item.label}
193
+
194
+ <Tabs.Trigger
195
+ bind:ref={
196
+ () => {
197
+ if (item_els[idx]) return item_els[idx];
198
+ if (typeof document !== 'undefined') return document.createElement('div');
199
+ },
200
+ (v) => {
201
+ if (v) item_els[idx] = v;
202
+ }
203
+ }
204
+ value={idx.toString()}
205
+ class={classes.item({ class: ui.item })}
206
+ data-variant={variant}
207
+ >
208
+ {@render RenderIcon(typeof item === 'string' ? undefined : item.icon)}
209
+
210
+ {label}
211
+ </Tabs.Trigger>
212
+ {/each}
213
+
214
+ <span
215
+ class={classes.indicator({ class: ui.indicator })}
216
+ style:--width="{rect.w}px"
217
+ style:--left="{rect.l}px"
218
+ style:--height="{rect.w}px"
219
+ style:--top="{rect.t}px"
220
+ ></span>
221
+ </Tabs.List>
222
+ {#each items as item, idx (idx)}
223
+ {#if typeof item === 'object' && item.content}
224
+ {@const Content = item.content}
225
+ <Tabs.Content value={idx.toString()} class={classes.content({ class: ui.content })}>
226
+ {#if `content_${idx}` in rest}
227
+ {@render rest[`content_${idx}`]({ item, value: idx })}
228
+ {:else if typeof Content === 'string'}
229
+ {Content}
230
+ {:else if isComponent(Content)}
231
+ <Content />
232
+ {/if}
233
+ </Tabs.Content>
234
+ {/if}
235
+ {/each}
236
+ </Tabs.Root>
237
+
238
+ {#snippet RenderIcon(IconProp?: string | Component | Snippet)}
239
+ {#if isSnippet(IconProp)}
240
+ {@render IconProp()}
241
+ {:else if isComponent(IconProp)}
242
+ <IconProp class={classes.icon({ class: ui.icon })} />
243
+ {:else if typeof IconProp === 'string'}
244
+ <Icon icon={IconProp} class={classes.icon({ class: ui.icon })} />
245
+ {/if}
246
+ {/snippet}
@@ -0,0 +1,34 @@
1
+ import { Tabs } from 'bits-ui';
2
+ import { type PropColor } from '../index.js';
3
+ import type { ClassNameValue } from 'tailwind-merge';
4
+ import { type Component, type Snippet } from 'svelte';
5
+ export type TabItem = string | {
6
+ label: string;
7
+ icon?: string | Component | Snippet;
8
+ iconposition?: 'before' | 'after';
9
+ content?: string | Component;
10
+ };
11
+ export type TabsProps = {
12
+ value?: number;
13
+ items: TabItem[];
14
+ color?: PropColor;
15
+ variant?: 'link' | 'pill';
16
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
17
+ disabled?: boolean;
18
+ orientation?: 'vertical' | 'horizontal';
19
+ ui?: {
20
+ root?: ClassNameValue;
21
+ item?: ClassNameValue;
22
+ list?: ClassNameValue;
23
+ content?: ClassNameValue;
24
+ icon?: ClassNameValue;
25
+ indicator?: ClassNameValue;
26
+ };
27
+ [k: `content_${string}`]: Snippet<[{
28
+ item: TabItem;
29
+ value: number;
30
+ }]>;
31
+ };
32
+ declare const Tabs: Component<TabsProps, {}, "value">;
33
+ type Tabs = ReturnType<typeof Tabs>;
34
+ export default Tabs;
@@ -0,0 +1,4 @@
1
+ export * from './components/index.js';
2
+ export * from './utilities.svelte.js';
3
+ export type PropColor = 'primary' | 'surface' | 'info' | 'success' | 'warning' | 'error';
4
+ export declare const COLORS: PropColor[];
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './components/index.js';
2
+ export * from './utilities.svelte.js';
3
+ export const COLORS = ['primary', 'surface', 'info', 'success', 'warning', 'error'];
@@ -0,0 +1,24 @@
1
+ import type { Component, Snippet } from 'svelte';
2
+ import { type MaybeGetter, type ElementSizeOptions } from 'runed';
3
+ /**
4
+ * Checks if a value is a Svelte component
5
+ * @param v - The value to check
6
+ * @returns true if the value is a component, false otherwise
7
+ */
8
+ export declare const isComponent: (v: unknown) => v is Component;
9
+ /**
10
+ * Checks if a value is a Svelte snippet
11
+ * @param v - The value to check
12
+ * @returns true if the value is a snippet, false otherwise
13
+ */
14
+ export declare const isSnippet: (v: unknown) => v is Snippet;
15
+ /**
16
+ * Returns a reactive value holding the dom rect of `node`s.
17
+ *
18
+ * Accepts an `options` object with the following properties:
19
+ * - `initialSize`: The initial size of the element. Defaults to `{ width: 0, height: 0 }`.
20
+ * - `box`: The box model to use. Can be either `"content-box"` or `"border-box"`. Defaults to `"border-box"`.
21
+ *
22
+ * @returns an array of dom rects.
23
+ */
24
+ export declare function useElementRects(nodes: MaybeGetter<HTMLElement[]>, options?: ElementSizeOptions): DOMRect[];
@@ -0,0 +1,47 @@
1
+ import { extract, useMutationObserver, useResizeObserver, } from 'runed';
2
+ /**
3
+ * Checks if a value is a Svelte component
4
+ * @param v - The value to check
5
+ * @returns true if the value is a component, false otherwise
6
+ */
7
+ export const isComponent = (v) => {
8
+ return typeof v === 'function' || (typeof v === 'object' && v !== null && !('$$render' in v));
9
+ };
10
+ /**
11
+ * Checks if a value is a Svelte snippet
12
+ * @param v - The value to check
13
+ * @returns true if the value is a snippet, false otherwise
14
+ */
15
+ export const isSnippet = (v) => {
16
+ return typeof v === 'object' && v !== null && '$$render' in v;
17
+ };
18
+ /**
19
+ * Returns a reactive value holding the dom rect of `node`s.
20
+ *
21
+ * Accepts an `options` object with the following properties:
22
+ * - `initialSize`: The initial size of the element. Defaults to `{ width: 0, height: 0 }`.
23
+ * - `box`: The box model to use. Can be either `"content-box"` or `"border-box"`. Defaults to `"border-box"`.
24
+ *
25
+ * @returns an array of dom rects.
26
+ */
27
+ export function useElementRects(nodes, options = {}) {
28
+ const rects = $state(extract(nodes).map((v) => v.getBoundingClientRect()));
29
+ const elements = $derived(extract(nodes));
30
+ const update = () => {
31
+ if (!elements || elements.length === 0)
32
+ return;
33
+ elements.forEach((el, idx) => (rects[idx] = el.getBoundingClientRect()));
34
+ };
35
+ $effect(() => {
36
+ const stops = [];
37
+ elements.forEach((v) => {
38
+ stops.push(useResizeObserver(() => v, update, { window: options.window }).stop);
39
+ stops.push(useMutationObserver(() => v, update, {
40
+ attributeFilter: ['style', 'class'],
41
+ window: options.window,
42
+ }).stop);
43
+ });
44
+ return () => stops.forEach((v) => v());
45
+ });
46
+ return rects;
47
+ }
package/dist/vite.d.ts ADDED
@@ -0,0 +1,51 @@
1
+ import { presetIcons } from 'unocss';
2
+ import { type WebFontsOptions } from '@unocss/preset-web-fonts';
3
+ import type { PropColor } from './index.js';
4
+ export type Colors = Record<string, string | Record<string, string>>;
5
+ export type NestedObject<K extends string, V> = {
6
+ [key in K]: NestedObject<K, V> | V;
7
+ };
8
+ export type PluginOptions = {
9
+ /**
10
+ * Colors as UnoCSS color name, hex color, or UnoCSS theme color object
11
+ * @example
12
+ * {
13
+ * primary: 'orange',
14
+ * surface: 'neutral',
15
+ * info: '#00F',
16
+ * success: '#0F0',
17
+ * warning: 'FF0',
18
+ * error: {
19
+ * 50: '#fef2f2';
20
+ * 100: '#fee2e2';
21
+ * 200: '#fecaca';
22
+ * 300: '#fca5a5';
23
+ * 400: '#f87171';
24
+ * 500: '#ef4444';
25
+ * 600: '#dc2626';
26
+ * 700: '#b91c1c';
27
+ * 800: '#991b1b';
28
+ * 900: '#7f1d1d';
29
+ * 950: '#450a0a';
30
+ * }
31
+ * }
32
+ */
33
+ colors?: Partial<Record<PropColor, string | Record<number, string>>>;
34
+ /**
35
+ * UnoCSS theme object for shared configuration between rules
36
+ */
37
+ theme?: object;
38
+ /**
39
+ * Options for the UnoCSS web fonts preset
40
+ */
41
+ fonts?: WebFontsOptions;
42
+ /**
43
+ * Corner radius for every* component
44
+ */
45
+ radius?: number;
46
+ /**
47
+ * Options for the UnoCSS icon preset
48
+ */
49
+ icons?: Parameters<typeof presetIcons>[0];
50
+ };
51
+ export declare function uisv(options: PluginOptions): import("vite").Plugin<any>[][];