@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,423 @@
1
+ <!-- SnackbarItem.svelte -->
2
+
3
+ <script lang="ts">
4
+ import { onMount } from 'svelte';
5
+ import type { Snippet } from 'svelte';
6
+ import { snackbar } from '../utils/snackbar.svelte';
7
+ import type { IconVariant } from '../types/icon';
8
+ import Icon from './Icon.svelte';
9
+ import IconButton from './IconButton.svelte';
10
+ import Button from './Button.svelte';
11
+
12
+ // =========================================================================
13
+ // Props, States & Constants
14
+ // =========================================================================
15
+
16
+ let {
17
+ // Snippet
18
+ children,
19
+
20
+ // 基本プロパティ
21
+ message,
22
+ type = 'info',
23
+ actionLabel,
24
+
25
+ // HTML属性系
26
+ id,
27
+
28
+ // スタイル/レイアウト
29
+ variant = 'filled',
30
+ position = 'bottom',
31
+ iconVariant = 'outlined',
32
+ color,
33
+ textColor,
34
+
35
+ // 状態/動作
36
+ duration = 3000,
37
+ closable = false,
38
+ closeButtonAriaLabel = 'このメッセージを閉じる',
39
+
40
+ // イベントハンドラー
41
+ onAction
42
+ }: {
43
+ // Snippet
44
+ children?: Snippet;
45
+
46
+ // 基本プロパティ
47
+ message?: string;
48
+ type?: 'info' | 'success' | 'warning' | 'error' | 'default';
49
+ actionLabel?: string;
50
+
51
+ // HTML属性系
52
+ id: string;
53
+
54
+ // スタイル/レイアウト
55
+ variant?: 'filled' | 'outlined';
56
+ position?: 'top' | 'bottom';
57
+ color?: string;
58
+ textColor?: string;
59
+
60
+ // 状態/動作
61
+ duration?: number;
62
+ closable?: boolean;
63
+ closeButtonAriaLabel?: string;
64
+ iconVariant?: IconVariant;
65
+
66
+ // イベントハンドラー
67
+ onAction?: () => void;
68
+ } = $props();
69
+
70
+ let visible = $state(true);
71
+ let timeoutId: ReturnType<typeof setTimeout> | null = null;
72
+
73
+ const typeIcons = {
74
+ info: 'info',
75
+ success: 'check_circle',
76
+ warning: 'warning',
77
+ error: 'error',
78
+ default: null // アイコンなし
79
+ };
80
+
81
+ let snackbarRef: HTMLDivElement;
82
+
83
+ // =========================================================================
84
+ // Lifecycle
85
+ // =========================================================================
86
+
87
+ onMount(() => {
88
+ if (duration > 0) {
89
+ timeoutId = setTimeout(() => {
90
+ handleClose();
91
+ }, duration);
92
+ }
93
+ });
94
+
95
+ // =========================================================================
96
+ // Methods
97
+ // =========================================================================
98
+
99
+ const handleClose = () => {
100
+ // アニメーション開始前に、他のSnackbarの位置を測定
101
+ if (snackbarRef) {
102
+ // 現在の要素の位置と親コンテナを取得
103
+ const currentRect = snackbarRef.getBoundingClientRect();
104
+
105
+ // コンテナの高さ(Snackbar本体 + gap)
106
+ const containerHeight =
107
+ currentRect.height +
108
+ parseInt(
109
+ getComputedStyle(document.documentElement)
110
+ .getPropertyValue('--svelte-ui-snackbar-item-space')
111
+ .replace('px', '')
112
+ );
113
+ const requiredMargin = -containerHeight;
114
+
115
+ snackbarRef.style.setProperty('--collapse-margin', `${requiredMargin}px`);
116
+
117
+ // CSSカスタムプロパティが確実に設定されるまで少し待つ
118
+ requestAnimationFrame(() => {
119
+ visible = false;
120
+ });
121
+
122
+ // animationendイベントでSnackbar削除
123
+ snackbarRef.addEventListener(
124
+ 'animationend',
125
+ () => {
126
+ snackbar.remove(id);
127
+ },
128
+ { once: true }
129
+ );
130
+ } else {
131
+ visible = false;
132
+ }
133
+ };
134
+
135
+ const handleAction = () => {
136
+ if (onAction) {
137
+ onAction();
138
+ }
139
+ handleClose();
140
+ };
141
+ </script>
142
+
143
+ <div
144
+ bind:this={snackbarRef}
145
+ class="snackbar-item snackbar-item--{position} {visible ? '' : 'snackbar-item--hidden'}"
146
+ data-testid="snackbar-item"
147
+ >
148
+ <div
149
+ class="snackbar-item__content snackbar-item__content--{type} snackbar-item__content--{variant} snackbar-item__content--{position} {visible
150
+ ? 'snackbar-item__content--visible'
151
+ : ''}"
152
+ style="--custom-color: {color ?? 'unset'}; --custom-text-color: {textColor ?? 'unset'};"
153
+ role={type === 'error' || type === 'warning' ? 'alert' : 'status'}
154
+ aria-live={type === 'error' || type === 'warning' ? 'assertive' : 'polite'}
155
+ aria-atomic="true"
156
+ aria-hidden={!visible}
157
+ >
158
+ {#if typeIcons[type]}
159
+ <div class="snackbar__icon" aria-hidden="true">
160
+ <Icon name={typeIcons[type]} size={32}>{typeIcons[type]}</Icon>
161
+ </div>
162
+ {/if}
163
+
164
+ <div class="snackbar__content">
165
+ {#if children}
166
+ {@render children()}
167
+ {:else}
168
+ <span class="snackbar-item__message">{message}</span>
169
+ {/if}
170
+ </div>
171
+
172
+ {#if actionLabel && onAction}
173
+ <Button
174
+ variant="outlined"
175
+ color="var(--svelte-ui-text-on-filled-color)"
176
+ onclick={handleAction}
177
+ aria-label="{actionLabel} - {message}"
178
+ >
179
+ {actionLabel}
180
+ </Button>
181
+ {/if}
182
+
183
+ {#if closable}
184
+ <div class="snackbar-item__close">
185
+ <IconButton
186
+ ariaLabel={closeButtonAriaLabel}
187
+ iconFilled={true}
188
+ {iconVariant}
189
+ color={variant === 'filled'
190
+ ? textColor || `var(--svelte-ui-snackbar-${type}-filled-text-color)`
191
+ : color || `var(--svelte-ui-snackbar-${type}-outlined-text-color)`}
192
+ size={24}
193
+ onclick={handleClose}
194
+ >
195
+ close
196
+ </IconButton>
197
+ </div>
198
+ {/if}
199
+ </div>
200
+ </div>
201
+
202
+ <style>
203
+ /* アニメーション定義 */
204
+ @keyframes slideInFromBottom {
205
+ from {
206
+ transform: translateY(100%);
207
+ opacity: 0;
208
+ }
209
+ to {
210
+ transform: translateY(0);
211
+ opacity: 1;
212
+ }
213
+ }
214
+
215
+ @keyframes slideOutWithCollapse {
216
+ 0% {
217
+ opacity: 1;
218
+ margin-bottom: 0;
219
+ }
220
+ 100% {
221
+ opacity: 0;
222
+ margin-bottom: var(--collapse-margin);
223
+ }
224
+ }
225
+
226
+ @keyframes slideOutWithCollapseTop {
227
+ 0% {
228
+ opacity: 1;
229
+ margin-top: 0;
230
+ }
231
+ 100% {
232
+ opacity: 0;
233
+ margin-top: var(--collapse-margin);
234
+ }
235
+ }
236
+
237
+ @keyframes slideInFromTop {
238
+ from {
239
+ transform: translateY(-100%);
240
+ opacity: 0;
241
+ }
242
+ to {
243
+ transform: translateY(0);
244
+ opacity: 1;
245
+ }
246
+ }
247
+
248
+ .snackbar-item--bottom {
249
+ padding-bottom: var(--svelte-ui-snackbar-item-space);
250
+ }
251
+
252
+ .snackbar-item--top {
253
+ padding-top: var(--svelte-ui-snackbar-item-space);
254
+ }
255
+
256
+ .snackbar-item--hidden {
257
+ animation: slideOutWithCollapse 400ms ease-in-out forwards;
258
+ }
259
+
260
+ .snackbar-item--top.snackbar-item--hidden {
261
+ animation: slideOutWithCollapseTop 400ms ease-in-out forwards;
262
+ }
263
+
264
+ .snackbar-item__content {
265
+ position: relative; /* コンテナ内での通常のフローに従う */
266
+ /* left/transformはコンテナが処理するので削除 */
267
+
268
+ display: flex;
269
+ align-items: center;
270
+ gap: var(--svelte-ui-snackbar-content-gap);
271
+
272
+ min-width: var(--svelte-ui-snackbar-min-width);
273
+ max-width: var(--svelte-ui-snackbar-max-width);
274
+ padding: var(--svelte-ui-snackbar-padding);
275
+
276
+ border-radius: var(--svelte-ui-snackbar-border-radius);
277
+ box-shadow: var(--svelte-ui-snackbar-shadow);
278
+
279
+ font-size: var(--svelte-ui-snackbar-font-size);
280
+ line-height: var(--svelte-ui-snackbar-line-height);
281
+ }
282
+
283
+ /* アニメーションクラス */
284
+ .snackbar-item__content--bottom.snackbar-item__content--visible {
285
+ animation: slideInFromBottom var(--svelte-ui-transition-duration, 300ms) ease-out forwards;
286
+ }
287
+
288
+ .snackbar-item__content--top.snackbar-item__content--visible {
289
+ animation: slideInFromTop var(--svelte-ui-transition-duration, 300ms) ease-out forwards;
290
+ }
291
+
292
+ /* Reduced motion support */
293
+ @media (prefers-reduced-motion: reduce) {
294
+ .snackbar-item__content--visible,
295
+ .snackbar-item--hidden {
296
+ animation-duration: 0.01s;
297
+ }
298
+ }
299
+
300
+ .snackbar-item__icon {
301
+ display: flex;
302
+ align-items: center;
303
+ flex-shrink: 0;
304
+ }
305
+
306
+ .snackbar-item__text {
307
+ flex: 1;
308
+ min-width: 0;
309
+ }
310
+
311
+ .snackbar-item__message {
312
+ word-break: break-word;
313
+ }
314
+
315
+ .snackbar-item__close {
316
+ display: flex;
317
+ align-items: center;
318
+ flex-shrink: 0;
319
+ margin-left: auto;
320
+ }
321
+
322
+ /* Type variants - filled */
323
+ .snackbar-item__content--filled.snackbar-item__content--info {
324
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-info-filled-bg));
325
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-info-filled-text-color));
326
+ }
327
+
328
+ .snackbar-item__content--filled.snackbar-item__content--info .snackbar-item__icon {
329
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-info-filled-text-color));
330
+ }
331
+
332
+ .snackbar-item__content--filled.snackbar-item__content--success {
333
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-success-filled-bg));
334
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-success-filled-text-color));
335
+ }
336
+
337
+ .snackbar-item__content--filled.snackbar-item__content--success .snackbar-item__icon {
338
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-success-filled-text-color));
339
+ }
340
+
341
+ .snackbar-item__content--filled.snackbar-item__content--warning {
342
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-warning-filled-bg));
343
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-warning-filled-text-color));
344
+ }
345
+
346
+ .snackbar-item__content--filled.snackbar-item__content--warning .snackbar-item__icon {
347
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-warning-filled-text-color));
348
+ }
349
+
350
+ .snackbar-item__content--filled.snackbar-item__content--error {
351
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-error-filled-bg));
352
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-error-filled-text-color));
353
+ }
354
+
355
+ .snackbar-item__content--filled.snackbar-item__content--error .snackbar-item__icon {
356
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-error-filled-text-color));
357
+ }
358
+
359
+ .snackbar-item__content--filled.snackbar-item__content--default {
360
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-default-filled-bg));
361
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-default-filled-text-color));
362
+ }
363
+
364
+ .snackbar-item__content--filled.snackbar-item__content--default .snackbar-item__icon {
365
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-default-filled-text-color));
366
+ }
367
+
368
+ /* Type variants - outlined */
369
+ .snackbar-item__content--outlined.snackbar-item__content--info {
370
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-info-outlined-bg));
371
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-info-outlined-text-color));
372
+ box-shadow: inset 0 0 0 1px
373
+ var(--custom-color, var(--svelte-ui-snackbar-info-outlined-border-color));
374
+ }
375
+
376
+ .snackbar-item__content--outlined.snackbar-item__content--info .snackbar-item__icon {
377
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-info-outlined-text-color));
378
+ }
379
+
380
+ .snackbar-item__content--outlined.snackbar-item__content--success {
381
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-success-outlined-bg));
382
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-success-outlined-text-color));
383
+ box-shadow: inset 0 0 0 1px
384
+ var(--custom-color, var(--svelte-ui-snackbar-success-outlined-border-color));
385
+ }
386
+
387
+ .snackbar-item__content--outlined.snackbar-item__content--success .snackbar-item__icon {
388
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-success-outlined-text-color));
389
+ }
390
+
391
+ .snackbar-item__content--outlined.snackbar-item__content--warning {
392
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-warning-outlined-bg));
393
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-warning-outlined-text-color));
394
+ box-shadow: inset 0 0 0 1px
395
+ var(--custom-color, var(--svelte-ui-snackbar-warning-outlined-border-color));
396
+ }
397
+
398
+ .snackbar-item__content--outlined.snackbar-item__content--warning .snackbar-item__icon {
399
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-warning-outlined-text-color));
400
+ }
401
+
402
+ .snackbar-item__content--outlined.snackbar-item__content--error {
403
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-error-outlined-bg));
404
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-error-outlined-text-color));
405
+ box-shadow: inset 0 0 0 1px
406
+ var(--custom-color, var(--svelte-ui-snackbar-error-outlined-border-color));
407
+ }
408
+
409
+ .snackbar-item__content--outlined.snackbar-item__content--error .snackbar-item__icon {
410
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-error-outlined-text-color));
411
+ }
412
+
413
+ .snackbar-item__content--outlined.snackbar-item__content--default {
414
+ background-color: var(--custom-color, var(--svelte-ui-snackbar-default-outlined-bg));
415
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-default-outlined-text-color));
416
+ box-shadow: inset 0 0 0 1px
417
+ var(--custom-color, var(--svelte-ui-snackbar-default-outlined-border-color));
418
+ }
419
+
420
+ .snackbar-item__content--outlined.snackbar-item__content--default .snackbar-item__icon {
421
+ color: var(--custom-text-color, var(--svelte-ui-snackbar-default-outlined-text-color));
422
+ }
423
+ </style>
@@ -0,0 +1,21 @@
1
+ import type { Snippet } from 'svelte';
2
+ import type { IconVariant } from '../types/icon';
3
+ type $$ComponentProps = {
4
+ children?: Snippet;
5
+ message?: string;
6
+ type?: 'info' | 'success' | 'warning' | 'error' | 'default';
7
+ actionLabel?: string;
8
+ id: string;
9
+ variant?: 'filled' | 'outlined';
10
+ position?: 'top' | 'bottom';
11
+ color?: string;
12
+ textColor?: string;
13
+ duration?: number;
14
+ closable?: boolean;
15
+ closeButtonAriaLabel?: string;
16
+ iconVariant?: IconVariant;
17
+ onAction?: () => void;
18
+ };
19
+ declare const SnackbarItem: import("svelte").Component<$$ComponentProps, {}, "">;
20
+ type SnackbarItem = ReturnType<typeof SnackbarItem>;
21
+ export default SnackbarItem;