secure-ui-components 0.1.0-beta.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.
- package/LICENSE +21 -0
- package/README.md +310 -0
- package/dist/components/secure-datetime/secure-datetime.css +263 -0
- package/dist/components/secure-datetime/secure-datetime.d.ts +124 -0
- package/dist/components/secure-datetime/secure-datetime.d.ts.map +1 -0
- package/dist/components/secure-datetime/secure-datetime.js +610 -0
- package/dist/components/secure-datetime/secure-datetime.js.map +1 -0
- package/dist/components/secure-file-upload/secure-file-upload.css +334 -0
- package/dist/components/secure-file-upload/secure-file-upload.d.ts +150 -0
- package/dist/components/secure-file-upload/secure-file-upload.d.ts.map +1 -0
- package/dist/components/secure-file-upload/secure-file-upload.js +911 -0
- package/dist/components/secure-file-upload/secure-file-upload.js.map +1 -0
- package/dist/components/secure-form/secure-form.css +62 -0
- package/dist/components/secure-form/secure-form.d.ts +128 -0
- package/dist/components/secure-form/secure-form.d.ts.map +1 -0
- package/dist/components/secure-form/secure-form.js +697 -0
- package/dist/components/secure-form/secure-form.js.map +1 -0
- package/dist/components/secure-input/secure-input.css +168 -0
- package/dist/components/secure-input/secure-input.d.ts +114 -0
- package/dist/components/secure-input/secure-input.d.ts.map +1 -0
- package/dist/components/secure-input/secure-input.js +785 -0
- package/dist/components/secure-input/secure-input.js.map +1 -0
- package/dist/components/secure-select/secure-select.css +195 -0
- package/dist/components/secure-select/secure-select.d.ts +149 -0
- package/dist/components/secure-select/secure-select.d.ts.map +1 -0
- package/dist/components/secure-select/secure-select.js +634 -0
- package/dist/components/secure-select/secure-select.js.map +1 -0
- package/dist/components/secure-submit-button/secure-submit-button.css +135 -0
- package/dist/components/secure-submit-button/secure-submit-button.d.ts +61 -0
- package/dist/components/secure-submit-button/secure-submit-button.d.ts.map +1 -0
- package/dist/components/secure-submit-button/secure-submit-button.js +399 -0
- package/dist/components/secure-submit-button/secure-submit-button.js.map +1 -0
- package/dist/components/secure-table/secure-table.css +341 -0
- package/dist/components/secure-table/secure-table.d.ts +64 -0
- package/dist/components/secure-table/secure-table.d.ts.map +1 -0
- package/dist/components/secure-table/secure-table.js +567 -0
- package/dist/components/secure-table/secure-table.js.map +1 -0
- package/dist/components/secure-textarea/secure-textarea.css +153 -0
- package/dist/components/secure-textarea/secure-textarea.d.ts +111 -0
- package/dist/components/secure-textarea/secure-textarea.d.ts.map +1 -0
- package/dist/components/secure-textarea/secure-textarea.js +477 -0
- package/dist/components/secure-textarea/secure-textarea.js.map +1 -0
- package/dist/core/base-component.d.ts +134 -0
- package/dist/core/base-component.d.ts.map +1 -0
- package/dist/core/base-component.js +303 -0
- package/dist/core/base-component.js.map +1 -0
- package/dist/core/base.css +37 -0
- package/dist/core/security-config.d.ts +89 -0
- package/dist/core/security-config.d.ts.map +1 -0
- package/dist/core/security-config.js +273 -0
- package/dist/core/security-config.js.map +1 -0
- package/dist/core/types.d.ts +212 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +7 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/package.json +89 -0
- package/dist/styles/tokens.css +257 -0
- package/package.json +118 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secure-datetime.d.ts","sourceRoot":"","sources":["../../../src/components/secure-datetime/secure-datetime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGnE;;;;;;;;GAQG;AACH,qBAAa,cAAe,SAAQ,mBAAmB;;IA+BrD;;;;OAIG;IACH,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAaxC;IAED;;OAEG;;IAKH;;;;;;;OAOG;IACH,SAAS,CAAC,MAAM,IAAI,gBAAgB,GAAG,WAAW,GAAG,IAAI;IAkZzD;;;;OAIG;IACH,SAAS,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAwBtG;;;;OAIG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IAED;;;;OAIG;IACH,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAItB;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,cAAc,IAAI,IAAI,GAAG,IAAI;IAa7B;;;;OAIG;IACH,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAoClC;;;;OAIG;IACH,IAAI,KAAK,IAAI,OAAO,CA0BnB;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAMb;;;;OAIG;IACH,IAAI,IAAI,IAAI;IAMZ;;OAEG;IACH,oBAAoB,IAAI,IAAI;CAQ7B;AAKD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Secure Date/Time Picker Component
|
|
3
|
+
*
|
|
4
|
+
* A security-first date/time picker component that implements progressive enhancement,
|
|
5
|
+
* validation, and audit logging.
|
|
6
|
+
*
|
|
7
|
+
* Progressive Enhancement Strategy:
|
|
8
|
+
* 1. Without JavaScript: Falls back to native HTML5 date/time inputs
|
|
9
|
+
* 2. With JavaScript: Enhances with validation, range limits, audit logging
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <secure-datetime
|
|
13
|
+
* security-tier="authenticated"
|
|
14
|
+
* name="appointment"
|
|
15
|
+
* label="Appointment Date"
|
|
16
|
+
* type="datetime-local"
|
|
17
|
+
* min="2024-01-01T00:00"
|
|
18
|
+
* max="2024-12-31T23:59"
|
|
19
|
+
* required
|
|
20
|
+
* ></secure-datetime>
|
|
21
|
+
*
|
|
22
|
+
* Security Features:
|
|
23
|
+
* - Input sanitization and validation
|
|
24
|
+
* - Date range enforcement
|
|
25
|
+
* - Rate limiting for sensitive/critical tiers
|
|
26
|
+
* - Comprehensive audit logging
|
|
27
|
+
* - Timezone awareness
|
|
28
|
+
* - Format validation
|
|
29
|
+
*
|
|
30
|
+
* @module secure-datetime
|
|
31
|
+
* @license MIT
|
|
32
|
+
*/
|
|
33
|
+
import { SecureBaseComponent } from '../../core/base-component.js';
|
|
34
|
+
import { SecurityTier } from '../../core/security-config.js';
|
|
35
|
+
/**
|
|
36
|
+
* Secure DateTime Web Component
|
|
37
|
+
*
|
|
38
|
+
* Provides a security-hardened date/time picker with progressive enhancement.
|
|
39
|
+
* The component works as a standard HTML5 date/time input without JavaScript and
|
|
40
|
+
* enhances with security features when JavaScript is available.
|
|
41
|
+
*
|
|
42
|
+
* @extends SecureBaseComponent
|
|
43
|
+
*/
|
|
44
|
+
export class SecureDateTime extends SecureBaseComponent {
|
|
45
|
+
/**
|
|
46
|
+
* Input element reference
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
#inputElement = null;
|
|
50
|
+
/**
|
|
51
|
+
* Label element reference
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
#labelElement = null;
|
|
55
|
+
/**
|
|
56
|
+
* Error container element reference
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
#errorContainer = null;
|
|
60
|
+
/**
|
|
61
|
+
* Timezone display element
|
|
62
|
+
* @private
|
|
63
|
+
*/
|
|
64
|
+
#timezoneElement = null;
|
|
65
|
+
/**
|
|
66
|
+
* Unique ID for this datetime instance
|
|
67
|
+
* @private
|
|
68
|
+
*/
|
|
69
|
+
#instanceId = `secure-datetime-${Math.random().toString(36).substr(2, 9)}`;
|
|
70
|
+
/**
|
|
71
|
+
* Observed attributes for this component
|
|
72
|
+
*
|
|
73
|
+
* @static
|
|
74
|
+
*/
|
|
75
|
+
static get observedAttributes() {
|
|
76
|
+
return [
|
|
77
|
+
...super.observedAttributes,
|
|
78
|
+
'name',
|
|
79
|
+
'type',
|
|
80
|
+
'label',
|
|
81
|
+
'required',
|
|
82
|
+
'min',
|
|
83
|
+
'max',
|
|
84
|
+
'step',
|
|
85
|
+
'value',
|
|
86
|
+
'show-timezone'
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Constructor
|
|
91
|
+
*/
|
|
92
|
+
constructor() {
|
|
93
|
+
super();
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Render the datetime component
|
|
97
|
+
*
|
|
98
|
+
* Security Note: We use native HTML5 date/time inputs wrapped in our web component
|
|
99
|
+
* to ensure progressive enhancement and browser-native date validation.
|
|
100
|
+
*
|
|
101
|
+
* @protected
|
|
102
|
+
*/
|
|
103
|
+
render() {
|
|
104
|
+
const fragment = document.createDocumentFragment();
|
|
105
|
+
const config = this.config;
|
|
106
|
+
// Create container
|
|
107
|
+
const container = document.createElement('div');
|
|
108
|
+
container.className = 'datetime-container';
|
|
109
|
+
// Create label
|
|
110
|
+
const label = this.getAttribute('label');
|
|
111
|
+
if (label) {
|
|
112
|
+
this.#labelElement = document.createElement('label');
|
|
113
|
+
this.#labelElement.htmlFor = this.#instanceId;
|
|
114
|
+
this.#labelElement.textContent = this.sanitizeValue(label);
|
|
115
|
+
// Add security tier suffix if configured
|
|
116
|
+
if (config.ui.labelSuffix) {
|
|
117
|
+
const suffix = document.createElement('span');
|
|
118
|
+
suffix.className = 'label-suffix';
|
|
119
|
+
suffix.textContent = config.ui.labelSuffix;
|
|
120
|
+
this.#labelElement.appendChild(suffix);
|
|
121
|
+
}
|
|
122
|
+
// Add security badge if configured
|
|
123
|
+
if (config.ui.showSecurityBadge) {
|
|
124
|
+
const badge = document.createElement('span');
|
|
125
|
+
badge.className = 'security-badge';
|
|
126
|
+
badge.textContent = config.name;
|
|
127
|
+
this.#labelElement.appendChild(badge);
|
|
128
|
+
}
|
|
129
|
+
container.appendChild(this.#labelElement);
|
|
130
|
+
}
|
|
131
|
+
// Create input wrapper
|
|
132
|
+
const inputWrapper = document.createElement('div');
|
|
133
|
+
inputWrapper.className = 'input-wrapper';
|
|
134
|
+
// Create the datetime input element
|
|
135
|
+
this.#inputElement = document.createElement('input');
|
|
136
|
+
this.#inputElement.id = this.#instanceId;
|
|
137
|
+
this.#inputElement.className = 'datetime-field';
|
|
138
|
+
// Apply attributes
|
|
139
|
+
this.#applyDateTimeAttributes();
|
|
140
|
+
// Set up event listeners
|
|
141
|
+
this.#attachEventListeners();
|
|
142
|
+
inputWrapper.appendChild(this.#inputElement);
|
|
143
|
+
// Add timezone display if requested
|
|
144
|
+
if (this.hasAttribute('show-timezone')) {
|
|
145
|
+
this.#timezoneElement = document.createElement('span');
|
|
146
|
+
this.#timezoneElement.className = 'timezone-display';
|
|
147
|
+
this.#timezoneElement.textContent = this.#getTimezoneString();
|
|
148
|
+
inputWrapper.appendChild(this.#timezoneElement);
|
|
149
|
+
}
|
|
150
|
+
container.appendChild(inputWrapper);
|
|
151
|
+
// Create error container
|
|
152
|
+
// role="alert" already implies aria-live="assertive" — do not override with polite
|
|
153
|
+
this.#errorContainer = document.createElement('div');
|
|
154
|
+
this.#errorContainer.className = 'error-container hidden';
|
|
155
|
+
this.#errorContainer.setAttribute('role', 'alert');
|
|
156
|
+
this.#errorContainer.id = `${this.#instanceId}-error`;
|
|
157
|
+
container.appendChild(this.#errorContainer);
|
|
158
|
+
// Add component styles (CSP-compliant via adoptedStyleSheets)
|
|
159
|
+
this.addComponentStyles(this.#getComponentStyles());
|
|
160
|
+
fragment.appendChild(container);
|
|
161
|
+
return fragment;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Apply attributes to the datetime input
|
|
165
|
+
*
|
|
166
|
+
* @private
|
|
167
|
+
*/
|
|
168
|
+
#applyDateTimeAttributes() {
|
|
169
|
+
const config = this.config;
|
|
170
|
+
// Name attribute
|
|
171
|
+
const name = this.getAttribute('name');
|
|
172
|
+
if (name) {
|
|
173
|
+
this.#inputElement.name = this.sanitizeValue(name);
|
|
174
|
+
}
|
|
175
|
+
// Accessible name fallback when no visible label is provided
|
|
176
|
+
if (!this.getAttribute('label') && name) {
|
|
177
|
+
this.#inputElement.setAttribute('aria-label', this.sanitizeValue(name));
|
|
178
|
+
}
|
|
179
|
+
// Link input to its error container for screen readers
|
|
180
|
+
this.#inputElement.setAttribute('aria-describedby', `${this.#instanceId}-error`);
|
|
181
|
+
// Timezone element label
|
|
182
|
+
if (this.#timezoneElement) {
|
|
183
|
+
this.#timezoneElement.setAttribute('aria-label', `Timezone: ${this.#getTimezoneString()}`);
|
|
184
|
+
}
|
|
185
|
+
// Type attribute (date, time, datetime-local, month, week)
|
|
186
|
+
const type = this.getAttribute('type') || 'date';
|
|
187
|
+
const validTypes = ['date', 'time', 'datetime-local', 'month', 'week'];
|
|
188
|
+
if (validTypes.includes(type)) {
|
|
189
|
+
this.#inputElement.type = type;
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
console.warn(`Invalid datetime type "${type}", defaulting to "date"`);
|
|
193
|
+
this.#inputElement.type = 'date';
|
|
194
|
+
}
|
|
195
|
+
// Required attribute
|
|
196
|
+
if (this.hasAttribute('required') || config.validation.required) {
|
|
197
|
+
this.#inputElement.required = true;
|
|
198
|
+
this.#inputElement.setAttribute('aria-required', 'true');
|
|
199
|
+
}
|
|
200
|
+
// Min/max constraints
|
|
201
|
+
const min = this.getAttribute('min');
|
|
202
|
+
if (min) {
|
|
203
|
+
this.#inputElement.min = this.#validateDateTimeValue(min);
|
|
204
|
+
}
|
|
205
|
+
const max = this.getAttribute('max');
|
|
206
|
+
if (max) {
|
|
207
|
+
this.#inputElement.max = this.#validateDateTimeValue(max);
|
|
208
|
+
}
|
|
209
|
+
// Step attribute
|
|
210
|
+
const step = this.getAttribute('step');
|
|
211
|
+
if (step) {
|
|
212
|
+
this.#inputElement.step = step;
|
|
213
|
+
}
|
|
214
|
+
// Disabled state
|
|
215
|
+
if (this.hasAttribute('disabled')) {
|
|
216
|
+
this.#inputElement.disabled = true;
|
|
217
|
+
}
|
|
218
|
+
// Readonly state
|
|
219
|
+
if (this.hasAttribute('readonly')) {
|
|
220
|
+
this.#inputElement.readOnly = true;
|
|
221
|
+
}
|
|
222
|
+
// Autocomplete control
|
|
223
|
+
if (!config.storage.allowAutocomplete) {
|
|
224
|
+
this.#inputElement.autocomplete = 'off';
|
|
225
|
+
}
|
|
226
|
+
// Initial value
|
|
227
|
+
const value = this.getAttribute('value');
|
|
228
|
+
if (value) {
|
|
229
|
+
this.#inputElement.value = this.#validateDateTimeValue(value);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Validate and sanitize datetime value
|
|
234
|
+
*
|
|
235
|
+
* Security Note: Prevent injection of invalid date formats
|
|
236
|
+
*
|
|
237
|
+
* @private
|
|
238
|
+
*/
|
|
239
|
+
#validateDateTimeValue(value) {
|
|
240
|
+
if (!value)
|
|
241
|
+
return '';
|
|
242
|
+
// Basic format validation based on input type
|
|
243
|
+
const type = this.#inputElement?.type || this.getAttribute('type') || 'date';
|
|
244
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
245
|
+
const patterns = {
|
|
246
|
+
'date': /^\d{4}-\d{2}-\d{2}$/,
|
|
247
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
248
|
+
'time': /^\d{2}:\d{2}(:\d{2})?$/,
|
|
249
|
+
// eslint-disable-next-line security/detect-unsafe-regex
|
|
250
|
+
'datetime-local': /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2})?$/,
|
|
251
|
+
'month': /^\d{4}-\d{2}$/,
|
|
252
|
+
'week': /^\d{4}-W\d{2}$/
|
|
253
|
+
};
|
|
254
|
+
const pattern = patterns[type];
|
|
255
|
+
if (pattern && !pattern.test(value)) {
|
|
256
|
+
console.warn(`Invalid ${type} format: ${value}`);
|
|
257
|
+
return '';
|
|
258
|
+
}
|
|
259
|
+
return value;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Get timezone string for display
|
|
263
|
+
*
|
|
264
|
+
* @private
|
|
265
|
+
*/
|
|
266
|
+
#getTimezoneString() {
|
|
267
|
+
const offset = new Date().getTimezoneOffset();
|
|
268
|
+
const hours = Math.abs(Math.floor(offset / 60));
|
|
269
|
+
const minutes = Math.abs(offset % 60);
|
|
270
|
+
const sign = offset <= 0 ? '+' : '-';
|
|
271
|
+
return `UTC${sign}${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Attach event listeners
|
|
275
|
+
*
|
|
276
|
+
* @private
|
|
277
|
+
*/
|
|
278
|
+
#attachEventListeners() {
|
|
279
|
+
// Focus event - audit logging
|
|
280
|
+
this.#inputElement.addEventListener('focus', () => {
|
|
281
|
+
this.audit('datetime_focused', {
|
|
282
|
+
name: this.#inputElement.name,
|
|
283
|
+
type: this.#inputElement.type
|
|
284
|
+
});
|
|
285
|
+
});
|
|
286
|
+
// Input event - real-time validation
|
|
287
|
+
this.#inputElement.addEventListener('input', (e) => {
|
|
288
|
+
this.#handleInput(e);
|
|
289
|
+
});
|
|
290
|
+
// Change event - validation and audit
|
|
291
|
+
this.#inputElement.addEventListener('change', (e) => {
|
|
292
|
+
this.#handleChange(e);
|
|
293
|
+
});
|
|
294
|
+
// Blur event - final validation
|
|
295
|
+
this.#inputElement.addEventListener('blur', () => {
|
|
296
|
+
this.#validateAndShowErrors();
|
|
297
|
+
this.audit('datetime_blurred', {
|
|
298
|
+
name: this.#inputElement.name,
|
|
299
|
+
hasValue: this.#inputElement.value.length > 0
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Handle input events
|
|
305
|
+
*
|
|
306
|
+
* @private
|
|
307
|
+
*/
|
|
308
|
+
#handleInput(_event) {
|
|
309
|
+
// Clear previous errors on input
|
|
310
|
+
this.#clearErrors();
|
|
311
|
+
// Dispatch custom event for parent forms
|
|
312
|
+
this.dispatchEvent(new CustomEvent('secure-datetime', {
|
|
313
|
+
detail: {
|
|
314
|
+
name: this.#inputElement.name,
|
|
315
|
+
value: this.#inputElement.value,
|
|
316
|
+
type: this.#inputElement.type,
|
|
317
|
+
tier: this.securityTier
|
|
318
|
+
},
|
|
319
|
+
bubbles: true,
|
|
320
|
+
composed: true
|
|
321
|
+
}));
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Handle change events
|
|
325
|
+
*
|
|
326
|
+
* @private
|
|
327
|
+
*/
|
|
328
|
+
#handleChange(_event) {
|
|
329
|
+
const value = this.#inputElement.value;
|
|
330
|
+
// Validate the value
|
|
331
|
+
const isValid = this.#validateDateTimeValue(value);
|
|
332
|
+
if (!isValid && value) {
|
|
333
|
+
this.#showError('Invalid date/time format');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
// Clear errors
|
|
337
|
+
this.#clearErrors();
|
|
338
|
+
// Audit log
|
|
339
|
+
this.audit('datetime_changed', {
|
|
340
|
+
name: this.#inputElement.name,
|
|
341
|
+
type: this.#inputElement.type,
|
|
342
|
+
value: value
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* Validate the datetime and show error messages
|
|
347
|
+
*
|
|
348
|
+
* @private
|
|
349
|
+
*/
|
|
350
|
+
#validateAndShowErrors() {
|
|
351
|
+
// Check rate limit first
|
|
352
|
+
const rateLimitCheck = this.checkRateLimit();
|
|
353
|
+
if (!rateLimitCheck.allowed) {
|
|
354
|
+
this.#showError(`Too many attempts. Please wait ${Math.ceil(rateLimitCheck.retryAfter / 1000)} seconds.`);
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const value = this.#inputElement.value;
|
|
358
|
+
// Check required
|
|
359
|
+
if (this.#inputElement.required && !value) {
|
|
360
|
+
this.#showError('This field is required');
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
// Check min/max constraints
|
|
364
|
+
if (value) {
|
|
365
|
+
if (this.#inputElement.min && value < this.#inputElement.min) {
|
|
366
|
+
this.#showError(`Value must be after ${this.#formatDateForDisplay(this.#inputElement.min)}`);
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (this.#inputElement.max && value > this.#inputElement.max) {
|
|
370
|
+
this.#showError(`Value must be before ${this.#formatDateForDisplay(this.#inputElement.max)}`);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// Additional validation for CRITICAL tier
|
|
375
|
+
if (this.securityTier === SecurityTier.CRITICAL && value) {
|
|
376
|
+
const date = new Date(value);
|
|
377
|
+
// Ensure date is valid
|
|
378
|
+
if (isNaN(date.getTime())) {
|
|
379
|
+
this.#showError('Invalid date/time');
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
// Prevent dates too far in the past or future (potential attack)
|
|
383
|
+
const year = date.getFullYear();
|
|
384
|
+
if (year < 1900 || year > 2100) {
|
|
385
|
+
this.#showError('Date must be between 1900 and 2100');
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Format date for display in error messages
|
|
392
|
+
*
|
|
393
|
+
* @private
|
|
394
|
+
*/
|
|
395
|
+
#formatDateForDisplay(dateString) {
|
|
396
|
+
try {
|
|
397
|
+
const date = new Date(dateString);
|
|
398
|
+
return date.toLocaleString();
|
|
399
|
+
}
|
|
400
|
+
catch (_e) {
|
|
401
|
+
return dateString;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Show error message
|
|
406
|
+
*
|
|
407
|
+
* @private
|
|
408
|
+
*/
|
|
409
|
+
#showError(message) {
|
|
410
|
+
this.#errorContainer.textContent = message;
|
|
411
|
+
// Force reflow so browser registers the hidden state with content,
|
|
412
|
+
// then remove hidden to trigger the CSS transition
|
|
413
|
+
void this.#errorContainer.offsetHeight;
|
|
414
|
+
this.#errorContainer.classList.remove('hidden');
|
|
415
|
+
this.#inputElement.classList.add('error');
|
|
416
|
+
this.#inputElement.setAttribute('aria-invalid', 'true');
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Clear error messages
|
|
420
|
+
*
|
|
421
|
+
* @private
|
|
422
|
+
*/
|
|
423
|
+
#clearErrors() {
|
|
424
|
+
// Start the hide animation first, clear text only after transition ends
|
|
425
|
+
this.#errorContainer.classList.add('hidden');
|
|
426
|
+
this.#errorContainer.addEventListener('transitionend', () => {
|
|
427
|
+
if (this.#errorContainer.classList.contains('hidden')) {
|
|
428
|
+
this.#errorContainer.textContent = '';
|
|
429
|
+
}
|
|
430
|
+
}, { once: true });
|
|
431
|
+
this.#inputElement.classList.remove('error');
|
|
432
|
+
this.#inputElement.removeAttribute('aria-invalid');
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* Get component-specific styles
|
|
436
|
+
*
|
|
437
|
+
* @private
|
|
438
|
+
*/
|
|
439
|
+
#getComponentStyles() {
|
|
440
|
+
return new URL('./secure-datetime.css', import.meta.url).href;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Handle attribute changes
|
|
444
|
+
*
|
|
445
|
+
* @protected
|
|
446
|
+
*/
|
|
447
|
+
handleAttributeChange(name, _oldValue, newValue) {
|
|
448
|
+
if (!this.#inputElement)
|
|
449
|
+
return;
|
|
450
|
+
switch (name) {
|
|
451
|
+
case 'disabled':
|
|
452
|
+
this.#inputElement.disabled = this.hasAttribute('disabled');
|
|
453
|
+
break;
|
|
454
|
+
case 'readonly':
|
|
455
|
+
this.#inputElement.readOnly = this.hasAttribute('readonly');
|
|
456
|
+
break;
|
|
457
|
+
case 'value':
|
|
458
|
+
if (newValue !== this.#inputElement.value) {
|
|
459
|
+
this.#inputElement.value = this.#validateDateTimeValue(newValue || '');
|
|
460
|
+
}
|
|
461
|
+
break;
|
|
462
|
+
case 'min':
|
|
463
|
+
this.#inputElement.min = this.#validateDateTimeValue(newValue || '');
|
|
464
|
+
break;
|
|
465
|
+
case 'max':
|
|
466
|
+
this.#inputElement.max = this.#validateDateTimeValue(newValue || '');
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Get the current value
|
|
472
|
+
*
|
|
473
|
+
* @public
|
|
474
|
+
*/
|
|
475
|
+
get value() {
|
|
476
|
+
return this.#inputElement ? this.#inputElement.value : '';
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Set the value
|
|
480
|
+
*
|
|
481
|
+
* @public
|
|
482
|
+
*/
|
|
483
|
+
set value(value) {
|
|
484
|
+
if (this.#inputElement) {
|
|
485
|
+
this.#inputElement.value = this.#validateDateTimeValue(value || '');
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Get the input name
|
|
490
|
+
*
|
|
491
|
+
* @public
|
|
492
|
+
*/
|
|
493
|
+
get name() {
|
|
494
|
+
return this.#inputElement ? this.#inputElement.name : '';
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Get value as Date object
|
|
498
|
+
*
|
|
499
|
+
* @public
|
|
500
|
+
*/
|
|
501
|
+
getValueAsDate() {
|
|
502
|
+
if (!this.#inputElement || !this.#inputElement.value) {
|
|
503
|
+
return null;
|
|
504
|
+
}
|
|
505
|
+
try {
|
|
506
|
+
const date = new Date(this.#inputElement.value);
|
|
507
|
+
return isNaN(date.getTime()) ? null : date;
|
|
508
|
+
}
|
|
509
|
+
catch (_e) {
|
|
510
|
+
return null;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Set value from Date object
|
|
515
|
+
*
|
|
516
|
+
* @public
|
|
517
|
+
*/
|
|
518
|
+
setValueFromDate(date) {
|
|
519
|
+
if (!this.#inputElement || !(date instanceof Date)) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const type = this.#inputElement.type;
|
|
523
|
+
let value = '';
|
|
524
|
+
switch (type) {
|
|
525
|
+
case 'date':
|
|
526
|
+
value = date.toISOString().split('T')[0];
|
|
527
|
+
break;
|
|
528
|
+
case 'time':
|
|
529
|
+
value = date.toTimeString().slice(0, 5);
|
|
530
|
+
break;
|
|
531
|
+
case 'datetime-local':
|
|
532
|
+
value = date.toISOString().slice(0, 16);
|
|
533
|
+
break;
|
|
534
|
+
case 'month':
|
|
535
|
+
value = date.toISOString().slice(0, 7);
|
|
536
|
+
break;
|
|
537
|
+
case 'week':
|
|
538
|
+
// ISO week calculation
|
|
539
|
+
const weekDate = new Date(date);
|
|
540
|
+
weekDate.setHours(0, 0, 0, 0);
|
|
541
|
+
weekDate.setDate(weekDate.getDate() + 4 - (weekDate.getDay() || 7));
|
|
542
|
+
const yearStart = new Date(weekDate.getFullYear(), 0, 1);
|
|
543
|
+
const weekNo = Math.ceil((((weekDate.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);
|
|
544
|
+
value = `${weekDate.getFullYear()}-W${weekNo.toString().padStart(2, '0')}`;
|
|
545
|
+
break;
|
|
546
|
+
}
|
|
547
|
+
this.#inputElement.value = value;
|
|
548
|
+
}
|
|
549
|
+
/**
|
|
550
|
+
* Check if the datetime is valid
|
|
551
|
+
*
|
|
552
|
+
* @public
|
|
553
|
+
*/
|
|
554
|
+
get valid() {
|
|
555
|
+
const required = this.hasAttribute('required') || this.config.validation.required;
|
|
556
|
+
const value = this.#inputElement ? this.#inputElement.value : '';
|
|
557
|
+
// Check required
|
|
558
|
+
if (required && !value) {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
// Check format
|
|
562
|
+
if (value && !this.#validateDateTimeValue(value)) {
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
// Check min/max
|
|
566
|
+
if (this.#inputElement) {
|
|
567
|
+
if (this.#inputElement.min && value < this.#inputElement.min) {
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
if (this.#inputElement.max && value > this.#inputElement.max) {
|
|
571
|
+
return false;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
return true;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Focus the input
|
|
578
|
+
*
|
|
579
|
+
* @public
|
|
580
|
+
*/
|
|
581
|
+
focus() {
|
|
582
|
+
if (this.#inputElement) {
|
|
583
|
+
this.#inputElement.focus();
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
/**
|
|
587
|
+
* Blur the input
|
|
588
|
+
*
|
|
589
|
+
* @public
|
|
590
|
+
*/
|
|
591
|
+
blur() {
|
|
592
|
+
if (this.#inputElement) {
|
|
593
|
+
this.#inputElement.blur();
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Cleanup on disconnect
|
|
598
|
+
*/
|
|
599
|
+
disconnectedCallback() {
|
|
600
|
+
super.disconnectedCallback();
|
|
601
|
+
// Clear value
|
|
602
|
+
if (this.#inputElement) {
|
|
603
|
+
this.#inputElement.value = '';
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
// Define the custom element
|
|
608
|
+
customElements.define('secure-datetime', SecureDateTime);
|
|
609
|
+
export default SecureDateTime;
|
|
610
|
+
//# sourceMappingURL=secure-datetime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secure-datetime.js","sourceRoot":"","sources":["../../../src/components/secure-datetime/secure-datetime.ts"],"names":[],"mappings":"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"}
|