@crowdstrike/glide-core 0.29.2 → 0.30.1

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 (122) hide show
  1. package/dist/accordion.js +240 -1
  2. package/dist/accordion.styles.js +13 -7
  3. package/dist/button-group.button.js +143 -1
  4. package/dist/button-group.button.styles.js +43 -15
  5. package/dist/button-group.js +249 -1
  6. package/dist/button-group.styles.js +10 -5
  7. package/dist/button.js +206 -1
  8. package/dist/button.styles.js +12 -7
  9. package/dist/checkbox-group.js +479 -14
  10. package/dist/checkbox-group.styles.js +5 -2
  11. package/dist/checkbox.js +519 -32
  12. package/dist/checkbox.styles.js +10 -5
  13. package/dist/drawer.js +168 -1
  14. package/dist/drawer.styles.js +5 -2
  15. package/dist/dropdown.js +2423 -123
  16. package/dist/dropdown.option.js +536 -1
  17. package/dist/dropdown.option.styles.js +5 -2
  18. package/dist/dropdown.styles.js +15 -8
  19. package/dist/form-controls-layout.js +102 -1
  20. package/dist/form-controls-layout.styles.js +5 -2
  21. package/dist/icon-button.js +139 -1
  22. package/dist/icon-button.styles.js +19 -7
  23. package/dist/icons/checked.js +28 -1
  24. package/dist/icons/chevron.js +21 -1
  25. package/dist/icons/magnifying-glass.js +23 -1
  26. package/dist/icons/pencil.js +21 -1
  27. package/dist/icons/severity-critical.js +20 -1
  28. package/dist/icons/severity-informational.js +20 -1
  29. package/dist/icons/severity-medium.js +20 -1
  30. package/dist/icons/x.js +21 -1
  31. package/dist/inline-alert.js +118 -1
  32. package/dist/inline-alert.styles.js +5 -2
  33. package/dist/input.d.ts +8 -2
  34. package/dist/input.js +505 -41
  35. package/dist/input.styles.js +25 -4
  36. package/dist/label.js +303 -1
  37. package/dist/label.styles.js +11 -5
  38. package/dist/library/assert-slot.js +136 -1
  39. package/dist/library/expect-unhandled-rejection.js +14 -1
  40. package/dist/library/expect-window-error.js +26 -1
  41. package/dist/library/final.js +18 -1
  42. package/dist/library/form-control.js +1 -1
  43. package/dist/library/localize.js +10 -1
  44. package/dist/library/mouse.js +35 -1
  45. package/dist/library/on-resize.js +24 -1
  46. package/dist/library/required.js +35 -1
  47. package/dist/library/shadow-root-mode.js +4 -1
  48. package/dist/library/unique-id.js +3 -1
  49. package/dist/link.js +92 -1
  50. package/dist/link.styles.js +10 -5
  51. package/dist/menu.d.ts +3 -2
  52. package/dist/menu.js +1259 -1
  53. package/dist/menu.styles.js +35 -19
  54. package/dist/modal.d.ts +4 -0
  55. package/dist/modal.icon-button.js +60 -1
  56. package/dist/modal.icon-button.styles.js +5 -2
  57. package/dist/modal.js +473 -1
  58. package/dist/modal.styles.js +71 -22
  59. package/dist/option.d.ts +74 -0
  60. package/dist/option.js +498 -0
  61. package/dist/option.styles.js +140 -0
  62. package/dist/{menu.options.d.ts → options.d.ts} +5 -6
  63. package/dist/options.js +130 -0
  64. package/dist/options.styles.js +21 -0
  65. package/dist/popover.js +620 -1
  66. package/dist/popover.styles.js +11 -5
  67. package/dist/radio-group.js +624 -17
  68. package/dist/radio-group.radio.js +211 -1
  69. package/dist/radio-group.radio.styles.js +9 -4
  70. package/dist/radio-group.styles.js +5 -2
  71. package/dist/slider.js +1040 -61
  72. package/dist/slider.styles.js +9 -4
  73. package/dist/spinner.js +60 -1
  74. package/dist/spinner.styles.js +5 -2
  75. package/dist/split-button.js +116 -1
  76. package/dist/split-button.primary-button.js +100 -1
  77. package/dist/split-button.primary-button.styles.js +13 -6
  78. package/dist/split-button.primary-link.js +102 -1
  79. package/dist/split-button.secondary-button.d.ts +2 -3
  80. package/dist/split-button.secondary-button.js +121 -1
  81. package/dist/split-button.secondary-button.styles.js +12 -7
  82. package/dist/split-button.styles.js +9 -4
  83. package/dist/styles/focus-outline.js +9 -3
  84. package/dist/styles/fonts.css +6 -1
  85. package/dist/styles/opacity-and-scale-animation.js +6 -3
  86. package/dist/styles/skeleton.js +6 -3
  87. package/dist/styles/variables.css +410 -1
  88. package/dist/styles/visually-hidden.js +6 -3
  89. package/dist/tab.group.js +386 -1
  90. package/dist/tab.group.styles.js +5 -2
  91. package/dist/tab.js +133 -1
  92. package/dist/tab.panel.js +93 -1
  93. package/dist/tab.panel.styles.js +11 -5
  94. package/dist/tab.styles.js +9 -4
  95. package/dist/tag.js +207 -1
  96. package/dist/tag.styles.js +10 -5
  97. package/dist/textarea.js +353 -19
  98. package/dist/textarea.styles.js +23 -4
  99. package/dist/toast.js +130 -1
  100. package/dist/toast.toasts.js +248 -25
  101. package/dist/toast.toasts.styles.js +9 -4
  102. package/dist/toggle.js +178 -1
  103. package/dist/toggle.styles.js +25 -5
  104. package/dist/tooltip.container.js +130 -1
  105. package/dist/tooltip.container.styles.js +5 -2
  106. package/dist/tooltip.js +484 -1
  107. package/dist/tooltip.styles.js +21 -5
  108. package/dist/translations/en.js +36 -1
  109. package/dist/translations/fr.js +37 -1
  110. package/dist/translations/ja.js +37 -1
  111. package/package.json +8 -12
  112. package/dist/menu.button.d.ts +0 -42
  113. package/dist/menu.button.js +0 -1
  114. package/dist/menu.button.styles.js +0 -32
  115. package/dist/menu.link.d.ts +0 -44
  116. package/dist/menu.link.js +0 -1
  117. package/dist/menu.link.styles.js +0 -35
  118. package/dist/menu.options.js +0 -1
  119. package/dist/menu.options.styles.d.ts +0 -2
  120. package/dist/menu.options.styles.js +0 -20
  121. /package/dist/{menu.button.styles.d.ts → option.styles.d.ts} +0 -0
  122. /package/dist/{menu.link.styles.d.ts → options.styles.d.ts} +0 -0
package/dist/textarea.js CHANGED
@@ -1,10 +1,126 @@
1
- var __decorate=this&&this.__decorate||function(e,t,i,a){var r,s=arguments.length,o=s<3?t:null===a?a=Object.getOwnPropertyDescriptor(t,i):a;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)o=Reflect.decorate(e,t,i,a);else for(var l=e.length-1;l>=0;l--)(r=e[l])&&(o=(s<3?r(o):s>3?r(t,i,o):r(t,i))||o);return s>3&&o&&Object.defineProperty(t,i,o),o};import"./label.js";import{html,LitElement,nothing}from"lit";import{classMap}from"lit/directives/class-map.js";import{createRef,ref}from"lit/directives/ref.js";import{customElement,property,state}from"lit/decorators.js";import{ifDefined}from"lit/directives/if-defined.js";import{unsafeHTML}from"lit/directives/unsafe-html.js";import{when}from"lit/directives/when.js";import packageJson from"../package.json"with{type:"json"};import{LocalizeController}from"./library/localize.js";import styles from"./textarea.styles.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";import required from"./library/required.js";let Textarea=class Textarea extends LitElement{static{this.formAssociated=!0}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode,delegatesFocus:!0}}static{this.styles=styles}checkValidity(){this.isCheckingValidity=!0;const e=this.#e.checkValidity();return this.isCheckingValidity=!1,e}disconnectedCallback(){super.disconnectedCallback(),this.form?.removeEventListener("formdata",this.#t)}get form(){return this.#e.form}get validity(){return!this.required||this.value||this.disabled?this.required&&this.#e.validity.valueMissing&&this.value?(this.#e.setValidity({}),this.#e.validity):(this.required||!this.#e.validity.valueMissing||this.value||this.#e.setValidity({}),this.#e.validity):(this.#e.setValidity({customError:Boolean(this.validityMessage),valueMissing:!0}," ",this.#i.value),this.#e.validity)}formAssociatedCallback(){this.form?.addEventListener("formdata",this.#t)}formResetCallback(){this.value=this.getAttribute("value")??""}render(){return html`<glide-core-private-label
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import './label.js';
8
+ import { html, LitElement, nothing } from 'lit';
9
+ import { classMap } from 'lit/directives/class-map.js';
10
+ import { createRef, ref } from 'lit/directives/ref.js';
11
+ import { customElement, property, state } from 'lit/decorators.js';
12
+ import { ifDefined } from 'lit/directives/if-defined.js';
13
+ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
14
+ import { when } from 'lit/directives/when.js';
15
+ import packageJson from '../package.json' with { type: 'json' };
16
+ import { LocalizeController } from './library/localize.js';
17
+ import styles from './textarea.styles.js';
18
+ import shadowRootMode from './library/shadow-root-mode.js';
19
+ import final from './library/final.js';
20
+ import required from './library/required.js';
21
+ /**
22
+ * @attr {string} label
23
+ * @attr {'on'|'off'|'none'|'sentences'|'words'|'characters'} [autocapitalize='on']
24
+ * @attr {'on'|'off'} [autocomplete='on']
25
+ * @attr {boolean} [disabled=false]
26
+ * @attr {boolean} [hide-label=false]
27
+ * @attr {number} [maxlength]
28
+ * @attr {string} [name='']
29
+ * @attr {'horizontal'|'vertical'} [orientation='horizontal']
30
+ * @attr {string} [placeholder]
31
+ * @attr {boolean} [readonly=false]
32
+ * @attr {boolean} [required=false]
33
+ * @attr {boolean} [spellcheck=false]
34
+ * @attr {string} [tooltip]
35
+ * @attr {string} [value='']
36
+ *
37
+ * @readonly
38
+ * @attr {string} [version]
39
+ *
40
+ * @slot {Element | string} [description] - Additional information or context
41
+ *
42
+ * @fires {Event} change
43
+ * @fires {Event} invalid
44
+ *
45
+ * @readonly
46
+ * @prop {HTMLFormElement | null} form
47
+ *
48
+ * @readonly
49
+ * @prop {ValidityState} validity
50
+ *
51
+ * @method checkValidity
52
+ * @returns boolean
53
+ *
54
+ * @method formAssociatedCallback
55
+ * @method formResetCallback
56
+ *
57
+ * @method reportValidity
58
+ * @returns boolean
59
+ *
60
+ * @method resetValidityFeedback
61
+ *
62
+ * @method setCustomValidity
63
+ * @param {string} message
64
+ *
65
+ * @method setValidity
66
+ * @param {ValidityStateFlags} [flags]
67
+ * @param {string} [message]
68
+ */
69
+ let Textarea = class Textarea extends LitElement {
70
+ static { this.formAssociated = true; }
71
+ static { this.shadowRootOptions = {
72
+ ...LitElement.shadowRootOptions,
73
+ mode: shadowRootMode,
74
+ delegatesFocus: true,
75
+ }; }
76
+ static { this.styles = styles; }
77
+ checkValidity() {
78
+ this.isCheckingValidity = true;
79
+ const isValid = this.#internals.checkValidity();
80
+ this.isCheckingValidity = false;
81
+ return isValid;
82
+ }
83
+ disconnectedCallback() {
84
+ super.disconnectedCallback();
85
+ this.form?.removeEventListener('formdata', this.#onFormdata);
86
+ }
87
+ get form() {
88
+ return this.#internals.form;
89
+ }
90
+ get validity() {
91
+ if (this.required && !this.value && !this.disabled) {
92
+ // A validation message is required but unused because we disable native
93
+ // validation feedback. And an empty string isn't allowed. Thus a single space.
94
+ this.#internals.setValidity({ customError: Boolean(this.validityMessage), valueMissing: true }, ' ', this.#textareaElementRef.value);
95
+ return this.#internals.validity;
96
+ }
97
+ if (this.required && this.#internals.validity.valueMissing && this.value) {
98
+ this.#internals.setValidity({});
99
+ return this.#internals.validity;
100
+ }
101
+ if (!this.required &&
102
+ this.#internals.validity.valueMissing &&
103
+ !this.value) {
104
+ this.#internals.setValidity({});
105
+ return this.#internals.validity;
106
+ }
107
+ return this.#internals.validity;
108
+ }
109
+ formAssociatedCallback() {
110
+ this.form?.addEventListener('formdata', this.#onFormdata);
111
+ }
112
+ formResetCallback() {
113
+ this.value = this.getAttribute('value') ?? '';
114
+ }
115
+ render() {
116
+ return html `<glide-core-private-label
2
117
  label=${ifDefined(this.label)}
3
- split=${ifDefined(this.privateSplit??void 0)}
118
+ split=${ifDefined(this.privateSplit ?? undefined)}
4
119
  tooltip=${ifDefined(this.tooltip)}
5
120
  orientation=${this.orientation}
6
121
  ?disabled=${this.disabled}
7
- ?error=${this.#a||this.#r}
122
+ ?error=${this.#isShowValidationFeedback ||
123
+ this.#isMaxCharacterCountExceeded}
8
124
  ?hide=${this.hideLabel}
9
125
  ?required=${this.required}
10
126
  >
@@ -13,8 +129,12 @@ var __decorate=this&&this.__decorate||function(e,t,i,a){var r,s=arguments.length
13
129
  <div class="textarea-container" slot="control">
14
130
  <textarea
15
131
  aria-describedby="meta"
16
- aria-invalid=${this.#a||this.#r}
17
- class=${classMap({error:this.#a||this.#r})}
132
+ aria-invalid=${this.#isShowValidationFeedback ||
133
+ this.#isMaxCharacterCountExceeded}
134
+ class=${classMap({
135
+ error: this.#isShowValidationFeedback ||
136
+ this.#isMaxCharacterCountExceeded,
137
+ })}
18
138
  data-test="textarea"
19
139
  id="textarea"
20
140
  name=${ifDefined(this.name)}
@@ -26,18 +146,21 @@ var __decorate=this&&this.__decorate||function(e,t,i,a){var r,s=arguments.length
26
146
  ?required=${this.required}
27
147
  ?readonly=${this.readonly}
28
148
  ?disabled=${this.disabled}
29
- ${ref(this.#i)}
30
- @blur=${this.#s}
31
- @change=${this.#o}
32
- @input=${this.#l}
33
- @keydown=${this.#n}
149
+ ${ref(this.#textareaElementRef)}
150
+ @blur=${this.#onTextareaBlur}
151
+ @change=${this.#onTextareaChange}
152
+ @input=${this.#onTextareaInput}
153
+ @keydown=${this.#onTextareaKeydown}
34
154
  >
35
155
  </textarea>
36
156
  </div>
37
157
 
38
158
  <div class="meta" id="meta" slot="description">
39
159
  <slot
40
- class=${classMap({description:!0,hidden:Boolean(this.#a&&this.validityMessage)})}
160
+ class=${classMap({
161
+ description: true,
162
+ hidden: Boolean(this.#isShowValidationFeedback && this.validityMessage),
163
+ })}
41
164
  name="description"
42
165
  >
43
166
  <!--
@@ -46,20 +169,231 @@ var __decorate=this&&this.__decorate||function(e,t,i,a){var r,s=arguments.length
46
169
  -->
47
170
  </slot>
48
171
 
49
- ${when(this.#a&&this.validityMessage,(()=>html`<span class="validity-message" data-test="validity-message"
172
+ ${when(this.#isShowValidationFeedback && this.validityMessage, () => html `<span class="validity-message" data-test="validity-message"
50
173
  >${unsafeHTML(this.validityMessage)}</span
51
- >`))}
52
- ${this.maxlength?html`<div
53
- class=${classMap({"character-count":!0,error:this.#r})}
174
+ >`)}
175
+ ${this.maxlength
176
+ ? html `<div
177
+ class=${classMap({
178
+ 'character-count': true,
179
+ error: this.#isMaxCharacterCountExceeded,
180
+ })}
54
181
  data-test="character-count-container"
55
182
  >
56
183
  <span aria-hidden="true" data-test="character-count-text">
57
- ${this.#d.term("displayedCharacterCount",this.#h,this.maxlength)}
184
+ ${this.#localize.term('displayedCharacterCount', this.#valueCharacterCount, this.maxlength)}
58
185
  </span>
59
186
 
60
187
  <span class="hidden" data-test="character-count-announcement"
61
- >${this.#d.term("announcedCharacterCount",this.#h,this.maxlength)}</span
188
+ >${this.#localize.term('announcedCharacterCount', this.#valueCharacterCount, this.maxlength)}</span
62
189
  >
63
- </div>`:nothing}
190
+ </div>`
191
+ : nothing}
64
192
  </div></glide-core-private-label
65
- >`}reportValidity(){this.isReportValidityOrSubmit=!0;const e=this.#e.reportValidity();return this.requestUpdate(),e}resetValidityFeedback(){this.isReportValidityOrSubmit=!1}setCustomValidity(e){this.validityMessage=e,""===e?this.#e.setValidity({customError:!1},"",this.#i.value):this.#e.setValidity({customError:!0,valueMissing:this.#e.validity.valueMissing}," ",this.#i.value)}setValidity(e,t){this.validityMessage=t,this.#e.setValidity(e," ",this.#i.value)}constructor(){super(),this.autocapitalize="on",this.autocomplete="on",this.disabled=!1,this.hideLabel=!1,this.name="",this.orientation="horizontal",this.spellcheck=!1,this.required=!1,this.readonly=!1,this.value="",this.version=packageJson.version,this.isBlurring=!1,this.isCheckingValidity=!1,this.isReportValidityOrSubmit=!1,this.#d=new LocalizeController(this),this.#i=createRef(),this.#t=({formData:e})=>{this.name&&this.value&&!this.disabled&&e.append(this.name,this.value)},this.#e=this.attachInternals(),this.addEventListener("invalid",(e=>{if(e?.preventDefault(),this.isCheckingValidity||this.isBlurring)return;this.isReportValidityOrSubmit=!0;this.form?.querySelector(":invalid")===this&&this.focus()}))}#e;#d;#i;#t;get#a(){return!this.disabled&&!this.readonly&&!this.validity.valid&&this.isReportValidityOrSubmit}get#h(){return this.value.length}get#r(){return Boolean(!this.disabled&&!this.readonly&&this.maxlength&&this.#h>this.maxlength)}#s(){this.isBlurring=!0,this.reportValidity(),this.isBlurring=!1}#o(){this.#i.value&&(this.value=this.#i.value.value),this.dispatchEvent(new Event("change",{bubbles:!0,composed:!0}))}#l(){this.#i.value&&(this.value=this.#i.value.value)}#n(e){"Enter"===e.key&&(e.metaKey||e.ctrlKey)&&this.form?.requestSubmit()}};__decorate([property({reflect:!0}),required],Textarea.prototype,"label",void 0),__decorate([property({reflect:!0,useDefault:!0})],Textarea.prototype,"autocapitalize",void 0),__decorate([property({reflect:!0,useDefault:!0})],Textarea.prototype,"autocomplete",void 0),__decorate([property({reflect:!0,type:Boolean})],Textarea.prototype,"disabled",void 0),__decorate([property({attribute:"hide-label",reflect:!0,type:Boolean})],Textarea.prototype,"hideLabel",void 0),__decorate([property({type:Number,converter:e=>e&&Number.parseInt(e,10),reflect:!0})],Textarea.prototype,"maxlength",void 0),__decorate([property({reflect:!0,useDefault:!0})],Textarea.prototype,"name",void 0),__decorate([property({reflect:!0,useDefault:!0})],Textarea.prototype,"orientation",void 0),__decorate([property({reflect:!0})],Textarea.prototype,"placeholder",void 0),__decorate([property()],Textarea.prototype,"privateSplit",void 0),__decorate([property({reflect:!0,type:Boolean,useDefault:!0})],Textarea.prototype,"spellcheck",void 0),__decorate([property({reflect:!0,type:Boolean})],Textarea.prototype,"required",void 0),__decorate([property({reflect:!0,type:Boolean})],Textarea.prototype,"readonly",void 0),__decorate([property({reflect:!0})],Textarea.prototype,"tooltip",void 0),__decorate([property()],Textarea.prototype,"value",void 0),__decorate([property({reflect:!0})],Textarea.prototype,"version",void 0),__decorate([state()],Textarea.prototype,"isBlurring",void 0),__decorate([state()],Textarea.prototype,"isCheckingValidity",void 0),__decorate([state()],Textarea.prototype,"isReportValidityOrSubmit",void 0),__decorate([state()],Textarea.prototype,"validityMessage",void 0),Textarea=__decorate([customElement("glide-core-textarea"),final],Textarea);export default Textarea;
193
+ >`;
194
+ }
195
+ reportValidity() {
196
+ this.isReportValidityOrSubmit = true;
197
+ const isValid = this.#internals.reportValidity();
198
+ // Ensures that getters referencing `this.validity.valid` are updated.
199
+ this.requestUpdate();
200
+ return isValid;
201
+ }
202
+ resetValidityFeedback() {
203
+ this.isReportValidityOrSubmit = false;
204
+ }
205
+ setCustomValidity(message) {
206
+ this.validityMessage = message;
207
+ if (message === '') {
208
+ this.#internals.setValidity({ customError: false }, '', this.#textareaElementRef.value);
209
+ }
210
+ else {
211
+ this.#internals.setValidity({
212
+ customError: true,
213
+ valueMissing: this.#internals.validity.valueMissing,
214
+ }, ' ', this.#textareaElementRef.value);
215
+ }
216
+ }
217
+ setValidity(flags, message) {
218
+ this.validityMessage = message;
219
+ this.#internals.setValidity(flags, ' ', this.#textareaElementRef.value);
220
+ }
221
+ constructor() {
222
+ super();
223
+ this.autocapitalize = 'on';
224
+ this.autocomplete = 'on';
225
+ this.disabled = false;
226
+ this.hideLabel = false;
227
+ this.name = '';
228
+ this.orientation = 'horizontal';
229
+ // It's typed by TypeScript as a boolean. But we treat it as a string throughout.
230
+ this.spellcheck = false;
231
+ this.required = false;
232
+ this.readonly = false;
233
+ // Intentionally not reflected to match native.
234
+ this.value = '';
235
+ this.version = packageJson.version;
236
+ this.isBlurring = false;
237
+ this.isCheckingValidity = false;
238
+ this.isReportValidityOrSubmit = false;
239
+ this.#localize = new LocalizeController(this);
240
+ this.#textareaElementRef = createRef();
241
+ // An arrow function field instead of a method so `this` is closed over and
242
+ // set to the component instead of `document`.
243
+ this.#onFormdata = ({ formData }) => {
244
+ if (this.name && this.value && !this.disabled) {
245
+ formData.append(this.name, this.value);
246
+ }
247
+ };
248
+ this.#internals = this.attachInternals();
249
+ // Event handlers on the host aren't great because consumers can remove them.
250
+ // Unfortunately, the host is the only thing on which this event is dispatched
251
+ // because it's the host that is form-associated.
252
+ this.addEventListener('invalid', (event) => {
253
+ event?.preventDefault(); // Canceled so a native validation message isn't shown.
254
+ // We only want to focus the input if the "invalid" event resulted from either:
255
+ //
256
+ // 1. A form submission.
257
+ // 2. A call of `reportValidity()` that did not result from the input's "blur"
258
+ // event.
259
+ if (this.isCheckingValidity || this.isBlurring) {
260
+ return;
261
+ }
262
+ this.isReportValidityOrSubmit = true;
263
+ const isFirstInvalidFormElement = this.form?.querySelector(':invalid') === this;
264
+ if (isFirstInvalidFormElement) {
265
+ // - `this.#internals.delegatesFocus` is preferred because it's declarative. But
266
+ // it's limited to focusing the first focusable element. That doesn't work for
267
+ // us because our first focusable element is the tooltip when it's present.
268
+ //
269
+ // - Canceling this event means the input won't get focus, even if we were to use
270
+ // `this.#internals.delegatesFocus`.
271
+ //
272
+ // - The browser will ignore this if Input isn't the first invalid form control.
273
+ //
274
+ // TODO
275
+ // Try passing `focusVisible` after browsers support it. It may prevent the issue
276
+ // where the input itself has a focus outline after this call.
277
+ //
278
+ // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#focusvisible
279
+ this.focus();
280
+ }
281
+ });
282
+ }
283
+ #internals;
284
+ #localize;
285
+ #textareaElementRef;
286
+ // An arrow function field instead of a method so `this` is closed over and
287
+ // set to the component instead of `document`.
288
+ #onFormdata;
289
+ get #isShowValidationFeedback() {
290
+ return (!this.disabled &&
291
+ !this.readonly &&
292
+ !this.validity.valid &&
293
+ this.isReportValidityOrSubmit);
294
+ }
295
+ get #valueCharacterCount() {
296
+ return this.value.length;
297
+ }
298
+ get #isMaxCharacterCountExceeded() {
299
+ return Boolean(!this.disabled &&
300
+ !this.readonly &&
301
+ this.maxlength &&
302
+ this.#valueCharacterCount > this.maxlength);
303
+ }
304
+ #onTextareaBlur() {
305
+ this.isBlurring = true;
306
+ this.reportValidity();
307
+ this.isBlurring = false;
308
+ }
309
+ #onTextareaChange() {
310
+ if (this.#textareaElementRef.value) {
311
+ this.value = this.#textareaElementRef.value.value;
312
+ }
313
+ // Unlike "input" events, "change" events aren't composed. So we have to
314
+ // manually dispatch them.
315
+ this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
316
+ }
317
+ #onTextareaInput() {
318
+ if (this.#textareaElementRef.value) {
319
+ this.value = this.#textareaElementRef.value.value;
320
+ }
321
+ }
322
+ #onTextareaKeydown(event) {
323
+ if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
324
+ this.form?.requestSubmit();
325
+ }
326
+ }
327
+ };
328
+ __decorate([
329
+ property({ reflect: true }),
330
+ required
331
+ ], Textarea.prototype, "label", void 0);
332
+ __decorate([
333
+ property({ reflect: true, useDefault: true })
334
+ ], Textarea.prototype, "autocapitalize", void 0);
335
+ __decorate([
336
+ property({ reflect: true, useDefault: true })
337
+ ], Textarea.prototype, "autocomplete", void 0);
338
+ __decorate([
339
+ property({ reflect: true, type: Boolean })
340
+ ], Textarea.prototype, "disabled", void 0);
341
+ __decorate([
342
+ property({ attribute: 'hide-label', reflect: true, type: Boolean })
343
+ ], Textarea.prototype, "hideLabel", void 0);
344
+ __decorate([
345
+ property({
346
+ type: Number,
347
+ converter(value) {
348
+ return value && Number.parseInt(value, 10);
349
+ },
350
+ reflect: true,
351
+ })
352
+ ], Textarea.prototype, "maxlength", void 0);
353
+ __decorate([
354
+ property({ reflect: true, useDefault: true })
355
+ ], Textarea.prototype, "name", void 0);
356
+ __decorate([
357
+ property({ reflect: true, useDefault: true })
358
+ ], Textarea.prototype, "orientation", void 0);
359
+ __decorate([
360
+ property({ reflect: true })
361
+ ], Textarea.prototype, "placeholder", void 0);
362
+ __decorate([
363
+ property()
364
+ ], Textarea.prototype, "privateSplit", void 0);
365
+ __decorate([
366
+ property({ reflect: true, type: Boolean, useDefault: true })
367
+ ], Textarea.prototype, "spellcheck", void 0);
368
+ __decorate([
369
+ property({ reflect: true, type: Boolean })
370
+ ], Textarea.prototype, "required", void 0);
371
+ __decorate([
372
+ property({ reflect: true, type: Boolean })
373
+ ], Textarea.prototype, "readonly", void 0);
374
+ __decorate([
375
+ property({ reflect: true })
376
+ ], Textarea.prototype, "tooltip", void 0);
377
+ __decorate([
378
+ property()
379
+ ], Textarea.prototype, "value", void 0);
380
+ __decorate([
381
+ property({ reflect: true })
382
+ ], Textarea.prototype, "version", void 0);
383
+ __decorate([
384
+ state()
385
+ ], Textarea.prototype, "isBlurring", void 0);
386
+ __decorate([
387
+ state()
388
+ ], Textarea.prototype, "isCheckingValidity", void 0);
389
+ __decorate([
390
+ state()
391
+ ], Textarea.prototype, "isReportValidityOrSubmit", void 0);
392
+ __decorate([
393
+ state()
394
+ ], Textarea.prototype, "validityMessage", void 0);
395
+ Textarea = __decorate([
396
+ customElement('glide-core-textarea'),
397
+ final
398
+ ], Textarea);
399
+ export default Textarea;
@@ -1,6 +1,24 @@
1
- import{css,unsafeCSS}from"lit";import visuallyHidden from"./styles/visually-hidden.js";const fieldSizingContent=unsafeCSS("\n field-sizing: content;\n");export default[css`
2
- ${visuallyHidden(".character-count .hidden")}
3
- `,css`
1
+ import { css, unsafeCSS } from 'lit';
2
+ import visuallyHidden from './styles/visually-hidden.js';
3
+ /*
4
+ `field-sizing` is only supported in Chrome and Edge
5
+ at the moment (https://caniuse.com/mdn-css_properties_field-sizing),
6
+ making this a progressive enhancement. This functionality is additive,
7
+ rather than required for use with our components.
8
+
9
+ `field-sizing` is also not recognized by lit-plugin, so we are seeing
10
+ https://github.com/runem/lit-analyzer/issues/157 when
11
+ attempting to use it directly in our CSS below. This use of unsafeCSS
12
+ is a workaround for that bug for the time being.
13
+ */
14
+ const fieldSizingContent = unsafeCSS(`
15
+ field-sizing: content;
16
+ `);
17
+ export default [
18
+ css `
19
+ ${visuallyHidden('.character-count .hidden')}
20
+ `,
21
+ css `
4
22
  glide-core-private-label[orientation='horizontal']::part(private-tooltips) {
5
23
  align-items: flex-start;
6
24
  margin-block-start: var(--glide-core-spacing-base-sm);
@@ -107,4 +125,5 @@ import{css,unsafeCSS}from"lit";import visuallyHidden from"./styles/visually-hidd
107
125
  font-weight: var(--glide-core-typography-weight-bold);
108
126
  }
109
127
  }
110
- `];
128
+ `,
129
+ ];
package/dist/toast.js CHANGED
@@ -1 +1,130 @@
1
- var __decorate=this&&this.__decorate||function(t,e,o,r){var i,s=arguments.length,a=s<3?e:null===r?r=Object.getOwnPropertyDescriptor(e,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)a=Reflect.decorate(t,e,o,r);else for(var p=t.length-1;p>=0;p--)(i=t[p])&&(a=(s<3?i(a):s>3?i(e,o,a):i(e,o))||a);return s>3&&a&&Object.defineProperty(e,o,a),a};import"./icon-button.js";import{LitElement,html}from"lit";import{customElement,property}from"lit/decorators.js";import packageJson from"../package.json"with{type:"json"};import Toasts from"./toast.toasts.js";import shadowRootMode from"./library/shadow-root-mode.js";import final from"./library/final.js";import required from"./library/required.js";import Link from"./link.js";import assertSlot from"./library/assert-slot.js";import uniqueId from"./library/unique-id.js";let Toast=class Toast extends LitElement{constructor(){super(...arguments),this.duration=5e3,this.privateDismissing=!1,this.privateDismissingViaButton=!1,this.privateId=uniqueId(),this.privateShow=!1,this.variant="informational",this.version=packageJson.version}static{this.shadowRootOptions={...LitElement.shadowRootOptions,mode:shadowRootMode}}dismiss(){this.dispatchEvent(new Event("dismiss",{bubbles:!0,composed:!0})),this.remove()}firstUpdated(){(async()=>{await(this.querySelector("glide-core-link")?.updateComplete),Toasts.show(this)})()}render(){return html`<slot hidden ${assertSlot([Link,Text],!0)}></slot>`}};__decorate([property({reflect:!0}),required],Toast.prototype,"label",void 0),__decorate([property()],Toast.prototype,"privateDescription",void 0),__decorate([property({reflect:!0,type:Number,useDefault:!0})],Toast.prototype,"duration",void 0),__decorate([property({type:Boolean})],Toast.prototype,"privateDismissing",void 0),__decorate([property({type:Boolean})],Toast.prototype,"privateDismissingViaButton",void 0),__decorate([property()],Toast.prototype,"privateId",void 0),__decorate([property({type:Boolean})],Toast.prototype,"privateShow",void 0),__decorate([property({attribute:!1})],Toast.prototype,"privateTimeoutId",void 0),__decorate([property({reflect:!0,useDefault:!0})],Toast.prototype,"variant",void 0),__decorate([property({reflect:!0})],Toast.prototype,"version",void 0),Toast=__decorate([customElement("glide-core-toast"),final],Toast);export default Toast;
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import './icon-button.js';
8
+ import { LitElement, html } from 'lit';
9
+ import { customElement, property } from 'lit/decorators.js';
10
+ import packageJson from '../package.json' with { type: 'json' };
11
+ import Toasts from './toast.toasts.js';
12
+ import shadowRootMode from './library/shadow-root-mode.js';
13
+ import final from './library/final.js';
14
+ import required from './library/required.js';
15
+ import Link from './link.js';
16
+ import assertSlot from './library/assert-slot.js';
17
+ import uniqueId from './library/unique-id.js';
18
+ /**
19
+ * @attr {string} label
20
+ * @attr {number} [duration=5000] - Set to `Infinity` to make it persist until dismissed by the user
21
+ * @attr {'informational'|'success'|'error'} [variant='informational']
22
+ *
23
+ * @readonly
24
+ * @attr {string} [version]
25
+ *
26
+ * @slot {Link | string} - A description
27
+ *
28
+ * @fires {Event} dismiss
29
+ *
30
+ * @method dismiss
31
+ */
32
+ let Toast = class Toast extends LitElement {
33
+ constructor() {
34
+ super(...arguments);
35
+ /**
36
+ * Set to `Infinity` to make it persist until dismissed by the user
37
+ **/
38
+ this.duration = 5000;
39
+ this.privateDismissing = false;
40
+ this.privateDismissingViaButton = false;
41
+ // `privateId` instead of `id` so consumers can specify their own `id` to
42
+ // determine, via `event.target.id`, which Toast was dismissed and then update
43
+ // whatever data structure they're using to render Toasts.
44
+ this.privateId = uniqueId();
45
+ this.privateShow = false;
46
+ this.variant = 'informational';
47
+ this.version = packageJson.version;
48
+ }
49
+ static { this.shadowRootOptions = {
50
+ ...LitElement.shadowRootOptions,
51
+ mode: shadowRootMode,
52
+ }; }
53
+ dismiss() {
54
+ this.dispatchEvent(new Event('dismiss', { bubbles: true, composed: true }));
55
+ // It's a tough call whether we should remove Toast for the consumers or ask
56
+ // them should remove it themselves. It's never ideal to manipulate a consumer's
57
+ // DOM. But a stale element on the page is likely to cause confusion given some
58
+ // consumers are unlikely to remove it, whether they know they should or not.
59
+ // For those who do, removing it is an additional and clunky step.
60
+ this.remove();
61
+ }
62
+ // `firstUpdated()` instead of `connectedCallback()` so the Toast isn't shown
63
+ // before `assertSlot()` has had a chance to check the slot.
64
+ firstUpdated() {
65
+ (async () => {
66
+ // A workaround for a Glimmmer rendering quirk.
67
+ //
68
+ // When an attribute's value is dynamic, Glimmer doesn't render it immediately
69
+ // with the rest of a component's markup. Instead, it appears to schedule setting
70
+ // the attribute, delaying its render by a tick or so.
71
+ //
72
+ // In practice, this means Link receives its attributes sometime between its
73
+ // `connectedCallback()` and `firstUpdated()` lifecycle methods. So we wait
74
+ // for `firstUpdated()` via `updateComplete`. If we don't, Links will be rendered
75
+ // inside the Toasts component without their attributes.
76
+ //
77
+ // This workaround is, of course, dependent on Glimmmer not delaying attribute
78
+ // rendering past `firstUpdated()`. But it may be the best we can do. If Glimmmer
79
+ // does change how it renders dynamic attributes, it hopefully renders them sooner
80
+ // not later.
81
+ await this.querySelector('glide-core-link')?.updateComplete;
82
+ Toasts.show(this);
83
+ })();
84
+ }
85
+ render() {
86
+ // `hidden` is used to avoid a stylesheet for a single style.
87
+ return html `<slot hidden ${assertSlot([Link, Text], true)}>
88
+ <!--
89
+ A description
90
+ @type {Link | string}
91
+ -->
92
+ </slot>`;
93
+ }
94
+ };
95
+ __decorate([
96
+ property({ reflect: true }),
97
+ required
98
+ ], Toast.prototype, "label", void 0);
99
+ __decorate([
100
+ property()
101
+ ], Toast.prototype, "privateDescription", void 0);
102
+ __decorate([
103
+ property({ reflect: true, type: Number, useDefault: true })
104
+ ], Toast.prototype, "duration", void 0);
105
+ __decorate([
106
+ property({ type: Boolean })
107
+ ], Toast.prototype, "privateDismissing", void 0);
108
+ __decorate([
109
+ property({ type: Boolean })
110
+ ], Toast.prototype, "privateDismissingViaButton", void 0);
111
+ __decorate([
112
+ property()
113
+ ], Toast.prototype, "privateId", void 0);
114
+ __decorate([
115
+ property({ type: Boolean })
116
+ ], Toast.prototype, "privateShow", void 0);
117
+ __decorate([
118
+ property({ attribute: false })
119
+ ], Toast.prototype, "privateTimeoutId", void 0);
120
+ __decorate([
121
+ property({ reflect: true, useDefault: true })
122
+ ], Toast.prototype, "variant", void 0);
123
+ __decorate([
124
+ property({ reflect: true })
125
+ ], Toast.prototype, "version", void 0);
126
+ Toast = __decorate([
127
+ customElement('glide-core-toast'),
128
+ final
129
+ ], Toast);
130
+ export default Toast;