@14ch/svelte-ui 0.0.14 → 0.0.16

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 (39) hide show
  1. package/dist/assets/styles/variables.scss +6 -12
  2. package/dist/components/Checkbox.svelte +2 -1
  3. package/dist/components/ColorPicker.svelte +14 -5
  4. package/dist/components/ColorPicker.svelte.d.ts +1 -1
  5. package/dist/components/Combobox.svelte +4 -3
  6. package/dist/components/Datepicker.svelte +12 -12
  7. package/dist/components/Drawer.svelte +7 -3
  8. package/dist/components/Drawer.svelte.d.ts +1 -1
  9. package/dist/components/Icon.svelte +20 -24
  10. package/dist/components/Icon.svelte.d.ts +1 -1
  11. package/dist/components/IconButton.svelte +1 -1
  12. package/dist/components/Input.svelte +499 -268
  13. package/dist/components/Input.svelte.d.ts +17 -0
  14. package/dist/components/Radio.svelte +2 -1
  15. package/dist/components/SegmentedControl.svelte +3 -3
  16. package/dist/components/Select.svelte +1 -1
  17. package/dist/components/Tab.svelte +1 -0
  18. package/dist/components/TabItem.svelte +22 -1
  19. package/dist/components/TabItem.svelte.d.ts +1 -0
  20. package/dist/components/Textarea.svelte +280 -173
  21. package/dist/components/Textarea.svelte.d.ts +7 -3
  22. package/dist/components/skeleton/Skeleton.svelte +48 -6
  23. package/dist/i18n/index.d.ts +48 -1
  24. package/dist/i18n/index.js +3 -13
  25. package/dist/i18n/locales/de.d.ts +8 -0
  26. package/dist/i18n/locales/de.js +10 -2
  27. package/dist/i18n/locales/en.d.ts +8 -0
  28. package/dist/i18n/locales/en.js +10 -2
  29. package/dist/i18n/locales/es.d.ts +8 -0
  30. package/dist/i18n/locales/es.js +10 -2
  31. package/dist/i18n/locales/fr.d.ts +8 -0
  32. package/dist/i18n/locales/fr.js +10 -2
  33. package/dist/i18n/locales/ja.d.ts +8 -0
  34. package/dist/i18n/locales/ja.js +10 -2
  35. package/dist/i18n/locales/zh-cn.d.ts +8 -0
  36. package/dist/i18n/locales/zh-cn.js +10 -2
  37. package/dist/utils/formatText.d.ts +2 -2
  38. package/dist/utils/formatText.js +2 -2
  39. package/package.json +1 -1
@@ -163,14 +163,13 @@
163
163
  --svelte-ui-surface-inverse-color: var(--base-800-transparent);
164
164
 
165
165
  /* スケルトン色 */
166
- --svelte-ui-skeleton-color: var(--base-200-transparent);
167
- --svelte-ui-skeleton-shimmer-color: var(--white-300-transparent);
166
+ --svelte-ui-skeleton-color: var(--base-100-transparent);
168
167
 
169
168
  /* UIカラー */
170
169
  --svelte-ui-handle-color: #ffffff;
171
170
 
172
171
  /* hover & select 効果 */
173
- --svelte-ui-hover-overlay: var(--base-50-transparent);
172
+ --svelte-ui-hover-overlay: var(--base-100-transparent);
174
173
  --svelte-ui-select-overlay: var(--primary-200-transparent);
175
174
 
176
175
  /* ドロップダウンアイコン */
@@ -216,8 +215,7 @@
216
215
  --svelte-ui-surface-inverse-color: var(--white-800-transparent);
217
216
 
218
217
  /* スケルトン色 */
219
- --svelte-ui-skeleton-color: var(--white-200-transparent);
220
- --svelte-ui-skeleton-shimmer-color: var(--white-100-transparent);
218
+ --svelte-ui-skeleton-color: var(--white-100-transparent);
221
219
 
222
220
  /* hover & select 効果 */
223
221
  --svelte-ui-hover-overlay: var(--white-100-transparent);
@@ -376,7 +374,7 @@
376
374
  --svelte-ui-input-icon-space-double-inline: calc(var(--svelte-ui-form-icon-space) * 2);
377
375
  --svelte-ui-input-bg: var(--svelte-ui-form-bg);
378
376
  --svelte-ui-input-border-color: var(--svelte-ui-border-weak-color);
379
- --svelte-ui-input-text-color: var(--svelte-ui-text-color);
377
+ --svelte-ui-input-unit-font-size: max(0.5em, var(--svelte-ui-font-size-sm));
380
378
  --svelte-ui-input-placeholder-color: var(--svelte-ui-text-placeholder-color);
381
379
  --svelte-ui-input-icon-color: var(--svelte-ui-text-subtle-color);
382
380
 
@@ -387,7 +385,6 @@
387
385
  --svelte-ui-textarea-border-radius-rounded: calc(var(--svelte-ui-textarea-min-height) / 2);
388
386
  --svelte-ui-textarea-bg: var(--svelte-ui-form-bg);
389
387
  --svelte-ui-textarea-border-color: var(--svelte-ui-border-weak-color);
390
- --svelte-ui-textarea-text-color: var(--svelte-ui-text-color);
391
388
  --svelte-ui-textarea-placeholder-color: var(--svelte-ui-text-placeholder-color);
392
389
  --svelte-ui-textarea-icon-space: calc(
393
390
  var(--svelte-ui-form-icon-space) + var(--svelte-ui-form-icon-offset)
@@ -409,7 +406,6 @@
409
406
  --svelte-ui-select-border-radius-rounded: var(--svelte-ui-form-border-radius-rounded);
410
407
  --svelte-ui-select-bg: var(--svelte-ui-form-bg);
411
408
  --svelte-ui-select-border-color: var(--svelte-ui-border-weak-color);
412
- --svelte-ui-select-text-color: var(--svelte-ui-text-color);
413
409
  --svelte-ui-select-dropdown-icon-color: var(--svelte-ui-dropdown-icon-color);
414
410
  --svelte-ui-select-placeholder-color: var(--svelte-ui-text-placeholder-color);
415
411
 
@@ -510,7 +506,6 @@
510
506
  --svelte-ui-colorpicker-border-color: var(--svelte-ui-border-weak-color);
511
507
  --svelte-ui-colorpicker-trigger-border-color: var(--svelte-ui-border-color);
512
508
  --svelte-ui-colorpicker-bg: var(--svelte-ui-form-bg);
513
- --svelte-ui-colorpicker-text-color: var(--svelte-ui-text-color);
514
509
  --svelte-ui-colorpicker-placeholder-color: var(--svelte-ui-text-placeholder-color);
515
510
 
516
511
  /* Combobox */
@@ -524,14 +519,13 @@
524
519
  --svelte-ui-combobox-border-radius-rounded: var(--svelte-ui-form-border-radius-rounded);
525
520
  --svelte-ui-combobox-border-color: var(--svelte-ui-border-weak-color);
526
521
  --svelte-ui-combobox-bg: var(--svelte-ui-surface-color);
527
- --svelte-ui-combobox-text-color: var(--svelte-ui-text-color);
528
522
  --svelte-ui-combobox-dropdown-icon-color: var(--svelte-ui-dropdown-icon-color);
529
523
  --svelte-ui-combobox-option-hover-bg: var(--svelte-ui-hover-overlay);
530
524
  --svelte-ui-combobox-option-selected-bg: var(--svelte-ui-select-overlay);
531
525
  --svelte-ui-combobox-no-options-color: var(--svelte-ui-text-subtle-color);
532
526
 
533
527
  /* FileUploader */
534
- --svelte-ui-file-uploader-border-width: 2px;
528
+ --svelte-ui-file-uploader-border-width: 1px;
535
529
  --svelte-ui-file-uploader-border-style: dashed;
536
530
  --svelte-ui-file-uploader-bg: var(--svelte-ui-form-bg);
537
531
  --svelte-ui-file-uploader-border-color: var(--svelte-ui-border-color);
@@ -541,7 +535,7 @@
541
535
  --svelte-ui-file-uploader-item-bg: var(--svelte-ui-form-bg);
542
536
 
543
537
  /* ImageUploader */
544
- --svelte-ui-image-uploader-border-width: 2px;
538
+ --svelte-ui-image-uploader-border-width: 1px;
545
539
  --svelte-ui-image-uploader-border-style: dashed;
546
540
  --svelte-ui-image-uploader-preview-border-radius: var(--svelte-ui-border-radius);
547
541
  --svelte-ui-image-uploader-preview-border-radius-rounded: var(--svelte-ui-border-radius-rounded);
@@ -339,10 +339,11 @@
339
339
  * ========================================================================= */
340
340
 
341
341
  .checkbox {
342
- display: flex;
342
+ display: inline-flex;
343
343
  align-items: center;
344
344
  width: fit-content;
345
345
  min-height: var(--svelte-ui-checkbox-min-height);
346
+ vertical-align: top;
346
347
  contain: layout;
347
348
  }
348
349
 
@@ -19,7 +19,7 @@
19
19
  // =========================================================================
20
20
  export type ColorPickerProps = {
21
21
  // 基本プロパティ
22
- value: string;
22
+ value: string | null | undefined;
23
23
 
24
24
  // HTML属性系
25
25
  id?: string;
@@ -141,7 +141,12 @@
141
141
  ...restProps
142
142
  }: ColorPickerProps = $props();
143
143
 
144
- let localValue: string | undefined = $state(value);
144
+ const getNormalizedValue = (val: string | null | undefined): string => {
145
+ if (val === null || val === undefined) return '';
146
+ return val;
147
+ };
148
+
149
+ let localValue: string = $state(getNormalizedValue(value));
145
150
  let prevValue: string = $state('');
146
151
  let isFocused: boolean = $state(false);
147
152
 
@@ -154,7 +159,7 @@
154
159
  value;
155
160
  untrack(() => {
156
161
  /* value を localValue に反映 */
157
- localValue = value;
162
+ localValue = getNormalizedValue(value);
158
163
 
159
164
  /* value が更新されたらonchangeを実行 */
160
165
  handleValueChange();
@@ -165,7 +170,7 @@
165
170
  localValue;
166
171
  untrack(() => {
167
172
  /* localValue がクリアされた時に value もクリア */
168
- if (localValue === '' || localValue === undefined) {
173
+ if (localValue === '') {
169
174
  value = '';
170
175
  prevValue = '';
171
176
  }
@@ -392,7 +397,10 @@
392
397
  {...inputAttributes}
393
398
  {...restProps}
394
399
  />
395
- <div class="color-picker__color-display" style="background-color: {value};"></div>
400
+ <div
401
+ class="color-picker__color-display"
402
+ style="background-color: {getNormalizedValue(value)};"
403
+ ></div>
396
404
  </div>
397
405
  </div>
398
406
 
@@ -407,6 +415,7 @@
407
415
  position: relative;
408
416
  width: auto;
409
417
  max-width: 100%;
418
+ vertical-align: top;
410
419
  }
411
420
 
412
421
  /* =============================================
@@ -2,7 +2,7 @@ import type { HTMLInputAttributes } from 'svelte/elements';
2
2
  import type { IconVariant } from '../types/icon';
3
3
  import type { FocusHandler, KeyboardHandler, MouseHandler, TouchHandler, PointerHandler } from '../types/callbackHandlers';
4
4
  export type ColorPickerProps = {
5
- value: string;
5
+ value: string | null | undefined;
6
6
  id?: string;
7
7
  inputAttributes?: HTMLInputAttributes | undefined;
8
8
  customStyle?: string;
@@ -104,7 +104,7 @@
104
104
  customStyle = '',
105
105
  inline = false,
106
106
  focusStyle = 'outline',
107
- placeholder = '選択してください',
107
+ placeholder = t('combobox.placeholder'),
108
108
  fullWidth = false,
109
109
  minWidth = inline ? null : 120,
110
110
  maxWidth = null,
@@ -503,7 +503,7 @@
503
503
  </button>
504
504
  </div>
505
505
  {:else}
506
- <div class="combobox__no-options">該当するオプションがありません</div>
506
+ <div class="combobox__no-options">{t('combobox.noOptions')}</div>
507
507
  {/each}
508
508
  </div>
509
509
  </Popup>
@@ -518,6 +518,7 @@
518
518
  position: relative;
519
519
  width: auto;
520
520
  max-width: 100%;
521
+ vertical-align: top;
521
522
  }
522
523
 
523
524
  .combobox--full-width {
@@ -547,7 +548,7 @@
547
548
  text-align: left;
548
549
  cursor: pointer;
549
550
  font-size: inherit;
550
- color: var(--svelte-ui-combobox-text-color);
551
+ color: var(--svelte-ui-text-color);
551
552
  transition: background-color var(--svelte-ui-transition-duration) ease;
552
553
 
553
554
  @media (hover: hover) {
@@ -234,13 +234,13 @@
234
234
  // =========================================================================
235
235
  // Effects
236
236
  // =========================================================================
237
- const effectiveLocale = $derived(locale ?? getLocale());
237
+ const resolvedLocale = $derived(locale ?? getLocale());
238
238
 
239
239
  $effect(() => {
240
240
  // range モードのときは、value を「start <= end」の順序に正規化
241
241
  if (mode === 'range' && value && 'start' in value && 'end' in value) {
242
- const startDay = dayjs(value.start).locale(effectiveLocale);
243
- const endDay = dayjs(value.end).locale(effectiveLocale);
242
+ const startDay = dayjs(value.start).locale(resolvedLocale);
243
+ const endDay = dayjs(value.end).locale(resolvedLocale);
244
244
  if (startDay.isAfter(endDay)) {
245
245
  value = { start: value.end, end: value.start };
246
246
  }
@@ -248,8 +248,7 @@
248
248
  });
249
249
 
250
250
  $effect(() => {
251
- const formatWithLocale = (date: Date) =>
252
- dayjs(date).locale(effectiveLocale).format(finalFormat);
251
+ const formatWithLocale = (date: Date) => dayjs(date).locale(resolvedLocale).format(finalFormat);
253
252
 
254
253
  if (mode === 'range' && value && 'start' in value && 'end' in value) {
255
254
  displayValue = `${formatWithLocale(value.start)}${rangeSeparator}${formatWithLocale(value.end)}`;
@@ -267,11 +266,11 @@
267
266
  // スクリーンリーダーアナウンス
268
267
  if (value) {
269
268
  if (mode === 'range' && typeof value === 'object' && 'start' in value && 'end' in value) {
270
- const startDate = dayjs(value.start).locale(effectiveLocale).format(finalFormat);
271
- const endDate = dayjs(value.end).locale(effectiveLocale).format(finalFormat);
269
+ const startDate = dayjs(value.start).locale(resolvedLocale).format(finalFormat);
270
+ const endDate = dayjs(value.end).locale(resolvedLocale).format(finalFormat);
272
271
  announceToScreenReader(`Date range selected: ${startDate} to ${endDate}`);
273
272
  } else if (value instanceof Date) {
274
- const formattedDate = dayjs(value).locale(effectiveLocale).format(finalFormat);
273
+ const formattedDate = dayjs(value).locale(resolvedLocale).format(finalFormat);
275
274
  announceToScreenReader(`Date selected: ${formattedDate}`);
276
275
  }
277
276
  }
@@ -512,7 +511,7 @@
512
511
 
513
512
  // 日付パース処理
514
513
  if (mode === 'range') {
515
- const parsedRange = parseRangeInput(inputStr, effectiveLocale);
514
+ const parsedRange = parseRangeInput(inputStr, resolvedLocale);
516
515
  if (!parsedRange) return;
517
516
 
518
517
  value = parsedRange;
@@ -521,7 +520,7 @@
521
520
  }
522
521
 
523
522
  // single モードでは先頭の「日付本体」のみを解釈する
524
- const parsedSingle = parseSingleInput(inputStr, effectiveLocale);
523
+ const parsedSingle = parseSingleInput(inputStr, resolvedLocale);
525
524
  if (!parsedSingle) return;
526
525
 
527
526
  value = parsedSingle;
@@ -589,7 +588,7 @@
589
588
  // $derived
590
589
  // =========================================================================
591
590
  const calendarId = $derived(`${id}-calendar`);
592
- const currentLocaleConfig = $derived(localeConfig[effectiveLocale]);
591
+ const currentLocaleConfig = $derived(localeConfig[resolvedLocale]);
593
592
  const finalFormat = $derived(
594
593
  format ||
595
594
  (mode === 'range' ? currentLocaleConfig.rangeFormat : currentLocaleConfig.defaultFormat)
@@ -670,7 +669,7 @@
670
669
  onchange={handleChange}
671
670
  {minDate}
672
671
  {maxDate}
673
- locale={effectiveLocale}
672
+ locale={resolvedLocale}
674
673
  id={calendarId}
675
674
  />
676
675
  </Popup>
@@ -679,6 +678,7 @@
679
678
  position: relative;
680
679
  display: inline-block;
681
680
  width: auto;
681
+ vertical-align: top;
682
682
  }
683
683
  .datepicker.datepicker--full-width {
684
684
  display: block;
@@ -34,7 +34,7 @@
34
34
  id?: string;
35
35
 
36
36
  // スタイル/レイアウト
37
- width?: string | number;
37
+ width?: string | number | undefined;
38
38
  position?: 'left' | 'right';
39
39
  bodyStyle?: string;
40
40
  noPadding?: boolean;
@@ -64,7 +64,7 @@
64
64
  id,
65
65
 
66
66
  // スタイル/レイアウト
67
- width = 240,
67
+ width = undefined,
68
68
  position = 'left',
69
69
  bodyStyle = '',
70
70
  noPadding = false,
@@ -106,7 +106,11 @@
106
106
  // =========================================================================
107
107
  const drawerStyles = $derived(() => {
108
108
  const styles = [];
109
- styles.push(`width: ${getStyleFromNumber(width)}`);
109
+ if (width !== undefined) {
110
+ styles.push(`width: ${getStyleFromNumber(width)}`);
111
+ } else {
112
+ styles.push('width: max-content');
113
+ }
110
114
  styles.push('height: 100%');
111
115
  styles.push('min-height: 100%');
112
116
  styles.push(`${position}: 0`);
@@ -18,7 +18,7 @@ export type DrawerProps = {
18
18
  title?: string;
19
19
  description?: string;
20
20
  id?: string;
21
- width?: string | number;
21
+ width?: string | number | undefined;
22
22
  position?: 'left' | 'right';
23
23
  bodyStyle?: string;
24
24
  noPadding?: boolean;
@@ -17,7 +17,7 @@
17
17
  fallbackText?: string;
18
18
 
19
19
  // スタイル/レイアウト
20
- size?: number;
20
+ size?: number | string;
21
21
  color?: string;
22
22
  customStyle?: string;
23
23
 
@@ -53,7 +53,7 @@
53
53
  filled = false,
54
54
  weight = 300,
55
55
  grade = 0,
56
- opticalSize = size,
56
+ opticalSize = typeof size === 'number' ? size : 24,
57
57
  variant = 'outlined',
58
58
 
59
59
  // ARIA/アクセシビリティ
@@ -61,13 +61,16 @@
61
61
  decorative = true,
62
62
 
63
63
  // その他
64
+ class: className,
64
65
  ...restProps
65
66
  }: IconProps = $props();
66
67
 
67
68
  // =========================================================================
68
69
  // $derived
69
70
  // =========================================================================
70
- const iconClasses = $derived(`material-symbols-${variant}`);
71
+ const iconClasses = $derived(
72
+ ['icon', `icon--${variant}`, `material-symbols-${variant}`, className].filter(Boolean).join(' ')
73
+ );
71
74
 
72
75
  const fontVariationSettings = $derived(
73
76
  `'FILL' ${filled ? 1 : 0}, 'wght' ${weight}, 'GRAD' ${grade}, 'opsz' ${opticalSize}`
@@ -79,12 +82,13 @@
79
82
  role: !decorative && ariaLabel ? 'img' : undefined
80
83
  });
81
84
 
82
- const iconStyle = $derived(
83
- `width: ${size}px; height: ${size}px; font-size: ${size}px;
84
- color: ${color}; line-height: 1;
85
+ const iconStyle = $derived.by(() => {
86
+ const sizeStyle = getStyleFromNumber(size);
87
+ return `width: ${sizeStyle}; height: ${sizeStyle}; font-size: ${sizeStyle};
88
+ color: ${color};
85
89
  font-variation-settings: ${fontVariationSettings};
86
- ${customStyle}`
87
- );
90
+ ${customStyle}`;
91
+ });
88
92
  </script>
89
93
 
90
94
  <i
@@ -102,7 +106,7 @@
102
106
  <!-- Unicode文字での代替表示 -->
103
107
  <span
104
108
  class="icon-fallback-text"
105
- style="width: {size}px; height: {size}px; font-size: {size}px; {customStyle}"
109
+ style={customStyle}
106
110
  {...ariaAttributes}
107
111
  {...restProps}
108
112
  data-testid="icon-fallback"
@@ -112,13 +116,11 @@
112
116
  {/if}
113
117
 
114
118
  <style>
115
- .material-symbols-outlined,
116
- .material-symbols-rounded,
117
- .material-symbols-sharp {
119
+ .icon {
118
120
  display: block;
119
121
  font-size: inherit;
120
122
  color: inherit;
121
- line-height: inherit;
123
+ line-height: 1;
122
124
  text-transform: none;
123
125
  letter-spacing: normal;
124
126
  word-wrap: normal;
@@ -129,15 +131,15 @@
129
131
  transition-timing-function: ease;
130
132
  }
131
133
 
132
- .material-symbols-outlined {
134
+ .icon.material-symbols-outlined {
133
135
  font-family: 'Material Symbols Outlined';
134
136
  }
135
137
 
136
- .material-symbols-rounded {
138
+ .icon.material-symbols-rounded {
137
139
  font-family: 'Material Symbols Rounded';
138
140
  }
139
141
 
140
- .material-symbols-sharp {
142
+ .icon.material-symbols-sharp {
141
143
  font-family: 'Material Symbols Sharp';
142
144
  }
143
145
 
@@ -157,10 +159,7 @@
157
159
 
158
160
  /* Prefers reduced motion */
159
161
  @media (prefers-reduced-motion: reduce) {
160
- .material-symbols-outlined,
161
- .material-symbols-filled,
162
- .material-symbols-rounded,
163
- .material-symbols-sharp,
162
+ .icon,
164
163
  .icon-fallback-text {
165
164
  transition: none;
166
165
  }
@@ -168,10 +167,7 @@
168
167
 
169
168
  /* Print styles */
170
169
  @media print {
171
- .material-symbols-outlined,
172
- .material-symbols-filled,
173
- .material-symbols-rounded,
174
- .material-symbols-sharp,
170
+ .icon,
175
171
  .icon-fallback-text {
176
172
  color: black !important;
177
173
  }
@@ -4,7 +4,7 @@ export type IconProps = {
4
4
  children: Snippet;
5
5
  title?: string;
6
6
  fallbackText?: string;
7
- size?: number;
7
+ size?: number | string;
8
8
  color?: string;
9
9
  customStyle?: string;
10
10
  filled?: boolean;
@@ -383,7 +383,7 @@
383
383
  {:else}
384
384
  <div class="icon-button__icon" class:icon-button__icon--hidden={loading}>
385
385
  <Icon
386
- filled={true}
386
+ filled={iconFilled}
387
387
  size={fontSize}
388
388
  weight={iconWeight}
389
389
  grade={iconGrade}