svelte-comp 1.3.3 → 1.3.6

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 (138) hide show
  1. package/LICENSE.md +21 -21
  2. package/README.md +101 -100
  3. package/dist/App.svelte +507 -507
  4. package/dist/Container.svelte +59 -59
  5. package/dist/app.css +234 -235
  6. package/dist/app.d.ts +10 -0
  7. package/dist/lib/Accordion.svelte +155 -155
  8. package/dist/lib/Badge.svelte +44 -44
  9. package/dist/lib/Button.svelte +185 -170
  10. package/dist/lib/Calendar.svelte +384 -384
  11. package/dist/lib/Card.svelte +103 -103
  12. package/dist/lib/Carousel.svelte +293 -293
  13. package/dist/lib/Carousel.svelte.d.ts +1 -1
  14. package/dist/lib/CheckBox.svelte +210 -210
  15. package/dist/lib/CodeView.svelte +308 -307
  16. package/dist/lib/ColorPicker.svelte +159 -159
  17. package/dist/lib/ContextMenu.svelte +328 -322
  18. package/dist/lib/DatePicker.svelte +246 -246
  19. package/dist/lib/Dialog.svelte +233 -233
  20. package/dist/lib/Field.svelte +299 -299
  21. package/dist/lib/FilePicker.svelte +295 -240
  22. package/dist/lib/FilePicker.svelte.d.ts +6 -1
  23. package/dist/lib/Form.svelte +438 -438
  24. package/dist/lib/Hamburger.svelte +217 -217
  25. package/dist/lib/InstallPWA.svelte +94 -94
  26. package/dist/lib/Menu.svelte +623 -623
  27. package/dist/lib/NoticeBase.svelte +140 -140
  28. package/dist/lib/PaginatedCard.svelte +73 -73
  29. package/dist/lib/Pagination.svelte +119 -119
  30. package/dist/lib/PrimaryColorSelect.svelte +111 -111
  31. package/dist/lib/ProgressBar.svelte +141 -141
  32. package/dist/lib/ProgressCircle.svelte +190 -190
  33. package/dist/lib/Radio.svelte +189 -189
  34. package/dist/lib/SearchInput.svelte +104 -104
  35. package/dist/lib/Select.svelte +524 -524
  36. package/dist/lib/Slider.svelte +253 -253
  37. package/dist/lib/Splitter.svelte +159 -150
  38. package/dist/lib/Switch.svelte +168 -167
  39. package/dist/lib/Table.svelte +299 -299
  40. package/dist/lib/Tabs.svelte +213 -213
  41. package/dist/lib/ThemeToggle.svelte +128 -127
  42. package/dist/lib/TimePicker.svelte +312 -312
  43. package/dist/lib/TimePickerNew.svelte +634 -0
  44. package/dist/lib/TimePickerNew.svelte.d.ts +49 -0
  45. package/dist/lib/Toast.svelte +123 -123
  46. package/dist/lib/Tooltip.svelte +110 -110
  47. package/dist/lib/Topbar.svelte +107 -107
  48. package/dist/lib/__tests__/Accordion.test.d.ts +1 -0
  49. package/dist/lib/__tests__/Accordion.test.js +171 -0
  50. package/dist/lib/__tests__/Badge.test.d.ts +1 -0
  51. package/dist/lib/__tests__/Badge.test.js +41 -0
  52. package/dist/lib/__tests__/Button.test.d.ts +1 -0
  53. package/dist/lib/__tests__/Button.test.js +269 -0
  54. package/dist/lib/__tests__/Calendar.test.d.ts +1 -0
  55. package/dist/lib/__tests__/Calendar.test.js +171 -0
  56. package/dist/lib/__tests__/Card.test.d.ts +1 -0
  57. package/dist/lib/__tests__/Card.test.js +148 -0
  58. package/dist/lib/__tests__/Carousel.test.d.ts +1 -0
  59. package/dist/lib/__tests__/Carousel.test.js +439 -0
  60. package/dist/lib/__tests__/CheckBox.test.d.ts +1 -0
  61. package/dist/lib/__tests__/CheckBox.test.js +152 -0
  62. package/dist/lib/__tests__/CodeView.test.d.ts +1 -0
  63. package/dist/lib/__tests__/CodeView.test.js +157 -0
  64. package/dist/lib/__tests__/ColorPicker.test.d.ts +1 -0
  65. package/dist/lib/__tests__/ColorPicker.test.js +93 -0
  66. package/dist/lib/__tests__/ContextMenu.test.d.ts +1 -0
  67. package/dist/lib/__tests__/ContextMenu.test.js +67 -0
  68. package/dist/lib/__tests__/DatePicker.test.d.ts +1 -0
  69. package/dist/lib/__tests__/DatePicker.test.js +108 -0
  70. package/dist/lib/__tests__/Dialog.test.d.ts +1 -0
  71. package/dist/lib/__tests__/Dialog.test.js +183 -0
  72. package/dist/lib/__tests__/Field.test.d.ts +1 -0
  73. package/dist/lib/__tests__/Field.test.js +190 -0
  74. package/dist/lib/__tests__/FilePicker.test.d.ts +1 -0
  75. package/dist/lib/__tests__/FilePicker.test.js +179 -0
  76. package/dist/lib/__tests__/Form.integration.test.d.ts +1 -0
  77. package/dist/lib/__tests__/Form.integration.test.js +158 -0
  78. package/dist/lib/__tests__/Form.test.d.ts +1 -0
  79. package/dist/lib/__tests__/Form.test.js +463 -0
  80. package/dist/lib/__tests__/Hamburger.test.d.ts +1 -0
  81. package/dist/lib/__tests__/Hamburger.test.js +161 -0
  82. package/dist/lib/__tests__/InstallPWA.test.d.ts +1 -0
  83. package/dist/lib/__tests__/InstallPWA.test.js +15 -0
  84. package/dist/lib/__tests__/Menu.test.d.ts +1 -0
  85. package/dist/lib/__tests__/Menu.test.js +285 -0
  86. package/dist/lib/__tests__/NoticeBase.test.d.ts +1 -0
  87. package/dist/lib/__tests__/NoticeBase.test.js +60 -0
  88. package/dist/lib/__tests__/PaginatedCard.test.d.ts +1 -0
  89. package/dist/lib/__tests__/PaginatedCard.test.js +89 -0
  90. package/dist/lib/__tests__/Pagination.test.d.ts +1 -0
  91. package/dist/lib/__tests__/Pagination.test.js +168 -0
  92. package/dist/lib/__tests__/PrimaryColorSelect.test.d.ts +1 -0
  93. package/dist/lib/__tests__/PrimaryColorSelect.test.js +92 -0
  94. package/dist/lib/__tests__/ProgressBar.test.d.ts +1 -0
  95. package/dist/lib/__tests__/ProgressBar.test.js +69 -0
  96. package/dist/lib/__tests__/ProgressCircle.test.d.ts +1 -0
  97. package/dist/lib/__tests__/ProgressCircle.test.js +71 -0
  98. package/dist/lib/__tests__/Radio.test.d.ts +1 -0
  99. package/dist/lib/__tests__/Radio.test.js +127 -0
  100. package/dist/lib/__tests__/SearchInput.test.d.ts +1 -0
  101. package/dist/lib/__tests__/SearchInput.test.js +80 -0
  102. package/dist/lib/__tests__/Select.test.d.ts +1 -0
  103. package/dist/lib/__tests__/Select.test.js +408 -0
  104. package/dist/lib/__tests__/Slider.test.d.ts +1 -0
  105. package/dist/lib/__tests__/Slider.test.js +213 -0
  106. package/dist/lib/__tests__/Splitter.test.d.ts +1 -0
  107. package/dist/lib/__tests__/Splitter.test.js +87 -0
  108. package/dist/lib/__tests__/Switch.test.d.ts +1 -0
  109. package/dist/lib/__tests__/Switch.test.js +97 -0
  110. package/dist/lib/__tests__/Table.test.d.ts +1 -0
  111. package/dist/lib/__tests__/Table.test.js +349 -0
  112. package/dist/lib/__tests__/Tabs.test.d.ts +1 -0
  113. package/dist/lib/__tests__/Tabs.test.js +262 -0
  114. package/dist/lib/__tests__/ThemeToggle.test.d.ts +1 -0
  115. package/dist/lib/__tests__/ThemeToggle.test.js +84 -0
  116. package/dist/lib/__tests__/TimePicker.test.d.ts +1 -0
  117. package/dist/lib/__tests__/TimePicker.test.js +146 -0
  118. package/dist/lib/__tests__/TimePickerNew.test.d.ts +1 -0
  119. package/dist/lib/__tests__/TimePickerNew.test.js +322 -0
  120. package/dist/lib/__tests__/Toast.test.d.ts +1 -0
  121. package/dist/lib/__tests__/Toast.test.js +135 -0
  122. package/dist/lib/__tests__/Tooltip.test.d.ts +1 -0
  123. package/dist/lib/__tests__/Tooltip.test.js +171 -0
  124. package/dist/lib/__tests__/Topbar.test.d.ts +1 -0
  125. package/dist/lib/__tests__/Topbar.test.js +25 -0
  126. package/dist/lib/__tests__/setupLangContext.d.ts +1 -0
  127. package/dist/lib/__tests__/setupLangContext.js +65 -0
  128. package/dist/lib/__tests__/storage.test.d.ts +1 -0
  129. package/dist/lib/__tests__/storage.test.js +124 -0
  130. package/dist/lib/__tests__/utils.test.d.ts +1 -0
  131. package/dist/lib/__tests__/utils.test.js +11 -0
  132. package/dist/lib/index.d.ts +1 -0
  133. package/dist/lib/index.js +1 -0
  134. package/dist/lib/lang.d.ts +4 -0
  135. package/dist/lib/lang.js +4 -0
  136. package/dist/styles.css +234 -232
  137. package/dist/utils/index.js +15 -4
  138. package/package.json +52 -52
@@ -1,233 +1,233 @@
1
- <!-- src/lib/Dialog.svelte -->
2
- <script lang="ts">
3
- /**
4
- * @component Dialog
5
- * @description Modal dialog for confirmations or alerts.
6
- *
7
- * @prop open {boolean} - Controls dialog visibility
8
- * @default false
9
- *
10
- * @prop title {string} - Dialog title used for labeling
11
- * @default ""
12
- *
13
- * @prop message {string} - Simple message content
14
- * @default ""
15
- *
16
- * @prop onConfirm {() => void} - Fired when the confirm action is triggered
17
- * @default () => {}
18
- *
19
- * @prop onCancel {() => void} - Fired when the cancel action is triggered
20
- * @default () => {}
21
- *
22
- * @prop onClose {() => void} - Fired after confirm or cancel to centralize cleanup
23
- * @default () => {}
24
- *
25
- * @prop modal {boolean} - Enables modal mode with overlay and focus trap
26
- * @default true
27
- *
28
- * @prop class {string} - Extra classes applied to the dialog container
29
- * @default ""
30
- *
31
- * @prop sz {SizeKey} - Size preset for padding and text
32
- * @options xs|sm|md|lg|xl
33
- * @default md
34
- *
35
- * @prop children {Snippet} - Custom dialog body content
36
- *
37
- * @note In modal mode the first interactive element is focused automatically and focus is trapped inside the dialog; `Escape` triggers cancel.
38
- * @note `onClose` runs after `onConfirm`/`onCancel`, so you can centralize cleanup.
39
- * @note Non-modal mode (`modal=false`) renders a floating panel without overlay or focus trap.
40
- * @note Buttons are labeled "OK" and "Cancel" and aren't customizable via props; provide `children` for full custom UI.
41
- * @note Set a meaningful `title` for accessibility; it's used as the dialog's `aria-label`.
42
- * @note `sz` adjusts both dialog padding and text sizes to match the rest of the system tokens.
43
- */
44
- import type { Snippet } from "svelte";
45
- import Button from "./Button.svelte";
46
- import { type SizeKey, TEXT } from "./types";
47
- import { cx, focusFirstInteractive, trapFocus } from "../utils";
48
- import { getComponentText, getLangContext, getLangKey } from "./lang-context";
49
-
50
- type Props = {
51
- open?: boolean;
52
- title?: string;
53
- message?: string;
54
- onConfirm?: () => void;
55
- onCancel?: () => void;
56
- onClose?: () => void;
57
- modal?: boolean;
58
- class?: string;
59
- sz?: SizeKey;
60
- children?: Snippet<[SizeKey]>;
61
- };
62
-
63
- let {
64
- open = false,
65
- title = "",
66
- message = "",
67
- onConfirm = () => {},
68
- onCancel = () => {},
69
- onClose = () => {},
70
- modal = true,
71
- class: externalClass = "",
72
- sz = "md",
73
- children,
74
- }: Props = $props();
75
-
76
- const langCtx = getLangContext();
77
- const langKey = $derived(getLangKey(langCtx));
78
- const L = $derived(getComponentText("dialog", langKey));
79
-
80
- let panelEl = $state<HTMLDivElement | null>(null);
81
- let releaseFocus: (() => void) | null = null;
82
-
83
- function handleConfirm() {
84
- onConfirm();
85
- onClose();
86
- }
87
-
88
- function handleCancel() {
89
- onCancel();
90
- onClose();
91
- }
92
-
93
- function handleKeydown(e: KeyboardEvent) {
94
- if (e.key === "Escape") {
95
- e.preventDefault();
96
- handleCancel();
97
- }
98
- }
99
-
100
- const panelBase =
101
- "fusion-dialog bg-[var(--color-bg-surface)] rounded-[var(--radius-lg)] shadow-lg min-w-80 max-w-md w-full border border-[var(--border-color-default)]";
102
-
103
- const paddingBySize: Record<SizeKey, string> = {
104
- xs: "p-[var(--spacing-sm)]",
105
- sm: "p-[var(--spacing-md)]",
106
- md: "p-[var(--spacing-lg)]",
107
- lg: "p-[var(--spacing-xl)]",
108
- xl: "p-[var(--spacing-xl)]",
109
- };
110
-
111
- const titleTextBySize: Record<SizeKey, string> = {
112
- xs: TEXT.md,
113
- sm: TEXT.md,
114
- md: TEXT.xl,
115
- lg: TEXT.xl,
116
- xl: "text-2xl",
117
- };
118
-
119
- const panelClass = $derived(cx(panelBase, externalClass));
120
- const paddingCls = $derived(paddingBySize[sz]);
121
- const footerPaddingCls = $derived(cx(paddingCls, "pt-0"));
122
- const titleTextCls = $derived(titleTextBySize[sz]);
123
- const bodyTextCls = $derived(TEXT[sz]);
124
-
125
- $effect(() => {
126
- releaseFocus?.();
127
- if (open && panelEl) {
128
- queueMicrotask(() => {
129
- focusFirstInteractive(panelEl!);
130
- if (modal) {
131
- releaseFocus = trapFocus(panelEl!);
132
- }
133
- });
134
- } else {
135
- releaseFocus = null;
136
- }
137
-
138
- return () => {
139
- releaseFocus?.();
140
- releaseFocus = null;
141
- };
142
- });
143
- </script>
144
-
145
- {#snippet titleBlock()}
146
- <h3
147
- class={cx(
148
- "mb-2 font-[var(--font-weight-semibold)] color-[var(--color-text-default)]",
149
- titleTextCls
150
- )}
151
- >
152
- {title}
153
- </h3>
154
- <p
155
- class={cx(
156
- "leading-[var(--line-height-normal)] color-[var(--color-text-muted)]",
157
- bodyTextCls
158
- )}
159
- >
160
- {message}
161
- </p>
162
- {/snippet}
163
-
164
- {#if open}
165
- {#if modal}
166
- <div
167
- class="fixed inset-0 z-[var(--z-modal)] bg-oklch(0_0_0/var(--opacity-overlay)) flex items-center justify-center p-4"
168
- role="presentation"
169
- tabindex="-1"
170
- onkeydown={handleKeydown}
171
- >
172
- <div
173
- class={panelClass}
174
- role="dialog"
175
- aria-modal="true"
176
- aria-label={title}
177
- bind:this={panelEl}
178
- >
179
- <div class={paddingCls}>
180
- {@render titleBlock()}
181
-
182
- {#if children}
183
- <div class="mt-3">
184
- {@render children?.(sz)}
185
- </div>
186
- {/if}
187
- </div>
188
-
189
- <div class={cx("flex gap-2 justify-end", footerPaddingCls)}>
190
- <Button {sz} variant="primary" onClick={handleConfirm}>{L.ok}</Button>
191
- <Button {sz} variant="secondary" onClick={handleCancel}>{L.cancel}</Button
192
- >
193
- </div>
194
- </div>
195
- </div>
196
- {:else}
197
- <div
198
- class="fixed top-4 right-4 z-[var(--z-modal)]"
199
- role="dialog"
200
- aria-modal="false"
201
- aria-label={title}
202
- tabindex="-1"
203
- onkeydown={handleKeydown}
204
- >
205
- <div class={panelClass} bind:this={panelEl}>
206
- <div class={paddingCls}>
207
- {@render titleBlock()}
208
-
209
- {#if children}
210
- <div class={cx("mt-3", bodyTextCls)}>
211
- {@render children?.(sz)}
212
- </div>
213
- {/if}
214
- </div>
215
-
216
- <div class={cx("flex gap-2 justify-end", footerPaddingCls)}>
217
- <Button {sz} variant="primary" onClick={handleConfirm}>{L.ok}</Button>
218
- <Button {sz} variant="secondary" onClick={handleCancel}>{L.cancel}</Button
219
- >
220
- </div>
221
- </div>
222
- </div>
223
- {/if}
224
- {/if}
225
- <style>
226
- :global(.fusion-dialog h3) {
227
- color: var(--color-text-default);
228
- }
229
-
230
- :global(.fusion-dialog p) {
231
- color: var(--color-text-muted);
232
- }
233
- </style>
1
+ <!-- src/lib/Dialog.svelte -->
2
+ <script lang="ts">
3
+ /**
4
+ * @component Dialog
5
+ * @description Modal dialog for confirmations or alerts.
6
+ *
7
+ * @prop open {boolean} - Controls dialog visibility
8
+ * @default false
9
+ *
10
+ * @prop title {string} - Dialog title used for labeling
11
+ * @default ""
12
+ *
13
+ * @prop message {string} - Simple message content
14
+ * @default ""
15
+ *
16
+ * @prop onConfirm {() => void} - Fired when the confirm action is triggered
17
+ * @default () => {}
18
+ *
19
+ * @prop onCancel {() => void} - Fired when the cancel action is triggered
20
+ * @default () => {}
21
+ *
22
+ * @prop onClose {() => void} - Fired after confirm or cancel to centralize cleanup
23
+ * @default () => {}
24
+ *
25
+ * @prop modal {boolean} - Enables modal mode with overlay and focus trap
26
+ * @default true
27
+ *
28
+ * @prop class {string} - Extra classes applied to the dialog container
29
+ * @default ""
30
+ *
31
+ * @prop sz {SizeKey} - Size preset for padding and text
32
+ * @options xs|sm|md|lg|xl
33
+ * @default md
34
+ *
35
+ * @prop children {Snippet} - Custom dialog body content
36
+ *
37
+ * @note In modal mode the first interactive element is focused automatically and focus is trapped inside the dialog; `Escape` triggers cancel.
38
+ * @note `onClose` runs after `onConfirm`/`onCancel`, so you can centralize cleanup.
39
+ * @note Non-modal mode (`modal=false`) renders a floating panel without overlay or focus trap.
40
+ * @note Buttons are labeled "OK" and "Cancel" and aren't customizable via props; provide `children` for full custom UI.
41
+ * @note Set a meaningful `title` for accessibility; it's used as the dialog's `aria-label`.
42
+ * @note `sz` adjusts both dialog padding and text sizes to match the rest of the system tokens.
43
+ */
44
+ import type { Snippet } from "svelte";
45
+ import Button from "./Button.svelte";
46
+ import { type SizeKey, TEXT } from "./types";
47
+ import { cx, focusFirstInteractive, trapFocus } from "../utils";
48
+ import { getComponentText, getLangContext, getLangKey } from "./lang-context";
49
+
50
+ type Props = {
51
+ open?: boolean;
52
+ title?: string;
53
+ message?: string;
54
+ onConfirm?: () => void;
55
+ onCancel?: () => void;
56
+ onClose?: () => void;
57
+ modal?: boolean;
58
+ class?: string;
59
+ sz?: SizeKey;
60
+ children?: Snippet<[SizeKey]>;
61
+ };
62
+
63
+ let {
64
+ open = false,
65
+ title = "",
66
+ message = "",
67
+ onConfirm = () => {},
68
+ onCancel = () => {},
69
+ onClose = () => {},
70
+ modal = true,
71
+ class: externalClass = "",
72
+ sz = "md",
73
+ children,
74
+ }: Props = $props();
75
+
76
+ const langCtx = getLangContext();
77
+ const langKey = $derived(getLangKey(langCtx));
78
+ const L = $derived(getComponentText("dialog", langKey));
79
+
80
+ let panelEl = $state<HTMLDivElement | null>(null);
81
+ let releaseFocus: (() => void) | null = null;
82
+
83
+ function handleConfirm() {
84
+ onConfirm();
85
+ onClose();
86
+ }
87
+
88
+ function handleCancel() {
89
+ onCancel();
90
+ onClose();
91
+ }
92
+
93
+ function handleKeydown(e: KeyboardEvent) {
94
+ if (e.key === "Escape") {
95
+ e.preventDefault();
96
+ handleCancel();
97
+ }
98
+ }
99
+
100
+ const panelBase =
101
+ "fusion-dialog bg-[var(--color-bg-surface)] rounded-[var(--radius-lg)] shadow-[0_8px_24px_var(--shadow-color)] min-w-0 max-w-[min(100%,28rem)] max-h-[calc(100svh-var(--spacing-lg)*2)] overflow-auto w-full border border-[var(--border-color-default)]";
102
+
103
+ const paddingBySize: Record<SizeKey, string> = {
104
+ xs: "p-[var(--spacing-sm)]",
105
+ sm: "p-[var(--spacing-md)]",
106
+ md: "p-[var(--spacing-lg)]",
107
+ lg: "p-[var(--spacing-xl)]",
108
+ xl: "p-[var(--spacing-xl)]",
109
+ };
110
+
111
+ const titleTextBySize: Record<SizeKey, string> = {
112
+ xs: TEXT.md,
113
+ sm: TEXT.md,
114
+ md: TEXT.xl,
115
+ lg: TEXT.xl,
116
+ xl: "text-2xl",
117
+ };
118
+
119
+ const panelClass = $derived(cx(panelBase, externalClass));
120
+ const paddingCls = $derived(paddingBySize[sz]);
121
+ const footerPaddingCls = $derived(cx(paddingCls, "pt-0"));
122
+ const titleTextCls = $derived(titleTextBySize[sz]);
123
+ const bodyTextCls = $derived(TEXT[sz]);
124
+
125
+ $effect(() => {
126
+ releaseFocus?.();
127
+ if (open && panelEl) {
128
+ queueMicrotask(() => {
129
+ focusFirstInteractive(panelEl!);
130
+ if (modal) {
131
+ releaseFocus = trapFocus(panelEl!);
132
+ }
133
+ });
134
+ } else {
135
+ releaseFocus = null;
136
+ }
137
+
138
+ return () => {
139
+ releaseFocus?.();
140
+ releaseFocus = null;
141
+ };
142
+ });
143
+ </script>
144
+
145
+ {#snippet titleBlock()}
146
+ <h3
147
+ class={cx(
148
+ "mb-2 font-[var(--font-weight-semibold)] color-[var(--color-text-default)]",
149
+ titleTextCls
150
+ )}
151
+ >
152
+ {title}
153
+ </h3>
154
+ <p
155
+ class={cx(
156
+ "leading-[var(--line-height-normal)] color-[var(--color-text-muted)]",
157
+ bodyTextCls
158
+ )}
159
+ >
160
+ {message}
161
+ </p>
162
+ {/snippet}
163
+
164
+ {#if open}
165
+ {#if modal}
166
+ <div
167
+ class="fixed inset-0 z-[var(--z-modal)] bg-[oklch(0_0_0/var(--opacity-overlay))] flex items-center justify-center p-[var(--spacing-md)]"
168
+ role="presentation"
169
+ tabindex="-1"
170
+ onkeydown={handleKeydown}
171
+ >
172
+ <div
173
+ class={panelClass}
174
+ role="dialog"
175
+ aria-modal="true"
176
+ aria-label={title}
177
+ bind:this={panelEl}
178
+ >
179
+ <div class={paddingCls}>
180
+ {@render titleBlock()}
181
+
182
+ {#if children}
183
+ <div class="mt-3">
184
+ {@render children?.(sz)}
185
+ </div>
186
+ {/if}
187
+ </div>
188
+
189
+ <div class={cx("flex gap-2 justify-end", footerPaddingCls)}>
190
+ <Button {sz} variant="primary" onClick={handleConfirm}>{L.ok}</Button>
191
+ <Button {sz} variant="secondary" onClick={handleCancel}>{L.cancel}</Button
192
+ >
193
+ </div>
194
+ </div>
195
+ </div>
196
+ {:else}
197
+ <div
198
+ class="fixed top-[var(--spacing-md)] right-[var(--spacing-md)] z-[var(--z-modal)] max-w-[calc(100vw-var(--spacing-md)*2)]"
199
+ role="dialog"
200
+ aria-modal="false"
201
+ aria-label={title}
202
+ tabindex="-1"
203
+ onkeydown={handleKeydown}
204
+ >
205
+ <div class={panelClass} bind:this={panelEl}>
206
+ <div class={paddingCls}>
207
+ {@render titleBlock()}
208
+
209
+ {#if children}
210
+ <div class={cx("mt-3", bodyTextCls)}>
211
+ {@render children?.(sz)}
212
+ </div>
213
+ {/if}
214
+ </div>
215
+
216
+ <div class={cx("flex gap-2 justify-end", footerPaddingCls)}>
217
+ <Button {sz} variant="primary" onClick={handleConfirm}>{L.ok}</Button>
218
+ <Button {sz} variant="secondary" onClick={handleCancel}>{L.cancel}</Button
219
+ >
220
+ </div>
221
+ </div>
222
+ </div>
223
+ {/if}
224
+ {/if}
225
+ <style>
226
+ :global(.fusion-dialog h3) {
227
+ color: var(--color-text-default);
228
+ }
229
+
230
+ :global(.fusion-dialog p) {
231
+ color: var(--color-text-muted);
232
+ }
233
+ </style>