@lanrenbang/basecoat-ultra-svelte 0.1.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 (88) hide show
  1. package/dist/components/Accordion.svelte +64 -0
  2. package/dist/components/Accordion.svelte.d.ts +14 -0
  3. package/dist/components/Alert.svelte +51 -0
  4. package/dist/components/Alert.svelte.d.ts +12 -0
  5. package/dist/components/Avatar.svelte +57 -0
  6. package/dist/components/Avatar.svelte.d.ts +13 -0
  7. package/dist/components/Badge.svelte +30 -0
  8. package/dist/components/Badge.svelte.d.ts +10 -0
  9. package/dist/components/Breadcrumb.svelte +54 -0
  10. package/dist/components/Breadcrumb.svelte.d.ts +14 -0
  11. package/dist/components/Button.svelte +38 -0
  12. package/dist/components/Button.svelte.d.ts +12 -0
  13. package/dist/components/ButtonGroup.svelte +26 -0
  14. package/dist/components/ButtonGroup.svelte.d.ts +10 -0
  15. package/dist/components/Card.svelte +67 -0
  16. package/dist/components/Card.svelte.d.ts +13 -0
  17. package/dist/components/Carousel.svelte +142 -0
  18. package/dist/components/Carousel.svelte.d.ts +11 -0
  19. package/dist/components/CatppuccinThemeSwitcher.svelte +132 -0
  20. package/dist/components/CatppuccinThemeSwitcher.svelte.d.ts +3 -0
  21. package/dist/components/Checkbox.svelte +20 -0
  22. package/dist/components/Checkbox.svelte.d.ts +8 -0
  23. package/dist/components/Collapsible.svelte +39 -0
  24. package/dist/components/Collapsible.svelte.d.ts +13 -0
  25. package/dist/components/Command.svelte +78 -0
  26. package/dist/components/Command.svelte.d.ts +12 -0
  27. package/dist/components/DatePicker.svelte +172 -0
  28. package/dist/components/DatePicker.svelte.d.ts +13 -0
  29. package/dist/components/Dialog.svelte +91 -0
  30. package/dist/components/Dialog.svelte.d.ts +14 -0
  31. package/dist/components/Drawer.svelte +127 -0
  32. package/dist/components/Drawer.svelte.d.ts +12 -0
  33. package/dist/components/DropdownMenu.svelte +62 -0
  34. package/dist/components/DropdownMenu.svelte.d.ts +14 -0
  35. package/dist/components/Empty.svelte +58 -0
  36. package/dist/components/Empty.svelte.d.ts +12 -0
  37. package/dist/components/Input.svelte +22 -0
  38. package/dist/components/Input.svelte.d.ts +9 -0
  39. package/dist/components/InputOTP.svelte +189 -0
  40. package/dist/components/InputOTP.svelte.d.ts +12 -0
  41. package/dist/components/Item.svelte +64 -0
  42. package/dist/components/Item.svelte.d.ts +14 -0
  43. package/dist/components/Kbd.svelte +28 -0
  44. package/dist/components/Kbd.svelte.d.ts +9 -0
  45. package/dist/components/Label.svelte +30 -0
  46. package/dist/components/Label.svelte.d.ts +10 -0
  47. package/dist/components/Pagination.svelte +120 -0
  48. package/dist/components/Pagination.svelte.d.ts +35 -0
  49. package/dist/components/Popover.svelte +68 -0
  50. package/dist/components/Popover.svelte.d.ts +16 -0
  51. package/dist/components/Progress.svelte +26 -0
  52. package/dist/components/Progress.svelte.d.ts +9 -0
  53. package/dist/components/Radio.svelte +22 -0
  54. package/dist/components/Radio.svelte.d.ts +9 -0
  55. package/dist/components/Resizable.svelte +66 -0
  56. package/dist/components/Resizable.svelte.d.ts +13 -0
  57. package/dist/components/Select.svelte +183 -0
  58. package/dist/components/Select.svelte.d.ts +16 -0
  59. package/dist/components/Separator.svelte +19 -0
  60. package/dist/components/Separator.svelte.d.ts +8 -0
  61. package/dist/components/Sheet.svelte +182 -0
  62. package/dist/components/Sheet.svelte.d.ts +13 -0
  63. package/dist/components/Skeleton.svelte +27 -0
  64. package/dist/components/Skeleton.svelte.d.ts +8 -0
  65. package/dist/components/Slider.svelte +38 -0
  66. package/dist/components/Slider.svelte.d.ts +11 -0
  67. package/dist/components/Spinner.svelte +28 -0
  68. package/dist/components/Spinner.svelte.d.ts +8 -0
  69. package/dist/components/Switch.svelte +20 -0
  70. package/dist/components/Switch.svelte.d.ts +8 -0
  71. package/dist/components/Table.svelte +61 -0
  72. package/dist/components/Table.svelte.d.ts +13 -0
  73. package/dist/components/Tabs.svelte +97 -0
  74. package/dist/components/Tabs.svelte.d.ts +15 -0
  75. package/dist/components/Textarea.svelte +22 -0
  76. package/dist/components/Textarea.svelte.d.ts +9 -0
  77. package/dist/components/Toast.svelte +73 -0
  78. package/dist/components/Toast.svelte.d.ts +3 -0
  79. package/dist/components/Toggle.svelte +69 -0
  80. package/dist/components/Toggle.svelte.d.ts +13 -0
  81. package/dist/components/ToggleGroup.svelte +69 -0
  82. package/dist/components/ToggleGroup.svelte.d.ts +12 -0
  83. package/dist/components/Tooltip.svelte +32 -0
  84. package/dist/components/Tooltip.svelte.d.ts +11 -0
  85. package/dist/index.d.ts +42 -0
  86. package/dist/index.js +47 -0
  87. package/dist/reference.css +2 -0
  88. package/package.json +70 -0
@@ -0,0 +1,132 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+
4
+ const THEMES = ['latte', 'frappe', 'macchiato', 'mocha'];
5
+ const DARK_THEMES = ['frappe', 'macchiato', 'mocha'];
6
+ const ACCENTS = [
7
+ 'rosewater', 'flamingo', 'pink', 'mauve', 'red', 'maroon', 'peach',
8
+ 'yellow', 'green', 'teal', 'sky', 'sapphire', 'blue', 'lavender'
9
+ ];
10
+
11
+ let currentFlavor = $state('mocha'); // UI 预览用的口味
12
+ let appliedFlavor = $state(''); // 实际应用的口味
13
+ let appliedAccent = $state(''); // 实际应用的强调色
14
+
15
+ function setTheme(theme: string, accent: string) {
16
+ const root = document.documentElement;
17
+
18
+ // 1. 彻底清除旧的主题类名
19
+ THEMES.forEach(t => root.classList.remove(`theme-${t}`));
20
+ ACCENTS.forEach(a => root.classList.remove(`accent-${a}`));
21
+
22
+ // 2. 应用新的主题与强调色类名
23
+ root.classList.add(`theme-${theme}`);
24
+ root.classList.add(`accent-${accent}`);
25
+
26
+ // 3. 同步亮/暗模式 (Basecoat 变量依赖 .dark)
27
+ if (DARK_THEMES.includes(theme)) {
28
+ root.classList.add('dark');
29
+ } else {
30
+ root.classList.remove('dark');
31
+ }
32
+
33
+ appliedFlavor = theme;
34
+ appliedAccent = accent;
35
+
36
+ try {
37
+ localStorage.setItem('catppuccin-theme', theme);
38
+ localStorage.setItem('catppuccin-accent', accent);
39
+ localStorage.removeItem('basecoat-mode');
40
+ } catch (e) {}
41
+ }
42
+
43
+ function resetTheme() {
44
+ const root = document.documentElement;
45
+ const wasDark = root.classList.contains('dark');
46
+
47
+ THEMES.forEach(t => root.classList.remove(`theme-${t}`));
48
+ ACCENTS.forEach(a => root.classList.remove(`accent-${a}`));
49
+
50
+ localStorage.removeItem('catppuccin-theme');
51
+ localStorage.removeItem('catppuccin-accent');
52
+ localStorage.setItem('basecoat-mode', wasDark ? 'dark' : 'light');
53
+
54
+ // 恢复到系统/手动模式默认
55
+ if (wasDark) {
56
+ root.classList.add('dark');
57
+ currentFlavor = 'mocha';
58
+ } else {
59
+ root.classList.remove('dark');
60
+ currentFlavor = 'latte';
61
+ }
62
+ appliedFlavor = '';
63
+ appliedAccent = '';
64
+ }
65
+
66
+ onMount(() => {
67
+ const savedTheme = localStorage.getItem('catppuccin-theme');
68
+ const savedAccent = localStorage.getItem('catppuccin-accent');
69
+ if (savedTheme && savedAccent) {
70
+ currentFlavor = savedTheme;
71
+ appliedFlavor = savedTheme;
72
+ appliedAccent = savedAccent;
73
+ // 确保初始化时类名也同步
74
+ setTheme(savedTheme, savedAccent);
75
+ } else {
76
+ const isDark = document.documentElement.classList.contains('dark');
77
+ currentFlavor = isDark ? 'mocha' : 'latte';
78
+ }
79
+ });
80
+
81
+ // 预览色计算
82
+ const previewColors = $derived.by(() => {
83
+ const colors: Record<string, string> = { background: `var(--ctp-${currentFlavor}-base)` };
84
+ ACCENTS.forEach(accent => {
85
+ colors[accent] = `var(--ctp-${currentFlavor}-${accent})`;
86
+ });
87
+ return colors;
88
+ });
89
+ </script>
90
+
91
+ <div class="catppuccin-theme-switcher w-full max-w-sm space-y-6">
92
+ <!-- Flavors: 仅更新预览状态 -->
93
+ <div class="button-group w-full" data-orientation="horizontal">
94
+ {#each THEMES as theme}
95
+ <button
96
+ type="button"
97
+ class={['btn btn-sm capitalize flex-1', currentFlavor === theme ? 'btn-primary' : 'btn-ghost'].join(' ')}
98
+ onclick={() => currentFlavor = theme}
99
+ >
100
+ {theme}
101
+ </button>
102
+ {/each}
103
+ </div>
104
+
105
+ <!-- Accents: 点击应用主题 -->
106
+ <div
107
+ class="grid grid-cols-7 gap-3 place-items-center p-4 rounded-xl border border-border/50 transition-colors duration-300 shadow-inner"
108
+ style:background-color={previewColors.background}
109
+ >
110
+ {#each ACCENTS as accent}
111
+ <button
112
+ type="button"
113
+ class={['size-6 rounded-full border border-white/20 shadow-sm transition-transform hover:scale-110 focus:outline-none focus:ring-2 focus:ring-ring relative flex items-center justify-center',
114
+ appliedAccent === accent && appliedFlavor === currentFlavor ? 'ring-2 ring-white ring-offset-2 scale-110' : ''
115
+ ].join(' ')}
116
+ title={accent}
117
+ style:background-color={previewColors[accent]}
118
+ onclick={() => setTheme(currentFlavor, accent)}
119
+ >
120
+ {#if appliedAccent === accent && appliedFlavor === currentFlavor}
121
+ <svg class="text-white drop-shadow-sm" style="width: 12px; height: 12px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
122
+ {/if}
123
+ </button>
124
+ {/each}
125
+ </div>
126
+
127
+ <div class="flex justify-center">
128
+ <button type="button" class="theme-reset btn btn-sm btn-ghost text-muted-foreground hover:text-destructive w-full" onclick={resetTheme}>
129
+ Reset Theme
130
+ </button>
131
+ </div>
132
+ </div>
@@ -0,0 +1,3 @@
1
+ declare const CatppuccinThemeSwitcher: import("svelte").Component<Record<string, never>, {}, "">;
2
+ type CatppuccinThemeSwitcher = ReturnType<typeof CatppuccinThemeSwitcher>;
3
+ export default CatppuccinThemeSwitcher;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ let {
3
+ checked = $bindable(false),
4
+ class: className = '',
5
+ ...rest
6
+ }: {
7
+ checked?: boolean;
8
+ class?: string;
9
+ [key: string]: any;
10
+ } = $props();
11
+
12
+ const finalClass = $derived(['input', className].filter(Boolean).join(' '));
13
+ </script>
14
+
15
+ <input type="checkbox" class={finalClass} bind:checked {...rest} />
16
+
17
+ <style>
18
+ @import "../../../../ultra/src/css/parts/components/checkbox.css";
19
+ @reference "../reference.css";
20
+ </style>
@@ -0,0 +1,8 @@
1
+ type $$ComponentProps = {
2
+ checked?: boolean;
3
+ class?: string;
4
+ [key: string]: any;
5
+ };
6
+ declare const Checkbox: import("svelte").Component<$$ComponentProps, {}, "checked">;
7
+ type Checkbox = ReturnType<typeof Checkbox>;
8
+ export default Checkbox;
@@ -0,0 +1,39 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ let {
5
+ open = $bindable(false),
6
+ trigger,
7
+ children,
8
+ class: className = '',
9
+ ...rest
10
+ }: {
11
+ open?: boolean;
12
+ trigger: Snippet<{ open: boolean }>;
13
+ children: Snippet;
14
+ class?: string;
15
+ [key: string]: any;
16
+ } = $props();
17
+ </script>
18
+
19
+ <div class={['collapsible', className].filter(Boolean).join(' ')} {...rest}>
20
+ <div
21
+ role="button"
22
+ tabindex="0"
23
+ onclick={() => open = !open}
24
+ onkeydown={(e) => e.key === 'Enter' && (open = !open)}
25
+ >
26
+ {@render trigger({ open })}
27
+ </div>
28
+
29
+ {#if open}
30
+ <div class="collapsible-content">
31
+ {@render children()}
32
+ </div>
33
+ {/if}
34
+ </div>
35
+
36
+ <style>
37
+ @import "../../../../ultra/src/css/parts/components/collapsible.css";
38
+ @reference "../reference.css";
39
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ open?: boolean;
4
+ trigger: Snippet<{
5
+ open: boolean;
6
+ }>;
7
+ children: Snippet;
8
+ class?: string;
9
+ [key: string]: any;
10
+ };
11
+ declare const Collapsible: import("svelte").Component<$$ComponentProps, {}, "open">;
12
+ type Collapsible = ReturnType<typeof Collapsible>;
13
+ export default Collapsible;
@@ -0,0 +1,78 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ let {
5
+ value = $bindable(''),
6
+ placeholder = 'Type a command or search...',
7
+ children,
8
+ class: className = '',
9
+ onselect,
10
+ ...rest
11
+ }: {
12
+ value?: string;
13
+ placeholder?: string;
14
+ children?: Snippet;
15
+ class?: string;
16
+ onselect?: (value: string) => void;
17
+ [key: string]: any;
18
+ } = $props();
19
+
20
+ let container: HTMLDivElement;
21
+ let activeIndex = $state(-1);
22
+
23
+ function handleKeyDown(event: KeyboardEvent) {
24
+ const items = container?.querySelectorAll('[role="menuitem"]:not([aria-disabled="true"])') as NodeListOf<HTMLElement>;
25
+ if (!items.length) return;
26
+
27
+ switch (event.key) {
28
+ case 'ArrowDown':
29
+ event.preventDefault();
30
+ activeIndex = (activeIndex + 1) % items.length;
31
+ items[activeIndex]?.focus();
32
+ break;
33
+ case 'ArrowUp':
34
+ event.preventDefault();
35
+ activeIndex = (activeIndex - 1 + items.length) % items.length;
36
+ items[activeIndex]?.focus();
37
+ break;
38
+ case 'Enter':
39
+ if (activeIndex >= 0) {
40
+ event.preventDefault();
41
+ items[activeIndex]?.click();
42
+ }
43
+ break;
44
+ }
45
+ }
46
+ </script>
47
+
48
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
49
+ <div
50
+ bind:this={container}
51
+ class={['command bg-background flex flex-col overflow-hidden', className].filter(Boolean).join(' ')}
52
+ onkeydown={handleKeyDown}
53
+ {...rest}
54
+ >
55
+ <header class="flex items-center border-b px-3">
56
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="opacity-50 mr-2 shrink-0"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
57
+ <input
58
+ type="text"
59
+ bind:value
60
+ {placeholder}
61
+ class="flex h-10 w-full bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 border-none focus:ring-0"
62
+ onkeydown={(e) => {
63
+ if (e.key === 'ArrowDown') {
64
+ handleKeyDown(e);
65
+ }
66
+ }}
67
+ />
68
+ </header>
69
+
70
+ <div role="menu" class="max-h-40 overflow-y-auto overflow-x-hidden p-1 scrollbar">
71
+ {@render children?.()}
72
+ </div>
73
+ </div>
74
+
75
+ <style>
76
+ @import "../../../../ultra/src/css/parts/components/command.css";
77
+ @reference "../reference.css";
78
+ </style>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ value?: string;
4
+ placeholder?: string;
5
+ children?: Snippet;
6
+ class?: string;
7
+ onselect?: (value: string) => void;
8
+ [key: string]: any;
9
+ };
10
+ declare const Command: import("svelte").Component<$$ComponentProps, {}, "value">;
11
+ type Command = ReturnType<typeof Command>;
12
+ export default Command;
@@ -0,0 +1,172 @@
1
+ <script lang="ts">
2
+ import { onMount, onDestroy } from 'svelte';
3
+ import flatpickr from 'flatpickr';
4
+ import { Mandarin } from 'flatpickr/dist/l10n/zh.js';
5
+ import { MandarinTraditional } from 'flatpickr/dist/l10n/zh-tw.js';
6
+ import type { Instance } from 'flatpickr/dist/types/instance';
7
+ import type { Options } from 'flatpickr/dist/types/options';
8
+
9
+ // Custom English configurations
10
+ const EnglishFull = {
11
+ weekdays: {
12
+ shorthand: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
13
+ longhand: [
14
+ "Sunday",
15
+ "Monday",
16
+ "Tuesday",
17
+ "Wednesday",
18
+ "Thursday",
19
+ "Friday",
20
+ "Saturday",
21
+ ],
22
+ },
23
+ months: {
24
+ shorthand: [
25
+ "January",
26
+ "February",
27
+ "March",
28
+ "April",
29
+ "May",
30
+ "June",
31
+ "July",
32
+ "August",
33
+ "September",
34
+ "October",
35
+ "November",
36
+ "December",
37
+ ],
38
+ longhand: [
39
+ "January",
40
+ "February",
41
+ "March",
42
+ "April",
43
+ "May",
44
+ "June",
45
+ "July",
46
+ "August",
47
+ "September",
48
+ "October",
49
+ "November",
50
+ "December",
51
+ ],
52
+ },
53
+ };
54
+
55
+ const EnglishShort = {
56
+ weekdays: {
57
+ shorthand: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
58
+ longhand: [
59
+ "Sunday",
60
+ "Monday",
61
+ "Tuesday",
62
+ "Wednesday",
63
+ "Thursday",
64
+ "Friday",
65
+ "Saturday",
66
+ ],
67
+ },
68
+ months: {
69
+ shorthand: [
70
+ "Jan",
71
+ "Feb",
72
+ "Mar",
73
+ "Apr",
74
+ "May",
75
+ "Jun",
76
+ "Jul",
77
+ "Aug",
78
+ "Sep",
79
+ "Oct",
80
+ "Nov",
81
+ "Dec",
82
+ ],
83
+ longhand: [
84
+ "Jan",
85
+ "Feb",
86
+ "Mar",
87
+ "Apr",
88
+ "May",
89
+ "Jun",
90
+ "Jul",
91
+ "Aug",
92
+ "Sep",
93
+ "Oct",
94
+ "Nov",
95
+ "Dec",
96
+ ],
97
+ },
98
+ };
99
+
100
+ // Locale configurations
101
+ const locales = {
102
+ 'zh': Mandarin,
103
+ 'zh-tw': MandarinTraditional,
104
+ 'en-full': EnglishFull,
105
+ 'en-short': EnglishShort,
106
+ };
107
+
108
+ let {
109
+ value = $bindable(''),
110
+ options = {},
111
+ placeholder = 'Select date',
112
+ inline = false,
113
+ locale = 'en-short',
114
+ class: className = '',
115
+ ...rest
116
+ }: {
117
+ value?: string | Date | Date[];
118
+ options?: Options;
119
+ placeholder?: string;
120
+ inline?: boolean;
121
+ locale?: string;
122
+ class?: string;
123
+ [key: string]: any;
124
+ } = $props();
125
+
126
+ let element: HTMLElement | undefined = $state();
127
+ let instance: Instance;
128
+
129
+ const finalClass = $derived(
130
+ inline
131
+ ? ['datepicker', className].filter(Boolean).join(' ')
132
+ : ['input datepicker', className].filter(Boolean).join(' ')
133
+ );
134
+
135
+ onMount(() => {
136
+ if (element) {
137
+ // Get locale configuration
138
+ const localeConfig = locales[locale] || EnglishShort;
139
+
140
+ instance = flatpickr(element, {
141
+ ...options,
142
+ inline,
143
+ defaultDate: value,
144
+ locale: localeConfig,
145
+ shorthandCurrentMonth: locale === "en-short", // Only use shorthand for English abbreviated
146
+ onChange: (selectedDates, dateStr) => {
147
+ value = dateStr;
148
+ }
149
+ });
150
+ }
151
+ });
152
+
153
+ onDestroy(() => {
154
+ instance?.destroy();
155
+ });
156
+ </script>
157
+
158
+ {#if inline}
159
+ <div bind:this={element} class={finalClass} {...rest}></div>
160
+ {:else}
161
+ <input
162
+ bind:this={element}
163
+ type="text"
164
+ class={finalClass}
165
+ {placeholder}
166
+ {...rest}
167
+ />
168
+ {/if}
169
+
170
+ <style>
171
+ @reference "../reference.css";
172
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Options } from 'flatpickr/dist/types/options';
2
+ type $$ComponentProps = {
3
+ value?: string | Date | Date[];
4
+ options?: Options;
5
+ placeholder?: string;
6
+ inline?: boolean;
7
+ locale?: string;
8
+ class?: string;
9
+ [key: string]: any;
10
+ };
11
+ declare const DatePicker: import("svelte").Component<$$ComponentProps, {}, "value">;
12
+ type DatePicker = ReturnType<typeof DatePicker>;
13
+ export default DatePicker;
@@ -0,0 +1,91 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { onMount } from 'svelte';
4
+
5
+ let {
6
+ open = $bindable(false),
7
+ title,
8
+ description,
9
+ children,
10
+ footer,
11
+ role = 'dialog',
12
+ class: className = '',
13
+ ...rest
14
+ }: {
15
+ open?: boolean;
16
+ title?: string | Snippet;
17
+ description?: string | Snippet;
18
+ children: Snippet;
19
+ footer?: Snippet;
20
+ role?: 'dialog' | 'alertdialog';
21
+ class?: string;
22
+ [key: string]: any;
23
+ } = $props();
24
+
25
+ let dialogElement: HTMLDialogElement;
26
+
27
+ $effect(() => {
28
+ if (open) {
29
+ dialogElement?.showModal();
30
+ } else {
31
+ dialogElement?.close();
32
+ }
33
+ });
34
+
35
+ const handleClose = () => {
36
+ open = false;
37
+ };
38
+ </script>
39
+
40
+ <!-- svelte-ignore a11y_click_events_have_key_events -->
41
+ <!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
42
+ <dialog
43
+ bind:this={dialogElement}
44
+ class={['dialog', className].filter(Boolean).join(' ')}
45
+ {role}
46
+ onclose={handleClose}
47
+ onclick={(e) => {
48
+ // Only close on backdrop click for regular dialog, not alertdialog
49
+ if (role !== 'alertdialog' && e.target === dialogElement) {
50
+ handleClose();
51
+ }
52
+ }}
53
+ {...rest}
54
+ >
55
+ <!-- Only show close button for regular dialogs, not alert dialogs -->
56
+ {#if role !== 'alertdialog'}
57
+ <button class="close" aria-label="Close" onclick={handleClose}>
58
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
59
+ </button>
60
+ {/if}
61
+
62
+ {#if title || description}
63
+ <header>
64
+ {#if title}
65
+ <h2>
66
+ {#if typeof title === 'string'}{title}{:else}{@render title()}{/if}
67
+ </h2>
68
+ {/if}
69
+ {#if description}
70
+ <p>
71
+ {#if typeof description === 'string'}{description}{:else}{@render description()}{/if}
72
+ </p>
73
+ {/if}
74
+ </header>
75
+ {/if}
76
+
77
+ <section>
78
+ {@render children()}
79
+ </section>
80
+
81
+ {#if footer}
82
+ <footer>
83
+ {@render footer()}
84
+ </footer>
85
+ {/if}
86
+ </dialog>
87
+
88
+ <style>
89
+ @import "../../../../ultra/src/css/parts/components/dialog.css";
90
+ @reference "../reference.css";
91
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ type $$ComponentProps = {
3
+ open?: boolean;
4
+ title?: string | Snippet;
5
+ description?: string | Snippet;
6
+ children: Snippet;
7
+ footer?: Snippet;
8
+ role?: 'dialog' | 'alertdialog';
9
+ class?: string;
10
+ [key: string]: any;
11
+ };
12
+ declare const Dialog: import("svelte").Component<$$ComponentProps, {}, "open">;
13
+ type Dialog = ReturnType<typeof Dialog>;
14
+ export default Dialog;