@design.estate/dees-catalog 9.6.2 → 9.7.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.
Files changed (51) hide show
  1. package/dist_bundle/bundle.js +2945 -2681
  2. package/dist_bundle/bundle.js.map +1 -1
  3. package/dist_ts_web/00_commitinfo_data.js +1 -1
  4. package/dist_ts_web/demos/inputs.d.ts +1 -1
  5. package/dist_ts_web/demos/inputs.js +5 -4
  6. package/dist_ts_web/elements/00group-form/dees-form/dees-form.d.ts +5 -1
  7. package/dist_ts_web/elements/00group-form/dees-form/dees-form.js +27 -3
  8. package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.d.ts +1 -0
  9. package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.js +11 -2
  10. package/dist_ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.d.ts +3 -0
  11. package/dist_ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.demo.js +4 -1
  12. package/dist_ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.js +51 -13
  13. package/dist_ts_web/elements/00group-input/dees-input-datepicker/component.d.ts +18 -3
  14. package/dist_ts_web/elements/00group-input/dees-input-datepicker/component.js +181 -144
  15. package/dist_ts_web/elements/00group-input/dees-input-datepicker/date-validation.d.ts +13 -0
  16. package/dist_ts_web/elements/00group-input/dees-input-datepicker/date-validation.js +65 -0
  17. package/dist_ts_web/elements/00group-input/dees-input-datepicker/datepicker-popup.js +44 -56
  18. package/dist_ts_web/elements/00group-input/dees-input-datepicker/styles.js +6 -1
  19. package/dist_ts_web/elements/00group-input/dees-input-datepicker/template.js +11 -5
  20. package/dist_ts_web/elements/00group-input/dees-input-text/dees-input-text.d.ts +8 -8
  21. package/dist_ts_web/elements/00group-input/dees-input-text/dees-input-text.js +6 -53
  22. package/dist_ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.d.ts +62 -0
  23. package/dist_ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.demo.d.ts +1 -0
  24. package/dist_ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.demo.js +3 -0
  25. package/dist_ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.js +224 -0
  26. package/dist_ts_web/elements/00group-input/dees-input-textarea/index.d.ts +1 -0
  27. package/dist_ts_web/elements/00group-input/dees-input-textarea/index.js +2 -0
  28. package/dist_ts_web/elements/00group-input/index.d.ts +1 -0
  29. package/dist_ts_web/elements/00group-input/index.js +2 -1
  30. package/dist_ts_web/elements/00group-input/text-input-contextmenu.d.ts +29 -0
  31. package/dist_ts_web/elements/00group-input/text-input-contextmenu.js +29 -0
  32. package/package.json +1 -1
  33. package/readme.md +59 -4
  34. package/scripts/check-packed-consumer.mjs +8 -5
  35. package/ts_web/00_commitinfo_data.ts +1 -1
  36. package/ts_web/demos/inputs.ts +5 -4
  37. package/ts_web/elements/00group-form/dees-form/dees-form.ts +25 -2
  38. package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.ts +4 -0
  39. package/ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.demo.ts +3 -0
  40. package/ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.ts +37 -11
  41. package/ts_web/elements/00group-input/dees-input-datepicker/component.ts +149 -148
  42. package/ts_web/elements/00group-input/dees-input-datepicker/date-validation.ts +64 -0
  43. package/ts_web/elements/00group-input/dees-input-datepicker/datepicker-popup.ts +40 -40
  44. package/ts_web/elements/00group-input/dees-input-datepicker/styles.ts +5 -0
  45. package/ts_web/elements/00group-input/dees-input-datepicker/template.ts +10 -4
  46. package/ts_web/elements/00group-input/dees-input-text/dees-input-text.ts +5 -52
  47. package/ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.demo.ts +2 -0
  48. package/ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.ts +128 -0
  49. package/ts_web/elements/00group-input/dees-input-textarea/index.ts +1 -0
  50. package/ts_web/elements/00group-input/index.ts +1 -0
  51. package/ts_web/elements/00group-input/text-input-contextmenu.ts +31 -0
@@ -0,0 +1,224 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
35
+ import { customElement, property, html, css } from '@design.estate/dees-element';
36
+ import { DeesInputBase } from '../dees-input-base/dees-input-base.js';
37
+ import { textInputContextMenuItems } from '../text-input-contextmenu.js';
38
+ import { demoFunc } from './dees-input-textarea.demo.js';
39
+ import '../../00group-overlay/dees-contextmenu/dees-contextmenu.js';
40
+ let DeesInputTextarea = (() => {
41
+ let _classDecorators = [customElement('dees-input-textarea')];
42
+ let _classDescriptor;
43
+ let _classExtraInitializers = [];
44
+ let _classThis;
45
+ let _classSuper = DeesInputBase;
46
+ let _value_decorators;
47
+ let _value_initializers = [];
48
+ let _value_extraInitializers = [];
49
+ let _placeholder_decorators;
50
+ let _placeholder_initializers = [];
51
+ let _placeholder_extraInitializers = [];
52
+ let _rows_decorators;
53
+ let _rows_initializers = [];
54
+ let _rows_extraInitializers = [];
55
+ let _maxLength_decorators;
56
+ let _maxLength_initializers = [];
57
+ let _maxLength_extraInitializers = [];
58
+ let _validationState_decorators;
59
+ let _validationState_initializers = [];
60
+ let _validationState_extraInitializers = [];
61
+ let _validationText_decorators;
62
+ let _validationText_initializers = [];
63
+ let _validationText_extraInitializers = [];
64
+ let _validationFunction_decorators;
65
+ let _validationFunction_initializers = [];
66
+ let _validationFunction_extraInitializers = [];
67
+ var DeesInputTextarea = class extends _classSuper {
68
+ static { _classThis = this; }
69
+ static {
70
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
71
+ _value_decorators = [property({ type: String })];
72
+ _placeholder_decorators = [property({ type: String })];
73
+ _rows_decorators = [property({ type: Number })];
74
+ _maxLength_decorators = [property({ type: Number })];
75
+ _validationState_decorators = [property({ type: String, reflect: true })];
76
+ _validationText_decorators = [property({ type: String })];
77
+ _validationFunction_decorators = [property({ attribute: false })];
78
+ __esDecorate(this, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
79
+ __esDecorate(this, null, _placeholder_decorators, { kind: "accessor", name: "placeholder", static: false, private: false, access: { has: obj => "placeholder" in obj, get: obj => obj.placeholder, set: (obj, value) => { obj.placeholder = value; } }, metadata: _metadata }, _placeholder_initializers, _placeholder_extraInitializers);
80
+ __esDecorate(this, null, _rows_decorators, { kind: "accessor", name: "rows", static: false, private: false, access: { has: obj => "rows" in obj, get: obj => obj.rows, set: (obj, value) => { obj.rows = value; } }, metadata: _metadata }, _rows_initializers, _rows_extraInitializers);
81
+ __esDecorate(this, null, _maxLength_decorators, { kind: "accessor", name: "maxLength", static: false, private: false, access: { has: obj => "maxLength" in obj, get: obj => obj.maxLength, set: (obj, value) => { obj.maxLength = value; } }, metadata: _metadata }, _maxLength_initializers, _maxLength_extraInitializers);
82
+ __esDecorate(this, null, _validationState_decorators, { kind: "accessor", name: "validationState", static: false, private: false, access: { has: obj => "validationState" in obj, get: obj => obj.validationState, set: (obj, value) => { obj.validationState = value; } }, metadata: _metadata }, _validationState_initializers, _validationState_extraInitializers);
83
+ __esDecorate(this, null, _validationText_decorators, { kind: "accessor", name: "validationText", static: false, private: false, access: { has: obj => "validationText" in obj, get: obj => obj.validationText, set: (obj, value) => { obj.validationText = value; } }, metadata: _metadata }, _validationText_initializers, _validationText_extraInitializers);
84
+ __esDecorate(this, null, _validationFunction_decorators, { kind: "accessor", name: "validationFunction", static: false, private: false, access: { has: obj => "validationFunction" in obj, get: obj => obj.validationFunction, set: (obj, value) => { obj.validationFunction = value; } }, metadata: _metadata }, _validationFunction_initializers, _validationFunction_extraInitializers);
85
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
86
+ DeesInputTextarea = _classThis = _classDescriptor.value;
87
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
88
+ }
89
+ static demo = demoFunc;
90
+ static demoGroups = ['Input'];
91
+ static inputLayout = 'compound';
92
+ #value_accessor_storage = __runInitializers(this, _value_initializers, '');
93
+ get value() { return this.#value_accessor_storage; }
94
+ set value(value) { this.#value_accessor_storage = value; }
95
+ #placeholder_accessor_storage = (__runInitializers(this, _value_extraInitializers), __runInitializers(this, _placeholder_initializers, ''));
96
+ get placeholder() { return this.#placeholder_accessor_storage; }
97
+ set placeholder(value) { this.#placeholder_accessor_storage = value; }
98
+ #rows_accessor_storage = (__runInitializers(this, _placeholder_extraInitializers), __runInitializers(this, _rows_initializers, 3));
99
+ get rows() { return this.#rows_accessor_storage; }
100
+ set rows(value) { this.#rows_accessor_storage = value; }
101
+ #maxLength_accessor_storage = (__runInitializers(this, _rows_extraInitializers), __runInitializers(this, _maxLength_initializers, -1));
102
+ get maxLength() { return this.#maxLength_accessor_storage; }
103
+ set maxLength(value) { this.#maxLength_accessor_storage = value; }
104
+ #validationState_accessor_storage = (__runInitializers(this, _maxLength_extraInitializers), __runInitializers(this, _validationState_initializers, void 0));
105
+ get validationState() { return this.#validationState_accessor_storage; }
106
+ set validationState(value) { this.#validationState_accessor_storage = value; }
107
+ #validationText_accessor_storage = (__runInitializers(this, _validationState_extraInitializers), __runInitializers(this, _validationText_initializers, ''));
108
+ get validationText() { return this.#validationText_accessor_storage; }
109
+ set validationText(value) { this.#validationText_accessor_storage = value; }
110
+ #validationFunction_accessor_storage = (__runInitializers(this, _validationText_extraInitializers), __runInitializers(this, _validationFunction_initializers, void 0));
111
+ get validationFunction() { return this.#validationFunction_accessor_storage; }
112
+ set validationFunction(value) { this.#validationFunction_accessor_storage = value; }
113
+ touched = (__runInitializers(this, _validationFunction_extraInitializers), false);
114
+ lastValidity;
115
+ static styles = [...DeesInputBase.baseStyles, css `
116
+ textarea { display: block; width: 100%; height: auto; padding: 10px 12px; resize: vertical; text-align: left; }
117
+ .field-messages { grid-column: 1 / -1; }
118
+ .validationText { font-size: var(--dees-font-footnote-size); line-height: var(--dees-font-footnote-line); color: var(--dees-color-text-error); }
119
+ .validationText:not(:empty) { margin-top: var(--dees-spacing-xs); }
120
+ :host([validationstate="invalid"]) textarea { border-color: var(--dees-color-accent-error); }
121
+ :host([validationstate="warn"]) .validationText { color: var(--dees-color-text-warning); }
122
+ :host([validationstate="valid"]) .validationText { color: var(--dees-color-text-success); }
123
+ `];
124
+ render() {
125
+ return html `<div class="input-wrapper">
126
+ <dees-label .label=${this.label} .infoText=${this.infoText} .required=${this.required} @click=${() => this.focus()}></dees-label>
127
+ <div class="input-container">
128
+ <textarea class="field-control" .value=${this.value} .rows=${Math.max(1, this.rows)}
129
+ placeholder=${this.placeholder} ?disabled=${this.disabled} ?required=${this.required}
130
+ aria-label=${this.label ?? ''} aria-invalid=${this.validationState === 'invalid' ? 'true' : 'false'}
131
+ aria-describedby="field-description field-validation"
132
+ @input=${this.handleInput} @blur=${() => this.validate()}></textarea>
133
+ </div>
134
+ <div class="field-messages">
135
+ <div id="field-description">${this.renderDescription()}</div>
136
+ <div id="field-validation" class="validationText" role="status">${this.validationText}</div>
137
+ </div>
138
+ </div>`;
139
+ }
140
+ willUpdate(changed) {
141
+ super.willUpdate(changed);
142
+ if (changed.has('value') && this.value == null)
143
+ this.value = '';
144
+ }
145
+ updated(changed) {
146
+ super.updated(changed);
147
+ const input = this.shadowRoot?.querySelector('textarea');
148
+ if (this.maxLength >= 0)
149
+ input?.setAttribute('maxlength', String(this.maxLength));
150
+ else
151
+ input?.removeAttribute('maxlength');
152
+ if (['value', 'required', 'maxLength', 'validationFunction', 'disabled'].some(key => changed.has(key))) {
153
+ this.validate(this.touched || Boolean(this.value));
154
+ }
155
+ else if (changed.has('validationState') || changed.has('validationText')) {
156
+ this.syncValidity();
157
+ }
158
+ }
159
+ ruleMessage() {
160
+ if (this.disabled)
161
+ return '';
162
+ if (this.required && !this.value.length)
163
+ return 'Enter a value.';
164
+ if (this.maxLength >= 0 && this.value.length > this.maxLength)
165
+ return `Use ${this.maxLength} characters or fewer.`;
166
+ const result = this.validationFunction?.(this.value);
167
+ return result && !result.valid ? result.message || 'Check this value.' : '';
168
+ }
169
+ syncValidity() {
170
+ const message = this.disabled ? '' : this.ruleMessage() || (this.validationState === 'invalid' ? this.validationText || 'Check this value.' : '');
171
+ this.shadowRoot?.querySelector('textarea')?.setCustomValidity(message);
172
+ const valid = !message;
173
+ if (valid !== this.lastValidity) {
174
+ this.lastValidity = valid;
175
+ this.dispatchEvent(new CustomEvent('validation-change', { detail: { valid, message }, bubbles: true, composed: true }));
176
+ }
177
+ }
178
+ validate(showMessage = true) {
179
+ if (showMessage)
180
+ this.touched = true;
181
+ const message = this.ruleMessage();
182
+ this.validationText = showMessage ? message : '';
183
+ this.validationState = showMessage ? message ? 'invalid' : 'valid' : undefined;
184
+ this.syncValidity();
185
+ return !message;
186
+ }
187
+ checkValidity() {
188
+ return this.disabled || (!this.ruleMessage() && this.validationState !== 'invalid');
189
+ }
190
+ reportValidity() {
191
+ // Preserve a host-supplied validation message until the value changes.
192
+ const valid = this.validationState === 'invalid' ? this.checkValidity() : this.validate();
193
+ if (!valid)
194
+ this.focus();
195
+ return valid;
196
+ }
197
+ handleInput = () => {
198
+ if (this.disabled)
199
+ return;
200
+ this.value = this.shadowRoot.querySelector('textarea').value;
201
+ this.validate();
202
+ this.changeSubject.next(this);
203
+ };
204
+ getContextMenuItems() {
205
+ return textInputContextMenuItems({ input: this.shadowRoot.querySelector('textarea'), disabled: this.disabled,
206
+ commit: value => { this.value = value; this.validate(); this.changeSubject.next(this); } });
207
+ }
208
+ getValue() { return this.value; }
209
+ setValue(value) {
210
+ this.value = value ?? '';
211
+ this.touched = false;
212
+ this.validate(false);
213
+ }
214
+ reset() { this.setValue(''); }
215
+ focus(options) { this.shadowRoot?.querySelector('textarea')?.focus(options); }
216
+ blur() { this.shadowRoot?.querySelector('textarea')?.blur(); }
217
+ static {
218
+ __runInitializers(_classThis, _classExtraInitializers);
219
+ }
220
+ };
221
+ return DeesInputTextarea = _classThis;
222
+ })();
223
+ export { DeesInputTextarea };
224
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVlcy1pbnB1dC10ZXh0YXJlYS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3RzX3dlYi9lbGVtZW50cy8wMGdyb3VwLWlucHV0L2RlZXMtaW5wdXQtdGV4dGFyZWEvZGVlcy1pbnB1dC10ZXh0YXJlYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUEsT0FBTyxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBdUIsTUFBTSw2QkFBNkIsQ0FBQztBQUN0RyxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sdUNBQXVDLENBQUM7QUFDdEUsT0FBTyxFQUFFLHlCQUF5QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDekUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ3pELE9BQU8sNERBQTRELENBQUM7SUFLdkQsaUJBQWlCOzRCQUQ3QixhQUFhLENBQUMscUJBQXFCLENBQUM7Ozs7c0JBQ0UsYUFBYTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztpQ0FBckIsU0FBUSxXQUFnQzs7OztpQ0FLcEUsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO3VDQUMxQixRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7Z0NBQzFCLFFBQVEsQ0FBQyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztxQ0FDMUIsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzJDQUMxQixRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsQ0FBQzswQ0FDekMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDOzhDQUMxQixRQUFRLENBQUMsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQUM7WUFOSCxvS0FB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
@@ -0,0 +1 @@
1
+ export * from './dees-input-textarea.js';
@@ -0,0 +1,2 @@
1
+ export * from './dees-input-textarea.js';
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1pbnB1dC9kZWVzLWlucHV0LXRleHRhcmVhL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsMEJBQTBCLENBQUMifQ==
@@ -14,6 +14,7 @@ export * from './dees-input-richtext/index.js';
14
14
  export * from './dees-input-searchselect/index.js';
15
15
  export * from './dees-input-tags/index.js';
16
16
  export * from './dees-input-text/index.js';
17
+ export * from './dees-input-textarea/index.js';
17
18
  export * from './dees-input-toggle/index.js';
18
19
  export * from './dees-input-typelist/index.js';
19
20
  export * from './dees-input-wysiwyg.js';
@@ -15,8 +15,9 @@ export * from './dees-input-richtext/index.js';
15
15
  export * from './dees-input-searchselect/index.js';
16
16
  export * from './dees-input-tags/index.js';
17
17
  export * from './dees-input-text/index.js';
18
+ export * from './dees-input-textarea/index.js';
18
19
  export * from './dees-input-toggle/index.js';
19
20
  export * from './dees-input-typelist/index.js';
20
21
  export * from './dees-input-wysiwyg.js';
21
22
  export * from './profilepicture/dees-input-profilepicture.js';
22
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1pbnB1dC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxtQkFBbUI7QUFDbkIsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLHdDQUF3QyxDQUFDO0FBQ3ZELGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDhCQUE4QixDQUFDO0FBQzdDLGNBQWMsZ0NBQWdDLENBQUM7QUFDL0MsY0FBYyx5QkFBeUIsQ0FBQztBQUN4QyxjQUFjLCtDQUErQyxDQUFDIn0=
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90c193ZWIvZWxlbWVudHMvMDBncm91cC1pbnB1dC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxtQkFBbUI7QUFDbkIsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyxrQ0FBa0MsQ0FBQztBQUNqRCxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLDRCQUE0QixDQUFDO0FBQzNDLGNBQWMsbUNBQW1DLENBQUM7QUFDbEQsY0FBYyw2QkFBNkIsQ0FBQztBQUM1QyxjQUFjLHdDQUF3QyxDQUFDO0FBQ3ZELGNBQWMsa0NBQWtDLENBQUM7QUFDakQsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLG9DQUFvQyxDQUFDO0FBQ25ELGNBQWMsNEJBQTRCLENBQUM7QUFDM0MsY0FBYyw0QkFBNEIsQ0FBQztBQUMzQyxjQUFjLGdDQUFnQyxDQUFDO0FBQy9DLGNBQWMsOEJBQThCLENBQUM7QUFDN0MsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLHlCQUF5QixDQUFDO0FBQ3hDLGNBQWMsK0NBQStDLENBQUMifQ==
@@ -0,0 +1,29 @@
1
+ interface ITextInputContext {
2
+ input: HTMLInputElement | HTMLTextAreaElement;
3
+ disabled: boolean;
4
+ commit: (value: string) => void;
5
+ }
6
+ /** Shared plain-text editing commands for single- and multiline fields. */
7
+ export declare const textInputContextMenuItems: ({ input, disabled, commit }: ITextInputContext) => ({
8
+ name: string;
9
+ iconName: string;
10
+ shortcut: string;
11
+ disabled: boolean;
12
+ action: () => Promise<void>;
13
+ divider?: undefined;
14
+ } | {
15
+ divider: true;
16
+ name?: undefined;
17
+ iconName?: undefined;
18
+ shortcut?: undefined;
19
+ disabled?: undefined;
20
+ action?: undefined;
21
+ } | {
22
+ name: string;
23
+ iconName: string;
24
+ shortcut: string;
25
+ action: () => void;
26
+ disabled?: undefined;
27
+ divider?: undefined;
28
+ })[];
29
+ export {};
@@ -0,0 +1,29 @@
1
+ /** Shared plain-text editing commands for single- and multiline fields. */
2
+ export const textInputContextMenuItems = ({ input, disabled, commit }) => {
3
+ const selectedText = () => input.value.substring(input.selectionStart ?? 0, input.selectionEnd ?? 0);
4
+ const replaceSelection = (text) => {
5
+ if (disabled || input.disabled)
6
+ return;
7
+ input.setRangeText(text, input.selectionStart ?? 0, input.selectionEnd ?? 0, 'end');
8
+ commit(input.value);
9
+ };
10
+ return [
11
+ { name: 'Cut', iconName: 'lucide:Scissors', shortcut: 'Cmd+X', disabled: disabled || !selectedText(), action: async () => {
12
+ if (disabled || input.disabled)
13
+ return;
14
+ await navigator.clipboard.writeText(selectedText());
15
+ replaceSelection('');
16
+ } },
17
+ { name: 'Copy', iconName: 'lucide:Copy', shortcut: 'Cmd+C', disabled: !selectedText(), action: async () => {
18
+ await navigator.clipboard.writeText(selectedText());
19
+ } },
20
+ { name: 'Paste', iconName: 'lucide:ClipboardPaste', shortcut: 'Cmd+V', disabled, action: async () => {
21
+ if (disabled || input.disabled)
22
+ return;
23
+ replaceSelection(await navigator.clipboard.readText());
24
+ } },
25
+ { divider: true },
26
+ { name: 'Select All', iconName: 'lucide:TextCursorInput', shortcut: 'Cmd+A', action: () => input.select() },
27
+ ];
28
+ };
29
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGV4dC1pbnB1dC1jb250ZXh0bWVudS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3RzX3dlYi9lbGVtZW50cy8wMGdyb3VwLWlucHV0L3RleHQtaW5wdXQtY29udGV4dG1lbnUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTUEsMkVBQTJFO0FBQzNFLE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBcUIsRUFBRSxFQUFFO0lBQzFGLE1BQU0sWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxjQUFjLElBQUksQ0FBQyxFQUFFLEtBQUssQ0FBQyxZQUFZLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDckcsTUFBTSxnQkFBZ0IsR0FBRyxDQUFDLElBQVksRUFBRSxFQUFFO1FBQ3hDLElBQUksUUFBUSxJQUFJLEtBQUssQ0FBQyxRQUFRO1lBQUUsT0FBTztRQUN2QyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsY0FBYyxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsWUFBWSxJQUFJLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUNwRixNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RCLENBQUMsQ0FBQztJQUNGLE9BQU87UUFDTCxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLGlCQUFpQixFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsSUFBSSxDQUFDLFlBQVksRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDdkgsSUFBSSxRQUFRLElBQUksS0FBSyxDQUFDLFFBQVE7b0JBQUUsT0FBTztnQkFDdkMsTUFBTSxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO2dCQUNwRCxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN2QixDQUFDLEVBQUU7UUFDSCxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLGFBQWEsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDLFlBQVksRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLElBQUksRUFBRTtnQkFDeEcsTUFBTSxTQUFTLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDO1lBQ3RELENBQUMsRUFBRTtRQUNILEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsdUJBQXVCLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEtBQUssSUFBSSxFQUFFO2dCQUNsRyxJQUFJLFFBQVEsSUFBSSxLQUFLLENBQUMsUUFBUTtvQkFBRSxPQUFPO2dCQUN2QyxnQkFBZ0IsQ0FBQyxNQUFNLFNBQVMsQ0FBQyxTQUFTLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUN6RCxDQUFDLEVBQUU7UUFDSCxFQUFFLE9BQU8sRUFBRSxJQUFhLEVBQUU7UUFDMUIsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSx3QkFBd0IsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLEVBQUU7S0FDNUcsQ0FBQztBQUNKLENBQUMsQ0FBQyJ9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@design.estate/dees-catalog",
3
- "version": "9.6.2",
3
+ "version": "9.7.0",
4
4
  "private": false,
5
5
  "description": "A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.",
6
6
  "main": "dist_ts_web/index.js",
package/readme.md CHANGED
@@ -31,6 +31,7 @@ switcher**, **view-toggle**, and **single-selection toggle** all lead to
31
31
  | Show products with quantities or select a kit | [`dees-shopping-productcard`](#deesshoppingproductcard) | Independent quantity and selection events; the application owns the cart and inventory. |
32
32
  | See components composed into one working application | [Integrated App UI demo](#integrated-app-ui-demo) | Shared state, layout presets, navigation, service tabs, charts, files, settings and activity. Start here before assembling a shell. |
33
33
  | Collect and submit form values | [`dees-form`](#deesform), [`dees-form-submit`](#deesformsubmit) | Give each input a stable `key`; use the form's collection and validation flow. |
34
+ | Edit multiline plain text | [`dees-input-textarea`](#deesinputtextarea) | Notes and descriptions as strings, with validation and form reset; no rich-text editor. |
34
35
  | Search, filter, sort, edit and act on records | [`dees-table`](#deestable) | Use its columns, selection and data actions before building a table toolbar or row-action layer. |
35
36
  | Show metrics, health and operational context | [`dees-statsgrid`](#deesstatsgrid), [`dees-dataview-statusobject`](#deesdataviewstatusobject) | Metric tiles versus structured status details and actions. |
36
37
  | Plot a time series, compare categories, show proportions, capacity or profiles | [Chart components](#visualization-components) | Area, bar, donut, gauge and radar have distinct data contracts. |
@@ -105,10 +106,13 @@ node scripts/check-packed-consumer.mjs
105
106
 
106
107
  `pnpm test` rebuilds the package first. The consumer check installs its tarball in
107
108
  an isolated temporary project and checks the table, settings, modal, PDF viewer,
108
- PDF thumbnail and harness message-list declarations with TypeScript 5.9.3 and
109
+ PDF thumbnail, harness message-list, datepicker, textarea and composer declarations with TypeScript 5.9.3 and
109
110
  6.0.3, `strict: true` and `skipLibCheck: false`. It also runs Chromium construction,
110
111
  reconnect, selection/copy and real keyboard checks against the installed modules
111
- and bundle. No source aliases or vendor declarations are used. Pass an existing
112
+ and bundle. The packed tests also exercise strict calendar validation, multiline
113
+ form values and attachment capabilities. Trusted keyboard entry inside a native
114
+ dialog is checked in UTC, Los Angeles, Berlin and São Paulo. No source aliases or
115
+ vendor declarations are used. Pass an existing
112
116
  release tarball as the script's argument to verify those exact bytes.
113
117
 
114
118
  ## Component index
@@ -195,6 +199,7 @@ task guide and examples deliberately; the generated table does not replace them.
195
199
  | `dees-input-richtext` | input | [DeesInputRichtext](#deesinputrichtext) | [Source](ts_web/elements/00group-input/dees-input-richtext/component.ts) |
196
200
  | `dees-input-tags` | input | [DeesInputTags](#deesinputtags) | [Source](ts_web/elements/00group-input/dees-input-tags/dees-input-tags.ts) |
197
201
  | `dees-input-text` | input | [DeesInputText](#deesinputtext) | [Source](ts_web/elements/00group-input/dees-input-text/dees-input-text.ts) |
202
+ | `dees-input-textarea` | input | [DeesInputTextarea](#deesinputtextarea) | [Source](ts_web/elements/00group-input/dees-input-textarea/dees-input-textarea.ts) |
198
203
  | `dees-input-toggle` | input | [DeesInputToggle](#deesinputtoggle) | [Source](ts_web/elements/00group-input/dees-input-toggle/dees-input-toggle.ts) |
199
204
  | `dees-input-typelist` | input | [DeesInputTypelist](#deesinputtypelist) | [Source](ts_web/elements/00group-input/dees-input-typelist/dees-input-typelist.ts) |
200
205
  | `dees-input-wysiwyg` | input | [DeesInputWysiwyg](#deesinputwysiwyg) | [Source](ts_web/elements/00group-input/dees-input-wysiwyg/dees-input-wysiwyg.ts) |
@@ -512,8 +517,13 @@ Floating action bar for contextual actions.
512
517
  #### `DeesForm`
513
518
  Collect keyed inputs with `await form.collectFormData()` or receive `event.detail.data`
514
519
  from `formData` when a `dees-form-submit` is activated. `changeSubject` publishes
515
- updated form data as fields change. Required values control the submit button;
516
- component-specific validation is owned by the field. There is no `formValidation` event.
520
+ updated form data as fields change. Required values and fields implementing
521
+ `checkValidity()` control the submit button. Invalid fields implementing
522
+ `reportValidity()` receive a validation/focus request on attempted submission.
523
+ Fields notify the form with a bubbling `validation-change` event when their
524
+ validity changes; this does not publish a successful value change. Disabled fields
525
+ do not block submission. `reset()` calls each field's reset method when available.
526
+ There is no `formValidation` event.
517
527
 
518
528
  ```typescript
519
529
  html`<dees-form @formData=${(event) => savePreferences(event.detail.data)}>
@@ -577,6 +587,29 @@ Text input field with validation, info tooltips, description text, and context m
577
587
 
578
588
  > 💡 **All input components** share these common properties from `DeesInputBase`: `key`, `label`, `required`, `disabled`, `infoText`, `description`, `layoutMode`, `labelPosition`.
579
589
 
590
+ #### `DeesInputTextarea`
591
+ Plain multiline string input for notes and descriptions. Uses a native textarea;
592
+ line breaks, whitespace and literal HTML remain plain text. It does not load Tiptap.
593
+ The field uses the shared input styling, a top label and vertical resizing.
594
+
595
+ ```typescript
596
+ html`<dees-input-textarea key="notes" label="Payment notes"
597
+ .value=${'Invoice 42\nReference: equipment'} .rows=${3} .maxLength=${1000}
598
+ .disabled=${false} .required=${true}
599
+ description="Stored as plain text."
600
+ .validationFunction=${(value: string) => ({ valid: value.length <= 1000, message: 'Use up to 1000 characters.' })}
601
+ ></dees-input-textarea>`
602
+ ```
603
+
604
+ `value` defaults to `''`, `rows` to `3`, and `maxLength` to `-1` (unlimited).
605
+ Use `changeSubject` or collect the keyed string with `dees-form`. Enter inserts a
606
+ line break inside forms. Cut, Copy, Paste and Select All use plain-text editing.
607
+ `getValue()`, `setValue(string | null)`, `reset()`, `focus()` and `blur()` are supported;
608
+ null and reset clear the field. Required, length and custom rules integrate with
609
+ `checkValidity()`, `reportValidity()`, native custom validity, `aria-invalid` and a
610
+ live validation message. Hosts can set `validationState` (`valid`, `warn`, `invalid`)
611
+ and `validationText` for server feedback, which persists until the next value change.
612
+
580
613
  #### `DeesInputCheckbox`
581
614
  Checkbox input component for boolean values.
582
615
 
@@ -841,6 +874,20 @@ Profile picture input with cropping, zoom, and image processing.
841
874
  #### `DeesInputDatepicker`
842
875
  Date and time picker component with calendar interface and manual typing support.
843
876
  Use `changeSubject` for field updates, or collect `.value` through `dees-form`.
877
+ Typing validates a draft; **blur or Enter commits** a valid date. Invalid calendar
878
+ fields (including non-leap February 29 and February 31) never roll into another
879
+ month. Invalid draft text remains visible with an accessible message, and the last
880
+ committed value remains unchanged without a successful `changeSubject` emission.
881
+ `checkValidity()` and `reportValidity()` include draft validity, so `dees-form`
882
+ cannot submit a stale date while its displayed draft is invalid.
883
+
884
+ `minDate` and `maxDate` are inclusive local calendar-day bounds. `disabledDates`
885
+ uses the same calendar-day comparison for typing, day buttons and Today. ISO
886
+ date-only values are interpreted locally, without a UTC-midnight shift. Empty
887
+ input or Clear clears the value; `required` then makes it invalid. `setValue()`
888
+ and `reset()` discard drafts and synchronize the field and next-opened calendar.
889
+ Alt+Down opens the calendar; Escape closes it. The popup also works inside native
890
+ dialogs.
844
891
 
845
892
  ```typescript
846
893
  <dees-input-datepicker
@@ -2627,6 +2674,14 @@ Place optional reply or task context in `slot="context"` to integrate it above t
2627
2674
 
2628
2675
  Prompt input: autogrow textarea, attachment picker/paste/drag-drop with configurable `maxAttachmentCount`, `maxAttachmentBytes` (10 MB default), and `maxTotalAttachmentBytes` (30 MB default), image/text/binary classification, optional account, model, and reasoning-effort dropdowns, Cmd/Ctrl+Enter to send. Attachment count is unlimited unless the host sets it. `dees-harness-chat` forwards all three limits and `suggestions` to its composer. Controlled component — the host owns `value`, `attachments`, `suggestions`, `account`, and the other selections. Set `accountOptions` to `{ label, value }[]` so the dropdown displays readable labels while events retain opaque stable account values. Account changes emit `harness-account-change` with `{ account }`; `harness-send` includes optional `account` alongside `model` and `reasoningEffort`.
2629
2676
 
2677
+ For text-only hosts, set **`.attachmentsEnabled=${false}`** on either
2678
+ `dees-harness-composer` or `dees-harness-chat` (a JavaScript property, default `true`).
2679
+ This removes the attachment action, file input and chips; rejects file paste/drop
2680
+ and `addFiles()` ingestion; cancels queued/in-flight additions; and sends an empty
2681
+ `attachments` array for both send and input steering. Normal text paste still works,
2682
+ and file drops cannot navigate away from the page. The host-owned attachments array
2683
+ is retained, so re-enabling the capability restores its chips without data loss.
2684
+
2630
2685
  Set `suggestions` to `IHarnessComposerSuggestion[]`, where each item is `{ label, value, description? }`. The composer does not filter or generate suggestions: listen for `harness-input`, update the controlled `value`, and provide a fresh filtered array. While the textarea owns focus, the listbox stays anchored above the composer; moving focus to another control closes it. Arrow keys wrap through rows, Enter chooses the active row, and Escape dismisses the current list until the next text input or fresh suggestions array. Choosing a row sets `value` to the suggestion's `value` and emits the existing bubbling/composed `harness-input` event; it does not emit `harness-send`.
2631
2686
 
2632
2687
  While `busy`, Stop renders as an additional button and Send stays available so hosts can queue messages. Set `queueingEnabled` to label busy sends **Queue next**. Set `inputSteeringEnabled` to add a separate **Steer now** button that emits `harness-steer-input` with the same `IHarnessComposerSendDetail` as `harness-send`; it requires a nonempty draft. The host binds that input to its active turn and owns acknowledgment and clearing the draft. Both capabilities default false and are forwarded by `dees-harness-chat`.
@@ -29,10 +29,13 @@ writeFileSync(join(consumer, 'package.json'), JSON.stringify({
29
29
  },
30
30
  }, null, 2));
31
31
  writeFileSync(join(consumer, 'pnpm-workspace.yaml'), 'packages:\n - "."\n');
32
- // Run the same construction regression against installed JavaScript, not sources.
33
- const browserTest = readFileSync(join(root, 'test/test.table-construction.browser.ts'), 'utf8')
34
- .replaceAll('../ts_web/', '@design.estate/dees-catalog/dist_ts_web/');
35
- writeFileSync(join(consumer, 'test.table-construction.browser.ts'), browserTest);
32
+ // Run the same regressions against installed JavaScript, not sources.
33
+ const browserTests = ['table-construction', 'datepicker-validation', 'textarea', 'composer-attachments'];
34
+ for (const name of browserTests) {
35
+ const browserTest = readFileSync(join(root, `test/test.${name}.browser.ts`), 'utf8')
36
+ .replaceAll('../ts_web/', '@design.estate/dees-catalog/dist_ts_web/');
37
+ writeFileSync(join(consumer, `test.${name}.browser.ts`), browserTest);
38
+ }
36
39
  console.log(`Packed consumer: ${consumer}`);
37
40
  run(['install', '--ignore-scripts']);
38
41
  run(['exec', 'tsc', '--version']);
@@ -41,5 +44,5 @@ run(['exec', 'tsc', '--project', 'tsconfig.json']);
41
44
  run(['add', '--save-dev', '--save-exact', '--ignore-scripts', 'typescript@6.0.3']);
42
45
  run(['exec', 'tsc', '--version']);
43
46
  run(['exec', 'tsc', '--project', 'tsconfig.json']);
44
- run(['exec', 'tstest', 'test.table-construction.browser.ts', '--verbose', '--logfile']);
47
+ run(['exec', 'tstest', 'test.*.browser.ts', '--verbose', '--logfile']);
45
48
  run(['exec', 'node', 'browser.mjs']);
@@ -3,6 +3,6 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@design.estate/dees-catalog',
6
- version: '9.6.2',
6
+ version: '9.7.0',
7
7
  description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.'
8
8
  }
@@ -4,20 +4,21 @@ import { demoPage } from './templates.js';
4
4
  import type { TFormData } from '../elements/00group-form/dees-form/dees-form.js';
5
5
 
6
6
  /** One fixture vocabulary for the showcase and each input's focused demo. */
7
- export type TInputExample = 'text' | 'dropdown' | 'datepicker' | 'checkbox' | 'toggle' | 'radiogroup' | 'multitoggle' | 'quantityselector' | 'phone' | 'iban' | 'tags' | 'typelist' | 'list' | 'fileupload' | 'profilepicture' | 'richtext' | 'wysiwyg' | 'code';
7
+ export type TInputExample = 'text' | 'textarea' | 'dropdown' | 'datepicker' | 'checkbox' | 'toggle' | 'radiogroup' | 'multitoggle' | 'quantityselector' | 'phone' | 'iban' | 'tags' | 'typelist' | 'list' | 'fileupload' | 'profilepicture' | 'richtext' | 'wysiwyg' | 'code';
8
8
 
9
9
  const titles: Record<TInputExample, string> = {
10
- text: 'Text fields', dropdown: 'Dropdowns', datepicker: 'Dates & times', checkbox: 'Checkboxes', toggle: 'Switches',
10
+ text: 'Text fields', textarea: 'Multiline text', dropdown: 'Dropdowns', datepicker: 'Dates & times', checkbox: 'Checkboxes', toggle: 'Switches',
11
11
  radiogroup: 'Radio choices', multitoggle: 'Segmented controls', quantityselector: 'Quantities', phone: 'Phone numbers',
12
12
  iban: 'IBAN', tags: 'Tags', typelist: 'Type lists', list: 'Editable lists', fileupload: 'File uploads',
13
13
  profilepicture: 'Profile pictures', richtext: 'Rich text', wysiwyg: 'Block editor', code: 'Code editor',
14
14
  };
15
- const compound: TInputExample[] = ['tags', 'typelist', 'list', 'fileupload', 'profilepicture', 'richtext', 'wysiwyg', 'code'];
15
+ const compound: TInputExample[] = ['textarea', 'tags', 'typelist', 'list', 'fileupload', 'profilepicture', 'richtext', 'wysiwyg', 'code'];
16
16
  const visibility = [{ key: 'team', option: 'Team members' }, { key: 'private', option: 'Only me' }, { key: 'public', option: 'Anyone with the link' }];
17
17
 
18
18
  export const inputExample = (kind: TInputExample, disabled = false): TemplateResult => {
19
19
  switch (kind) {
20
20
  case 'text': return html`<dees-input-text key="name" label="Workspace name" value="Design studio" required ?disabled=${disabled} description="The name your teammates see."></dees-input-text>`;
21
+ case 'textarea': return html`<dees-input-textarea key="paymentNotes" label="Payment notes" .value=${'Invoice 2026-042\nReference: studio equipment'} .rows=${3} .maxLength=${1000} ?disabled=${disabled} description="Plain text. Line breaks are preserved."></dees-input-textarea>`;
21
22
  case 'dropdown': return html`<dees-input-dropdown key="visibility" label="Visible to" .options=${visibility} .selectedOption=${visibility[0]} ?disabled=${disabled}></dees-input-dropdown>`;
22
23
  case 'datepicker': return html`<dees-input-datepicker key="review" label="Next review" value="2026-09-14T09:00:00" .enableTime=${true} timeFormat="24h" .minuteIncrement=${15} ?disabled=${disabled}></dees-input-datepicker>`;
23
24
  case 'checkbox': return html`<dees-input-checkbox key="digest" label="Include a weekly summary" .value=${true} ?disabled=${disabled}></dees-input-checkbox>`;
@@ -96,7 +97,7 @@ export class DeesDemoInputWorkspace extends DeesElement {
96
97
  <dees-form @formData=${this.submit} style="gap:0">
97
98
  ${this.section('General', 'Make this space your own.', ['text', 'dropdown', 'datepicker'])}
98
99
  ${this.section('Your team', 'A setup that fits the way you work.', ['radiogroup', 'quantityselector', 'multitoggle', 'toggle', 'checkbox'])}
99
- ${this.section('Profile & billing', 'Your picture and contact details.', ['profilepicture', 'phone', 'iban'])}
100
+ ${this.section('Profile & billing', 'Your picture and contact details.', ['profilepicture', 'phone', 'iban', 'textarea'])}
100
101
  ${this.section('Organization', 'Small details that keep work moving.', ['tags', 'typelist', 'list'])}
101
102
  ${this.section('Documents', 'The context behind the work.', ['fileupload', 'richtext', 'wysiwyg'])}
102
103
  ${this.section('Automation', 'Fine-tune the workspace configuration.', ['code'])}
@@ -13,6 +13,7 @@ import { DeesInputCheckbox } from '../../00group-input/dees-input-checkbox/dees-
13
13
  import { DeesInputCode } from '../../00group-input/dees-input-code/dees-input-code.js';
14
14
  import { DeesInputDatepicker } from '../../00group-input/dees-input-datepicker/index.js';
15
15
  import { DeesInputText } from '../../00group-input/dees-input-text/dees-input-text.js';
16
+ import { DeesInputTextarea } from '../../00group-input/dees-input-textarea/dees-input-textarea.js';
16
17
  import { DeesInputQuantitySelector } from '../../00group-input/dees-input-quantityselector/dees-input-quantityselector.js';
17
18
  import { DeesInputRadiogroup } from '../../00group-input/dees-input-radiogroup/dees-input-radiogroup.js';
18
19
  import { DeesInputDropdown } from '../../00group-input/dees-input-dropdown/dees-input-dropdown.js';
@@ -44,6 +45,7 @@ const FORM_INPUT_TYPES = [
44
45
  DeesInputQuantitySelector,
45
46
  DeesInputRadiogroup,
46
47
  DeesInputText,
48
+ DeesInputTextarea,
47
49
  DeesInputToggle,
48
50
  DeesInputTypelist,
49
51
  DeesInputTags,
@@ -65,6 +67,9 @@ export interface IFormCompatibleElement extends HTMLElement {
65
67
  };
66
68
  getValue?: () => unknown;
67
69
  setValue?: (value: unknown) => void;
70
+ checkValidity?: () => boolean;
71
+ reportValidity?: () => boolean;
72
+ reset?: () => void;
68
73
  }
69
74
 
70
75
  export type TFormDataValue =
@@ -96,6 +101,7 @@ export type TFormInputElement =
96
101
  | DeesInputQuantitySelector
97
102
  | DeesInputRadiogroup
98
103
  | DeesInputText
104
+ | DeesInputTextarea
99
105
  | DeesInputToggle
100
106
  | DeesInputTypelist
101
107
  | DeesInputTags
@@ -281,7 +287,9 @@ export class DeesForm extends DeesElement {
281
287
  public async updateRequiredStatus() {
282
288
  let requiredOK = true;
283
289
  for (const childArg of this.getFormElements()) {
284
- if (childArg.required && !getFormElementValue(childArg)) {
290
+ if (childArg.disabled) continue;
291
+ if ((childArg.required && !getFormElementValue(childArg))
292
+ || (childArg as IFormCompatibleElement).checkValidity?.() === false) {
285
293
  requiredOK = false;
286
294
  }
287
295
  }
@@ -312,6 +320,15 @@ export class DeesForm extends DeesElement {
312
320
  }
313
321
 
314
322
  public async gatherAndDispatch() {
323
+ for (const child of this.getFormElements()) {
324
+ if (child.disabled) continue;
325
+ const input = child as IFormCompatibleElement;
326
+ if (input.checkValidity?.() === false) {
327
+ input.reportValidity?.();
328
+ child.focus();
329
+ return;
330
+ }
331
+ }
315
332
  const valueObject = await this.collectFormData();
316
333
  const formDataEvent = new CustomEvent('formData', {
317
334
  detail: {
@@ -371,12 +388,18 @@ export class DeesForm extends DeesElement {
371
388
  const inputChildren = this.getFormElements();
372
389
 
373
390
  for (const inputChild of inputChildren) {
374
- setFormElementValue(inputChild, null);
391
+ const input = inputChild as IFormCompatibleElement;
392
+ if (input.reset) input.reset();
393
+ else setFormElementValue(inputChild, null);
375
394
  }
376
395
  this.setStatus('normal', 'Submit');
396
+ void this.updateRequiredStatus();
377
397
  }
378
398
 
379
399
  public async addBehaviours() {
400
+ this.addEventListener('validation-change', event => {
401
+ if (this.getFormElements().includes(event.target as TFormInputElement)) void this.updateRequiredStatus();
402
+ });
380
403
  // Use event delegation
381
404
  this.addEventListener('keydown', (event: KeyboardEvent) => {
382
405
  const target = event.target as DeesElement;