plasma-svelte 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.
Files changed (95) hide show
  1. package/README.md +65 -0
  2. package/dist/accordion/Accordion.svelte +28 -0
  3. package/dist/accordion/Accordion.svelte.d.ts +8 -0
  4. package/dist/accordion/AccordionItem.svelte +193 -0
  5. package/dist/accordion/AccordionItem.svelte.d.ts +14 -0
  6. package/dist/avatar/Avatar.svelte +178 -0
  7. package/dist/avatar/Avatar.svelte.d.ts +16 -0
  8. package/dist/badge/Badge.svelte +162 -0
  9. package/dist/badge/Badge.svelte.d.ts +16 -0
  10. package/dist/breadcrumb/Breadcrumb.svelte +59 -0
  11. package/dist/breadcrumb/Breadcrumb.svelte.d.ts +9 -0
  12. package/dist/breadcrumb/BreadcrumbItem.svelte +151 -0
  13. package/dist/breadcrumb/BreadcrumbItem.svelte.d.ts +14 -0
  14. package/dist/button/Button.svelte +274 -0
  15. package/dist/button/Button.svelte.d.ts +22 -0
  16. package/dist/button/ButtonGroup.svelte +98 -0
  17. package/dist/button/ButtonGroup.svelte.d.ts +12 -0
  18. package/dist/card/Card.svelte +191 -0
  19. package/dist/card/Card.svelte.d.ts +18 -0
  20. package/dist/checkbox/Checkbox.svelte +199 -0
  21. package/dist/checkbox/Checkbox.svelte.d.ts +12 -0
  22. package/dist/datepicker/DatePicker.svelte +509 -0
  23. package/dist/datepicker/DatePicker.svelte.d.ts +14 -0
  24. package/dist/divider/Divider.svelte +112 -0
  25. package/dist/divider/Divider.svelte.d.ts +13 -0
  26. package/dist/drawer/Drawer.svelte +330 -0
  27. package/dist/drawer/Drawer.svelte.d.ts +21 -0
  28. package/dist/dropzone/DropZone.svelte +282 -0
  29. package/dist/dropzone/DropZone.svelte.d.ts +17 -0
  30. package/dist/emptystate/EmptyState.svelte +169 -0
  31. package/dist/emptystate/EmptyState.svelte.d.ts +15 -0
  32. package/dist/headerbar/HeaderBar.svelte +210 -0
  33. package/dist/headerbar/HeaderBar.svelte.d.ts +17 -0
  34. package/dist/index.d.ts +44 -0
  35. package/dist/index.js +44 -0
  36. package/dist/input/Input.svelte +227 -0
  37. package/dist/input/Input.svelte.d.ts +14 -0
  38. package/dist/layout/Flex.svelte +110 -0
  39. package/dist/layout/Flex.svelte.d.ts +20 -0
  40. package/dist/layout/Grid.svelte +78 -0
  41. package/dist/layout/Grid.svelte.d.ts +19 -0
  42. package/dist/layout/Space.svelte +64 -0
  43. package/dist/layout/Space.svelte.d.ts +16 -0
  44. package/dist/layout/utils.d.ts +2 -0
  45. package/dist/layout/utils.js +19 -0
  46. package/dist/menu/Menu.svelte +156 -0
  47. package/dist/menu/Menu.svelte.d.ts +14 -0
  48. package/dist/menu/MenuDivider.svelte +19 -0
  49. package/dist/menu/MenuDivider.svelte.d.ts +6 -0
  50. package/dist/menu/MenuItem.svelte +126 -0
  51. package/dist/menu/MenuItem.svelte.d.ts +13 -0
  52. package/dist/message/InlineMessage.svelte +226 -0
  53. package/dist/message/InlineMessage.svelte.d.ts +15 -0
  54. package/dist/modal/ConfirmDialog.svelte +151 -0
  55. package/dist/modal/ConfirmDialog.svelte.d.ts +19 -0
  56. package/dist/modal/Modal.svelte +279 -0
  57. package/dist/modal/Modal.svelte.d.ts +18 -0
  58. package/dist/pagination/Pagination.svelte +258 -0
  59. package/dist/pagination/Pagination.svelte.d.ts +16 -0
  60. package/dist/progress/ProgressBar.svelte +179 -0
  61. package/dist/progress/ProgressBar.svelte.d.ts +15 -0
  62. package/dist/radio/Radio.svelte +161 -0
  63. package/dist/radio/Radio.svelte.d.ts +13 -0
  64. package/dist/searchfield/SearchField.svelte +246 -0
  65. package/dist/searchfield/SearchField.svelte.d.ts +15 -0
  66. package/dist/select/Select.svelte +392 -0
  67. package/dist/select/Select.svelte.d.ts +20 -0
  68. package/dist/sidebar/Sidebar.svelte +78 -0
  69. package/dist/sidebar/Sidebar.svelte.d.ts +11 -0
  70. package/dist/sidebar/SidebarGroup.svelte +51 -0
  71. package/dist/sidebar/SidebarGroup.svelte.d.ts +9 -0
  72. package/dist/sidebar/SidebarItem.svelte +185 -0
  73. package/dist/sidebar/SidebarItem.svelte.d.ts +16 -0
  74. package/dist/slider/Slider.svelte +204 -0
  75. package/dist/slider/Slider.svelte.d.ts +16 -0
  76. package/dist/spinbox/SpinBox.svelte +299 -0
  77. package/dist/spinbox/SpinBox.svelte.d.ts +20 -0
  78. package/dist/spinner/Spinner.svelte +130 -0
  79. package/dist/spinner/Spinner.svelte.d.ts +11 -0
  80. package/dist/style/base.css +178 -0
  81. package/dist/style/index.css +2 -0
  82. package/dist/style/token.css +230 -0
  83. package/dist/switch/Switch.svelte +199 -0
  84. package/dist/switch/Switch.svelte.d.ts +13 -0
  85. package/dist/table/Table.svelte +305 -0
  86. package/dist/table/Table.svelte.d.ts +32 -0
  87. package/dist/tabs/Tabs.svelte +216 -0
  88. package/dist/tabs/Tabs.svelte.d.ts +21 -0
  89. package/dist/textarea/TextArea.svelte +114 -0
  90. package/dist/textarea/TextArea.svelte.d.ts +14 -0
  91. package/dist/timepicker/TimePicker.svelte +452 -0
  92. package/dist/timepicker/TimePicker.svelte.d.ts +16 -0
  93. package/dist/tooltip/Tooltip.svelte +122 -0
  94. package/dist/tooltip/Tooltip.svelte.d.ts +12 -0
  95. package/package.json +66 -0
@@ -0,0 +1,258 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+
4
+ type PaginationSize = "sm" | "md" | "lg" | "small" | "medium" | "large";
5
+
6
+ interface Props extends Omit<HTMLAttributes<HTMLElement>, "size" | "onchange"> {
7
+
8
+ current?: number;
9
+ total?: number;
10
+ pageSize?: number;
11
+ showTotal?: boolean;
12
+ showSizeChanger?: boolean;
13
+ pageSizeOptions?: number[];
14
+ size?: PaginationSize;
15
+ disabled?: boolean;
16
+ onchange?: (page: number, pageSize: number) => void;
17
+ }
18
+
19
+ let {
20
+ current = $bindable(1),
21
+ total = 0,
22
+ pageSize = $bindable(10),
23
+ showTotal = true,
24
+ showSizeChanger = false,
25
+ pageSizeOptions = [10, 20, 50, 100],
26
+ size = "md",
27
+ disabled = false,
28
+ onchange,
29
+ class: customClass = "",
30
+ ...restProps
31
+ }: Props = $props();
32
+
33
+ const totalPages = $derived(Math.max(1, Math.ceil(total / pageSize)));
34
+
35
+ const resolvedSize = $derived(
36
+ size === "small"
37
+ ? "sm"
38
+ : size === "large"
39
+ ? "lg"
40
+ : size === "medium"
41
+ ? "md"
42
+ : size
43
+ );
44
+
45
+ // Generate page numbers with ellipses
46
+ const pageItems = $derived.by(() => {
47
+ const pages: (number | string)[] = [];
48
+ if (totalPages <= 7) {
49
+ for (let i = 1; i <= totalPages; i++) pages.push(i);
50
+ } else {
51
+ pages.push(1);
52
+ if (current > 3) pages.push("...");
53
+ const start = Math.max(2, current - 1);
54
+ const end = Math.min(totalPages - 1, current + 1);
55
+ for (let i = start; i <= end; i++) {
56
+ if (!pages.includes(i)) pages.push(i);
57
+ }
58
+ if (current < totalPages - 2) pages.push("...");
59
+ if (!pages.includes(totalPages)) pages.push(totalPages);
60
+ }
61
+ return pages;
62
+ });
63
+
64
+ function setPage(p: number) {
65
+ if (disabled || p < 1 || p > totalPages || p === current) return;
66
+ current = p;
67
+ onchange?.(current, pageSize);
68
+ }
69
+
70
+ function handleSizeChange(e: Event) {
71
+ const select = e.target as HTMLSelectElement;
72
+ pageSize = Number(select.value);
73
+ current = 1;
74
+ onchange?.(current, pageSize);
75
+ }
76
+
77
+ const startItem = $derived(total === 0 ? 0 : (current - 1) * pageSize + 1);
78
+ const endItem = $derived(Math.min(total, current * pageSize));
79
+ </script>
80
+
81
+ <nav
82
+ aria-label="Pagination"
83
+ class="plasma-pagination plasma-pagination--{resolvedSize} {customClass}"
84
+ class:plasma-pagination--disabled={disabled}
85
+ {...restProps}
86
+ >
87
+ {#if showTotal}
88
+ <span class="plasma-pagination-total">
89
+ Showing {startItem}–{endItem} of {total}
90
+ </span>
91
+ {/if}
92
+
93
+ <ul class="plasma-pagination-list">
94
+ <!-- Prev Button -->
95
+ <li>
96
+ <button
97
+ type="button"
98
+ class="plasma-page-btn plasma-page-nav"
99
+ disabled={disabled || current <= 1}
100
+ onclick={() => setPage(current - 1)}
101
+ aria-label="Previous page"
102
+ >
103
+
104
+ </button>
105
+ </li>
106
+
107
+ <!-- Page Numbers -->
108
+ {#each pageItems as item, idx}
109
+ <li>
110
+ {#if item === "..."}
111
+ <span class="plasma-page-ellipsis">…</span>
112
+ {:else}
113
+ <button
114
+ type="button"
115
+ class="plasma-page-btn"
116
+ class:plasma-page-btn--active={current === item}
117
+ {disabled}
118
+ onclick={() => setPage(Number(item))}
119
+ aria-current={current === item ? "page" : undefined}
120
+ >
121
+ {item}
122
+ </button>
123
+ {/if}
124
+ </li>
125
+ {/each}
126
+
127
+ <!-- Next Button -->
128
+ <li>
129
+ <button
130
+ type="button"
131
+ class="plasma-page-btn plasma-page-nav"
132
+ disabled={disabled || current >= totalPages}
133
+ onclick={() => setPage(current + 1)}
134
+ aria-label="Next page"
135
+ >
136
+
137
+ </button>
138
+ </li>
139
+ </ul>
140
+
141
+ {#if showSizeChanger}
142
+ <div class="plasma-pagination-size-changer">
143
+ <select
144
+ value={pageSize}
145
+ onchange={handleSizeChange}
146
+ {disabled}
147
+ class="plasma-page-size-select"
148
+ aria-label="Items per page"
149
+ >
150
+ {#each pageSizeOptions as opt}
151
+ <option value={opt}>{opt} / page</option>
152
+ {/each}
153
+ </select>
154
+ </div>
155
+ {/if}
156
+ </nav>
157
+
158
+ <style>
159
+ .plasma-pagination {
160
+ display: inline-flex;
161
+ align-items: center;
162
+ gap: var(--plasma-space-md);
163
+ font-family: var(--plasma-font-sans);
164
+ color: var(--plasma-color-text);
165
+ user-select: none;
166
+ box-sizing: border-box;
167
+ }
168
+
169
+ .plasma-pagination-total {
170
+ font-size: var(--plasma-font-size-sm);
171
+ color: var(--plasma-color-text-muted);
172
+ }
173
+
174
+ .plasma-pagination-list {
175
+ display: inline-flex;
176
+ align-items: center;
177
+ gap: 4px;
178
+ margin: 0;
179
+ padding: 0;
180
+ list-style: none;
181
+ }
182
+
183
+ .plasma-page-btn {
184
+ display: inline-flex;
185
+ align-items: center;
186
+ justify-content: center;
187
+ min-width: 28px;
188
+ height: 28px;
189
+ padding: 0 6px;
190
+ border: 1px solid var(--plasma-color-border);
191
+ border-radius: var(--plasma-radius-sm);
192
+ background-color: var(--plasma-color-surface);
193
+ color: var(--plasma-color-text);
194
+ font-size: var(--plasma-font-size-sm);
195
+ cursor: pointer;
196
+ transition: var(--plasma-transition-fast);
197
+ }
198
+
199
+ .plasma-page-btn:hover:not(:disabled):not(.plasma-page-btn--active) {
200
+ background-color: var(--plasma-color-surface-hover);
201
+ border-color: var(--plasma-color-border-hover);
202
+ }
203
+
204
+ .plasma-page-btn--active {
205
+ background-color: var(--plasma-color-highlight) !important;
206
+ border-color: var(--plasma-color-highlight) !important;
207
+ color: #ffffff !important;
208
+ font-weight: var(--plasma-font-weight-bold);
209
+ }
210
+
211
+ .plasma-page-btn:disabled {
212
+ opacity: 0.4;
213
+ cursor: not-allowed;
214
+ }
215
+
216
+ .plasma-page-nav {
217
+ font-size: 16px;
218
+ line-height: 1;
219
+ }
220
+
221
+ .plasma-page-ellipsis {
222
+ display: inline-flex;
223
+ align-items: center;
224
+ justify-content: center;
225
+ width: 24px;
226
+ height: 28px;
227
+ color: var(--plasma-color-text-muted);
228
+ }
229
+
230
+ .plasma-page-size-select {
231
+ padding: 2px 6px;
232
+ background-color: var(--plasma-color-surface);
233
+ color: var(--plasma-color-text);
234
+ border: 1px solid var(--plasma-color-border);
235
+ border-radius: var(--plasma-radius-sm);
236
+ font-family: inherit;
237
+ font-size: var(--plasma-font-size-xs);
238
+ cursor: pointer;
239
+ }
240
+
241
+ /* Sizing */
242
+ .plasma-pagination--sm .plasma-page-btn {
243
+ min-width: 22px;
244
+ height: 22px;
245
+ font-size: var(--plasma-font-size-xs);
246
+ }
247
+
248
+ .plasma-pagination--lg .plasma-page-btn {
249
+ min-width: 36px;
250
+ height: 36px;
251
+ font-size: var(--plasma-font-size-md);
252
+ }
253
+
254
+ .plasma-pagination--disabled {
255
+ opacity: 0.5;
256
+ cursor: not-allowed;
257
+ }
258
+ </style>
@@ -0,0 +1,16 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ type PaginationSize = "sm" | "md" | "lg" | "small" | "medium" | "large";
3
+ interface Props extends Omit<HTMLAttributes<HTMLElement>, "size" | "onchange"> {
4
+ current?: number;
5
+ total?: number;
6
+ pageSize?: number;
7
+ showTotal?: boolean;
8
+ showSizeChanger?: boolean;
9
+ pageSizeOptions?: number[];
10
+ size?: PaginationSize;
11
+ disabled?: boolean;
12
+ onchange?: (page: number, pageSize: number) => void;
13
+ }
14
+ declare const Pagination: import("svelte").Component<Props, {}, "current" | "pageSize">;
15
+ type Pagination = ReturnType<typeof Pagination>;
16
+ export default Pagination;
@@ -0,0 +1,179 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from "svelte/elements";
3
+
4
+ type ProgressVariant =
5
+ | "default"
6
+ | "primary"
7
+ | "positive"
8
+ | "neutral"
9
+ | "negative";
10
+
11
+ type ProgressSize = "sm" | "md" | "lg";
12
+
13
+ interface Props extends HTMLAttributes<HTMLDivElement> {
14
+ value?: number;
15
+ max?: number;
16
+ indeterminate?: boolean;
17
+ variant?: ProgressVariant;
18
+ size?: ProgressSize;
19
+ showValue?: boolean;
20
+ label?: string;
21
+ }
22
+
23
+ let {
24
+ value = 0,
25
+ max = 100,
26
+ indeterminate = false,
27
+ variant = "primary",
28
+ size = "md",
29
+ showValue = false,
30
+ label,
31
+ class: customClass = "",
32
+ ...restProps
33
+ }: Props = $props();
34
+
35
+ const percentage = $derived(
36
+ Math.min(100, Math.max(0, (value / max) * 100))
37
+ );
38
+
39
+ const resolvedVariant = $derived(
40
+ variant === "default" ? "primary" : variant
41
+ );
42
+ </script>
43
+
44
+ <div
45
+ class="plasma-progress plasma-progress--{size} {customClass}"
46
+ {...restProps}
47
+ >
48
+ {#if label || showValue}
49
+ <div class="plasma-progress-header">
50
+ {#if label}
51
+ <span class="plasma-progress-label">{label}</span>
52
+ {/if}
53
+ {#if showValue && !indeterminate}
54
+ <span class="plasma-progress-value">{Math.round(percentage)}%</span>
55
+ {/if}
56
+ </div>
57
+ {/if}
58
+
59
+ <div
60
+ role="progressbar"
61
+ aria-valuenow={indeterminate ? undefined : value}
62
+ aria-valuemin={0}
63
+ aria-valuemax={max}
64
+ class="plasma-progress-track"
65
+ class:plasma-progress-track--indeterminate={indeterminate}
66
+ >
67
+ {#if !indeterminate}
68
+ <div
69
+ class="plasma-progress-fill plasma-progress-fill--{resolvedVariant}"
70
+ style="width: {percentage}%;"
71
+ ></div>
72
+ {:else}
73
+ <div
74
+ class="plasma-progress-indeterminate plasma-progress-fill--{resolvedVariant}"
75
+ ></div>
76
+ {/if}
77
+ </div>
78
+ </div>
79
+
80
+ <style>
81
+ .plasma-progress {
82
+ display: flex;
83
+ flex-direction: column;
84
+ gap: var(--plasma-space-xs);
85
+ width: 100%;
86
+ font-family: var(--plasma-font-sans);
87
+ box-sizing: border-box;
88
+ }
89
+
90
+ .plasma-progress-header {
91
+ display: flex;
92
+ justify-content: space-between;
93
+ align-items: center;
94
+ font-size: var(--plasma-font-size-sm);
95
+ }
96
+
97
+ .plasma-progress-label {
98
+ color: var(--plasma-color-text);
99
+ font-weight: var(--plasma-font-weight-medium);
100
+ }
101
+
102
+ .plasma-progress-value {
103
+ font-family: var(--plasma-font-mono);
104
+ font-size: var(--plasma-font-size-xs);
105
+ color: var(--plasma-color-text-muted);
106
+ }
107
+
108
+ /* --------------------------------------------------------------------------
109
+ Track
110
+ -------------------------------------------------------------------------- */
111
+ .plasma-progress-track {
112
+ position: relative;
113
+ width: 100%;
114
+ overflow: hidden;
115
+ background-color: var(--plasma-color-surface-sunken);
116
+ border: 1px solid var(--plasma-color-border-subtle);
117
+ border-radius: var(--plasma-radius-full);
118
+ box-sizing: border-box;
119
+ }
120
+
121
+ /* Sizes */
122
+ .plasma-progress--sm .plasma-progress-track {
123
+ height: 4px;
124
+ }
125
+ .plasma-progress--md .plasma-progress-track {
126
+ height: 6px;
127
+ }
128
+ .plasma-progress--lg .plasma-progress-track {
129
+ height: 10px;
130
+ }
131
+
132
+ /* --------------------------------------------------------------------------
133
+ Fill (Determinate)
134
+ -------------------------------------------------------------------------- */
135
+ .plasma-progress-fill {
136
+ height: 100%;
137
+ border-radius: var(--plasma-radius-full);
138
+ transition: width var(--plasma-duration-base) var(--plasma-ease-default);
139
+ }
140
+
141
+ .plasma-progress-fill--primary {
142
+ background-color: var(--plasma-color-highlight);
143
+ }
144
+ .plasma-progress-fill--positive {
145
+ background-color: var(--plasma-color-positive);
146
+ }
147
+ .plasma-progress-fill--neutral {
148
+ background-color: var(--plasma-color-neutral);
149
+ }
150
+ .plasma-progress-fill--negative {
151
+ background-color: var(--plasma-color-negative);
152
+ }
153
+
154
+ /* --------------------------------------------------------------------------
155
+ Indeterminate (KDE Breeze Shimmer Animation)
156
+ -------------------------------------------------------------------------- */
157
+ .plasma-progress-indeterminate {
158
+ position: absolute;
159
+ top: 0;
160
+ bottom: 0;
161
+ border-radius: var(--plasma-radius-full);
162
+ animation: plasma-progress-shimmer 1.5s infinite ease-in-out;
163
+ }
164
+
165
+ @keyframes plasma-progress-shimmer {
166
+ 0% {
167
+ left: -35%;
168
+ width: 35%;
169
+ }
170
+ 50% {
171
+ left: 30%;
172
+ width: 50%;
173
+ }
174
+ 100% {
175
+ left: 100%;
176
+ width: 35%;
177
+ }
178
+ }
179
+ </style>
@@ -0,0 +1,15 @@
1
+ import type { HTMLAttributes } from "svelte/elements";
2
+ type ProgressVariant = "default" | "primary" | "positive" | "neutral" | "negative";
3
+ type ProgressSize = "sm" | "md" | "lg";
4
+ interface Props extends HTMLAttributes<HTMLDivElement> {
5
+ value?: number;
6
+ max?: number;
7
+ indeterminate?: boolean;
8
+ variant?: ProgressVariant;
9
+ size?: ProgressSize;
10
+ showValue?: boolean;
11
+ label?: string;
12
+ }
13
+ declare const ProgressBar: import("svelte").Component<Props, {}, "">;
14
+ type ProgressBar = ReturnType<typeof ProgressBar>;
15
+ export default ProgressBar;
@@ -0,0 +1,161 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from "svelte";
3
+ import type { HTMLInputAttributes } from "svelte/elements";
4
+
5
+ interface Props extends Omit<HTMLInputAttributes, "size" | "type" | "value"> {
6
+ value?: any;
7
+ group?: any;
8
+ checked?: boolean;
9
+ disabled?: boolean;
10
+ label?: string;
11
+ children?: Snippet;
12
+ }
13
+
14
+ let {
15
+ value,
16
+ group = $bindable(),
17
+ checked = $bindable(false),
18
+ disabled = false,
19
+ label,
20
+ children,
21
+ class: customClass = "",
22
+ id,
23
+ name,
24
+ ...restProps
25
+ }: Props = $props();
26
+
27
+ // If group is provided, derive checked from whether group === value
28
+ const isChecked = $derived(group !== undefined ? group === value : checked);
29
+
30
+ function handleChange() {
31
+ if (disabled) return;
32
+ if (group !== undefined) {
33
+ group = value;
34
+ } else {
35
+ checked = true;
36
+ }
37
+ }
38
+ </script>
39
+
40
+ <!-- biome-ignore lint/a11y/noLabelWithoutControl: id is passed as an attr -->
41
+ <label
42
+ class="plasma-radio-container {customClass}"
43
+ class:plasma-radio--disabled={disabled}
44
+ for={id}
45
+ >
46
+ <input
47
+ {id}
48
+ type="radio"
49
+ {name}
50
+ {value}
51
+ {disabled}
52
+ checked={isChecked}
53
+ onchange={handleChange}
54
+ class="plasma-radio-input"
55
+ {...restProps}
56
+ />
57
+
58
+ <span
59
+ class="plasma-radio-circle"
60
+ class:plasma-radio-circle--checked={isChecked}
61
+ >
62
+ <span class="plasma-radio-dot"></span>
63
+ </span>
64
+
65
+ {#if children}
66
+ <span class="plasma-radio-label">
67
+ {@render children()}
68
+ </span>
69
+ {:else if label}
70
+ <span class="plasma-radio-label">
71
+ {label}
72
+ </span>
73
+ {/if}
74
+ </label>
75
+
76
+ <style>
77
+ .plasma-radio-container {
78
+ display: inline-flex;
79
+ align-items: center;
80
+ gap: var(--plasma-space-sm);
81
+ cursor: pointer;
82
+ font-family: var(--plasma-font-sans);
83
+ font-size: var(--plasma-font-size-base);
84
+ color: var(--plasma-color-text);
85
+ user-select: none;
86
+ line-height: 1.2;
87
+ }
88
+
89
+ .plasma-radio--disabled {
90
+ opacity: 0.45;
91
+ cursor: not-allowed;
92
+ }
93
+
94
+ /* Visually hide native radio */
95
+ .plasma-radio-input {
96
+ position: absolute;
97
+ opacity: 0;
98
+ width: 0;
99
+ height: 0;
100
+ margin: 0;
101
+ pointer-events: none;
102
+ }
103
+
104
+ /* Breeze Radio Circle */
105
+ .plasma-radio-circle {
106
+ position: relative;
107
+ display: inline-flex;
108
+ align-items: center;
109
+ justify-content: center;
110
+ width: 16px;
111
+ height: 16px;
112
+ border-radius: var(--plasma-radius-full);
113
+ border: 1px solid var(--plasma-color-border);
114
+ background-color: var(--plasma-color-view-bg);
115
+ flex-shrink: 0;
116
+ transition: var(--plasma-transition-fast);
117
+ }
118
+
119
+ .plasma-radio-container:hover:not(.plasma-radio--disabled)
120
+ .plasma-radio-circle {
121
+ border-color: var(--plasma-color-border-hover);
122
+ }
123
+
124
+ .plasma-radio-input:focus-visible + .plasma-radio-circle {
125
+ outline: 2px solid var(--plasma-color-highlight);
126
+ outline-offset: 2px;
127
+ box-shadow: var(--plasma-shadow-focus);
128
+ }
129
+
130
+ /* Checked Outer Ring */
131
+ .plasma-radio-circle--checked {
132
+ border-color: var(--plasma-color-highlight);
133
+ }
134
+
135
+ .plasma-radio-container:hover:not(.plasma-radio--disabled)
136
+ .plasma-radio-circle--checked {
137
+ border-color: var(--plasma-color-highlight-hover);
138
+ }
139
+
140
+ /* Inner Dot */
141
+ .plasma-radio-dot {
142
+ width: 8px;
143
+ height: 8px;
144
+ border-radius: var(--plasma-radius-full);
145
+ background-color: var(--plasma-color-highlight);
146
+ transform: scale(0);
147
+ opacity: 0;
148
+ transition:
149
+ transform var(--plasma-duration-fast) var(--plasma-ease-default),
150
+ opacity var(--plasma-duration-fast) var(--plasma-ease-default);
151
+ }
152
+
153
+ .plasma-radio-circle--checked .plasma-radio-dot {
154
+ transform: scale(1);
155
+ opacity: 1;
156
+ }
157
+
158
+ .plasma-radio-label {
159
+ display: inline-block;
160
+ }
161
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from "svelte";
2
+ import type { HTMLInputAttributes } from "svelte/elements";
3
+ interface Props extends Omit<HTMLInputAttributes, "size" | "type" | "value"> {
4
+ value?: any;
5
+ group?: any;
6
+ checked?: boolean;
7
+ disabled?: boolean;
8
+ label?: string;
9
+ children?: Snippet;
10
+ }
11
+ declare const Radio: import("svelte").Component<Props, {}, "group" | "checked">;
12
+ type Radio = ReturnType<typeof Radio>;
13
+ export default Radio;