uni-textarea-field 1.0.1 → 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/index.html CHANGED
@@ -40,10 +40,8 @@ body{position:relative;inline-size:100vw;block-size:100vh;margin:0;}
40
40
  }
41
41
 
42
42
  uni-textarea-field {
43
- inline-size: 300px;
44
-
45
43
  &::part(icon-subject) {
46
- /*background-color: red;*/
44
+ /* style icon here */
47
45
  }
48
46
 
49
47
  &[data-hide-icon]::part(icon-subject) {
@@ -415,29 +413,21 @@ const handler = (evt) => {
415
413
  } else {
416
414
  textarea.removeAttribute('maxlength');
417
415
  }
418
-
419
- uniTextareaField.refresh();
420
416
  break;
421
417
  }
422
418
 
423
419
  case 'required': {
424
420
  textarea.required = fd['required'] === 'y';
425
-
426
- uniTextareaField.refresh();
427
421
  break;
428
422
  }
429
423
 
430
424
  case 'disabled': {
431
425
  textarea.disabled = fd['disabled'] === 'y';
432
-
433
- uniTextareaField.refresh();
434
426
  break;
435
427
  }
436
428
 
437
429
  case 'readonly': {
438
430
  textarea.readOnly = fd['readonly'] === 'y';
439
-
440
- uniTextareaField.refresh();
441
431
  break;
442
432
  }
443
433
 
@@ -82,34 +82,15 @@ ${_uniColorPalette}
82
82
  }
83
83
 
84
84
  :host {
85
- &:has([slot="textarea"][required]) {
86
- .main__subject__span::after {
87
- content: '*';
88
- color: var(--ct_icon_moderate_strong);
89
- margin-inline-start: 4px;
90
- }
91
- }
92
-
93
- &:has([slot="textarea"][maxlength]) {
94
- .main {
95
- --counter-display: block;
96
- }
97
- }
98
-
99
- &:has([slot="textarea"][readonly]) {
85
+ @container style(--show-required-sign: 'true') {
100
86
  .main {
101
- --background-color: transparent;
102
- --border-color: var(--border-color-readonly);
87
+ --required-sign-display: inline;
103
88
  }
104
89
  }
105
90
 
106
- &:has([slot="textarea"][disabled],[slot="textarea"][inert]) {
91
+ @container style(--show-counter: 'true') {
107
92
  .main {
108
- --text-color: var(--text-color-disabled);
109
- }
110
-
111
- slot[name="textarea"] {
112
- interactivity: inert;
93
+ --counter-display: block;
113
94
  }
114
95
  }
115
96
 
@@ -158,6 +139,7 @@ ${_uniColorPalette}
158
139
  --counter-color: var(--uni-textarea-field-counter-color, var(--ct_text_main_subtle));
159
140
  --caret-color: var(--uni-textarea-field-caret-color, var(--ct_input-caret_main_general));
160
141
 
142
+ --required-sign-display: none;
161
143
  --min-block-size: var(--uni-textarea-field-min-block-size, 100px);
162
144
 
163
145
  /* size */
@@ -189,6 +171,13 @@ ${_uniColorPalette}
189
171
  font-size: 12px;
190
172
  color: var(--subject-color);
191
173
  line-height: 1.667;
174
+
175
+ &::after {
176
+ content: '*';
177
+ color: var(--ct_icon_moderate_strong);
178
+ margin-inline-start: 4px;
179
+ display: var(--required-sign-display);
180
+ }
192
181
  }
193
182
 
194
183
  em {
@@ -269,6 +258,15 @@ ${_uniColorPalette}
269
258
  color: var(--placeholder-color);
270
259
  }
271
260
  }
261
+
262
+ ::slotted(textarea[readonly]) {
263
+ --background-color: transparent;
264
+ --border-color: var(--border-color-readonly);
265
+ }
266
+
267
+ ::slotted(textarea:is([disabled],[inert])) {
268
+ --text-color: var(--text-color-disabled);
269
+ }
272
270
  }
273
271
  </style>
274
272
 
@@ -285,6 +283,40 @@ ${_uniColorPalette}
285
283
  </div>
286
284
  `;
287
285
 
286
+ /* style injection */
287
+ const styleInjection = `
288
+ uni-textarea-field {
289
+ --show-required-sign: 'false';
290
+ --show-counter: 'false';
291
+
292
+ &:has(textarea[required]) {
293
+ --show-required-sign: 'true';
294
+ }
295
+
296
+ &:not([data-hide-counter]):has(textarea[maxlength]) {
297
+ --show-counter: 'true';
298
+ }
299
+ }
300
+
301
+ [inert] uni-textarea-field {
302
+ --interactivity: inert;
303
+ }
304
+ `;
305
+
306
+ const INJECT_KEY = Symbol.for('uni.textarea.field.ui.injected');
307
+ const uiInit = () => {
308
+ if (window[INJECT_KEY]) {
309
+ return;
310
+ }
311
+
312
+ const sheet = new CSSStyleSheet();
313
+ sheet.replaceSync(styleInjection);
314
+ document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet];
315
+
316
+ window[INJECT_KEY] = true;
317
+ };
318
+ uiInit();
319
+
288
320
  export class UniTextareaField extends HTMLElement {
289
321
  #data;
290
322
  #nodes;
@@ -445,9 +477,7 @@ export class UniTextareaField extends HTMLElement {
445
477
  }
446
478
 
447
479
  #setupEventListeners() {
448
- if (this.#data.elementController) {
449
- this.#data.elementController.abort();
450
- }
480
+ this.#data.elementController.abort?.();
451
481
 
452
482
  this.#nodes.textarea = this.querySelector('[slot=textarea]');
453
483
 
@@ -1,4 +1,4 @@
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=`
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"),styleInjection=(template.innerHTML=`
2
2
  <style>
3
3
  ${_wccss}
4
4
  ${_uniColorPalette}
@@ -63,34 +63,15 @@ ${_uniColorPalette}
63
63
  }
64
64
 
65
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]) {
66
+ @container style(--show-required-sign: 'true') {
81
67
  .main {
82
- --background-color: transparent;
83
- --border-color: var(--border-color-readonly);
68
+ --required-sign-display: inline;
84
69
  }
85
70
  }
86
71
 
87
- &:has([slot="textarea"][disabled],[slot="textarea"][inert]) {
72
+ @container style(--show-counter: 'true') {
88
73
  .main {
89
- --text-color: var(--text-color-disabled);
90
- }
91
-
92
- slot[name="textarea"] {
93
- interactivity: inert;
74
+ --counter-display: block;
94
75
  }
95
76
  }
96
77
 
@@ -139,6 +120,7 @@ ${_uniColorPalette}
139
120
  --counter-color: var(--uni-textarea-field-counter-color, var(--ct_text_main_subtle));
140
121
  --caret-color: var(--uni-textarea-field-caret-color, var(--ct_input-caret_main_general));
141
122
 
123
+ --required-sign-display: none;
142
124
  --min-block-size: var(--uni-textarea-field-min-block-size, 100px);
143
125
 
144
126
  /* size */
@@ -170,6 +152,13 @@ ${_uniColorPalette}
170
152
  font-size: 12px;
171
153
  color: var(--subject-color);
172
154
  line-height: 1.667;
155
+
156
+ &::after {
157
+ content: '*';
158
+ color: var(--ct_icon_moderate_strong);
159
+ margin-inline-start: 4px;
160
+ display: var(--required-sign-display);
161
+ }
173
162
  }
174
163
 
175
164
  em {
@@ -250,6 +239,15 @@ ${_uniColorPalette}
250
239
  color: var(--placeholder-color);
251
240
  }
252
241
  }
242
+
243
+ ::slotted(textarea[readonly]) {
244
+ --background-color: transparent;
245
+ --border-color: var(--border-color-readonly);
246
+ }
247
+
248
+ ::slotted(textarea:is([disabled],[inert])) {
249
+ --text-color: var(--text-color-disabled);
250
+ }
253
251
  }
254
252
  </style>
255
253
 
@@ -264,4 +262,21 @@ ${_uniColorPalette}
264
262
  <p class="main__info__counter" data-maxlength="?">0</p>
265
263
  </div>
266
264
  </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:"",elementController:""},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"),slot:this.shadowRoot.querySelector("slot[name=textarea]")},this.#config={...defaults,...e},this._onInput=this._onInput.bind(this),this._onKeydown=this._onKeydown.bind(this),this._onSlotchange=this._onSlotchange.bind(this)}async connectedCallback(){var{config:e,error:t}=await _wcl.getWCConfig(this),a=this.#nodes["slot"];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("slotchange",this._onSlotchange,{signal:t}),this.#setupEventListeners())}disconnectedCallback(){this.#data.controller.abort?.(),this.#data.elementController.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)}#setupEventListeners(){var e;this.#data.elementController&&this.#data.elementController.abort(),this.#nodes.textarea=this.querySelector("[slot=textarea]"),this.#nodes.textarea&&(this.#data.elementController=new AbortController,e=this.#data.elementController.signal,this.#nodes.textarea.addEventListener("input",this._onInput,{signal:e}),this.#nodes.textarea.addEventListener("keydown",this._onKeydown,{signal:e}),this._onInput())}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()}_onSlotchange(){this.#setupEventListeners()}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};
265
+ `,`
266
+ uni-textarea-field {
267
+ --show-required-sign: 'false';
268
+ --show-counter: 'false';
269
+
270
+ &:has(textarea[required]) {
271
+ --show-required-sign: 'true';
272
+ }
273
+
274
+ &:not([data-hide-counter]):has(textarea[maxlength]) {
275
+ --show-counter: 'true';
276
+ }
277
+ }
278
+
279
+ [inert] uni-textarea-field {
280
+ --interactivity: inert;
281
+ }
282
+ `),INJECT_KEY=Symbol.for("uni.textarea.field.ui.injected"),uiInit=()=>{var e;window[INJECT_KEY]||((e=new CSSStyleSheet).replaceSync(styleInjection),document.adoptedStyleSheets=[...document.adoptedStyleSheets,e],window[INJECT_KEY]=!0)};uiInit();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:"",elementController:""},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"),slot:this.shadowRoot.querySelector("slot[name=textarea]")},this.#config={...defaults,...e},this._onInput=this._onInput.bind(this),this._onKeydown=this._onKeydown.bind(this),this._onSlotchange=this._onSlotchange.bind(this)}async connectedCallback(){var{config:e,error:t}=await _wcl.getWCConfig(this),a=this.#nodes["slot"];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("slotchange",this._onSlotchange,{signal:t}),this.#setupEventListeners())}disconnectedCallback(){this.#data.controller.abort?.(),this.#data.elementController.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)}#setupEventListeners(){var e;this.#data.elementController.abort?.(),this.#nodes.textarea=this.querySelector("[slot=textarea]"),this.#nodes.textarea&&(this.#data.elementController=new AbortController,e=this.#data.elementController.signal,this.#nodes.textarea.addEventListener("input",this._onInput,{signal:e}),this.#nodes.textarea.addEventListener("keydown",this._onKeydown,{signal:e}),this._onInput())}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()}_onSlotchange(){this.#setupEventListeners()}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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uni-textarea-field",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
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
5
  "keywords": [
6
6
  "web"