@mrintel/villain-ui 0.2.2 → 0.3.0

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 (133) hide show
  1. package/dist/components/buttons/Button.svelte +33 -0
  2. package/dist/components/buttons/Button.svelte.d.ts +11 -0
  3. package/dist/components/buttons/ButtonGroup.svelte +30 -0
  4. package/dist/components/buttons/ButtonGroup.svelte.d.ts +8 -0
  5. package/dist/components/buttons/FloatingActionButton.svelte +44 -0
  6. package/dist/components/buttons/FloatingActionButton.svelte.d.ts +11 -0
  7. package/dist/components/buttons/IconButton.svelte +53 -0
  8. package/dist/components/buttons/IconButton.svelte.d.ts +13 -0
  9. package/dist/components/buttons/LinkButton.svelte +37 -0
  10. package/dist/components/buttons/LinkButton.svelte.d.ts +12 -0
  11. package/dist/components/buttons/buttonClasses.d.ts +10 -0
  12. package/dist/components/buttons/buttonClasses.js +10 -0
  13. package/dist/components/buttons/index.d.ts +5 -0
  14. package/dist/components/buttons/index.js +5 -0
  15. package/dist/components/cards/Card.svelte +46 -0
  16. package/dist/components/cards/Card.svelte.d.ts +11 -0
  17. package/dist/components/cards/Container.svelte +33 -0
  18. package/dist/components/cards/Container.svelte.d.ts +10 -0
  19. package/dist/components/cards/Divider.svelte +52 -0
  20. package/dist/components/cards/Divider.svelte.d.ts +9 -0
  21. package/dist/components/cards/Grid.svelte +44 -0
  22. package/dist/components/cards/Grid.svelte.d.ts +10 -0
  23. package/dist/components/cards/Panel.svelte +32 -0
  24. package/dist/components/cards/Panel.svelte.d.ts +10 -0
  25. package/dist/components/cards/SectionHeader.svelte +38 -0
  26. package/dist/components/cards/SectionHeader.svelte.d.ts +11 -0
  27. package/dist/components/cards/index.d.ts +6 -0
  28. package/dist/components/cards/index.js +6 -0
  29. package/dist/components/data/Avatar.svelte +67 -0
  30. package/dist/components/data/Avatar.svelte.d.ts +10 -0
  31. package/dist/components/data/Badge.svelte +32 -0
  32. package/dist/components/data/Badge.svelte.d.ts +8 -0
  33. package/dist/components/data/CodeBlock.svelte +121 -0
  34. package/dist/components/data/CodeBlock.svelte.d.ts +32 -0
  35. package/dist/components/data/List.svelte +64 -0
  36. package/dist/components/data/List.svelte.d.ts +8 -0
  37. package/dist/components/data/Pagination.svelte +123 -0
  38. package/dist/components/data/Pagination.svelte.d.ts +9 -0
  39. package/dist/components/data/Stat.svelte +103 -0
  40. package/dist/components/data/Stat.svelte.d.ts +11 -0
  41. package/dist/components/data/Table.svelte +76 -0
  42. package/dist/components/data/Table.svelte.d.ts +9 -0
  43. package/dist/components/data/Tag.svelte +53 -0
  44. package/dist/components/data/Tag.svelte.d.ts +9 -0
  45. package/dist/components/data/index.d.ts +8 -0
  46. package/dist/components/data/index.js +8 -0
  47. package/dist/components/forms/Checkbox.svelte +51 -0
  48. package/dist/components/forms/Checkbox.svelte.d.ts +10 -0
  49. package/dist/components/forms/FileUpload.svelte +164 -0
  50. package/dist/components/forms/FileUpload.svelte.d.ts +22 -0
  51. package/dist/components/forms/Input.svelte +57 -0
  52. package/dist/components/forms/Input.svelte.d.ts +13 -0
  53. package/dist/components/forms/InputGroup.svelte +7 -0
  54. package/dist/components/forms/InputGroup.svelte.d.ts +20 -0
  55. package/dist/components/forms/RadioGroup.svelte +87 -0
  56. package/dist/components/forms/RadioGroup.svelte.d.ts +15 -0
  57. package/dist/components/forms/RangeSlider.svelte +116 -0
  58. package/dist/components/forms/RangeSlider.svelte.d.ts +14 -0
  59. package/dist/components/forms/Select.svelte +71 -0
  60. package/dist/components/forms/Select.svelte.d.ts +16 -0
  61. package/dist/components/forms/Switch.svelte +56 -0
  62. package/dist/components/forms/Switch.svelte.d.ts +10 -0
  63. package/dist/components/forms/Textarea.svelte +57 -0
  64. package/dist/components/forms/Textarea.svelte.d.ts +13 -0
  65. package/dist/components/forms/index.d.ts +9 -0
  66. package/dist/components/forms/index.js +9 -0
  67. package/dist/components/navigation/Breadcrumbs.svelte +59 -0
  68. package/dist/components/navigation/Breadcrumbs.svelte.d.ts +14 -0
  69. package/dist/components/navigation/ContextMenu.svelte +83 -0
  70. package/dist/components/navigation/ContextMenu.svelte.d.ts +11 -0
  71. package/dist/components/navigation/DropdownMenu.svelte +80 -0
  72. package/dist/components/navigation/DropdownMenu.svelte.d.ts +10 -0
  73. package/dist/components/navigation/Menu.svelte +48 -0
  74. package/dist/components/navigation/Menu.svelte.d.ts +15 -0
  75. package/dist/components/navigation/Navbar.svelte +32 -0
  76. package/dist/components/navigation/Navbar.svelte.d.ts +9 -0
  77. package/dist/components/navigation/Sidebar.svelte +35 -0
  78. package/dist/components/navigation/Sidebar.svelte.d.ts +10 -0
  79. package/dist/components/navigation/Tabs.svelte +54 -0
  80. package/dist/components/navigation/Tabs.svelte.d.ts +15 -0
  81. package/dist/components/navigation/index.d.ts +7 -0
  82. package/dist/components/navigation/index.js +7 -0
  83. package/dist/components/overlays/Alert.svelte +99 -0
  84. package/dist/components/overlays/Alert.svelte.d.ts +11 -0
  85. package/dist/components/overlays/CommandPalette.svelte +217 -0
  86. package/dist/components/overlays/CommandPalette.svelte.d.ts +16 -0
  87. package/dist/components/overlays/Drawer.svelte +167 -0
  88. package/dist/components/overlays/Drawer.svelte.d.ts +14 -0
  89. package/dist/components/overlays/Dropdown.svelte +30 -0
  90. package/dist/components/overlays/Dropdown.svelte.d.ts +9 -0
  91. package/dist/components/overlays/Modal.svelte +130 -0
  92. package/dist/components/overlays/Modal.svelte.d.ts +13 -0
  93. package/dist/components/overlays/Popover.svelte +131 -0
  94. package/dist/components/overlays/Popover.svelte.d.ts +11 -0
  95. package/dist/components/overlays/ProgressBar.svelte +45 -0
  96. package/dist/components/overlays/ProgressBar.svelte.d.ts +10 -0
  97. package/dist/components/overlays/SkeletonLoader.svelte +82 -0
  98. package/dist/components/overlays/SkeletonLoader.svelte.d.ts +9 -0
  99. package/dist/components/overlays/Spinner.svelte +43 -0
  100. package/dist/components/overlays/Spinner.svelte.d.ts +7 -0
  101. package/dist/components/overlays/Toast.svelte +140 -0
  102. package/dist/components/overlays/Toast.svelte.d.ts +13 -0
  103. package/dist/components/overlays/Tooltip.svelte +115 -0
  104. package/dist/components/overlays/Tooltip.svelte.d.ts +10 -0
  105. package/dist/components/overlays/index.d.ts +11 -0
  106. package/dist/components/overlays/index.js +11 -0
  107. package/dist/components/typography/Code.svelte +14 -0
  108. package/dist/components/typography/Code.svelte.d.ts +6 -0
  109. package/dist/components/typography/Heading.svelte +22 -0
  110. package/dist/components/typography/Heading.svelte.d.ts +9 -0
  111. package/dist/components/typography/Text.svelte +24 -0
  112. package/dist/components/typography/Text.svelte.d.ts +9 -0
  113. package/dist/components/typography/index.d.ts +3 -0
  114. package/dist/components/typography/index.js +3 -0
  115. package/dist/components/utilities/Accordion.svelte +67 -0
  116. package/dist/components/utilities/Accordion.svelte.d.ts +14 -0
  117. package/dist/components/utilities/Carousel.svelte +152 -0
  118. package/dist/components/utilities/Carousel.svelte.d.ts +16 -0
  119. package/dist/components/utilities/Collapse.svelte +60 -0
  120. package/dist/components/utilities/Collapse.svelte.d.ts +10 -0
  121. package/dist/components/utilities/Portal.svelte +72 -0
  122. package/dist/components/utilities/Portal.svelte.d.ts +21 -0
  123. package/dist/components/utilities/ScrollArea.svelte +41 -0
  124. package/dist/components/utilities/ScrollArea.svelte.d.ts +8 -0
  125. package/dist/components/utilities/index.d.ts +5 -0
  126. package/dist/components/utilities/index.js +5 -0
  127. package/dist/index.d.ts +15 -175
  128. package/dist/index.js +24 -4560
  129. package/dist/lib/internal/id.d.ts +12 -0
  130. package/dist/lib/internal/id.js +15 -0
  131. package/dist/theme.css +218 -0
  132. package/package.json +6 -5
  133. package/dist/index.css +0 -1
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ variant?: 'default' | 'accent';
4
+ dismissible?: boolean;
5
+ ondismiss?: () => void;
6
+ children?: import('svelte').Snippet;
7
+ }
8
+
9
+ let { variant = 'default', dismissible = false, ondismiss, children }: Props = $props();
10
+
11
+ const variantClasses = {
12
+ default:
13
+ 'bg-[var(--color-base-2)] text-[var(--color-text-soft)] border-[var(--color-border)]',
14
+ accent:
15
+ 'bg-[rgba(127,61,255,0.1)] text-[var(--color-accent-soft)] border-[var(--color-accent)] shadow-[0_0_12px_rgba(127,61,255,0.2)]'
16
+ };
17
+
18
+ const classes = $derived(
19
+ `inline-flex items-center gap-2 px-3 py-1.5 rounded-[var(--radius-pill)] border font-[var(--font-body)] font-medium text-sm transition-all duration-300 hover:scale-[1.02] ${variantClasses[variant]}`
20
+ );
21
+
22
+ function handleDismiss() {
23
+ ondismiss?.();
24
+ }
25
+ </script>
26
+
27
+ <span class={classes}>
28
+ {@render children?.()}
29
+
30
+ {#if dismissible}
31
+ <button
32
+ class="ml-1 opacity-60 hover:opacity-100 hover:text-[var(--color-text)] transition-all duration-300"
33
+ onclick={handleDismiss}
34
+ aria-label="Remove tag"
35
+ >
36
+ <svg
37
+ width="14"
38
+ height="14"
39
+ viewBox="0 0 14 14"
40
+ fill="none"
41
+ xmlns="http://www.w3.org/2000/svg"
42
+ >
43
+ <path
44
+ d="M10.5 3.5L3.5 10.5M3.5 3.5L10.5 10.5"
45
+ stroke="currentColor"
46
+ stroke-width="1.5"
47
+ stroke-linecap="round"
48
+ stroke-linejoin="round"
49
+ />
50
+ </svg>
51
+ </button>
52
+ {/if}
53
+ </span>
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ variant?: 'default' | 'accent';
3
+ dismissible?: boolean;
4
+ ondismiss?: () => void;
5
+ children?: import('svelte').Snippet;
6
+ }
7
+ declare const Tag: import("svelte").Component<Props, {}, "">;
8
+ type Tag = ReturnType<typeof Tag>;
9
+ export default Tag;
@@ -0,0 +1,8 @@
1
+ export { default as Table } from './Table.svelte';
2
+ export { default as Pagination } from './Pagination.svelte';
3
+ export { default as Badge } from './Badge.svelte';
4
+ export { default as Tag } from './Tag.svelte';
5
+ export { default as List } from './List.svelte';
6
+ export { default as Avatar } from './Avatar.svelte';
7
+ export { default as CodeBlock } from './CodeBlock.svelte';
8
+ export { default as Stat } from './Stat.svelte';
@@ -0,0 +1,8 @@
1
+ export { default as Table } from './Table.svelte';
2
+ export { default as Pagination } from './Pagination.svelte';
3
+ export { default as Badge } from './Badge.svelte';
4
+ export { default as Tag } from './Tag.svelte';
5
+ export { default as List } from './List.svelte';
6
+ export { default as Avatar } from './Avatar.svelte';
7
+ export { default as CodeBlock } from './CodeBlock.svelte';
8
+ export { default as Stat } from './Stat.svelte';
@@ -0,0 +1,51 @@
1
+ <script lang="ts">
2
+ import { createId } from '../../lib/internal/id.js';
3
+
4
+ interface Props {
5
+ checked?: boolean;
6
+ disabled?: boolean;
7
+ label?: string;
8
+ id?: string;
9
+ onchange?: (event: Event) => void;
10
+ }
11
+
12
+ let {
13
+ checked = $bindable(false),
14
+ disabled = false,
15
+ label,
16
+ id = createId('checkbox'),
17
+ onchange
18
+ }: Props = $props();
19
+ </script>
20
+
21
+ <label for={id} class="flex items-center gap-2 cursor-pointer {disabled ? 'opacity-50 cursor-not-allowed' : ''}">
22
+ <input
23
+ type="checkbox"
24
+ {id}
25
+ {disabled}
26
+ bind:checked
27
+ onchange={onchange}
28
+ class="w-5 h-5 rounded-sm border-2 border-border-strong bg-transparent appearance-none transition-all duration-200 ease-luxe cursor-pointer checked:bg-accent checked:border-accent checked:accent-glow focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 focus:ring-offset-base-1 relative {disabled ? 'cursor-not-allowed' : ''}"
29
+ />
30
+ {#if label}
31
+ <span class="text-text text-sm select-none">
32
+ {label}
33
+ </span>
34
+ {/if}
35
+ </label>
36
+
37
+ <style>
38
+ input[type="checkbox"]:checked::after {
39
+ content: '';
40
+ position: absolute;
41
+ left: 50%;
42
+ top: 50%;
43
+ transform: translate(-50%, -50%);
44
+ width: 10px;
45
+ height: 10px;
46
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 10 10' fill='none'%3E%3Cpath d='M2 5L4 7L8 3' stroke='white' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
47
+ background-size: contain;
48
+ background-repeat: no-repeat;
49
+ background-position: center;
50
+ }
51
+ </style>
@@ -0,0 +1,10 @@
1
+ interface Props {
2
+ checked?: boolean;
3
+ disabled?: boolean;
4
+ label?: string;
5
+ id?: string;
6
+ onchange?: (event: Event) => void;
7
+ }
8
+ declare const Checkbox: import("svelte").Component<Props, {}, "checked">;
9
+ type Checkbox = ReturnType<typeof Checkbox>;
10
+ export default Checkbox;
@@ -0,0 +1,164 @@
1
+ <script lang="ts">
2
+ import { createId } from '../../lib/internal/id.js';
3
+
4
+ /**
5
+ * FileUpload component props.
6
+ *
7
+ * The `onchange` callback receives an event object with the following shape:
8
+ * `{ target: { files: FileList } }` for both drag-and-drop and click-based selection.
9
+ */
10
+ interface Props {
11
+ files?: FileList | null;
12
+ accept?: string;
13
+ multiple?: boolean;
14
+ disabled?: boolean;
15
+ label?: string;
16
+ id?: string;
17
+ onchange?: (event: { target: { files: FileList } }) => void;
18
+ }
19
+
20
+ let {
21
+ files = $bindable(null),
22
+ accept,
23
+ multiple = false,
24
+ disabled = false,
25
+ label,
26
+ id = createId('file-upload'),
27
+ onchange
28
+ }: Props = $props();
29
+
30
+ let isDragging = $state(false);
31
+ let inputElement: HTMLInputElement;
32
+
33
+ function handleDragOver(event: DragEvent) {
34
+ event.preventDefault();
35
+ if (!disabled) {
36
+ isDragging = true;
37
+ }
38
+ }
39
+
40
+ function handleDragLeave() {
41
+ isDragging = false;
42
+ }
43
+
44
+ function handleDrop(event: DragEvent) {
45
+ event.preventDefault();
46
+ isDragging = false;
47
+
48
+ if (!disabled && event.dataTransfer?.files) {
49
+ files = event.dataTransfer.files;
50
+ if (onchange) {
51
+ // Call onchange directly with synthetic event object
52
+ onchange({ target: { files: event.dataTransfer.files } });
53
+ }
54
+ }
55
+ }
56
+
57
+ function handleClick() {
58
+ if (!disabled) {
59
+ inputElement?.click();
60
+ }
61
+ }
62
+
63
+ function handleInputChange(event: Event) {
64
+ const input = event.target as HTMLInputElement;
65
+ if (onchange && input.files) {
66
+ // Call onchange with consistent event shape
67
+ onchange({ target: { files: input.files } });
68
+ }
69
+ }
70
+
71
+ const fileList = $derived(files ? Array.from(files) : []);
72
+ </script>
73
+
74
+ <div>
75
+ {#if label}
76
+ <div class="text-text-soft text-sm mb-2 block">
77
+ {label}
78
+ </div>
79
+ {/if}
80
+
81
+ <input
82
+ type="file"
83
+ {id}
84
+ {accept}
85
+ {multiple}
86
+ {disabled}
87
+ bind:this={inputElement}
88
+ bind:files
89
+ onchange={handleInputChange}
90
+ class="hidden"
91
+ />
92
+
93
+ <div
94
+ role="button"
95
+ tabindex={disabled ? -1 : 0}
96
+ aria-label="Click or drag files to upload"
97
+ ondragover={handleDragOver}
98
+ ondragleave={handleDragLeave}
99
+ ondrop={handleDrop}
100
+ onclick={handleClick}
101
+ onkeydown={(e) => e.key === 'Enter' && handleClick()}
102
+ class="glass-panel rounded-lg p-8 text-center cursor-pointer transition-all duration-300 ease-luxe {isDragging ? 'border-2 border-accent accent-glow bg-base-2' : ''} {disabled ? 'opacity-50 cursor-not-allowed pointer-events-none' : ''}"
103
+ >
104
+ <div class="flex flex-col items-center gap-2">
105
+ <svg
106
+ xmlns="http://www.w3.org/2000/svg"
107
+ width="48"
108
+ height="48"
109
+ viewBox="0 0 24 24"
110
+ fill="none"
111
+ stroke="currentColor"
112
+ stroke-width="2"
113
+ stroke-linecap="round"
114
+ stroke-linejoin="round"
115
+ class="text-text-soft"
116
+ >
117
+ <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
118
+ <polyline points="17 8 12 3 7 8" />
119
+ <line x1="12" y1="3" x2="12" y2="15" />
120
+ </svg>
121
+
122
+ <div>
123
+ <p class="text-text text-sm font-medium">
124
+ Click to upload or drag and drop
125
+ </p>
126
+ <p class="text-text-muted text-xs mt-1">
127
+ {accept ? `Accepted formats: ${accept}` : 'Any file type'}
128
+ </p>
129
+ </div>
130
+ </div>
131
+ </div>
132
+
133
+ {#if fileList.length > 0}
134
+ <div class="mt-4">
135
+ <p class="text-text-soft text-xs mb-2">
136
+ Selected files:
137
+ </p>
138
+ <ul class="space-y-1">
139
+ {#each fileList as file}
140
+ <li class="text-text text-xs flex items-center gap-2">
141
+ <svg
142
+ xmlns="http://www.w3.org/2000/svg"
143
+ width="12"
144
+ height="12"
145
+ viewBox="0 0 24 24"
146
+ fill="none"
147
+ stroke="currentColor"
148
+ stroke-width="2"
149
+ stroke-linecap="round"
150
+ stroke-linejoin="round"
151
+ >
152
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
153
+ <polyline points="14 2 14 8 20 8" />
154
+ </svg>
155
+ <span>{file.name}</span>
156
+ <span class="text-text-muted">
157
+ ({(file.size / 1024).toFixed(1)} KB)
158
+ </span>
159
+ </li>
160
+ {/each}
161
+ </ul>
162
+ </div>
163
+ {/if}
164
+ </div>
@@ -0,0 +1,22 @@
1
+ /**
2
+ * FileUpload component props.
3
+ *
4
+ * The `onchange` callback receives an event object with the following shape:
5
+ * `{ target: { files: FileList } }` for both drag-and-drop and click-based selection.
6
+ */
7
+ interface Props {
8
+ files?: FileList | null;
9
+ accept?: string;
10
+ multiple?: boolean;
11
+ disabled?: boolean;
12
+ label?: string;
13
+ id?: string;
14
+ onchange?: (event: {
15
+ target: {
16
+ files: FileList;
17
+ };
18
+ }) => void;
19
+ }
20
+ declare const FileUpload: import("svelte").Component<Props, {}, "files">;
21
+ type FileUpload = ReturnType<typeof FileUpload>;
22
+ export default FileUpload;
@@ -0,0 +1,57 @@
1
+ <script lang="ts">
2
+ import { createId } from '../../lib/internal/id.js';
3
+
4
+ interface Props {
5
+ type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url';
6
+ value?: string;
7
+ placeholder?: string;
8
+ disabled?: boolean;
9
+ error?: boolean;
10
+ label?: string;
11
+ id?: string;
12
+ oninput?: (event: Event) => void;
13
+ }
14
+
15
+ let {
16
+ type = 'text',
17
+ value = $bindable(''),
18
+ placeholder,
19
+ disabled = false,
20
+ error = false,
21
+ label,
22
+ id = createId('input'),
23
+ oninput
24
+ }: Props = $props();
25
+
26
+ const baseClasses = 'glass-panel rounded-lg px-4 py-3 font-body text-text placeholder:text-text-muted transition-all duration-300 ease-luxe w-full';
27
+ const focusClasses = 'focus:outline-none focus:border-accent focus:accent-glow';
28
+ const errorClasses = error ? 'border-error' : '';
29
+ const disabledClasses = disabled ? 'opacity-50 cursor-not-allowed' : '';
30
+ </script>
31
+
32
+ {#if label}
33
+ <div>
34
+ <label for={id} class="text-text-soft text-sm mb-2 block">
35
+ {label}
36
+ </label>
37
+ <input
38
+ {type}
39
+ {id}
40
+ {placeholder}
41
+ {disabled}
42
+ bind:value
43
+ oninput={oninput}
44
+ class="{baseClasses} {focusClasses} {errorClasses} {disabledClasses}"
45
+ />
46
+ </div>
47
+ {:else}
48
+ <input
49
+ {type}
50
+ {id}
51
+ {placeholder}
52
+ {disabled}
53
+ bind:value
54
+ oninput={oninput}
55
+ class="{baseClasses} {focusClasses} {errorClasses} {disabledClasses}"
56
+ />
57
+ {/if}
@@ -0,0 +1,13 @@
1
+ interface Props {
2
+ type?: 'text' | 'email' | 'password' | 'number' | 'tel' | 'url';
3
+ value?: string;
4
+ placeholder?: string;
5
+ disabled?: boolean;
6
+ error?: boolean;
7
+ label?: string;
8
+ id?: string;
9
+ oninput?: (event: Event) => void;
10
+ }
11
+ declare const Input: import("svelte").Component<Props, {}, "value">;
12
+ type Input = ReturnType<typeof Input>;
13
+ export default Input;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ // No props needed for standard slot usage
3
+ </script>
4
+
5
+ <div class="flex items-stretch rounded-[var(--radius-lg)] overflow-hidden glass-panel [&>*:not(:first-child)]:ml-[-1px] [&>*:not(:first-child):not(:last-child)]:rounded-none [&>*:first-child]:rounded-r-none [&>*:last-child]:rounded-l-none">
6
+ <slot />
7
+ </div>
@@ -0,0 +1,20 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const InputGroup: $$__sveltets_2_IsomorphicComponent<any, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {
17
+ default: {};
18
+ }, {}, string>;
19
+ type InputGroup = InstanceType<typeof InputGroup>;
20
+ export default InputGroup;
@@ -0,0 +1,87 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ value?: string;
4
+ options: Array<{ value: string; label: string }>;
5
+ name: string;
6
+ disabled?: boolean;
7
+ orientation?: 'vertical' | 'horizontal';
8
+ label?: string;
9
+ onchange?: (event: Event) => void;
10
+ }
11
+
12
+ let {
13
+ value = $bindable(''),
14
+ options,
15
+ name,
16
+ disabled = false,
17
+ orientation = 'vertical',
18
+ label,
19
+ onchange
20
+ }: Props = $props();
21
+
22
+ const containerClasses = $derived(orientation === 'vertical' ? 'flex flex-col gap-3' : 'flex flex-row gap-4');
23
+ </script>
24
+
25
+ {#if label}
26
+ <fieldset class={disabled ? 'opacity-50' : ''}>
27
+ <legend class="text-[var(--color-text-soft)] text-sm mb-3 block">
28
+ {label}
29
+ </legend>
30
+ <div class={containerClasses}>
31
+ {#each options as option}
32
+ {@const radioId = `${name}-${option.value}`}
33
+ <label for={radioId} class="flex items-center gap-2 cursor-pointer {disabled ? 'cursor-not-allowed' : ''}">
34
+ <input
35
+ type="radio"
36
+ id={radioId}
37
+ {name}
38
+ value={option.value}
39
+ {disabled}
40
+ bind:group={value}
41
+ onchange={onchange}
42
+ class="w-5 h-5 rounded-[var(--radius-pill)] border-2 border-[var(--color-border-strong)] bg-transparent appearance-none transition-all duration-200 ease-[var(--ease-luxe)] cursor-pointer checked:border-[var(--color-accent)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent)] focus:ring-offset-2 focus:ring-offset-[var(--color-base-1)] relative {disabled ? 'cursor-not-allowed' : ''}"
43
+ />
44
+ <span class="text-[var(--color-text)] text-sm select-none">
45
+ {option.label}
46
+ </span>
47
+ </label>
48
+ {/each}
49
+ </div>
50
+ </fieldset>
51
+ {:else}
52
+ <div class={containerClasses}>
53
+ {#each options as option}
54
+ {@const radioId = `${name}-${option.value}`}
55
+ <label for={radioId} class="flex items-center gap-2 cursor-pointer {disabled ? 'opacity-50 cursor-not-allowed' : ''}">
56
+ <input
57
+ type="radio"
58
+ id={radioId}
59
+ {name}
60
+ value={option.value}
61
+ {disabled}
62
+ bind:group={value}
63
+ onchange={onchange}
64
+ class="w-5 h-5 rounded-[var(--radius-pill)] border-2 border-[var(--color-border-strong)] bg-transparent appearance-none transition-all duration-200 ease-[var(--ease-luxe)] cursor-pointer checked:border-[var(--color-accent)] focus:outline-none focus:ring-2 focus:ring-[var(--color-accent)] focus:ring-offset-2 focus:ring-offset-[var(--color-base-1)] relative {disabled ? 'cursor-not-allowed' : ''}"
65
+ />
66
+ <span class="text-[var(--color-text)] text-sm select-none">
67
+ {option.label}
68
+ </span>
69
+ </label>
70
+ {/each}
71
+ </div>
72
+ {/if}
73
+
74
+ <style>
75
+ input[type="radio"]:checked::after {
76
+ content: '';
77
+ position: absolute;
78
+ left: 50%;
79
+ top: 50%;
80
+ transform: translate(-50%, -50%);
81
+ width: 0.625rem;
82
+ height: 0.625rem;
83
+ border-radius: var(--radius-pill);
84
+ background: var(--color-accent);
85
+ box-shadow: var(--shadow-accent-glow);
86
+ }
87
+ </style>
@@ -0,0 +1,15 @@
1
+ interface Props {
2
+ value?: string;
3
+ options: Array<{
4
+ value: string;
5
+ label: string;
6
+ }>;
7
+ name: string;
8
+ disabled?: boolean;
9
+ orientation?: 'vertical' | 'horizontal';
10
+ label?: string;
11
+ onchange?: (event: Event) => void;
12
+ }
13
+ declare const RadioGroup: import("svelte").Component<Props, {}, "value">;
14
+ type RadioGroup = ReturnType<typeof RadioGroup>;
15
+ export default RadioGroup;
@@ -0,0 +1,116 @@
1
+ <script lang="ts">
2
+ import { createId } from '../../lib/internal/id.js';
3
+
4
+ interface Props {
5
+ value?: number;
6
+ min?: number;
7
+ max?: number;
8
+ step?: number;
9
+ disabled?: boolean;
10
+ label?: string;
11
+ showValue?: boolean;
12
+ id?: string;
13
+ oninput?: (event: Event) => void;
14
+ }
15
+
16
+ let {
17
+ value = $bindable(0),
18
+ min = 0,
19
+ max = 100,
20
+ step = 1,
21
+ disabled = false,
22
+ label,
23
+ showValue = true,
24
+ id = createId('range'),
25
+ oninput
26
+ }: Props = $props();
27
+
28
+ const percentage = $derived(max === min ? 0 : ((value - min) / (max - min)) * 100);
29
+ </script>
30
+
31
+ <div>
32
+ {#if label || showValue}
33
+ <div class="flex justify-between items-center mb-2">
34
+ {#if label}
35
+ <label for={id} class="text-text-soft text-sm">
36
+ {label}
37
+ </label>
38
+ {/if}
39
+ {#if showValue}
40
+ <span class="text-text-soft text-sm">
41
+ {value}
42
+ </span>
43
+ {/if}
44
+ </div>
45
+ {/if}
46
+ <input
47
+ type="range"
48
+ {id}
49
+ {min}
50
+ {max}
51
+ {step}
52
+ {disabled}
53
+ bind:value
54
+ oninput={oninput}
55
+ aria-valuemin={min}
56
+ aria-valuemax={max}
57
+ aria-valuenow={value}
58
+ class="w-full h-2 rounded-pill appearance-none cursor-pointer transition-opacity duration-200 {disabled ? 'opacity-50 cursor-not-allowed' : ''}"
59
+ style="background: linear-gradient(to right, var(--color-accent) 0%, var(--color-accent) {percentage}%, var(--color-base-3) {percentage}%, var(--color-base-3) 100%); border: 1px solid var(--color-border);"
60
+ />
61
+ </div>
62
+
63
+ <style>
64
+ input[type="range"]::-webkit-slider-thumb {
65
+ appearance: none;
66
+ width: 1.25rem;
67
+ height: 1.25rem;
68
+ border-radius: var(--radius-pill);
69
+ background: var(--color-accent);
70
+ box-shadow: var(--shadow-accent-glow);
71
+ cursor: pointer;
72
+ transition: transform 0.2s var(--ease-luxe);
73
+ }
74
+
75
+ input[type="range"]::-webkit-slider-thumb:hover {
76
+ transform: scale(1.1);
77
+ }
78
+
79
+ input[type="range"]::-moz-range-thumb {
80
+ appearance: none;
81
+ width: 1.25rem;
82
+ height: 1.25rem;
83
+ border-radius: var(--radius-pill);
84
+ background: var(--color-accent);
85
+ box-shadow: var(--shadow-accent-glow);
86
+ cursor: pointer;
87
+ transition: transform 0.2s var(--ease-luxe);
88
+ border: none;
89
+ }
90
+
91
+ input[type="range"]::-moz-range-thumb:hover {
92
+ transform: scale(1.1);
93
+ }
94
+
95
+ input[type="range"]:focus::-webkit-slider-thumb {
96
+ box-shadow:
97
+ var(--shadow-accent-glow),
98
+ 0 0 0 3px var(--color-base-1),
99
+ 0 0 0 5px var(--color-accent);
100
+ }
101
+
102
+ input[type="range"]:focus::-moz-range-thumb {
103
+ box-shadow:
104
+ var(--shadow-accent-glow),
105
+ 0 0 0 3px var(--color-base-1),
106
+ 0 0 0 5px var(--color-accent);
107
+ }
108
+
109
+ input[type="range"]:disabled::-webkit-slider-thumb {
110
+ cursor: not-allowed;
111
+ }
112
+
113
+ input[type="range"]:disabled::-moz-range-thumb {
114
+ cursor: not-allowed;
115
+ }
116
+ </style>
@@ -0,0 +1,14 @@
1
+ interface Props {
2
+ value?: number;
3
+ min?: number;
4
+ max?: number;
5
+ step?: number;
6
+ disabled?: boolean;
7
+ label?: string;
8
+ showValue?: boolean;
9
+ id?: string;
10
+ oninput?: (event: Event) => void;
11
+ }
12
+ declare const RangeSlider: import("svelte").Component<Props, {}, "value">;
13
+ type RangeSlider = ReturnType<typeof RangeSlider>;
14
+ export default RangeSlider;