@14ch/svelte-ui 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 (109) hide show
  1. package/README.md +359 -0
  2. package/dist/assets/styles/README.md +144 -0
  3. package/dist/assets/styles/core.scss +61 -0
  4. package/dist/assets/styles/import.scss +11 -0
  5. package/dist/assets/styles/optional/fonts.scss +23 -0
  6. package/dist/assets/styles/optional/reset.scss +230 -0
  7. package/dist/assets/styles/variables.scss +805 -0
  8. package/dist/components/Button.svelte +574 -0
  9. package/dist/components/Button.svelte.d.ts +56 -0
  10. package/dist/components/COMPONENT_DESIGN_GUIDELINES.md +127 -0
  11. package/dist/components/Checkbox.svelte +523 -0
  12. package/dist/components/Checkbox.svelte.d.ts +42 -0
  13. package/dist/components/CheckboxGroup.svelte +82 -0
  14. package/dist/components/CheckboxGroup.svelte.d.ts +13 -0
  15. package/dist/components/ColorPicker.svelte +496 -0
  16. package/dist/components/ColorPicker.svelte.d.ts +45 -0
  17. package/dist/components/Combobox.svelte +576 -0
  18. package/dist/components/Combobox.svelte.d.ts +52 -0
  19. package/dist/components/ConfirmDialog.svelte +116 -0
  20. package/dist/components/ConfirmDialog.svelte.d.ts +20 -0
  21. package/dist/components/Datepicker.svelte +578 -0
  22. package/dist/components/Datepicker.svelte.d.ts +72 -0
  23. package/dist/components/DatepickerCalendar.svelte +925 -0
  24. package/dist/components/DatepickerCalendar.svelte.d.ts +31 -0
  25. package/dist/components/Dialog.svelte +245 -0
  26. package/dist/components/Dialog.svelte.d.ts +38 -0
  27. package/dist/components/Drawer.svelte +383 -0
  28. package/dist/components/Drawer.svelte.d.ts +39 -0
  29. package/dist/components/Fab.svelte +486 -0
  30. package/dist/components/Fab.svelte.d.ts +51 -0
  31. package/dist/components/FileUploader.svelte +456 -0
  32. package/dist/components/FileUploader.svelte.d.ts +36 -0
  33. package/dist/components/Icon.svelte +167 -0
  34. package/dist/components/Icon.svelte.d.ts +21 -0
  35. package/dist/components/IconButton.svelte +557 -0
  36. package/dist/components/IconButton.svelte.d.ts +60 -0
  37. package/dist/components/ImageUploader.svelte +516 -0
  38. package/dist/components/ImageUploader.svelte.d.ts +37 -0
  39. package/dist/components/ImageUploaderPreview.svelte +157 -0
  40. package/dist/components/ImageUploaderPreview.svelte.d.ts +13 -0
  41. package/dist/components/Input.svelte +885 -0
  42. package/dist/components/Input.svelte.d.ts +75 -0
  43. package/dist/components/LoadingSpinner.svelte +116 -0
  44. package/dist/components/LoadingSpinner.svelte.d.ts +10 -0
  45. package/dist/components/Modal.svelte +313 -0
  46. package/dist/components/Modal.svelte.d.ts +34 -0
  47. package/dist/components/Pagination.svelte +276 -0
  48. package/dist/components/Pagination.svelte.d.ts +14 -0
  49. package/dist/components/Popup.svelte +676 -0
  50. package/dist/components/Popup.svelte.d.ts +40 -0
  51. package/dist/components/PopupMenu.svelte +421 -0
  52. package/dist/components/PopupMenu.svelte.d.ts +24 -0
  53. package/dist/components/PopupMenuButton.svelte +365 -0
  54. package/dist/components/PopupMenuButton.svelte.d.ts +42 -0
  55. package/dist/components/Radio.svelte +548 -0
  56. package/dist/components/Radio.svelte.d.ts +42 -0
  57. package/dist/components/RadioGroup.svelte +74 -0
  58. package/dist/components/RadioGroup.svelte.d.ts +14 -0
  59. package/dist/components/Select.svelte +479 -0
  60. package/dist/components/Select.svelte.d.ts +47 -0
  61. package/dist/components/Slider.svelte +473 -0
  62. package/dist/components/Slider.svelte.d.ts +46 -0
  63. package/dist/components/Snackbar.svelte +124 -0
  64. package/dist/components/Snackbar.svelte.d.ts +9 -0
  65. package/dist/components/SnackbarItem.svelte +423 -0
  66. package/dist/components/SnackbarItem.svelte.d.ts +21 -0
  67. package/dist/components/Switch.svelte +454 -0
  68. package/dist/components/Switch.svelte.d.ts +40 -0
  69. package/dist/components/Tab.svelte +193 -0
  70. package/dist/components/Tab.svelte.d.ts +14 -0
  71. package/dist/components/TabItem.svelte +140 -0
  72. package/dist/components/TabItem.svelte.d.ts +17 -0
  73. package/dist/components/Textarea.svelte +702 -0
  74. package/dist/components/Textarea.svelte.d.ts +64 -0
  75. package/dist/components/skeleton/Skeleton.svelte +235 -0
  76. package/dist/components/skeleton/Skeleton.svelte.d.ts +13 -0
  77. package/dist/components/skeleton/SkeletonAvatar.svelte +97 -0
  78. package/dist/components/skeleton/SkeletonAvatar.svelte.d.ts +8 -0
  79. package/dist/components/skeleton/SkeletonBox.svelte +105 -0
  80. package/dist/components/skeleton/SkeletonBox.svelte.d.ts +12 -0
  81. package/dist/components/skeleton/SkeletonButton.svelte +71 -0
  82. package/dist/components/skeleton/SkeletonButton.svelte.d.ts +8 -0
  83. package/dist/components/skeleton/SkeletonHeading.svelte +49 -0
  84. package/dist/components/skeleton/SkeletonHeading.svelte.d.ts +8 -0
  85. package/dist/components/skeleton/SkeletonMedia.svelte +115 -0
  86. package/dist/components/skeleton/SkeletonMedia.svelte.d.ts +9 -0
  87. package/dist/components/skeleton/SkeletonText.svelte +75 -0
  88. package/dist/components/skeleton/SkeletonText.svelte.d.ts +8 -0
  89. package/dist/index.d.ts +42 -0
  90. package/dist/index.js +43 -0
  91. package/dist/types/icon.d.ts +4 -0
  92. package/dist/types/icon.js +2 -0
  93. package/dist/types/menuItem.d.ts +8 -0
  94. package/dist/types/menuItem.js +1 -0
  95. package/dist/types/options.d.ts +6 -0
  96. package/dist/types/options.js +4 -0
  97. package/dist/types/skeleton.d.ts +77 -0
  98. package/dist/types/skeleton.js +19 -0
  99. package/dist/utils/accessibility.d.ts +48 -0
  100. package/dist/utils/accessibility.js +87 -0
  101. package/dist/utils/formatText.d.ts +4 -0
  102. package/dist/utils/formatText.js +44 -0
  103. package/dist/utils/mobile.d.ts +9 -0
  104. package/dist/utils/mobile.js +47 -0
  105. package/dist/utils/snackbar.svelte.d.ts +51 -0
  106. package/dist/utils/snackbar.svelte.js +107 -0
  107. package/dist/utils/style.d.ts +17 -0
  108. package/dist/utils/style.js +22 -0
  109. package/package.json +102 -0
@@ -0,0 +1,31 @@
1
+ import 'dayjs/locale/ja';
2
+ import 'dayjs/locale/en';
3
+ import 'dayjs/locale/fr';
4
+ import 'dayjs/locale/de';
5
+ import 'dayjs/locale/es';
6
+ import 'dayjs/locale/zh-cn';
7
+ type $$ComponentProps = {
8
+ value: Date | {
9
+ start: Date;
10
+ end: Date;
11
+ } | undefined;
12
+ locale?: 'en' | 'ja' | 'fr' | 'de' | 'es' | 'zh-cn';
13
+ minDate?: Date;
14
+ maxDate?: Date;
15
+ id?: string;
16
+ mode?: 'single' | 'range';
17
+ onchange: (value: Date | {
18
+ start: Date;
19
+ end: Date;
20
+ } | undefined) => void;
21
+ onOpen?: Function;
22
+ onClose?: Function;
23
+ };
24
+ declare const DatepickerCalendar: import("svelte").Component<$$ComponentProps, {
25
+ reset: () => void;
26
+ focusCalendar: () => void;
27
+ handlePopupOpen: () => void;
28
+ handlePopupClose: () => void;
29
+ }, "value">;
30
+ type DatepickerCalendar = ReturnType<typeof DatepickerCalendar>;
31
+ export default DatepickerCalendar;
@@ -0,0 +1,245 @@
1
+ <!-- Dialog.svelte -->
2
+
3
+ <script lang="ts">
4
+ /**
5
+ * 🚨 CRITICAL: DO NOT MANAGE DIALOG STATE FROM PARENT COMPONENTS
6
+ *
7
+ * This Dialog component manages its own open/closed state internally.
8
+ * Parent components must NEVER create their own Dialog state variables.
9
+ *
10
+ * ❌ WRONG: let isDialogOpen = $state(false)
11
+ * ✅ RIGHT: Use dialogRef.open(), dialogRef.close(), dialogRef.toggle()
12
+ * ✅ RIGHT: Use onOpen/onClose callbacks for side effects
13
+ *
14
+ * This prevents state synchronization bugs and ensures consistent behavior.
15
+ */
16
+ import type { Snippet } from 'svelte';
17
+ import Modal from './Modal.svelte';
18
+ import { getStyleFromNumber } from '../utils/style';
19
+
20
+ // =========================================================================
21
+ // Props, States & Constants
22
+ // =========================================================================
23
+ let {
24
+ // Snippet
25
+ header,
26
+ children,
27
+ footer,
28
+
29
+ // 基本プロパティ
30
+ title = '',
31
+ description,
32
+
33
+ // HTML属性
34
+ id,
35
+
36
+ // スタイル/レイアウト
37
+ width = 320,
38
+ bodyStyle = '',
39
+ noPadding = false,
40
+
41
+ // 状態/動作
42
+ isOpen = $bindable(false),
43
+ scrollable = false,
44
+ closeIfClickOutside = true,
45
+ restoreFocus = false,
46
+
47
+ // ARIA/アクセシビリティ
48
+ ariaLabel,
49
+ ariaDescribedby
50
+ }: {
51
+ // Snippet
52
+ header?: Snippet;
53
+ children?: Snippet;
54
+ footer?: Snippet;
55
+
56
+ // 基本プロパティ
57
+ title?: string;
58
+ description?: string;
59
+
60
+ // HTML属性
61
+ id?: string;
62
+
63
+ // スタイル/レイアウト
64
+ width?: string | number;
65
+ bodyStyle?: string;
66
+ noPadding?: boolean;
67
+
68
+ // 状態/動作
69
+ isOpen?: boolean;
70
+ scrollable?: boolean;
71
+ closeIfClickOutside?: boolean;
72
+ restoreFocus?: boolean;
73
+
74
+ // ARIA/アクセシビリティ
75
+ ariaLabel?: string;
76
+ ariaDescribedby?: string;
77
+ } = $props();
78
+
79
+ let modalRef: Modal;
80
+
81
+ // =========================================================================
82
+ // Methods
83
+ // =========================================================================
84
+ export const open = (): void => {
85
+ modalRef?.open(title || ariaLabel);
86
+ };
87
+
88
+ export const close = (): void => {
89
+ modalRef?.close(title || ariaLabel);
90
+ };
91
+
92
+ export const toggle = (): void => {
93
+ modalRef?.toggle(title || ariaLabel);
94
+ };
95
+
96
+ export const closeEnd = (): void => {
97
+ modalRef?.closeEnd();
98
+ };
99
+
100
+ // =========================================================================
101
+ // $derived
102
+ // =========================================================================
103
+ const dialogStyles = $derived(
104
+ `width: ${getStyleFromNumber(width)}; border-radius: var(--svelte-ui-dialog-border-radius); overflow: hidden;`
105
+ );
106
+
107
+ const bodyStyles = $derived(() => {
108
+ const styles = [];
109
+ if (noPadding) {
110
+ styles.push('padding: 0');
111
+ }
112
+ if (bodyStyle) {
113
+ styles.push(bodyStyle);
114
+ }
115
+ return styles.join('; ');
116
+ });
117
+
118
+ const dialogClasses = $derived(['dialog', scrollable && 'scrollable'].filter(Boolean).join(' '));
119
+
120
+ const ariaLabelledby = $derived(title ? 'dialog-title' : undefined);
121
+ const ariaDescribedbyValue = $derived(
122
+ ariaDescribedby || (description ? 'dialog-description' : undefined)
123
+ );
124
+ </script>
125
+
126
+ <Modal
127
+ bind:this={modalRef}
128
+ bind:isOpen
129
+ {closeIfClickOutside}
130
+ {restoreFocus}
131
+ componentType="Dialog"
132
+ {ariaLabel}
133
+ {ariaLabelledby}
134
+ ariaDescribedby={ariaDescribedbyValue}
135
+ customClass={dialogClasses}
136
+ customStyles={dialogStyles}
137
+ id={id ? `${id}-modal` : undefined}
138
+ >
139
+ <div class="dialog">
140
+ {#if header || title}
141
+ <div class="dialog__header">
142
+ {#if header}
143
+ {@render header()}
144
+ {:else}
145
+ <div class="dialog__title" id={id ? `${id}-dialog-title` : undefined}>
146
+ {title || ''}
147
+ </div>
148
+ {/if}
149
+ </div>
150
+ {/if}
151
+ {#if description}
152
+ <div class="dialog__description" id={id ? `${id}-dialog-description` : undefined}>
153
+ {description}
154
+ </div>
155
+ {/if}
156
+ {#if children}
157
+ <div class="dialog__body" style={bodyStyles()}>
158
+ {@render children()}
159
+ </div>
160
+ {/if}
161
+ {#if footer}
162
+ <div class="dialog__footer">
163
+ {@render footer()}
164
+ </div>
165
+ {/if}
166
+ </div>
167
+ </Modal>
168
+
169
+ <style>:global(.dialog) {
170
+ color: var(--svelte-ui-dialog-title-color);
171
+ }
172
+
173
+ .dialog {
174
+ display: flex;
175
+ flex-direction: column;
176
+ justify-content: stretch;
177
+ max-height: calc(100dvh - 2em - 6px);
178
+ border: var(--svelte-ui-dialog-border);
179
+ border-radius: var(--svelte-ui-dialog-border-radius);
180
+ overflow: hidden;
181
+ }
182
+
183
+ .dialog__header {
184
+ display: flex;
185
+ gap: var(--svelte-ui-dialog-gap);
186
+ align-items: center;
187
+ justify-content: stretch;
188
+ min-height: var(--svelte-ui-dialog-header-height);
189
+ padding: var(--svelte-ui-dialog-padding);
190
+ margin-bottom: calc(0px - var(--svelte-ui-dialog-body-padding));
191
+ }
192
+ .dialog__header .dialog__title {
193
+ flex-grow: 1;
194
+ font-size: var(--svelte-ui-dialog-title-font-size);
195
+ line-height: normal;
196
+ color: var(--svelte-ui-dialog-title-color);
197
+ }
198
+
199
+ .dialog__body {
200
+ flex-shrink: 1;
201
+ position: relative;
202
+ padding: var(--svelte-ui-dialog-body-padding);
203
+ }
204
+
205
+ .dialog__footer {
206
+ display: flex;
207
+ gap: var(--svelte-ui-dialog-gap-sm);
208
+ justify-content: end;
209
+ padding: var(--svelte-ui-dialog-footer-padding);
210
+ }
211
+
212
+ .dialog__description {
213
+ color: var(--svelte-ui-dialog-description-color);
214
+ font-size: var(--svelte-ui-dialog-description-font-size);
215
+ line-height: 1.4;
216
+ margin: 0;
217
+ padding: var(--svelte-ui-dialog-description-padding);
218
+ border-bottom: 1px solid var(--svelte-ui-border-weak-color);
219
+ }
220
+
221
+ :global(.dialog.scrollable) .dialog__header {
222
+ margin-bottom: 0;
223
+ border-bottom: solid var(--svelte-ui-border-width, 1px) var(--svelte-ui-border-weak-color);
224
+ }
225
+ :global(.dialog.scrollable) .dialog__body {
226
+ flex-shrink: 1;
227
+ padding: var(--svelte-ui-dialog-body-padding);
228
+ overflow: auto;
229
+ }
230
+ :global(.dialog.scrollable) .dialog__footer {
231
+ border-top: solid var(--svelte-ui-border-width, 1px) var(--svelte-ui-border-weak-color);
232
+ }
233
+
234
+ /* Screen reader only content */
235
+ :global(.sr-only) {
236
+ position: absolute;
237
+ width: 1px;
238
+ height: 1px;
239
+ padding: 0;
240
+ margin: -1px;
241
+ overflow: hidden;
242
+ clip: rect(0, 0, 0, 0);
243
+ white-space: nowrap;
244
+ border: 0;
245
+ }</style>
@@ -0,0 +1,38 @@
1
+ /**
2
+ * 🚨 CRITICAL: DO NOT MANAGE DIALOG STATE FROM PARENT COMPONENTS
3
+ *
4
+ * This Dialog component manages its own open/closed state internally.
5
+ * Parent components must NEVER create their own Dialog state variables.
6
+ *
7
+ * ❌ WRONG: let isDialogOpen = $state(false)
8
+ * ✅ RIGHT: Use dialogRef.open(), dialogRef.close(), dialogRef.toggle()
9
+ * ✅ RIGHT: Use onOpen/onClose callbacks for side effects
10
+ *
11
+ * This prevents state synchronization bugs and ensures consistent behavior.
12
+ */
13
+ import type { Snippet } from 'svelte';
14
+ type $$ComponentProps = {
15
+ header?: Snippet;
16
+ children?: Snippet;
17
+ footer?: Snippet;
18
+ title?: string;
19
+ description?: string;
20
+ id?: string;
21
+ width?: string | number;
22
+ bodyStyle?: string;
23
+ noPadding?: boolean;
24
+ isOpen?: boolean;
25
+ scrollable?: boolean;
26
+ closeIfClickOutside?: boolean;
27
+ restoreFocus?: boolean;
28
+ ariaLabel?: string;
29
+ ariaDescribedby?: string;
30
+ };
31
+ declare const Dialog: import("svelte").Component<$$ComponentProps, {
32
+ open: () => void;
33
+ close: () => void;
34
+ toggle: () => void;
35
+ closeEnd: () => void;
36
+ }, "isOpen">;
37
+ type Dialog = ReturnType<typeof Dialog>;
38
+ export default Dialog;
@@ -0,0 +1,383 @@
1
+ <!-- Drawer.svelte -->
2
+
3
+ <script lang="ts">
4
+ /**
5
+ * 🚨 CRITICAL: DO NOT MANAGE DRAWER STATE FROM PARENT COMPONENTS
6
+ *
7
+ * This Drawer component manages its own open/closed state internally.
8
+ * Parent components must NEVER create their own Drawer state variables.
9
+ *
10
+ * ❌ WRONG: let isDrawerOpen = $state(false)
11
+ * ✅ RIGHT: Use drawerRef.open(), drawerRef.close(), drawerRef.toggle()
12
+ * ✅ RIGHT: Use onOpen/onClose callbacks for side effects
13
+ *
14
+ * This prevents state synchronization bugs and ensures consistent behavior.
15
+ */
16
+ import type { Snippet } from 'svelte';
17
+ import Modal from './Modal.svelte';
18
+ import { getStyleFromNumber } from '../utils/style';
19
+
20
+ // =========================================================================
21
+ // Props, States & Constants
22
+ // =========================================================================
23
+ let {
24
+ // Snippet
25
+ header,
26
+ children,
27
+ footer,
28
+
29
+ // 基本プロパティ
30
+ title = '',
31
+ description,
32
+
33
+ // HTML属性
34
+ id,
35
+
36
+ // スタイル/レイアウト
37
+ width = 240,
38
+ position = 'left',
39
+ bodyStyle = '',
40
+ noPadding = false,
41
+
42
+ // 状態/動作
43
+ isOpen = $bindable(false),
44
+ scrollable = true,
45
+ closeIfClickOutside = true,
46
+ restoreFocus = false,
47
+
48
+ // ARIA/アクセシビリティ
49
+ ariaLabel = 'Drawer',
50
+ ariaDescribedby
51
+ }: {
52
+ // Snippet
53
+ header?: Snippet;
54
+ children?: Snippet;
55
+ footer?: Snippet;
56
+
57
+ // 基本プロパティ
58
+ title?: string;
59
+ description?: string;
60
+
61
+ // HTML属性
62
+ id?: string;
63
+
64
+ // スタイル/レイアウト
65
+ width?: string | number;
66
+ position?: 'left' | 'right';
67
+ bodyStyle?: string;
68
+ noPadding?: boolean;
69
+
70
+ // 状態/動作
71
+ isOpen?: boolean;
72
+ scrollable?: boolean;
73
+ closeIfClickOutside?: boolean;
74
+ restoreFocus?: boolean;
75
+
76
+ // ARIA/アクセシビリティ
77
+ ariaLabel?: string;
78
+ ariaDescribedby?: string;
79
+ } = $props();
80
+
81
+ let modalRef: Modal;
82
+
83
+ // =========================================================================
84
+ // Methods
85
+ // =========================================================================
86
+ export const open = (): void => {
87
+ modalRef?.open(title || ariaLabel);
88
+ };
89
+
90
+ export const close = (): void => {
91
+ modalRef?.close(title || ariaLabel);
92
+ };
93
+
94
+ export const toggle = (): void => {
95
+ modalRef?.toggle(title || ariaLabel);
96
+ };
97
+
98
+ export const closeEnd = (): void => {
99
+ modalRef?.closeEnd();
100
+ };
101
+
102
+ // =========================================================================
103
+ // $derived
104
+ // =========================================================================
105
+ const drawerStyles = $derived(() => {
106
+ const styles = [];
107
+ styles.push(`width: ${getStyleFromNumber(width)}`);
108
+ styles.push('height: 100%');
109
+ styles.push('min-height: 100%');
110
+ styles.push(`${position}: 0`);
111
+ return styles.join('; ');
112
+ });
113
+
114
+ const bodyStyles = $derived(() => {
115
+ const styles = [];
116
+ if (noPadding) {
117
+ styles.push('padding: 0');
118
+ }
119
+ if (bodyStyle) {
120
+ styles.push(bodyStyle);
121
+ }
122
+ return styles.join('; ');
123
+ });
124
+
125
+ const drawerClasses = $derived(
126
+ ['drawer', `drawer--${position}`, scrollable && 'drawer--scrollable'].filter(Boolean).join(' ')
127
+ );
128
+
129
+ const ariaLabelledby = $derived(title ? 'drawer-title' : undefined);
130
+ const ariaDescribedbyValue = $derived(
131
+ ariaDescribedby || (description ? 'drawer-description' : undefined)
132
+ );
133
+ </script>
134
+
135
+ <Modal
136
+ bind:this={modalRef}
137
+ bind:isOpen
138
+ {closeIfClickOutside}
139
+ {restoreFocus}
140
+ componentType="Drawer"
141
+ {ariaLabel}
142
+ {ariaLabelledby}
143
+ ariaDescribedby={ariaDescribedbyValue}
144
+ customClass={drawerClasses}
145
+ customStyles={drawerStyles()}
146
+ id={id ? `${id}-modal` : undefined}
147
+ >
148
+ <div class="drawer drawer--{position} {scrollable ? 'drawer--scrollable' : ''}">
149
+ {#if header || title}
150
+ <div class="drawer__header">
151
+ {#if header}
152
+ {@render header()}
153
+ {:else}
154
+ <div class="drawer__title" id={id ? `${id}-drawer-title` : undefined}>
155
+ {title || ''}
156
+ </div>
157
+ {/if}
158
+ </div>
159
+ {/if}
160
+ {#if description}
161
+ <div class="drawer__description" id={id ? `${id}-drawer-description` : undefined}>
162
+ {description}
163
+ </div>
164
+ {/if}
165
+ {#if children}
166
+ <div class="drawer__body" style={bodyStyles()}>
167
+ {@render children()}
168
+ </div>
169
+ {/if}
170
+ {#if footer}
171
+ <div class="drawer__footer">
172
+ {@render footer()}
173
+ </div>
174
+ {/if}
175
+ </div>
176
+ </Modal>
177
+
178
+ <style>@charset "UTF-8";
179
+ :global(.drawer) {
180
+ width: 100%;
181
+ height: 100%;
182
+ min-height: 100%;
183
+ padding: 0;
184
+ margin: 0;
185
+ overflow: hidden;
186
+ color: var(--svelte-ui-drawer-title-color);
187
+ }
188
+
189
+ :global(.drawer:-internal-dialog-in-top-layer) {
190
+ max-height: none;
191
+ max-width: none;
192
+ width: 100%;
193
+ }
194
+
195
+ /* 位置固有のアニメーション */
196
+ @keyframes fadeIn {
197
+ from {
198
+ opacity: 0;
199
+ }
200
+ to {
201
+ opacity: 1;
202
+ }
203
+ }
204
+ @keyframes fadeOut {
205
+ from {
206
+ opacity: 1;
207
+ }
208
+ to {
209
+ opacity: 0;
210
+ }
211
+ }
212
+ @keyframes fadeInFromLeft {
213
+ from {
214
+ opacity: 0;
215
+ right: 100%;
216
+ transform: translateX(-50%);
217
+ }
218
+ to {
219
+ opacity: 1;
220
+ right: 100%;
221
+ transform: translateX(0);
222
+ }
223
+ }
224
+ @keyframes fadeInFromRight {
225
+ from {
226
+ opacity: 0;
227
+ left: 100%;
228
+ transform: translateX(-50%);
229
+ }
230
+ to {
231
+ opacity: 1;
232
+ left: 100%;
233
+ transform: translateX(-100%);
234
+ }
235
+ }
236
+ @keyframes fadeOutToLeft {
237
+ from {
238
+ opacity: 1;
239
+ right: 100%;
240
+ transform: translateX(0);
241
+ }
242
+ to {
243
+ opacity: 0;
244
+ right: 100%;
245
+ transform: translateX(-50%);
246
+ }
247
+ }
248
+ @keyframes fadeOutToRight {
249
+ from {
250
+ opacity: 1;
251
+ left: 100%;
252
+ transform: translateX(-100%);
253
+ }
254
+ to {
255
+ opacity: 0;
256
+ left: 100%;
257
+ transform: translateX(-50%);
258
+ }
259
+ }
260
+ :global(.drawer--right.fade-in) {
261
+ animation: fadeInFromRight var(--svelte-ui-transition-duration, 300ms) forwards;
262
+ }
263
+
264
+ :global(.drawer--right.fade-in::backdrop) {
265
+ animation: fadeIn var(--svelte-ui-transition-duration, 300ms) forwards;
266
+ }
267
+
268
+ :global(.drawer--left.fade-in) {
269
+ animation: fadeInFromLeft var(--svelte-ui-transition-duration, 300ms) forwards;
270
+ }
271
+
272
+ :global(.drawer--left.fade-in::backdrop) {
273
+ animation: fadeIn var(--svelte-ui-transition-duration, 300ms) forwards;
274
+ }
275
+
276
+ :global(.drawer--left.fade-out) {
277
+ animation: fadeOutToLeft var(--svelte-ui-transition-duration, 300ms) forwards;
278
+ }
279
+
280
+ :global(.drawer--right.fade-out) {
281
+ animation: fadeOutToRight var(--svelte-ui-transition-duration, 300ms) forwards;
282
+ }
283
+
284
+ :global(.drawer.fade-out::backdrop) {
285
+ animation: fadeOut var(--svelte-ui-transition-duration, 300ms) forwards;
286
+ }
287
+
288
+ .drawer {
289
+ display: flex;
290
+ flex-direction: column;
291
+ justify-content: stretch;
292
+ height: 100%;
293
+ overflow: hidden;
294
+ }
295
+
296
+ /* Position-based borders */
297
+ .drawer--left {
298
+ border-right: var(--svelte-ui-drawer-border);
299
+ }
300
+
301
+ .drawer--right {
302
+ border-left: var(--svelte-ui-drawer-border);
303
+ }
304
+
305
+ .drawer__header {
306
+ display: flex;
307
+ gap: var(--svelte-ui-drawer-gap);
308
+ align-items: center;
309
+ justify-content: stretch;
310
+ min-height: var(--svelte-ui-drawer-header-height);
311
+ padding: var(--svelte-ui-drawer-padding);
312
+ margin-bottom: calc(0px - var(--svelte-ui-drawer-body-padding));
313
+ }
314
+ .drawer__header .drawer__title {
315
+ flex-grow: 1;
316
+ font-size: var(--svelte-ui-drawer-title-font-size);
317
+ line-height: normal;
318
+ color: var(--svelte-ui-drawer-title-color);
319
+ }
320
+
321
+ .drawer__body {
322
+ flex-shrink: 1;
323
+ position: relative;
324
+ padding: var(--svelte-ui-drawer-body-padding);
325
+ flex-grow: 1;
326
+ }
327
+
328
+ .drawer__footer {
329
+ display: flex;
330
+ gap: var(--svelte-ui-drawer-gap-sm);
331
+ justify-content: end;
332
+ padding: var(--svelte-ui-drawer-footer-padding);
333
+ }
334
+
335
+ .drawer__description {
336
+ color: var(--svelte-ui-drawer-description-color);
337
+ font-size: var(--svelte-ui-drawer-description-font-size);
338
+ line-height: 1.4;
339
+ margin: 0;
340
+ padding: var(--svelte-ui-drawer-description-padding);
341
+ border-bottom: 1px solid var(--svelte-ui-border-weak-color);
342
+ }
343
+
344
+ .drawer--scrollable .drawer__header {
345
+ margin-bottom: 0;
346
+ border-bottom: solid var(--svelte-ui-border-width, 1px) var(--svelte-ui-border-weak-color);
347
+ }
348
+ .drawer--scrollable .drawer__body {
349
+ flex-shrink: 1;
350
+ padding: var(--svelte-ui-drawer-body-padding);
351
+ overflow: auto;
352
+ }
353
+ .drawer--scrollable .drawer__footer {
354
+ border-top: solid var(--svelte-ui-border-width, 1px) var(--svelte-ui-border-weak-color);
355
+ }
356
+
357
+ /* Reduced motion support */
358
+ @media (prefers-reduced-motion: reduce) {
359
+ :global(.drawer.fade-in),
360
+ :global(.drawer.fade-in::backdrop),
361
+ :global(.drawer.fade-out),
362
+ :global(.drawer.fade-out::backdrop),
363
+ :global(.drawer--left.fade-in),
364
+ :global(.drawer--left.fade-in::backdrop),
365
+ :global(.drawer--left.fade-out),
366
+ :global(.drawer--right.fade-in),
367
+ :global(.drawer--right.fade-in::backdrop),
368
+ :global(.drawer--right.fade-out) {
369
+ animation-duration: 0.01s;
370
+ }
371
+ }
372
+ /* Screen reader only content */
373
+ :global(.sr-only) {
374
+ position: absolute;
375
+ width: 1px;
376
+ height: 1px;
377
+ padding: 0;
378
+ margin: -1px;
379
+ overflow: hidden;
380
+ clip: rect(0, 0, 0, 0);
381
+ white-space: nowrap;
382
+ border: 0;
383
+ }</style>