podo-ui 0.9.7 → 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.
Files changed (74) hide show
  1. package/cdn/podo-datepicker.css +1 -1
  2. package/cdn/podo-datepicker.js +1 -1
  3. package/cdn/podo-datepicker.min.css +1 -1
  4. package/cdn/podo-datepicker.min.js +1 -1
  5. package/cdn/podo-ui.css +4 -1
  6. package/cdn/podo-ui.min.css +1 -1
  7. package/dist/react/atom/editor.d.ts.map +1 -1
  8. package/dist/react/atom/editor.js +94 -2
  9. package/dist/svelte/actions/portal.d.ts +18 -0
  10. package/dist/svelte/actions/portal.js +42 -0
  11. package/dist/svelte/atom/Avatar.svelte +97 -0
  12. package/dist/svelte/atom/Avatar.svelte.d.ts +31 -0
  13. package/dist/svelte/atom/Button.svelte +86 -0
  14. package/dist/svelte/atom/Button.svelte.d.ts +26 -0
  15. package/dist/svelte/atom/Checkbox.svelte +56 -0
  16. package/dist/svelte/atom/Checkbox.svelte.d.ts +16 -0
  17. package/dist/svelte/atom/Chip.svelte +60 -0
  18. package/dist/svelte/atom/Chip.svelte.d.ts +25 -0
  19. package/dist/svelte/atom/Editor.svelte +1314 -0
  20. package/dist/svelte/atom/Editor.svelte.d.ts +30 -0
  21. package/dist/svelte/atom/EditorView.svelte +16 -0
  22. package/dist/svelte/atom/EditorView.svelte.d.ts +9 -0
  23. package/dist/svelte/atom/File.svelte +33 -0
  24. package/dist/svelte/atom/File.svelte.d.ts +14 -0
  25. package/dist/svelte/atom/Input.svelte +80 -0
  26. package/dist/svelte/atom/Input.svelte.d.ts +19 -0
  27. package/dist/svelte/atom/Label.svelte +43 -0
  28. package/dist/svelte/atom/Label.svelte.d.ts +19 -0
  29. package/dist/svelte/atom/Radio.svelte +69 -0
  30. package/dist/svelte/atom/Radio.svelte.d.ts +26 -0
  31. package/dist/svelte/atom/RadioGroup.svelte +46 -0
  32. package/dist/svelte/atom/RadioGroup.svelte.d.ts +16 -0
  33. package/dist/svelte/atom/Select.svelte +65 -0
  34. package/dist/svelte/atom/Select.svelte.d.ts +26 -0
  35. package/dist/svelte/atom/Textarea.svelte +53 -0
  36. package/dist/svelte/atom/Textarea.svelte.d.ts +13 -0
  37. package/dist/svelte/atom/Toggle.svelte +48 -0
  38. package/dist/svelte/atom/Toggle.svelte.d.ts +14 -0
  39. package/dist/svelte/atom/Tooltip.svelte +78 -0
  40. package/dist/svelte/atom/Tooltip.svelte.d.ts +23 -0
  41. package/dist/svelte/atom/avatar.module.scss +82 -0
  42. package/dist/svelte/atom/editor-view.module.scss +251 -0
  43. package/dist/svelte/atom/input.module.scss +98 -0
  44. package/dist/svelte/atom/textarea.module.scss +17 -0
  45. package/dist/svelte/atom/tooltip.module.scss +227 -0
  46. package/dist/svelte/index.d.ts +26 -0
  47. package/dist/svelte/index.js +30 -0
  48. package/dist/svelte/molecule/DatePicker.svelte +986 -0
  49. package/dist/svelte/molecule/DatePicker.svelte.d.ts +71 -0
  50. package/dist/svelte/molecule/Field.svelte +81 -0
  51. package/dist/svelte/molecule/Field.svelte.d.ts +26 -0
  52. package/dist/svelte/molecule/Pagination.svelte +95 -0
  53. package/dist/svelte/molecule/Pagination.svelte.d.ts +14 -0
  54. package/dist/svelte/molecule/Tab.svelte +69 -0
  55. package/dist/svelte/molecule/Tab.svelte.d.ts +26 -0
  56. package/dist/svelte/molecule/TabPanel.svelte +24 -0
  57. package/dist/svelte/molecule/TabPanel.svelte.d.ts +14 -0
  58. package/dist/svelte/molecule/Table.svelte +109 -0
  59. package/dist/svelte/molecule/Table.svelte.d.ts +54 -0
  60. package/dist/svelte/molecule/Toast.svelte +111 -0
  61. package/dist/svelte/molecule/Toast.svelte.d.ts +25 -0
  62. package/dist/svelte/molecule/ToastProvider.svelte +74 -0
  63. package/dist/svelte/molecule/ToastProvider.svelte.d.ts +8 -0
  64. package/dist/svelte/molecule/field.module.scss +22 -0
  65. package/dist/svelte/molecule/pagination.module.scss +61 -0
  66. package/dist/svelte/molecule/toast-container.module.scss +70 -0
  67. package/dist/svelte/molecule/toast.module.scss +12 -0
  68. package/dist/svelte/stores/toast.d.ts +45 -0
  69. package/dist/svelte/stores/toast.js +55 -0
  70. package/dist/svelte/stores/validation.d.ts +15 -0
  71. package/dist/svelte/stores/validation.js +38 -0
  72. package/global.scss +1 -0
  73. package/package.json +32 -5
  74. package/vite-fonts.scss +1 -1
@@ -0,0 +1,78 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import styles from './tooltip.module.scss';
4
+
5
+ type TooltipVariant = 'default' | 'info';
6
+
7
+ type TooltipPosition =
8
+ | 'top'
9
+ | 'topLeft'
10
+ | 'topRight'
11
+ | 'bottom'
12
+ | 'bottomLeft'
13
+ | 'bottomRight'
14
+ | 'left'
15
+ | 'leftTop'
16
+ | 'leftBottom'
17
+ | 'right'
18
+ | 'rightTop'
19
+ | 'rightBottom';
20
+
21
+ interface Props {
22
+ /** Trigger element (button, icon, etc.) */
23
+ children: Snippet;
24
+ /** Tooltip content (can include any JSX) */
25
+ content: Snippet;
26
+ /** Tooltip visual variant */
27
+ variant?: TooltipVariant;
28
+ /** Arrow position */
29
+ position?: TooltipPosition;
30
+ /** Distance from trigger element in pixels */
31
+ offset?: number;
32
+ /** Control visibility externally (overrides hover state) */
33
+ isVisible?: boolean;
34
+ /** Additional CSS class */
35
+ class?: string;
36
+ }
37
+
38
+ let {
39
+ children,
40
+ content,
41
+ variant = 'default',
42
+ position = 'top',
43
+ offset = 8,
44
+ isVisible: controlledIsVisible,
45
+ class: className = '',
46
+ ...rest
47
+ }: Props & Record<string, unknown> = $props();
48
+
49
+ let hoverIsVisible = $state(false);
50
+
51
+ let variantClass = $derived(
52
+ variant === 'default' ? styles.variantDefault : styles.variantInfo
53
+ );
54
+
55
+ let tooltipClassNames = $derived(
56
+ [styles.tooltipBox, variantClass, styles[position], className]
57
+ .filter(Boolean)
58
+ .join(' ')
59
+ );
60
+
61
+ // Show tooltip if controlled visibility is true OR hover state is true
62
+ let shouldShowTooltip = $derived(controlledIsVisible === true || hoverIsVisible);
63
+ </script>
64
+
65
+ <div
66
+ class={styles.tooltipWrapper}
67
+ onmouseenter={() => (hoverIsVisible = true)}
68
+ onmouseleave={() => (hoverIsVisible = false)}
69
+ role="presentation"
70
+ {...rest}
71
+ >
72
+ {@render children()}
73
+ {#if shouldShowTooltip}
74
+ <div class={tooltipClassNames} style="--tooltip-offset: {offset}px;">
75
+ {@render content()}
76
+ </div>
77
+ {/if}
78
+ </div>
@@ -0,0 +1,23 @@
1
+ import type { Snippet } from 'svelte';
2
+ type TooltipVariant = 'default' | 'info';
3
+ type TooltipPosition = 'top' | 'topLeft' | 'topRight' | 'bottom' | 'bottomLeft' | 'bottomRight' | 'left' | 'leftTop' | 'leftBottom' | 'right' | 'rightTop' | 'rightBottom';
4
+ interface Props {
5
+ /** Trigger element (button, icon, etc.) */
6
+ children: Snippet;
7
+ /** Tooltip content (can include any JSX) */
8
+ content: Snippet;
9
+ /** Tooltip visual variant */
10
+ variant?: TooltipVariant;
11
+ /** Arrow position */
12
+ position?: TooltipPosition;
13
+ /** Distance from trigger element in pixels */
14
+ offset?: number;
15
+ /** Control visibility externally (overrides hover state) */
16
+ isVisible?: boolean;
17
+ /** Additional CSS class */
18
+ class?: string;
19
+ }
20
+ type $$ComponentProps = Props & Record<string, unknown>;
21
+ declare const Tooltip: import("svelte").Component<$$ComponentProps, {}, "">;
22
+ type Tooltip = ReturnType<typeof Tooltip>;
23
+ export default Tooltip;
@@ -0,0 +1,82 @@
1
+ @use '../../../mixin' as *;
2
+
3
+ .wrapper {
4
+ position: relative;
5
+ display: inline-flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ flex-shrink: 0;
9
+
10
+ &[role='button'] {
11
+ cursor: pointer;
12
+
13
+ &:hover {
14
+ opacity: 0.9;
15
+ }
16
+ }
17
+ }
18
+
19
+ .activityRing {
20
+ &::before {
21
+ content: '';
22
+ position: absolute;
23
+ top: 0;
24
+ left: 0;
25
+ right: 0;
26
+ bottom: 0;
27
+ border: 3px solid color('primary');
28
+ border-radius: r(full);
29
+ pointer-events: none;
30
+ }
31
+ }
32
+
33
+ .avatar {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ border-radius: r(full);
38
+ overflow: hidden;
39
+ position: relative;
40
+ font-weight: 600;
41
+ user-select: none;
42
+
43
+ // Type variations
44
+ &.type-image {
45
+ background-color: transparent;
46
+ }
47
+
48
+ &.type-icon,
49
+ &.type-text {
50
+ background-color: color('border');
51
+ color: color('text-sub');
52
+ }
53
+
54
+ // Image inside avatar
55
+ .image {
56
+ width: 100%;
57
+ height: 100%;
58
+ object-fit: cover;
59
+ }
60
+
61
+ // Icon styling
62
+ i[class^='icon-'],
63
+ i[class*=' icon-'] {
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ margin-right: 0 !important;
68
+ font-size: inherit;
69
+
70
+ &::before {
71
+ font-size: inherit !important;
72
+ line-height: 1;
73
+ }
74
+ }
75
+
76
+ // Text styling
77
+ span {
78
+ text-transform: uppercase;
79
+ line-height: 1;
80
+ font-size: inherit;
81
+ }
82
+ }
@@ -0,0 +1,251 @@
1
+ @use '../../../scss/color/function.scss' as *;
2
+ @use '../../../scss/typo/mixin.scss' as typo;
3
+ @use '../../../scss/layout/radius.scss' as *;
4
+
5
+ .editorView {
6
+ color: color(text-body);
7
+ font-family: inherit;
8
+ word-wrap: break-word;
9
+ overflow-wrap: break-word;
10
+
11
+ // 텍스트 서식
12
+ strong,
13
+ b {
14
+ font-weight: bold;
15
+ }
16
+
17
+ em,
18
+ i {
19
+ font-style: italic;
20
+ }
21
+
22
+ u {
23
+ text-decoration: underline;
24
+ }
25
+
26
+ s,
27
+ strike {
28
+ text-decoration: line-through;
29
+ }
30
+
31
+ // 제목 - podo-ui 스타일 상속
32
+ h1 {
33
+ @include typo.h1;
34
+ margin: 0.67em 0;
35
+ }
36
+
37
+ h2 {
38
+ @include typo.h2;
39
+ margin: 0.75em 0;
40
+ }
41
+
42
+ h3 {
43
+ @include typo.h3;
44
+ margin: 0.83em 0;
45
+ }
46
+
47
+ // p1~p5 스타일 클래스
48
+ .p1 {
49
+ @include typo.p1;
50
+ }
51
+
52
+ .p2 {
53
+ @include typo.p2;
54
+ }
55
+
56
+ .p3 {
57
+ @include typo.p3;
58
+ }
59
+
60
+ .p4 {
61
+ @include typo.p4;
62
+ }
63
+
64
+ .p5 {
65
+ @include typo.p5;
66
+ }
67
+
68
+ // Semibold 스타일
69
+ .p1_semibold {
70
+ @include typo.p1;
71
+ font-weight: 600;
72
+ }
73
+
74
+ .p2_semibold {
75
+ @include typo.p2;
76
+ font-weight: 600;
77
+ }
78
+
79
+ .p3_semibold {
80
+ @include typo.p3-semibold;
81
+ }
82
+
83
+ .p4_semibold {
84
+ @include typo.p4-semibold;
85
+ }
86
+
87
+ .p5_semibold {
88
+ @include typo.p5-semibold;
89
+ }
90
+
91
+ // 단락 - 기본 본문 스타일 p3 적용
92
+ p {
93
+ @include typo.p3;
94
+ margin: 1em 0;
95
+
96
+ &:first-child {
97
+ margin-top: 0;
98
+ }
99
+
100
+ &:last-child {
101
+ margin-bottom: 0;
102
+ }
103
+ }
104
+
105
+ // 링크
106
+ a {
107
+ color: color(link);
108
+ text-decoration: underline;
109
+ cursor: pointer;
110
+
111
+ &:hover {
112
+ color: color(link-hover);
113
+ }
114
+ }
115
+
116
+ // 목록 - podo-ui p3 스타일 적용
117
+ ul,
118
+ ol {
119
+ @include typo.p3;
120
+ margin: 1em 0 !important;
121
+ padding-left: 2em !important;
122
+ padding-top: 0 !important;
123
+ padding-right: 0 !important;
124
+ padding-bottom: 0 !important;
125
+
126
+ &:first-child {
127
+ margin-top: 0 !important;
128
+ }
129
+
130
+ &:last-child {
131
+ margin-bottom: 0 !important;
132
+ }
133
+ }
134
+
135
+ ul {
136
+ list-style: disc !important;
137
+ list-style-type: disc !important;
138
+ list-style-position: outside !important;
139
+ }
140
+
141
+ ol {
142
+ list-style: decimal !important;
143
+ list-style-type: decimal !important;
144
+ list-style-position: outside !important;
145
+ }
146
+
147
+ li {
148
+ display: list-item !important;
149
+ margin: 0.5em 0 !important;
150
+ padding: 0 !important;
151
+ list-style: inherit !important;
152
+ list-style-position: outside !important;
153
+
154
+ // 중첩된 리스트
155
+ ul,
156
+ ol {
157
+ margin: 0.5em 0 !important;
158
+ padding-left: 1.5em !important;
159
+ }
160
+
161
+ ul {
162
+ list-style-type: circle !important;
163
+ }
164
+
165
+ ol {
166
+ list-style-type: lower-alpha !important;
167
+ }
168
+ }
169
+
170
+ // 이미지
171
+ img {
172
+ display: inline-block !important;
173
+ vertical-align: middle;
174
+ max-width: 100%;
175
+ height: auto;
176
+ }
177
+
178
+ // 인용
179
+ blockquote {
180
+ @include typo.p3;
181
+ margin: 1em 0;
182
+ padding-left: 1em;
183
+ border-left: 4px solid color(border);
184
+ color: color(text-sub);
185
+ font-style: italic;
186
+ }
187
+
188
+ // 유튜브 컨테이너 (editor에서 삽입된 스타일 유지)
189
+ :global(.youtube-container) {
190
+ position: relative;
191
+ display: inline-block;
192
+ max-width: 100%;
193
+
194
+ iframe {
195
+ width: 100%;
196
+ height: 100%;
197
+ display: block;
198
+ }
199
+
200
+ :global(.youtube-overlay) {
201
+ display: none; // view 모드에서는 오버레이 숨김
202
+ }
203
+ }
204
+
205
+ // 인라인 코드
206
+ code {
207
+ @include typo.p4;
208
+ background: color(bg-elevation-1);
209
+ color: color(text-body);
210
+ padding: 2px 6px;
211
+ border-radius: r(1);
212
+ border: 1px solid color(default-outline);
213
+ }
214
+
215
+ // 코드 블록
216
+ pre {
217
+ @include typo.p3;
218
+ background: color(bg-elevation-1);
219
+ color: color(text-body);
220
+ padding: 12px 16px;
221
+ border-radius: r(2);
222
+ border: 1px solid color(default-outline);
223
+ overflow-x: auto;
224
+ margin: 1em 0;
225
+
226
+ code {
227
+ background: transparent;
228
+ border: none;
229
+ padding: 0;
230
+ }
231
+ }
232
+
233
+ // 하이라이트/배경색이 있는 요소 (다크모드 대응)
234
+ span[style*='background-color'] {
235
+ padding: 2px 4px;
236
+ border-radius: 2px;
237
+ }
238
+
239
+ // 텍스트 색상이 너무 밝거나 어두운 경우 자동 조정
240
+ span[style*='color: #fff'],
241
+ span[style*='color: white'],
242
+ span[style*='color: rgb(255, 255, 255)'] {
243
+ color: color(text-body) !important;
244
+ }
245
+
246
+ span[style*='color: #000'],
247
+ span[style*='color: black'],
248
+ span[style*='color: rgb(0, 0, 0)'] {
249
+ color: color(text-body) !important;
250
+ }
251
+ }
@@ -0,0 +1,98 @@
1
+ @use '../../../mixin.scss' as *;
2
+ .style {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: s(3);
6
+
7
+ > div {
8
+ position: relative;
9
+ width: fit-content;
10
+
11
+ > i {
12
+ position: absolute;
13
+ top: 50%;
14
+ transform: translateY(-50%);
15
+ color: color('text-sub');
16
+ pointer-events: none;
17
+ }
18
+
19
+ &:global(.with-icon) {
20
+ > i {
21
+ left: s(3);
22
+ }
23
+
24
+ > input {
25
+ padding-left: s(8);
26
+ }
27
+ }
28
+
29
+ &:global(.with-right-icon) {
30
+ > i {
31
+ right: s(3);
32
+ }
33
+
34
+ > input {
35
+ padding-right: s(7);
36
+ }
37
+ }
38
+
39
+ :global(.unit) {
40
+ position: absolute;
41
+ right: s(3);
42
+ top: 50%;
43
+ transform: translateY(-50%);
44
+ color: color('text-sub');
45
+ pointer-events: none;
46
+ }
47
+
48
+ > input {
49
+ @include p3;
50
+ padding: s(3) s(4);
51
+ background-color: color('bg-block');
52
+ border-radius: r(3);
53
+ border: 1px solid color('border-disabled');
54
+
55
+ &:focus-visible:not(:disabled) {
56
+ border-color: color('primary-base');
57
+ outline: 4px solid color('primary-outline');
58
+ }
59
+
60
+ &::placeholder {
61
+ color: color('placeholder');
62
+ }
63
+
64
+ &:global(.success) {
65
+ border-color: color('success');
66
+
67
+ &:focus-visible:not(:disabled) {
68
+ outline: 4px solid color('success-outline');
69
+ }
70
+ }
71
+
72
+ &:global(.danger) {
73
+ border-color: color('danger');
74
+
75
+ &:focus-visible:not(:disabled) {
76
+ outline: 4px solid color('danger-outline');
77
+ }
78
+ }
79
+
80
+ /* Chrome, Safari, Edge, Opera */
81
+ &::-webkit-outer-spin-button,
82
+ &::-webkit-inner-spin-button {
83
+ -webkit-appearance: none;
84
+ margin: 0;
85
+ }
86
+
87
+ /* Firefox */
88
+ &[type='number'] {
89
+ -moz-appearance: textfield;
90
+ }
91
+ }
92
+ }
93
+
94
+ :global(.validator) {
95
+ @include p4;
96
+ color: color('danger');
97
+ }
98
+ }
@@ -0,0 +1,17 @@
1
+ @use '../../../mixin.scss' as *;
2
+ .style {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: s(3);
6
+ &:global {
7
+ > textarea {
8
+ width: 100%;
9
+ }
10
+ > div.validator {
11
+ @include p4;
12
+ & {
13
+ color: color('text-sub');
14
+ }
15
+ }
16
+ }
17
+ }