uni-textarea-field 1.0.0

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.
@@ -0,0 +1,267 @@
1
+ import{_wcl}from"./common-lib.js";import{_wccss}from"./common-css.js";import{colorPalette as _uniColorPalette}from"https://unpkg.com/uni-input-field/mjs/uni-css.js";const defaults={subject:"",message:"",stat:"",appearance:"filled",size:"medium"},booleanAttrs=[],objectAttrs=[],custumEvents={},template=document.createElement("template");template.innerHTML=`
2
+ <style>
3
+ ${_wccss}
4
+ ${_uniColorPalette}
5
+
6
+ :host{position:relative;display:block;}
7
+
8
+ /* force hide counter */
9
+ :host([data-hide-counter]) {
10
+ .main .main__info__counter {
11
+ --counter-display: none;
12
+ }
13
+ }
14
+
15
+ :host([hidden]) {
16
+ display: none;
17
+ }
18
+
19
+ /* state */
20
+ :host([stat=valid]) {
21
+ .main {
22
+ --border-color: var(--border-color-valid);
23
+ --message-color: var(--message-color-valid);
24
+ }
25
+ }
26
+
27
+ :host([stat=invalid]) {
28
+ .main {
29
+ --text-color: var(--text-color-invalid);
30
+ --border-color: var(--border-color-invalid);
31
+ --message-color: var(--message-color-invalid);
32
+ }
33
+ }
34
+
35
+ /* appearance */
36
+ :host([appearance=outlined]) {
37
+ .main {
38
+ --border-color: var(--border-color-outline);
39
+ --background-color: transparent;
40
+ }
41
+ }
42
+
43
+ /* size */
44
+ :host([size=large]) {
45
+ .main {
46
+ --border-radius: var(--large-border-radius);
47
+ --padding: var(--large-padding);
48
+ }
49
+ }
50
+
51
+ :host([size=medium]) {
52
+ .main {
53
+ --border-radius: var(--medium-border-radius);
54
+ --padding: var(--medium-padding);
55
+ }
56
+ }
57
+
58
+ :host([size=small]) {
59
+ .main {
60
+ --border-radius: var(--small-border-radius);
61
+ --padding: var(--small-padding);
62
+ }
63
+ }
64
+
65
+ :host {
66
+ &:has([slot="textarea"][required]) {
67
+ .main__subject__span::after {
68
+ content: '*';
69
+ color: var(--ct_icon_moderate_strong);
70
+ margin-inline-start: 4px;
71
+ }
72
+ }
73
+
74
+ &:has([slot="textarea"][maxlength]) {
75
+ .main {
76
+ --counter-display: block;
77
+ }
78
+ }
79
+
80
+ &:has([slot="textarea"][readonly]) {
81
+ .main {
82
+ --background-color: transparent;
83
+ --border-color: var(--border-color-readonly);
84
+ }
85
+ }
86
+
87
+ &:has([slot="textarea"][disabled],[slot="textarea"][inert]) {
88
+ .main {
89
+ --text-color: var(--text-color-disabled);
90
+ }
91
+
92
+ slot[name="textarea"] {
93
+ interactivity: inert;
94
+ }
95
+ }
96
+
97
+ @container style(--interactivity: inert) {
98
+ .main {
99
+ --text-color: var(--text-color-disabled);
100
+ }
101
+
102
+ slot[name="textarea"] {
103
+ interactivity: inert;
104
+ }
105
+ }
106
+ }
107
+
108
+ .main {
109
+ --border-color-normal: var(--uni-textarea-field-border-color-normal, transparent);
110
+ --border-color-readonly: var(--uni-textarea-field-border-color-readonly, var(--ct_input-general_main_stroke_default));
111
+ --border-color-disabled: var(--uni-textarea-field-border-color-disabled, var(--ct_input-general_dim_container_default));
112
+ --border-color-valid: var(--uni-textarea-field-border-color-valid, var(--ct_text_success_general));
113
+ --border-color-invalid: var(--uni-textarea-field-border-color-invalid, var(--ct_text_danger_general));
114
+ --border-color-outline: var(--uni-textarea-field-border-color-outline, var(--ct_input-general_main_stroke_default));
115
+ --border-color: var(--border-color-normal);
116
+
117
+ --background-color-normal: var(--uni-textarea-field-background-color-normal, var(--ct_input-general_dim_container_default));
118
+ --background-color-readonly: var(--uni-textarea-field-background-color-readonly, var(--ct_input-general_dim_container_default));
119
+ --background-color-disabled: var(--uni-textarea-field-background-color-disabled, var(--ct_input-general_dim_container_default));
120
+ --background-color: var(--background-color-normal);
121
+
122
+ --placeholder-color-normal: var(--uni-textarea-field-placeholder-color-normal, var(--ct_text_main_subtlest));
123
+ --placeholder-color-readonly: var(--uni-textarea-field-placeholder-color-readonly, var(--ct_text_main_subtlest));
124
+ --placeholder-color-disabled: var(--uni-textarea-field-placeholder-color-disabled, var(--ct_text_main_subtlest));
125
+ --placeholder-color: var(--placeholder-color-normal);
126
+
127
+ --text-color-normal: var(--uni-textarea-field-text-color-normal, var(--ct_text_main_general));
128
+ --text-color-readonly: var(--uni-textarea-field-text-color-readonly, var(--ct_text_main_general));
129
+ --text-color-disabled: var(--uni-textarea-field-text-color-disabled, var(--ct_text_main_pale));
130
+ --text-color-invalid: var(--uni-textarea-field-text-color-invalid, var(--ct_text_danger_general));
131
+ --text-color: var(--text-color-normal);
132
+
133
+ --message-color-normal: var(--uni-textarea-field-message-color-normal, var(--ct_text_main_subtle));
134
+ --message-color-valid: var(--uni-textarea-field-message-color-valid, var(--ct_text_success_general));
135
+ --message-color-invalid: var(--uni-textarea-field-message-color-invalid, var(--ct_text_danger_general));
136
+ --message-color: var(--message-color-normal);
137
+
138
+ --subject-color: var(--uni-textarea-field-subject-color, var(--ct_text_main_subtle));
139
+ --counter-color: var(--uni-textarea-field-counter-color, var(--ct_text_main_subtle));
140
+ --caret-color: var(--uni-textarea-field-caret-color, var(--ct_input-caret_main_general));
141
+
142
+ --min-block-size: var(--uni-textarea-field-min-block-size, 100px);
143
+
144
+ /* size */
145
+ --large-border-radius: 24px;
146
+ --large-padding: 16px 12px 16px 16px;
147
+ --medium-border-radius: 24px;
148
+ --medium-padding: 8px 12px;
149
+ --small-border-radius: 24px;
150
+ --small-padding: 6.4px 4px 6.4px 12px;
151
+
152
+ --border-radius: var(--medium-border-radius);
153
+ --padding: var(--medium-padding);
154
+
155
+ --counter-display: none;
156
+
157
+ inline-size: 100%;
158
+
159
+ .main__subject {
160
+ padding-block-end: 4px;
161
+ display: flex;
162
+ align-items: center;
163
+ gap: 4px;
164
+
165
+ &:has(.main__subject__span:empty) {
166
+ display: none;
167
+ }
168
+
169
+ .main__subject__span {
170
+ font-size: 12px;
171
+ color: var(--subject-color);
172
+ line-height: 1.667;
173
+ }
174
+
175
+ em {
176
+ inline-size: 15px;
177
+ block-size: 15px;
178
+ clip-path: path('M7.1,0C3.2,0,0,3.2,0,7.1s3.2,7.1,7.1,7.1,7.1-3.2,7.1-7.1S11.1,0,7.1,0ZM7.1,12.7c-3.1,0-5.6-2.5-5.6-5.5S4.1,1.6,7.1,1.6s5.5,2.5,5.5,5.6-2.5,5.5-5.5,5.5h0ZM7.9,6.3h-1.6v4.7h1.6v-4.7ZM7.9,3.6h-1.6v1.5h1.6v-1.5Z');
179
+ background-color: var(--subject-color);
180
+ display: block;
181
+ }
182
+ }
183
+
184
+ .main__info {
185
+ --justify-content: space-between;
186
+
187
+ padding: 4px 8px;
188
+ box-sizing: border-box;
189
+ display: flex;
190
+ gap: 16px;
191
+ justify-content: var(--justify-content);
192
+ align-items: center;
193
+
194
+ &:has(.main__info__message:empty) {
195
+ --justify-content: flex-end;
196
+ }
197
+
198
+ .main__info__message {
199
+ font-size: 11px;
200
+ color: var(--message-color);
201
+ line-height: 1.3;
202
+
203
+ &:empty {
204
+ display: none;
205
+ }
206
+ }
207
+
208
+ .main__info__counter {
209
+ flex-shrink: 0;
210
+ font-size: 12px;
211
+ color: var(--counter-color);
212
+ display: var(--counter-display);
213
+
214
+ &::after {
215
+ content: ' / ' attr(data-maxlength);
216
+ }
217
+ }
218
+ }
219
+
220
+ slot[name=textarea] {
221
+ inline-size: 100%;
222
+ display: block;
223
+ }
224
+
225
+ /* textarea */
226
+ ::slotted(textarea) {
227
+ outline: 0 none;
228
+ resize: none;
229
+ appearance: none;
230
+ box-shadow: none;
231
+
232
+ display: block;
233
+
234
+ font-size: 16px;
235
+ line-height: 1.4;
236
+ color: var(--text-color);
237
+ inline-size: 100% !important;
238
+ box-sizing: border-box;
239
+ text-overflow: ellipsis;
240
+ border: 1px solid var(--border-color);
241
+ background-color: var(--background-color);
242
+ caret-color: var(--caret-color);
243
+
244
+ min-block-size: var(--min-block-size);
245
+ field-sizing: content;
246
+ border-radius: var(--border-radius);
247
+ padding: var(--padding) !important;
248
+
249
+ &::placeholder {
250
+ color: var(--placeholder-color);
251
+ }
252
+ }
253
+ }
254
+ </style>
255
+
256
+ <div class="main" ontouchstart="" tabindex="0">
257
+ <p class="main__subject">
258
+ <em part="icon-subject"></em>
259
+ <span class="main__subject__span"></span>
260
+ </p>
261
+ <slot name="textarea"></slot>
262
+ <div class="main__info">
263
+ <p class="main__info__message"></p>
264
+ <p class="main__info__counter" data-maxlength="?">0</p>
265
+ </div>
266
+ </div>
267
+ `;class UniTextareaField extends HTMLElement{#data;#nodes;#config;constructor(e){super(),this.attachShadow({mode:"open",delegatesFocus:!0}),this.shadowRoot.appendChild(template.content.cloneNode(!0)),this.#data={controller:""},this.#nodes={styleSheet:this.shadowRoot.querySelector("style"),textarea:this.querySelector("[slot=textarea]"),subject:this.shadowRoot.querySelector(".main__subject__span"),message:this.shadowRoot.querySelector(".main__info__message"),counter:this.shadowRoot.querySelector(".main__info__counter")},this.#config={...defaults,...e},this._onInput=this._onInput.bind(this),this._onKeydown=this._onKeydown.bind(this)}async connectedCallback(){var{config:e,error:t}=await _wcl.getWCConfig(this),a=this.#nodes["textarea"];t?(console.warn(_wcl.classToTagName(this.constructor.name)+": "+t),this.remove()):(this.#config={...this.#config,...e},Object.keys(defaults).forEach(e=>this.#upgradeProperty(e)),this.#data.controller=new AbortController,t=this.#data.controller.signal,a.addEventListener("input",this._onInput,{signal:t}),a.addEventListener("keydown",this._onKeydown,{signal:t}),this._onInput())}disconnectedCallback(){this.#data?.controller&&this.#data.controller.abort()}#format(e,t,a){if(null!==a)switch(e){case"subject":case"message":this.#config[e]=a;break;case"stat":this.#config[e]=["","valid","invalid"].includes(a)?a:defaults.state;break;case"appearance":this.#config[e]=["filled","outlined"].includes(a)?a:defaults.appearance;break;case"size":this.#config[e]=["large","medium","small"].includes(a)?a:defaults.size}else booleanAttrs.includes(e)?this.#config[e]=!1:this.#config[e]=defaults[e]}attributeChangedCallback(e,t,a){if(UniTextareaField.observedAttributes.includes(e))switch(this.#format(e,t,a),e){case"subject":this.#nodes.subject.textContent=this.subject;break;case"message":this.#nodes.message.textContent=this.message}}static get observedAttributes(){return Object.keys(defaults)}static get supportedEvents(){return Object.keys(custumEvents).map(e=>custumEvents[e])}#upgradeProperty(e){let t;UniTextareaField.observedAttributes.includes(e)&&(Object.prototype.hasOwnProperty.call(this,e)?(t=this[e],delete this[e]):t=booleanAttrs.includes(e)?!(!this.hasAttribute(e)&&!this.#config[e]):objectAttrs.includes(e)?this.hasAttribute(e)?this.getAttribute(e):JSON.stringify(this.#config[e]):this.hasAttribute(e)?this.getAttribute(e):this.#config[e],this[e]=t)}set subject(e){e?this.setAttribute("subject",e):this.removeAttribute("subject")}get subject(){return this.#config.subject}set message(e){e?this.setAttribute("message",e):this.removeAttribute("message")}get message(){return this.#config.message}set stat(e){e?this.setAttribute("stat",e):this.removeAttribute("stat")}get stat(){return this.#config.stat}set appearance(e){e?this.setAttribute("appearance",e):this.removeAttribute("appearance")}get appearance(){return this.#config.appearance}set size(e){e?this.setAttribute("size",e):this.removeAttribute("size")}get size(){return this.#config.size}_onInput(e){var{textarea:t,counter:a}=this.#nodes;a.dataset.maxlength=t.maxLength,a.textContent=t.value.length,e&&"invalid"===this.stat&&(this.stat="")}_onKeydown(e){var{key:e,isComposing:t}=e;"Enter"===e&&t&&event.preventDefault()}refresh(){this.hidden=!0,this.offsetHeight,this.hidden=!1}}const S=_wcl.supports(),T=_wcl.classToTagName("UniTextareaField");S.customElements&&S.shadowDOM&&S.template&&!window.customElements.get(T)&&window.customElements.define(_wcl.classToTagName("UniTextareaField"),UniTextareaField);export{UniTextareaField};
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "uni-textarea-field",
3
+ "version": "1.0.0",
4
+ "description": "<uni-textarea-field /> is an encapsulated Web Component built upon the foundation of the uniopen design language. Implementation is straightforward: simply slot a standard textarea element inside <uni-textarea-field />. The component instantly applies a user interface that aligns seamlessly with the uniopen design language guidelines. Furthermore, its visual styles can be dynamically adapted via native HTML attributes or JavaScript properties. The component also exposes comprehensive character count and textarea length metadata, providing users with a clear and intuitive understanding of predefined character constraints.",
5
+ "keywords": [
6
+ "web"
7
+ ],
8
+ "homepage": "https://github.com/meistudioli/uni-textarea-field#readme",
9
+ "bugs": {
10
+ "url": "https://github.com/meistudioli/uni-textarea-field/issues"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/meistudioli/uni-textarea-field.git"
15
+ },
16
+ "license": "MIT",
17
+ "author": "Paul Li",
18
+ "type": "commonjs",
19
+ "main": "index.html",
20
+ "scripts": {
21
+ "test": "echo \"Error: no test specified\" && exit 1"
22
+ }
23
+ }