podo-ui 1.0.0 → 1.0.2
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.
- package/cdn/podo-datepicker.css +1 -1
- package/cdn/podo-datepicker.js +1 -1
- package/cdn/podo-datepicker.min.css +1 -1
- package/cdn/podo-datepicker.min.js +1 -1
- package/cdn/podo-ui.css +4 -1
- package/cdn/podo-ui.min.css +1 -1
- package/dist/react/atom/editor.d.ts.map +1 -1
- package/dist/react/atom/editor.js +94 -2
- package/dist/svelte/atom/Avatar.svelte +3 -1
- package/dist/svelte/atom/Avatar.svelte.d.ts +2 -1
- package/dist/svelte/atom/Chip.svelte +3 -2
- package/dist/svelte/atom/Chip.svelte.d.ts +2 -1
- package/dist/svelte/atom/Editor.svelte +1314 -0
- package/dist/svelte/atom/Editor.svelte.d.ts +30 -0
- package/dist/svelte/atom/Radio.svelte +4 -2
- package/dist/svelte/atom/Tooltip.svelte +3 -1
- package/dist/svelte/atom/Tooltip.svelte.d.ts +2 -1
- package/dist/svelte/index.d.ts +2 -0
- package/dist/svelte/index.js +2 -0
- package/dist/svelte/molecule/DatePicker.svelte +986 -0
- package/dist/svelte/molecule/DatePicker.svelte.d.ts +71 -0
- package/dist/svelte/molecule/Field.svelte +5 -3
- package/dist/svelte/molecule/Field.svelte.d.ts +2 -1
- package/dist/svelte/molecule/Pagination.svelte +3 -2
- package/dist/svelte/molecule/Pagination.svelte.d.ts +2 -1
- package/dist/svelte/molecule/Tab.svelte +3 -2
- package/dist/svelte/molecule/Tab.svelte.d.ts +2 -1
- package/dist/svelte/molecule/Table.svelte +3 -2
- package/dist/svelte/molecule/Table.svelte.d.ts +1 -1
- package/dist/svelte/molecule/Toast.svelte +3 -2
- package/dist/svelte/molecule/Toast.svelte.d.ts +2 -1
- package/global.scss +1 -0
- package/package.json +1 -1
- package/vite-fonts.scss +1 -1
|
@@ -368,12 +368,104 @@ const Editor = ({ value = '', width = '100%', height = '400px', minHeight, maxHe
|
|
|
368
368
|
}
|
|
369
369
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
370
370
|
}, [onChange, addToHistory]);
|
|
371
|
+
// 이미지를 커서 위치에 삽입하는 함수
|
|
372
|
+
const insertImageAtCursor = useCallback((src, alt = '') => {
|
|
373
|
+
const selection = window.getSelection();
|
|
374
|
+
if (!selection || selection.rangeCount === 0)
|
|
375
|
+
return;
|
|
376
|
+
const range = selection.getRangeAt(0);
|
|
377
|
+
const img = document.createElement('img');
|
|
378
|
+
img.src = src;
|
|
379
|
+
img.alt = alt;
|
|
380
|
+
img.style.maxWidth = '100%';
|
|
381
|
+
range.deleteContents();
|
|
382
|
+
range.insertNode(img);
|
|
383
|
+
// 커서를 이미지 다음으로 이동
|
|
384
|
+
const newRange = document.createRange();
|
|
385
|
+
newRange.setStartAfter(img);
|
|
386
|
+
newRange.collapse(true);
|
|
387
|
+
selection.removeAllRanges();
|
|
388
|
+
selection.addRange(newRange);
|
|
389
|
+
handleInput();
|
|
390
|
+
}, []);
|
|
391
|
+
// 드래그 앤 드롭 이벤트 핸들러
|
|
392
|
+
const handleDragOver = useCallback((e) => {
|
|
393
|
+
e.preventDefault();
|
|
394
|
+
e.stopPropagation();
|
|
395
|
+
}, []);
|
|
396
|
+
const handleDrop = useCallback((e) => {
|
|
397
|
+
e.preventDefault();
|
|
398
|
+
e.stopPropagation();
|
|
399
|
+
const files = e.dataTransfer?.files;
|
|
400
|
+
if (!files || files.length === 0)
|
|
401
|
+
return;
|
|
402
|
+
// 이미지 파일만 처리
|
|
403
|
+
for (let i = 0; i < files.length; i++) {
|
|
404
|
+
const file = files[i];
|
|
405
|
+
if (file.type.startsWith('image/')) {
|
|
406
|
+
const reader = new FileReader();
|
|
407
|
+
reader.onload = (event) => {
|
|
408
|
+
const dataUrl = event.target?.result;
|
|
409
|
+
if (dataUrl) {
|
|
410
|
+
// 드롭 위치에 커서 설정
|
|
411
|
+
if (editorRef.current) {
|
|
412
|
+
editorRef.current.focus();
|
|
413
|
+
}
|
|
414
|
+
insertImageAtCursor(dataUrl, file.name || 'dropped-image');
|
|
415
|
+
}
|
|
416
|
+
};
|
|
417
|
+
reader.readAsDataURL(file);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}, [insertImageAtCursor]);
|
|
371
421
|
// 붙여넣기 이벤트 핸들러 - 지원하지 않는 스타일 제거
|
|
372
422
|
const handlePaste = useCallback((e) => {
|
|
373
|
-
e.preventDefault();
|
|
374
423
|
const clipboardData = e.clipboardData;
|
|
375
424
|
if (!clipboardData)
|
|
376
425
|
return;
|
|
426
|
+
// 클립보드에서 이미지 파일 확인
|
|
427
|
+
const items = clipboardData.items;
|
|
428
|
+
if (items) {
|
|
429
|
+
for (let i = 0; i < items.length; i++) {
|
|
430
|
+
const item = items[i];
|
|
431
|
+
if (item.type.startsWith('image/')) {
|
|
432
|
+
e.preventDefault();
|
|
433
|
+
const file = item.getAsFile();
|
|
434
|
+
if (file) {
|
|
435
|
+
const reader = new FileReader();
|
|
436
|
+
reader.onload = (event) => {
|
|
437
|
+
const dataUrl = event.target?.result;
|
|
438
|
+
if (dataUrl) {
|
|
439
|
+
insertImageAtCursor(dataUrl, file.name || 'pasted-image');
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
reader.readAsDataURL(file);
|
|
443
|
+
}
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
// 파일로 붙여넣은 경우 (드래그 앤 드롭 등)
|
|
449
|
+
const files = clipboardData.files;
|
|
450
|
+
if (files && files.length > 0) {
|
|
451
|
+
for (let i = 0; i < files.length; i++) {
|
|
452
|
+
const file = files[i];
|
|
453
|
+
if (file.type.startsWith('image/')) {
|
|
454
|
+
e.preventDefault();
|
|
455
|
+
const reader = new FileReader();
|
|
456
|
+
reader.onload = (event) => {
|
|
457
|
+
const dataUrl = event.target?.result;
|
|
458
|
+
if (dataUrl) {
|
|
459
|
+
insertImageAtCursor(dataUrl, file.name || 'pasted-image');
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
reader.readAsDataURL(file);
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
// HTML/텍스트 붙여넣기 처리
|
|
468
|
+
e.preventDefault();
|
|
377
469
|
// HTML 데이터 가져오기
|
|
378
470
|
const html = clipboardData.getData('text/html');
|
|
379
471
|
const text = clipboardData.getData('text/plain');
|
|
@@ -2963,7 +3055,7 @@ const Editor = ({ value = '', width = '100%', height = '400px', minHeight, maxHe
|
|
|
2963
3055
|
minHeight: height === 'contents' ? 'auto' : 0,
|
|
2964
3056
|
height: height === 'contents' && savedEditorHeight ? `${savedEditorHeight}px` : undefined,
|
|
2965
3057
|
resize: 'none'
|
|
2966
|
-
}, placeholder: placeholder })) : (_jsx("div", { ref: editorRef, id: editorID, className: styles.editorContent, contentEditable: true, onInput: handleInput, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd, onPaste: handlePaste, onClick: handleEditorClick, onContextMenu: handleEditorContextMenu, onKeyUp: () => {
|
|
3058
|
+
}, placeholder: placeholder })) : (_jsx("div", { ref: editorRef, id: editorID, className: styles.editorContent, contentEditable: true, onInput: handleInput, onCompositionStart: handleCompositionStart, onCompositionEnd: handleCompositionEnd, onPaste: handlePaste, onDragOver: handleDragOver, onDrop: handleDrop, onClick: handleEditorClick, onContextMenu: handleEditorContextMenu, onKeyUp: () => {
|
|
2967
3059
|
detectCurrentParagraphStyle();
|
|
2968
3060
|
detectCurrentAlign();
|
|
2969
3061
|
}, onKeyDown: handleKeyDown, style: {
|
|
@@ -40,7 +40,8 @@
|
|
|
40
40
|
class: className = '',
|
|
41
41
|
alt = 'Avatar',
|
|
42
42
|
onclick,
|
|
43
|
-
|
|
43
|
+
...rest
|
|
44
|
+
}: Props & Record<string, unknown> = $props();
|
|
44
45
|
|
|
45
46
|
let wrapperClasses = $derived(
|
|
46
47
|
[styles.wrapper, activityRing && styles.activityRing, className]
|
|
@@ -75,6 +76,7 @@
|
|
|
75
76
|
onkeydown={onclick ? (e) => e.key === 'Enter' && onclick() : undefined}
|
|
76
77
|
role={onclick ? 'button' : undefined}
|
|
77
78
|
tabindex={onclick ? 0 : undefined}
|
|
79
|
+
{...rest}
|
|
78
80
|
>
|
|
79
81
|
<div
|
|
80
82
|
class={avatarClasses}
|
|
@@ -25,6 +25,7 @@ interface Props {
|
|
|
25
25
|
/** Click handler */
|
|
26
26
|
onclick?: () => void;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
type $$ComponentProps = Props & Record<string, unknown>;
|
|
29
|
+
declare const Avatar: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
29
30
|
type Avatar = ReturnType<typeof Avatar>;
|
|
30
31
|
export default Avatar;
|
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
icon,
|
|
33
33
|
ondelete,
|
|
34
34
|
class: className = '',
|
|
35
|
-
|
|
35
|
+
...rest
|
|
36
|
+
}: Props & Record<string, unknown> = $props();
|
|
36
37
|
|
|
37
38
|
let chipClasses = $derived(
|
|
38
39
|
[
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
);
|
|
49
50
|
</script>
|
|
50
51
|
|
|
51
|
-
<div class={chipClasses}>
|
|
52
|
+
<div class={chipClasses} {...rest}>
|
|
52
53
|
{#if icon}
|
|
53
54
|
<i class="icon {icon}"></i>
|
|
54
55
|
{/if}
|
|
@@ -19,6 +19,7 @@ interface Props {
|
|
|
19
19
|
/** Additional class name */
|
|
20
20
|
class?: string;
|
|
21
21
|
}
|
|
22
|
-
|
|
22
|
+
type $$ComponentProps = Props & Record<string, unknown>;
|
|
23
|
+
declare const Chip: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
23
24
|
type Chip = ReturnType<typeof Chip>;
|
|
24
25
|
export default Chip;
|