@iyulab/components 0.1.3 → 0.1.5

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 (124) hide show
  1. package/CHANGELOG.md +18 -15
  2. package/LICENSE +20 -20
  3. package/README.md +33 -33
  4. package/dist/assets/icons/arrow-clockwise.svg.js +1 -1
  5. package/dist/assets/icons/arrow-down.svg.js +1 -1
  6. package/dist/assets/icons/arrow-up.svg.js +1 -1
  7. package/dist/assets/icons/ban.svg.js +1 -1
  8. package/dist/assets/icons/check-circle-fill.svg.js +1 -1
  9. package/dist/assets/icons/check-lg.svg.js +1 -1
  10. package/dist/assets/icons/chevron-down.svg.js +1 -1
  11. package/dist/assets/icons/chevron-left.svg.js +1 -1
  12. package/dist/assets/icons/chevron-right.svg.js +1 -1
  13. package/dist/assets/icons/chevron-up.svg.js +1 -1
  14. package/dist/assets/icons/copy.svg.js +1 -1
  15. package/dist/assets/icons/dash-lg.svg.js +1 -1
  16. package/dist/assets/icons/exclamation-circle-fill.svg.js +1 -1
  17. package/dist/assets/icons/exclamation-triangle-fill.svg.js +1 -1
  18. package/dist/assets/icons/info-circle-fill.svg.js +1 -1
  19. package/dist/assets/icons/layout-sidebar.svg.js +1 -1
  20. package/dist/assets/icons/lightbulb-fill.svg.js +1 -1
  21. package/dist/assets/icons/lightbulb-off.svg.js +1 -1
  22. package/dist/assets/icons/lightbulb.svg.js +1 -1
  23. package/dist/assets/icons/mic-fill.svg.js +1 -1
  24. package/dist/assets/icons/mic-mute-fill.svg.js +1 -1
  25. package/dist/assets/icons/paperclip.svg.js +1 -1
  26. package/dist/assets/icons/pencil-square.svg.js +1 -1
  27. package/dist/assets/icons/plus-lg.svg.js +1 -1
  28. package/dist/assets/icons/search.svg.js +1 -1
  29. package/dist/assets/icons/speedometer.svg.js +1 -1
  30. package/dist/assets/icons/x-lg.svg.js +1 -1
  31. package/dist/assets/styles/dark.css +129 -125
  32. package/dist/assets/styles/dark.css.js +1 -1
  33. package/dist/assets/styles/light.css +129 -126
  34. package/dist/assets/styles/light.css.js +1 -1
  35. package/dist/components/BaseElement.styles.js +2 -3
  36. package/dist/components/alert/Alert.d.ts +8 -4
  37. package/dist/components/alert/Alert.js +24 -15
  38. package/dist/components/alert/Alert.styles.js +32 -39
  39. package/dist/components/alert/index.js +5 -0
  40. package/dist/components/button/Button.js +4 -2
  41. package/dist/components/button/Button.styles.js +13 -20
  42. package/dist/components/button/index.js +5 -0
  43. package/dist/components/context-menu/index.js +5 -0
  44. package/dist/components/copy-button/CopyButton.d.ts +7 -3
  45. package/dist/components/copy-button/CopyButton.js +69 -0
  46. package/dist/components/copy-button/CopyButton.styles.js +17 -0
  47. package/dist/components/copy-button/index.js +5 -0
  48. package/dist/components/dialog/index.js +5 -0
  49. package/dist/components/divider/Divider.d.ts +25 -0
  50. package/dist/components/divider/Divider.js +89 -0
  51. package/dist/components/{split-panel/Splitter.styles.js → divider/Divider.styles.js} +25 -13
  52. package/dist/components/divider/index.d.ts +7 -0
  53. package/dist/components/divider/index.js +5 -0
  54. package/dist/components/form/Form.d.ts +3 -1
  55. package/dist/components/form/Form.js +3 -1
  56. package/dist/components/form/Form.styles.js +1 -0
  57. package/dist/components/form/index.js +5 -0
  58. package/dist/components/icon/Icon.d.ts +6 -16
  59. package/dist/components/icon/Icon.js +17 -40
  60. package/dist/components/icon/Icon.styles.js +1 -1
  61. package/dist/components/icon/index.js +5 -0
  62. package/dist/components/icon-button/IconButton.d.ts +3 -3
  63. package/dist/components/icon-button/IconButton.js +6 -6
  64. package/dist/components/icon-button/IconButton.styles.js +14 -29
  65. package/dist/components/icon-button/index.js +5 -0
  66. package/dist/components/index.d.ts +2 -1
  67. package/dist/components/input/Input.d.ts +14 -13
  68. package/dist/components/input/Input.js +56 -55
  69. package/dist/components/input/Input.styles.js +52 -54
  70. package/dist/components/input/index.js +5 -0
  71. package/dist/components/menu/index.js +5 -0
  72. package/dist/components/progress-bar/ProgressBar.d.ts +2 -2
  73. package/dist/components/progress-bar/ProgressBar.js +2 -2
  74. package/dist/components/progress-bar/ProgressBar.styles.js +10 -10
  75. package/dist/components/progress-bar/index.js +5 -0
  76. package/dist/components/progress-ring/ProgressRing.d.ts +2 -2
  77. package/dist/components/progress-ring/ProgressRing.js +9 -6
  78. package/dist/components/progress-ring/ProgressRing.styles.js +8 -9
  79. package/dist/components/progress-ring/index.js +5 -0
  80. package/dist/components/spinner/Spinner.styles.js +5 -3
  81. package/dist/components/spinner/index.js +5 -0
  82. package/dist/components/split-panel/SplitPanel.d.ts +8 -12
  83. package/dist/components/split-panel/SplitPanel.js +64 -91
  84. package/dist/components/split-panel/SplitPanel.styles.js +16 -1
  85. package/dist/components/split-panel/index.js +5 -0
  86. package/dist/components/tooltip/Tooltip.d.ts +8 -12
  87. package/dist/components/tooltip/Tooltip.js +39 -38
  88. package/dist/components/tooltip/Tooltip.styles.js +5 -5
  89. package/dist/components/tooltip/index.js +5 -0
  90. package/dist/components/tree/Tree.d.ts +2 -14
  91. package/dist/components/tree/Tree.js +9 -49
  92. package/dist/components/tree/Tree.styles.js +5 -5
  93. package/dist/components/tree/index.js +5 -0
  94. package/dist/components/tree-item/TreeItem.d.ts +10 -29
  95. package/dist/components/tree-item/TreeItem.js +63 -95
  96. package/dist/components/tree-item/TreeItem.styles.js +10 -41
  97. package/dist/components/tree-item/index.js +5 -0
  98. package/dist/index.js +25 -5
  99. package/dist/integrations/react/UDivider.d.ts +8 -0
  100. package/dist/integrations/react/UDivider.js +10 -0
  101. package/dist/integrations/react/index.d.ts +1 -1
  102. package/dist/integrations/react/index.js +1 -1
  103. package/dist/internals/index.d.ts +0 -1
  104. package/dist/utilities/decorators.js +2 -0
  105. package/dist/utilities/icons.d.ts +46 -0
  106. package/dist/{internals → utilities}/icons.js +74 -2
  107. package/dist/utilities/index.d.ts +1 -0
  108. package/dist/utilities/notifier.d.ts +17 -7
  109. package/dist/utilities/notifier.js +51 -41
  110. package/dist/utilities/theme.d.ts +15 -20
  111. package/dist/utilities/theme.js +36 -29
  112. package/package.json +59 -58
  113. package/dist/components/panel/Panel.d.ts +0 -10
  114. package/dist/components/panel/Panel.js +0 -21
  115. package/dist/components/panel/Panel.styles.js +0 -12
  116. package/dist/components/panel/index.d.ts +0 -7
  117. package/dist/components/split-panel/SplitPanel.types.d.ts +0 -2
  118. package/dist/components/split-panel/Splitter.d.ts +0 -17
  119. package/dist/components/split-panel/Splitter.js +0 -45
  120. package/dist/components/split-panel/Splitter.styles.d.ts +0 -1
  121. package/dist/integrations/react/UPanel.d.ts +0 -8
  122. package/dist/integrations/react/UPanel.js +0 -10
  123. package/dist/internals/icons.d.ts +0 -6
  124. /package/dist/components/{panel/Panel.styles.d.ts → divider/Divider.styles.d.ts} +0 -0
@@ -6,63 +6,48 @@ const styles = css`
6
6
  display: inline-flex;
7
7
 
8
8
  font-size: 16px;
9
- color: var(--u-icon-color);
10
9
  padding: 0.5em;
11
- background-color: var(--u-bg-color);
10
+ color: var(--u-icon-color);
12
11
  border: 1px solid var(--u-border-color);
13
12
  border-radius: 6px;
13
+ background-color: var(--u-bg-color);
14
14
 
15
15
  transition: all 0.2s ease;
16
16
  user-select: none;
17
17
  cursor: pointer;
18
18
  }
19
- :host([borderless]) {
20
- border: none;
21
- background-color: transparent;
22
- }
23
- :host([borderless]:hover) {
24
- border: none;
25
- background-color: transparent;
26
- }
27
- :host([borderless]:active) {
28
- border: none;
29
- background-color: transparent;
30
- }
31
- :host([loading]),
32
- :host([disabled]) {
33
- pointer-events: none;
34
- }
35
- :host([disabled]) {
36
- opacity: 0.6;
37
- color: var(--u-icon-color-disabled);
38
- }
39
19
  :host(:hover) {
40
20
  color: var(--u-icon-color-hover);
41
21
  background-color: var(--u-bg-color-hover);
42
- border-color: var(--u-border-color-strong);
43
22
  }
44
23
  :host(:active) {
45
24
  color: var(--u-icon-color-active);
46
25
  background-color: var(--u-bg-color-active);
47
26
  transform: translateY(1px);
48
27
  }
28
+ :host([borderless]) {
29
+ border: none;
30
+ background-color: transparent;
31
+ }
32
+ :host([loading]),
33
+ :host([disabled]) {
34
+ color: var(--u-icon-color-disabled);
35
+ pointer-events: none;
36
+ }
49
37
 
50
38
  button {
51
39
  all: unset;
52
40
  display: inline-flex;
53
- align-items: center;
54
- justify-content: center;
55
41
  }
56
42
  button:focus-visible {
57
43
  outline: 2px solid var(--u-blue-500, #3b82f6);
58
44
  outline-offset: 2px;
59
- border-radius: inherit;
60
45
  }
61
46
 
62
- u-icon,
63
- u-spinner {
64
- font-size: inherit;
47
+ u-spinner,
48
+ u-icon {
65
49
  color: inherit;
50
+ font-size: inherit;
66
51
  }
67
52
  `;
68
53
 
@@ -0,0 +1,5 @@
1
+ import { IconButton } from './IconButton.js';
2
+
3
+ IconButton.define("u-icon-button");
4
+
5
+ export { IconButton };
@@ -1,13 +1,14 @@
1
1
  export * from './alert';
2
2
  export * from './button';
3
3
  export * from './context-menu';
4
+ export * from './copy-button';
4
5
  export * from './dialog';
6
+ export * from './divider';
5
7
  export * from './form';
6
8
  export * from './icon';
7
9
  export * from './icon-button';
8
10
  export * from './input';
9
11
  export * from './menu';
10
- export * from './panel';
11
12
  export * from './progress-bar';
12
13
  export * from './progress-ring';
13
14
  export * from './spinner';
@@ -1,5 +1,7 @@
1
1
  import { PropertyValues } from 'lit';
2
2
  import { BaseElement } from '../BaseElement.js';
3
+ /** 지원하는 input 타입 */
4
+ type InputType = ('text' | 'password' | 'email' | 'tel' | 'url' | 'search' | 'number' | 'date' | 'time' | 'datetime-local' | 'month' | 'week');
3
5
  /**
4
6
  * Input 컴포넌트는 사용자 입력을 받는 텍스트 입력 필드입니다.
5
7
  * prefix, suffix 슬롯과 라벨, 도움말, 유효성 검사 등의 기능을 제공합니다.
@@ -7,23 +9,23 @@ import { BaseElement } from '../BaseElement.js';
7
9
  export declare class Input extends BaseElement {
8
10
  static styles: import('lit').CSSResultGroup[];
9
11
  static dependencies: Record<string, typeof BaseElement>;
10
- input: HTMLInputElement;
11
- /** password type인 경우 비밀번호 표시/숨김 상태 */
12
- showPassword: boolean;
12
+ inputEl: HTMLInputElement;
13
13
  /** 유효성 검사 실패 여부 */
14
14
  isInvalid: boolean;
15
15
  /** 현재 표시할 유효성 검사 메시지 */
16
16
  currentValidationMessage: string;
17
+ /** password type인 경우 비밀번호 표시/숨김 상태 */
18
+ showPassword: boolean;
17
19
  /** input 요소의 type 속성 */
18
- type: 'text' | 'email' | 'password' | 'search' | 'tel' | 'url' | 'number';
20
+ type: InputType;
19
21
  /** 필수 입력 여부 */
20
22
  required: boolean;
23
+ /** 읽기 전용 여부 */
24
+ readonly: boolean;
21
25
  /** 비활성화 여부 */
22
26
  disabled: boolean;
23
27
  /** 클리어 버튼 표시 여부 */
24
28
  clearable: boolean;
25
- /** 읽기 전용 여부 */
26
- readonly: boolean;
27
29
  /** input 요소의 name 속성 */
28
30
  name?: string;
29
31
  /** 라벨 텍스트 */
@@ -50,8 +52,6 @@ export declare class Input extends BaseElement {
50
52
  validationMessage?: string;
51
53
  protected updated(changedProperties: PropertyValues): void;
52
54
  render(): import('lit-html').TemplateResult<1>;
53
- /** 라벨 영역을 렌더링합니다. */
54
- private renderHeader;
55
55
  /** 유효성 검사를 수행합니다. */
56
56
  validate(): boolean;
57
57
  /** 입력값을 초기화합니다. */
@@ -63,11 +63,12 @@ export declare class Input extends BaseElement {
63
63
  /** input 이벤트 핸들러 */
64
64
  private handleInput;
65
65
  /** change 이벤트 핸들러 */
66
- private handleChange;
66
+ private handleInputChange;
67
67
  /** blur 이벤트 핸들러 */
68
- private handleBlur;
69
- /** 클리어 버튼 클릭 핸들러 */
70
- private handleClear;
68
+ private handleInputBlur;
71
69
  /** 비밀번호 표시/숨김 토글 핸들러 */
72
- private handlePasswordToggle;
70
+ private handlePasswordTogglerClick;
71
+ /** 클리어 버튼 클릭 핸들러 */
72
+ private handleClearBtnClick;
73
73
  }
74
+ export {};
@@ -1,4 +1,4 @@
1
- import { html, nothing } from 'lit';
1
+ import { nothing, html } from 'lit';
2
2
  import { query, state, property } from 'lit/decorators.js';
3
3
  import { ifDefined } from 'lit/directives/if-defined.js';
4
4
  import { live } from 'lit/directives/live.js';
@@ -19,14 +19,14 @@ var __decorateClass = (decorators, target, key, kind) => {
19
19
  class Input extends BaseElement {
20
20
  constructor() {
21
21
  super(...arguments);
22
- this.showPassword = false;
23
22
  this.isInvalid = false;
24
23
  this.currentValidationMessage = "";
24
+ this.showPassword = false;
25
25
  this.type = "text";
26
26
  this.required = false;
27
+ this.readonly = false;
27
28
  this.disabled = false;
28
29
  this.clearable = false;
29
- this.readonly = false;
30
30
  this.spellcheck = false;
31
31
  this.value = "";
32
32
  /** input 이벤트 핸들러 */
@@ -40,26 +40,28 @@ class Input extends BaseElement {
40
40
  this.emit("u-input", { value: this.value });
41
41
  };
42
42
  /** change 이벤트 핸들러 */
43
- this.handleChange = (e) => {
43
+ this.handleInputChange = (e) => {
44
44
  const input = e.target;
45
45
  this.value = input.value;
46
46
  this.emit("u-change", { value: this.value });
47
47
  };
48
48
  /** blur 이벤트 핸들러 */
49
- this.handleBlur = () => {
49
+ this.handleInputBlur = () => {
50
50
  this.validate();
51
51
  };
52
- /** 클리어 버튼 클릭 핸들러 */
53
- this.handleClear = (e) => {
54
- e.stopPropagation();
55
- this.clear();
56
- };
57
52
  /** 비밀번호 표시/숨김 토글 핸들러 */
58
- this.handlePasswordToggle = (e) => {
53
+ this.handlePasswordTogglerClick = (e) => {
54
+ e.preventDefault();
59
55
  e.stopPropagation();
60
56
  this.showPassword = !this.showPassword;
61
57
  this.focus();
62
58
  };
59
+ /** 클리어 버튼 클릭 핸들러 */
60
+ this.handleClearBtnClick = (e) => {
61
+ e.preventDefault();
62
+ e.stopPropagation();
63
+ this.clear();
64
+ };
63
65
  }
64
66
  static {
65
67
  this.styles = [super.styles, styles];
@@ -72,21 +74,34 @@ class Input extends BaseElement {
72
74
  }
73
75
  updated(changedProperties) {
74
76
  super.updated(changedProperties);
75
- if (changedProperties.has("value") && this.input) {
76
- if (this.input.value !== this.value) {
77
- this.input.value = this.value;
77
+ if (changedProperties.has("value") && this.inputEl) {
78
+ if (this.inputEl.value !== this.value) {
79
+ this.inputEl.value = this.value;
78
80
  }
79
81
  }
80
82
  }
81
83
  render() {
82
84
  return html`
83
- ${this.renderHeader()}
85
+ <div class="header" ?hidden=${!this.label}>
86
+ ${this.required ? html`<span class="required-mark">*</span>` : nothing}
87
+
88
+ <label class="label" @click=${this.focus}>
89
+ ${this.label}
90
+ </label>
91
+
92
+ ${this.labelhelp ? html`
93
+ <u-icon class="help-icon" lib="internal" name="info-circle-fill"></u-icon>
94
+ <u-tooltip class="help-tooltip" trigger-selectors=".help-icon" placement="right-end">
95
+ ${this.labelhelp}
96
+ </u-tooltip>` : nothing}
97
+ </div>
84
98
 
85
99
  <div class="container"
86
100
  ?invalid=${this.isInvalid}
87
101
  ?disabled=${this.disabled}
88
102
  ?readonly=${this.readonly}>
89
- <slot name="prefix" class="prefix"></slot>
103
+
104
+ <slot name="prefix"></slot>
90
105
 
91
106
  <input part="input"
92
107
  type=${this.type === "password" && this.showPassword ? "text" : this.type}
@@ -94,33 +109,37 @@ class Input extends BaseElement {
94
109
  ?required=${this.required}
95
110
  ?disabled=${this.disabled}
96
111
  ?readonly=${this.readonly}
97
- placeholder=${ifDefined(this.placeholder)}
98
112
  minlength=${ifDefined(this.minlength)}
99
113
  maxlength=${ifDefined(this.maxlength)}
100
114
  spellcheck=${this.spellcheck}
101
115
  autocomplete=${ifDefined(this.autocomplete)}
116
+ placeholder=${ifDefined(this.placeholder)}
102
117
  pattern=${ifDefined(this.pattern)}
103
118
  .value=${live(this.value)}
104
119
  @input=${this.handleInput}
105
- @change=${this.handleChange}
106
- @blur=${this.handleBlur}
120
+ @change=${this.handleInputChange}
121
+ @blur=${this.handleInputBlur}
107
122
  />
108
123
 
109
- <slot name="suffix" class="suffix"></slot>
124
+ <slot name="suffix"></slot>
110
125
 
111
126
  <div class="tools">
112
- <u-icon class="tool" name=${this.showPassword ? "eye-slash" : "eye"}
127
+ <u-icon
128
+ lib="internal"
129
+ name=${this.showPassword ? "eye-slash" : "eye"}
113
130
  ?hidden=${this.type !== "password" || this.disabled || this.readonly}
114
- @click=${this.handlePasswordToggle}
131
+ @click=${this.handlePasswordTogglerClick}
115
132
  ></u-icon>
116
- <u-icon class="tool" name="x-lg"
133
+ <u-icon
134
+ lib="internal"
135
+ name="x-lg"
117
136
  ?hidden=${!this.clearable || !this.value || this.disabled || this.readonly}
118
- @click=${this.handleClear}
137
+ @click=${this.handleClearBtnClick}
119
138
  ></u-icon>
120
139
  </div>
121
140
  </div>
122
141
 
123
- <div class="validation-error" role="alert" ?hidden=${!this.currentValidationMessage}>
142
+ <div class="validation-message" ?hidden=${!this.currentValidationMessage}>
124
143
  ${this.currentValidationMessage}
125
144
  </div>
126
145
 
@@ -129,30 +148,13 @@ class Input extends BaseElement {
129
148
  </div>
130
149
  `;
131
150
  }
132
- /** 라벨 영역을 렌더링합니다. */
133
- renderHeader() {
134
- if (!this.label) return nothing;
135
- return html`
136
- <div class="header">
137
- <label class="label" @click=${this.focus}>
138
- ${this.label}
139
- ${this.required ? html`<span class="required-mark">*</span>` : ""}
140
- </label>
141
-
142
- ${this.labelhelp ? html`
143
- <u-icon class="help-icon" name="info-circle-fill"></u-icon>
144
- <u-tooltip trigger-selectors=".help-icon" placement="right-end">${this.labelhelp}</u-tooltip>
145
- ` : nothing}
146
- </div>
147
- `;
148
- }
149
151
  /** 유효성 검사를 수행합니다. */
150
152
  validate() {
151
- if (!this.input) return true;
152
- const isValid = this.input.checkValidity();
153
+ if (!this.inputEl) return true;
154
+ const isValid = this.inputEl.checkValidity();
153
155
  this.isInvalid = !isValid;
154
156
  if (!isValid) {
155
- this.currentValidationMessage = this.validationMessage || this.input.validationMessage;
157
+ this.currentValidationMessage = this.validationMessage || this.inputEl.validationMessage;
156
158
  } else {
157
159
  this.currentValidationMessage = "";
158
160
  }
@@ -164,29 +166,28 @@ class Input extends BaseElement {
164
166
  this.isInvalid = false;
165
167
  this.currentValidationMessage = "";
166
168
  this.focus();
167
- this.emit("u-clear");
168
169
  }
169
170
  /** 입력 필드에 포커스를 설정합니다. */
170
171
  focus() {
171
- this.input?.focus();
172
+ this.inputEl?.focus();
172
173
  }
173
174
  /** 입력 필드의 포커스를 해제합니다. */
174
175
  blur() {
175
- this.input?.blur();
176
+ this.inputEl?.blur();
176
177
  }
177
178
  }
178
179
  __decorateClass([
179
180
  query("input")
180
- ], Input.prototype, "input");
181
- __decorateClass([
182
- state()
183
- ], Input.prototype, "showPassword");
181
+ ], Input.prototype, "inputEl");
184
182
  __decorateClass([
185
183
  state()
186
184
  ], Input.prototype, "isInvalid");
187
185
  __decorateClass([
188
186
  state()
189
187
  ], Input.prototype, "currentValidationMessage");
188
+ __decorateClass([
189
+ state()
190
+ ], Input.prototype, "showPassword");
190
191
  __decorateClass([
191
192
  property({ type: String, reflect: true })
192
193
  ], Input.prototype, "type");
@@ -195,13 +196,13 @@ __decorateClass([
195
196
  ], Input.prototype, "required");
196
197
  __decorateClass([
197
198
  property({ type: Boolean, reflect: true })
198
- ], Input.prototype, "disabled");
199
+ ], Input.prototype, "readonly");
199
200
  __decorateClass([
200
201
  property({ type: Boolean, reflect: true })
201
- ], Input.prototype, "clearable");
202
+ ], Input.prototype, "disabled");
202
203
  __decorateClass([
203
204
  property({ type: Boolean, reflect: true })
204
- ], Input.prototype, "readonly");
205
+ ], Input.prototype, "clearable");
205
206
  __decorateClass([
206
207
  property({ type: String })
207
208
  ], Input.prototype, "name");
@@ -3,99 +3,98 @@ import { css } from 'lit';
3
3
  const styles = css`
4
4
  :host {
5
5
  display: inline-block;
6
+ color: var(--u-txt-color);
6
7
  font-size: inherit;
8
+ font-family: var(--u-font-base);
7
9
  }
8
10
  :host([disabled]) {
9
- opacity: 0.5;
11
+ opacity: 0.6;
12
+ cursor: not-allowed;
10
13
  }
11
14
 
12
15
  /* 헤더 영역 */
13
16
  .header {
14
17
  display: flex;
18
+ flex-direction: row;
15
19
  align-items: center;
16
- gap: 0.375em;
17
20
  margin-bottom: 0.5em;
21
+ user-select: none;
18
22
  }
19
23
  .header .label {
20
24
  font-size: 0.8em;
21
25
  font-weight: 500;
22
- line-height: 1;
23
- color: var(--u-text-color);
24
- user-select: none;
26
+ line-height: 1.2;
25
27
  cursor: pointer;
26
28
  }
27
29
  .header .required-mark {
28
30
  color: var(--u-red-600);
29
- margin-left: 0.25em;
31
+ margin-right: 0.25em;
30
32
  }
31
33
  .header .help-icon {
32
34
  font-size: 0.8em;
35
+ margin-left: 0.5em;
33
36
  cursor: help;
34
37
  }
38
+ .header .help-tooltip {
39
+ font-size: 0.6em;
40
+ }
35
41
 
36
42
  /* 입력 래퍼 */
37
43
  .container {
38
44
  display: flex;
45
+ flex-direction: row;
39
46
  align-items: center;
40
- gap: 0.5em;
41
- padding: 0.5em 0.75em;
42
- background-color: var(--u-bg-color);
47
+ padding: 0.3em 0.6em;
43
48
  border: 1px solid var(--u-input-border-color);
44
- border-radius: 0.375em;
49
+ border-radius: 0.25em;
50
+ background-color: var(--u-input-bg-color);
45
51
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
46
52
  }
47
- .container[invalid] {
48
- border-color: var(--u-red-600);
49
- }
50
- .container[invalid]:focus-within {
51
- box-shadow: 0 0 0 0.125em rgba(244, 67, 54, 0.1);
52
- }
53
+ .container[readonly],
53
54
  .container[disabled] {
54
- background-color: var(--u-bg-color-disabled);
55
55
  border-color: var(--u-border-color-weak);
56
- cursor: not-allowed;
56
+ background-color: var(--u-bg-color-disabled);
57
57
  }
58
- .container[readonly] {
59
- background-color: var(--u-neutral-50);
60
- border-color: var(--u-border-color-weak);
58
+ .container:hover:not([readonly]):not([disabled]) {
59
+ box-shadow:
60
+ 0 0 0 1px var(--u-input-border-color-hover),
61
+ 0 0 0 3px rgba(59, 130, 246, 0.12);
61
62
  }
62
- .container:hover:not(([disabled])):not(([readonly])) {
63
- border-color: var(--u-input-border-hover);
63
+ .container:focus-within:not([readonly]):not([disabled]) {
64
+ box-shadow:
65
+ 0 0 0 1px var(--u-input-border-color-focus),
66
+ 0 0 0 3px rgba(59, 130, 246, 0.22);
64
67
  }
65
- .container:focus-within:not(([disabled])):not(([readonly])) {
66
- border-color: var(--u-input-border-focus);
67
- box-shadow: 0 0 0 0.125em rgba(33, 150, 243, 0.1);
68
- outline: none;
68
+ .container[invalid]:not([readonly]):not([disabled]) {
69
+ box-shadow:
70
+ 0 0 0 1px var(--u-input-border-color-invalid),
71
+ 0 0 0 3px rgba(220, 38, 38, 0.12);
69
72
  }
70
73
 
71
74
  /* 입력 필드 */
72
75
  input {
73
- flex: 1;
76
+ flex: 1 1 auto;
74
77
  min-width: 0;
75
- border: none;
76
- background: transparent;
77
- outline: none;
78
- font-family: inherit;
78
+ all: unset;
79
79
  font-size: 1em;
80
80
  line-height: 1.5;
81
- color: var(--u-text-color);
82
- padding: 0;
83
81
  }
84
82
  input::placeholder {
85
- color: var(--u-text-color-disabled);
83
+ color: var(--u-txt-color-weak);
86
84
  }
87
85
  input:disabled {
88
86
  cursor: not-allowed;
89
- color: var(--u-text-color-disabled);
90
87
  }
91
88
  input:read-only {
92
89
  cursor: default;
93
90
  }
94
91
 
95
- /* Prefix & Suffix 슬롯 */
96
- ::slotted([slot="prefix"]),
92
+ /* 슬롯에 내용이 있을 gap 적용 */
93
+ ::slotted([slot="prefix"]) {
94
+ margin-right: 0.5em;
95
+ }
97
96
  ::slotted([slot="suffix"]) {
98
- display: contents;
97
+ margin-left: 0.5em;
99
98
  }
100
99
 
101
100
  /* Tools 영역 (clear, password toggle 등) */
@@ -103,42 +102,41 @@ const styles = css`
103
102
  display: flex;
104
103
  flex-direction: row;
105
104
  align-items: center;
106
- gap: 0.375em;
107
105
  }
108
- .tool {
109
- font-size: 1.125em;
106
+ .tools u-icon {
110
107
  color: var(--u-icon-color);
108
+ font-size: 1em;
109
+ margin-left: 0.5em;
111
110
  transition: color 0.2s ease;
112
111
  cursor: pointer;
113
112
  }
114
- .tool:hover {
113
+ .tools u-icon:hover {
115
114
  color: var(--u-icon-color-hover);
116
115
  }
117
- .tool:active {
116
+ .tools u-icon:active {
118
117
  color: var(--u-icon-color-active);
119
118
  }
120
119
 
121
120
  /* 유효성 검사 에러 메시지 */
122
- .validation-error {
123
- margin-top: 0.375em;
124
- font-size: 0.8125em;
121
+ .validation-message {
122
+ margin-top: 0.5em;
125
123
  color: var(--u-red-600);
126
- line-height: 1.4;
124
+ font-size: 0.75em;
125
+ line-height: 1.2;
127
126
  }
128
127
 
129
128
  /* 설명 텍스트 */
130
129
  .description {
131
- margin-top: 0.375em;
132
- font-size: 0.8125em;
133
- color: var(--u-soft-text-color);
134
- line-height: 1.4;
130
+ margin-top: 0.5em;
131
+ color: var(--u-txt-color-weak);
132
+ font-size: 0.75em;
133
+ line-height: 1.2;
135
134
  }
136
135
 
137
- /* Number input 기본 스타일 제거 (브라우저 간 일관성 위해) */
136
+ /* input 기본 제공 스타일 초기화 */
138
137
  input[type="number"] {
139
138
  -moz-appearance: textfield;
140
139
  }
141
- /* Number input 스피너 제거 옵션 (선택적) */
142
140
  input[type="number"]::-webkit-inner-spin-button,
143
141
  input[type="number"]::-webkit-outer-spin-button {
144
142
  -webkit-appearance: none;
@@ -0,0 +1,5 @@
1
+ import { Input } from './Input.js';
2
+
3
+ Input.define("u-input");
4
+
5
+ export { Input };
@@ -0,0 +1,5 @@
1
+ import { Menu } from './Menu.js';
2
+
3
+ Menu.define("u-menu");
4
+
5
+ export { Menu };
@@ -1,5 +1,5 @@
1
1
  import { PropertyValues } from 'lit';
2
- import { BaseElement } from '@iyulab/components/dist/components/BaseElement.js';
2
+ import { BaseElement } from '../BaseElement.js';
3
3
  /**
4
4
  * ProgressBar 컴포넌트는 진행 상태를 시각적으로 표시합니다.
5
5
  * 로딩 상태나 작업 진행률을 표시하는데 사용됩니다.
@@ -23,5 +23,5 @@ export declare class ProgressBar extends BaseElement {
23
23
  protected willUpdate(changedProperties: PropertyValues): void;
24
24
  render(): import('lit-html').TemplateResult<1>;
25
25
  /** 내부 진행 상태 업데이트 */
26
- private updateProgress;
26
+ private updateProgressState;
27
27
  }
@@ -34,7 +34,7 @@ class ProgressBar extends BaseElement {
34
34
  this.progressState = this.indeterminate ? "indeterminate" : "turned-on";
35
35
  }
36
36
  if (changedProperties.has("minValue") || changedProperties.has("maxValue") || changedProperties.has("value")) {
37
- this.updateProgress();
37
+ this.updateProgressState();
38
38
  }
39
39
  }
40
40
  render() {
@@ -48,7 +48,7 @@ class ProgressBar extends BaseElement {
48
48
  `;
49
49
  }
50
50
  /** 내부 진행 상태 업데이트 */
51
- async updateProgress() {
51
+ async updateProgressState() {
52
52
  await this.updateComplete;
53
53
  if (this.indeterminate) return;
54
54
  const range = this.maxValue - this.minValue;