@14ch/svelte-ui 0.0.41 → 0.0.42

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.
@@ -4,7 +4,7 @@
4
4
  import IconButton from './IconButton.svelte';
5
5
  import { getStyleFromNumber } from '../utils/style';
6
6
  import { t } from '../i18n';
7
- import { convertToHtml, convertToHtmlWithLink } from '../utils/formatText';
7
+ import { escapeHtml, convertToLink } from '../utils/formatText';
8
8
  import type { HTMLTextareaAttributes } from 'svelte/elements';
9
9
  import type { IconVariant, IconWeight, IconGrade, IconOpticalSize } from '../types/icon';
10
10
  import type {
@@ -475,21 +475,14 @@
475
475
  value !== null && value !== undefined && !(typeof value === 'string' && value === '')
476
476
  );
477
477
 
478
- // HTML表示用の値(autoResize時の高さ調整用)
478
+ // HTML表示用の値(pre-wrap で表示するため HTML エスケープのみ行う)
479
479
  const displayValue = $derived.by(() => {
480
480
  const normalizedValue = value ?? '';
481
481
  if (normalizedValue !== '') {
482
- const converted = convertToHtml(normalizedValue);
483
- const html = String(converted ?? '');
484
- // 最後の行が空だったら空白を追加(高さ調整のため)
485
- const lines = html.split('<br />');
486
- if (lines.length > 0 && lines[lines.length - 1] === '') {
487
- return html + '&nbsp;';
488
- }
489
- return html;
482
+ return escapeHtml(normalizedValue);
490
483
  }
491
484
  // 値が空のとき: placeholder があればその幅・高さを確保して表示、なければ inline 時のみ &nbsp;
492
- return placeholder ? convertToHtml(placeholder) : inline ? '&nbsp;' : '';
485
+ return placeholder ? escapeHtml(placeholder) : inline ? '&nbsp;' : '';
493
486
  });
494
487
 
495
488
  // URLをリンク化した表示用HTML(クリック検出用オーバーレイで使用)
@@ -498,8 +491,7 @@
498
491
  if (!linkify || normalizedValue === '') {
499
492
  return '';
500
493
  }
501
- const result = convertToHtmlWithLink(normalizedValue);
502
- return String(result ?? '');
494
+ return convertToLink(escapeHtml(normalizedValue));
503
495
  });
504
496
 
505
497
  // --------------------------------
@@ -631,6 +623,7 @@
631
623
  position: relative;
632
624
  width: auto;
633
625
  max-width: 100%;
626
+ overflow: hidden;
634
627
 
635
628
  &.textarea--full-height {
636
629
  height: 100%;
@@ -699,6 +692,7 @@
699
692
  transition: none;
700
693
  overflow-y: auto;
701
694
  overflow-x: hidden;
695
+ max-height: 100%;
702
696
 
703
697
  &::before {
704
698
  content: '';
@@ -709,13 +703,15 @@
709
703
  }
710
704
  }
711
705
 
712
- /* display-text: スクロールバーの幅を確保しつつ透明にする(textarea と幅を一致させる) */
706
+ /* display-text: textarea white-space: pre-wrap に合わせて空白・改行を同じルールで扱う */
713
707
  .textarea__display-text {
708
+ white-space: pre-wrap;
714
709
  scrollbar-color: transparent transparent;
715
710
  }
716
711
 
717
- /* link-text: 絶対配置のオーバーレイなのでスクロールバーを完全に非表示 */
712
+ /* link-text: 絶対配置オーバーレイ。pre-wrap で textarea と空白・改行を同じルールで扱う */
718
713
  .textarea__link-text {
714
+ white-space: pre-wrap;
719
715
  scrollbar-width: none;
720
716
 
721
717
  &::-webkit-scrollbar {
@@ -18,7 +18,7 @@ export const convertToHtml = (value) => {
18
18
  };
19
19
  export const convertToLink = (str) => {
20
20
  let text = str;
21
- text = text.replace(/((http|https|ftp):\/\/[\w?=&./#~%-;,*!$'():@+]+(?![\w\s?&./#~%";,=*'()-]*>))/g, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a> ');
21
+ text = text.replace(/((http|https|ftp):\/\/[\w?=&./#~%-;,*!$'():@+]+(?![\w\s?&./#~%";,=*'()-]*>))/g, '<a href="$1" target="_blank" rel="noopener noreferrer">$1</a>');
22
22
  return text;
23
23
  };
24
24
  export const escapeHtml = (value) => {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@14ch/svelte-ui",
3
3
  "description": "Modern Svelte UI components library with TypeScript support",
4
4
  "private": false,
5
- "version": "0.0.41",
5
+ "version": "0.0.42",
6
6
  "type": "module",
7
7
  "keywords": [
8
8
  "svelte",