ts-util-core 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +411 -0
- package/dist/core/ajax.d.ts +30 -0
- package/dist/core/ajax.d.ts.map +1 -0
- package/dist/core/ajax.js +110 -0
- package/dist/core/ajax.js.map +1 -0
- package/dist/core/event-emitter.d.ts +29 -0
- package/dist/core/event-emitter.d.ts.map +1 -0
- package/dist/core/event-emitter.js +67 -0
- package/dist/core/event-emitter.js.map +1 -0
- package/dist/core/message.d.ts +28 -0
- package/dist/core/message.d.ts.map +1 -0
- package/dist/core/message.js +172 -0
- package/dist/core/message.js.map +1 -0
- package/dist/core/view.d.ts +49 -0
- package/dist/core/view.d.ts.map +1 -0
- package/dist/core/view.js +87 -0
- package/dist/core/view.js.map +1 -0
- package/dist/formatting/formatters.d.ts +9 -0
- package/dist/formatting/formatters.d.ts.map +1 -0
- package/dist/formatting/formatters.js +109 -0
- package/dist/formatting/formatters.js.map +1 -0
- package/dist/formatting/registry.d.ts +31 -0
- package/dist/formatting/registry.d.ts.map +1 -0
- package/dist/formatting/registry.js +49 -0
- package/dist/formatting/registry.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +104 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/dom.d.ts +38 -0
- package/dist/utils/dom.d.ts.map +1 -0
- package/dist/utils/dom.js +95 -0
- package/dist/utils/dom.js.map +1 -0
- package/dist/utils/sprintf.d.ts +16 -0
- package/dist/utils/sprintf.d.ts.map +1 -0
- package/dist/utils/sprintf.js +116 -0
- package/dist/utils/sprintf.js.map +1 -0
- package/dist/validation/constraints.d.ts +23 -0
- package/dist/validation/constraints.d.ts.map +1 -0
- package/dist/validation/constraints.js +131 -0
- package/dist/validation/constraints.js.map +1 -0
- package/dist/validation/validator.d.ts +45 -0
- package/dist/validation/validator.d.ts.map +1 -0
- package/dist/validation/validator.js +210 -0
- package/dist/validation/validator.js.map +1 -0
- package/package.json +26 -0
- package/readme.txt +4 -0
- package/src/core/ajax.ts +127 -0
- package/src/core/event-emitter.ts +84 -0
- package/src/core/message.ts +212 -0
- package/src/core/view.ts +101 -0
- package/src/formatting/formatters.ts +118 -0
- package/src/formatting/registry.ts +53 -0
- package/src/index.ts +142 -0
- package/src/types.ts +85 -0
- package/src/utils/dom.ts +105 -0
- package/src/utils/sprintf.ts +141 -0
- package/src/validation/constraints.ts +168 -0
- package/src/validation/validator.ts +276 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// ts-util-core — barrel export
|
|
3
|
+
//
|
|
4
|
+
// This is the main entry point. It wires all modules together and exposes
|
|
5
|
+
// the unified `#` (TS-Util) namespace.
|
|
6
|
+
//
|
|
7
|
+
// Usage with ES modules (recommended):
|
|
8
|
+
//
|
|
9
|
+
// import { AJAX, VIEW, MSG, Validation, Formatter } from 'ts-util-core';
|
|
10
|
+
//
|
|
11
|
+
// // or as a single namespace:
|
|
12
|
+
// import * as RS from 'ts-util-core';
|
|
13
|
+
// RS.AJAX.request({ url: '/api/save', form: myForm });
|
|
14
|
+
//
|
|
15
|
+
// Usage as a global (for non-module scripts):
|
|
16
|
+
//
|
|
17
|
+
// The library auto-registers `window.#` (accessed via `window['#']`)
|
|
18
|
+
// when loaded in a <script> tag without `type="module"`.
|
|
19
|
+
//
|
|
20
|
+
// Design patterns used:
|
|
21
|
+
// - Facade Pattern : one import gives access to all features
|
|
22
|
+
// - Mediator Pattern : the EventEmitter is the central coordinator —
|
|
23
|
+
// modules don't reference each other directly,
|
|
24
|
+
// they communicate through events
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// Re-export classes for advanced use
|
|
27
|
+
export { EventEmitter } from './core/event-emitter.js';
|
|
28
|
+
export { Ajax } from './core/ajax.js';
|
|
29
|
+
export { View } from './core/view.js';
|
|
30
|
+
export { Message } from './core/message.js';
|
|
31
|
+
export { Validator } from './validation/validator.js';
|
|
32
|
+
export { FormatterRegistry } from './formatting/registry.js';
|
|
33
|
+
// Re-export utilities
|
|
34
|
+
export { sprintf } from './utils/sprintf.js';
|
|
35
|
+
export { formToJSON, isDateValid, parseHTML, scrollToElement, defaults } from './utils/dom.js';
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Pre-wired singleton instances — the `#` namespace
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
import { EventEmitter } from './core/event-emitter.js';
|
|
40
|
+
import { Ajax } from './core/ajax.js';
|
|
41
|
+
import { View } from './core/view.js';
|
|
42
|
+
import { Message } from './core/message.js';
|
|
43
|
+
import { Validator } from './validation/validator.js';
|
|
44
|
+
import { FormatterRegistry } from './formatting/registry.js';
|
|
45
|
+
import { builtInFormatters } from './formatting/formatters.js';
|
|
46
|
+
// 1. Create the shared event bus (Mediator)
|
|
47
|
+
const emitter = new EventEmitter();
|
|
48
|
+
// 2. Instantiate modules — they receive the emitter, not each other
|
|
49
|
+
const ajax = new Ajax(emitter);
|
|
50
|
+
const view = new View(emitter, ajax);
|
|
51
|
+
const msg = new Message();
|
|
52
|
+
const validator = new Validator(emitter);
|
|
53
|
+
const formatter = new FormatterRegistry();
|
|
54
|
+
// 3. Wire cross-module dependencies via hooks (Observer Pattern)
|
|
55
|
+
// — The Validator tells the AJAX module how to validate forms
|
|
56
|
+
ajax.setValidator((form) => validator.validate(form));
|
|
57
|
+
// — The Validator registers its beforeLoad hook with VIEW
|
|
58
|
+
view.addBeforeLoad((context) => validator.initConstraints(context));
|
|
59
|
+
// — The FormatterRegistry registers its beforeLoad hook with VIEW
|
|
60
|
+
view.addBeforeLoad((context) => formatter.applyAll(context));
|
|
61
|
+
// 4. Register built-in formatters
|
|
62
|
+
for (const f of builtInFormatters) {
|
|
63
|
+
formatter.add(f);
|
|
64
|
+
}
|
|
65
|
+
// 5. Export pre-wired instances as the public API
|
|
66
|
+
/** AJAX module — HTTP requests with lifecycle hooks. */
|
|
67
|
+
export const AJAX = ajax;
|
|
68
|
+
/** VIEW module — load and initialize HTML fragments. */
|
|
69
|
+
export const VIEW = view;
|
|
70
|
+
/** MSG module — dialogs and notifications. */
|
|
71
|
+
export const MSG = msg;
|
|
72
|
+
/** Validation module — form validation engine. */
|
|
73
|
+
export const Validation = validator;
|
|
74
|
+
/** Formatter module — input masking registry. */
|
|
75
|
+
export const Formatter = formatter;
|
|
76
|
+
/** Event bus — subscribe to library-wide lifecycle events. */
|
|
77
|
+
export const Events = emitter;
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
// Auto-initialize on DOMContentLoaded (when running in a browser)
|
|
80
|
+
// ---------------------------------------------------------------------------
|
|
81
|
+
if (typeof document !== 'undefined') {
|
|
82
|
+
const init = () => view.initPage();
|
|
83
|
+
if (document.readyState === 'loading') {
|
|
84
|
+
document.addEventListener('DOMContentLoaded', init);
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
init();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// ---------------------------------------------------------------------------
|
|
91
|
+
// Global registration for non-module environments: window['#']
|
|
92
|
+
// ---------------------------------------------------------------------------
|
|
93
|
+
if (typeof window !== 'undefined') {
|
|
94
|
+
const ns = {
|
|
95
|
+
AJAX: ajax,
|
|
96
|
+
VIEW: view,
|
|
97
|
+
MSG: msg,
|
|
98
|
+
Validation: validator,
|
|
99
|
+
Formatter: formatter,
|
|
100
|
+
Events: emitter,
|
|
101
|
+
};
|
|
102
|
+
window['#'] = ns;
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/** Supported constraint types declared via the `constraint` HTML attribute. */
|
|
2
|
+
export type ConstraintType = 'required' | 'date' | 'number' | 'time' | 'upperCase' | 'onlyEn';
|
|
3
|
+
/** A record whose values are either a single string or an array of strings. */
|
|
4
|
+
export type FormDataRecord = Record<string, string | string[]>;
|
|
5
|
+
export interface AjaxRequestParams {
|
|
6
|
+
url: string;
|
|
7
|
+
data?: Record<string, unknown>;
|
|
8
|
+
form?: HTMLElement;
|
|
9
|
+
ignoreDisabled?: boolean;
|
|
10
|
+
noblock?: boolean;
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
success?: (data: unknown) => void;
|
|
13
|
+
error?: (error: Error) => void;
|
|
14
|
+
complete?: () => void;
|
|
15
|
+
}
|
|
16
|
+
export interface AjaxJsonRequestParams<T = unknown> extends Omit<AjaxRequestParams, 'success'> {
|
|
17
|
+
success?: (data: T) => void;
|
|
18
|
+
}
|
|
19
|
+
export interface ViewLoadParams extends Omit<AjaxRequestParams, 'success'> {
|
|
20
|
+
success?: (content: HTMLElement) => void;
|
|
21
|
+
}
|
|
22
|
+
export interface MessageOptions {
|
|
23
|
+
autoclose?: number;
|
|
24
|
+
title?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface ConfirmButton {
|
|
27
|
+
label: string;
|
|
28
|
+
value: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ValidationResult {
|
|
31
|
+
valid: boolean;
|
|
32
|
+
invalidElements: HTMLElement[];
|
|
33
|
+
labelNames: string[];
|
|
34
|
+
}
|
|
35
|
+
export interface TextareaValidationResult extends ValidationResult {
|
|
36
|
+
maxlengths: number[];
|
|
37
|
+
}
|
|
38
|
+
export interface Formatter {
|
|
39
|
+
key: string;
|
|
40
|
+
format: (element: HTMLInputElement) => void;
|
|
41
|
+
}
|
|
42
|
+
export interface AppEventMap {
|
|
43
|
+
'ajax:before': {
|
|
44
|
+
url: string;
|
|
45
|
+
};
|
|
46
|
+
'ajax:after': {
|
|
47
|
+
url: string;
|
|
48
|
+
};
|
|
49
|
+
'ajax:error': {
|
|
50
|
+
url: string;
|
|
51
|
+
error: Error;
|
|
52
|
+
};
|
|
53
|
+
'view:beforeLoad': {
|
|
54
|
+
context: HTMLElement;
|
|
55
|
+
};
|
|
56
|
+
'validation:invalid': {
|
|
57
|
+
labelNames: string[];
|
|
58
|
+
elements: HTMLElement[];
|
|
59
|
+
};
|
|
60
|
+
'validation:textareaTooLong': {
|
|
61
|
+
labelNames: string[];
|
|
62
|
+
maxlengths: number[];
|
|
63
|
+
elements: HTMLElement[];
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAIA,+EAA+E;AAC/E,MAAM,MAAM,cAAc,GACtB,UAAU,GACV,MAAM,GACN,QAAQ,GACR,MAAM,GACN,WAAW,GACX,QAAQ,CAAC;AAEb,+EAA+E;AAC/E,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAI/D,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,GAAG,OAAO,CAAE,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC;IAC5F,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;CAC7B;AAID,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC;IACxE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC;CAC1C;AAID,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAID,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,WAAW,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,wBAAyB,SAAQ,gBAAgB;IAChE,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAID,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CAC7C;AAID,MAAM,WAAW,WAAW;IAC1B,aAAa,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,YAAY,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,YAAY,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,CAAA;KAAE,CAAC;IAC5C,iBAAiB,EAAE;QAAE,OAAO,EAAE,WAAW,CAAA;KAAE,CAAC;IAC5C,oBAAoB,EAAE;QAAE,UAAU,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,WAAW,EAAE,CAAA;KAAE,CAAC;IACxE,4BAA4B,EAAE;QAC5B,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,QAAQ,EAAE,WAAW,EAAE,CAAC;KACzB,CAAC;CACH"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,2CAA2C;AAC3C,8EAA8E"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { FormDataRecord } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Convert all named form elements within a container to a key-value record.
|
|
4
|
+
*
|
|
5
|
+
* Replaces the original jQuery-based `formToJSON`.
|
|
6
|
+
*
|
|
7
|
+
* @param container - The DOM element containing form inputs.
|
|
8
|
+
* @param options.ignoreDisabled - Skip disabled elements (default `false`).
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const data = formToJSON(document.getElementById('myForm')!);
|
|
13
|
+
* // { username: "alice", roles: ["admin", "editor"] }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function formToJSON(container: HTMLElement, options?: {
|
|
17
|
+
ignoreDisabled?: boolean;
|
|
18
|
+
}): FormDataRecord;
|
|
19
|
+
/**
|
|
20
|
+
* Check whether a value is a valid date.
|
|
21
|
+
*
|
|
22
|
+
* Accepts a `Date` object or a string in `yyyy-MM-dd` / `yyyy/MM/dd` format.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isDateValid(date: Date | string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Parse an HTML string into a `DocumentFragment`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseHTML(html: string): DocumentFragment;
|
|
29
|
+
/**
|
|
30
|
+
* Smoothly scroll an element into view.
|
|
31
|
+
*/
|
|
32
|
+
export declare function scrollToElement(element: HTMLElement): void;
|
|
33
|
+
/**
|
|
34
|
+
* Merge multiple option objects (shallow). Later sources override earlier ones.
|
|
35
|
+
* A typed, zero-dependency replacement for `$.extend()`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function defaults<T extends Record<string, unknown>>(base: T, ...overrides: Partial<T>[]): T;
|
|
38
|
+
//# sourceMappingURL=dom.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CACxB,SAAS,EAAE,WAAW,EACtB,OAAO,GAAE;IAAE,cAAc,CAAC,EAAE,OAAO,CAAA;CAAO,GACzC,cAAc,CAyChB;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,CAGxD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAIxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAE1D;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxD,IAAI,EAAE,CAAC,EACP,GAAG,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,GACzB,CAAC,CAEH"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// DOM utility functions — vanilla TypeScript replacements for jQuery helpers
|
|
3
|
+
//
|
|
4
|
+
// Design patterns used:
|
|
5
|
+
// - Facade Pattern : simple API over verbose native DOM methods
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
/**
|
|
8
|
+
* Convert all named form elements within a container to a key-value record.
|
|
9
|
+
*
|
|
10
|
+
* Replaces the original jQuery-based `formToJSON`.
|
|
11
|
+
*
|
|
12
|
+
* @param container - The DOM element containing form inputs.
|
|
13
|
+
* @param options.ignoreDisabled - Skip disabled elements (default `false`).
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const data = formToJSON(document.getElementById('myForm')!);
|
|
18
|
+
* // { username: "alice", roles: ["admin", "editor"] }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function formToJSON(container, options = {}) {
|
|
22
|
+
const { ignoreDisabled = false } = options;
|
|
23
|
+
const selectors = 'input[name], textarea[name], select[name]';
|
|
24
|
+
let elements = Array.from(container.querySelectorAll(selectors));
|
|
25
|
+
if (ignoreDisabled) {
|
|
26
|
+
elements = elements.filter((el) => !el.disabled);
|
|
27
|
+
}
|
|
28
|
+
const params = {};
|
|
29
|
+
for (const el of elements) {
|
|
30
|
+
const name = el.name;
|
|
31
|
+
if (!name)
|
|
32
|
+
continue;
|
|
33
|
+
if (el instanceof HTMLInputElement && el.type === 'checkbox') {
|
|
34
|
+
if (!(name in params))
|
|
35
|
+
params[name] = [];
|
|
36
|
+
if (el.checked)
|
|
37
|
+
params[name].push(el.value);
|
|
38
|
+
}
|
|
39
|
+
else if (el instanceof HTMLSelectElement && el.multiple) {
|
|
40
|
+
if (!(name in params))
|
|
41
|
+
params[name] = [];
|
|
42
|
+
const selected = Array.from(el.selectedOptions).map((o) => o.value);
|
|
43
|
+
params[name].push(...selected);
|
|
44
|
+
}
|
|
45
|
+
else if (el instanceof HTMLInputElement && el.type === 'radio') {
|
|
46
|
+
if (el.checked)
|
|
47
|
+
params[name] = el.value;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
const existing = params[name];
|
|
51
|
+
if (existing === undefined) {
|
|
52
|
+
params[name] = el.value;
|
|
53
|
+
}
|
|
54
|
+
else if (typeof existing === 'string') {
|
|
55
|
+
params[name] = [existing, el.value];
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
existing.push(el.value);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return params;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Check whether a value is a valid date.
|
|
66
|
+
*
|
|
67
|
+
* Accepts a `Date` object or a string in `yyyy-MM-dd` / `yyyy/MM/dd` format.
|
|
68
|
+
*/
|
|
69
|
+
export function isDateValid(date) {
|
|
70
|
+
if (date instanceof Date)
|
|
71
|
+
return !isNaN(date.getTime());
|
|
72
|
+
return /^\d{4}[/-]\d{1,2}[/-]\d{1,2}$/.test(date);
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Parse an HTML string into a `DocumentFragment`.
|
|
76
|
+
*/
|
|
77
|
+
export function parseHTML(html) {
|
|
78
|
+
const template = document.createElement('template');
|
|
79
|
+
template.innerHTML = html.trim();
|
|
80
|
+
return template.content;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Smoothly scroll an element into view.
|
|
84
|
+
*/
|
|
85
|
+
export function scrollToElement(element) {
|
|
86
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Merge multiple option objects (shallow). Later sources override earlier ones.
|
|
90
|
+
* A typed, zero-dependency replacement for `$.extend()`.
|
|
91
|
+
*/
|
|
92
|
+
export function defaults(base, ...overrides) {
|
|
93
|
+
return Object.assign({}, base, ...overrides);
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=dom.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom.js","sourceRoot":"","sources":["../../src/utils/dom.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* C-style `sprintf` implementation.
|
|
3
|
+
*
|
|
4
|
+
* Supported format specifiers: `%b` `%c` `%d` `%f` `%o` `%s` `%x` `%X` `%%`
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* sprintf("Hello %s, you are %d years old", "Alice", 30)
|
|
9
|
+
* // → "Hello Alice, you are 30 years old"
|
|
10
|
+
*
|
|
11
|
+
* sprintf("%05d", 42)
|
|
12
|
+
* // → "00042"
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function sprintf(format: string, ...args: unknown[]): string;
|
|
16
|
+
//# sourceMappingURL=sprintf.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprintf.d.ts","sourceRoot":"","sources":["../../src/utils/sprintf.ts"],"names":[],"mappings":"AAkCA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CA4FlE"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// sprintf — printf-style string formatting
|
|
3
|
+
//
|
|
4
|
+
// Design patterns used:
|
|
5
|
+
// - Pure Function : no side effects, deterministic output
|
|
6
|
+
// ---------------------------------------------------------------------------
|
|
7
|
+
function convert(m, nosign = false) {
|
|
8
|
+
const sign = nosign ? '' : m.negative ? '-' : m.sign;
|
|
9
|
+
const padLen = m.min - m.argument.length + 1 - sign.length;
|
|
10
|
+
const pad = padLen > 0 ? m.pad.repeat(padLen) : '';
|
|
11
|
+
if (!m.left) {
|
|
12
|
+
return m.pad === '0' || nosign
|
|
13
|
+
? sign + pad + m.argument
|
|
14
|
+
: pad + sign + m.argument;
|
|
15
|
+
}
|
|
16
|
+
return m.pad === '0' || nosign
|
|
17
|
+
? sign + m.argument + pad.replace(/0/g, ' ')
|
|
18
|
+
: sign + m.argument + pad;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* C-style `sprintf` implementation.
|
|
22
|
+
*
|
|
23
|
+
* Supported format specifiers: `%b` `%c` `%d` `%f` `%o` `%s` `%x` `%X` `%%`
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* sprintf("Hello %s, you are %d years old", "Alice", 30)
|
|
28
|
+
* // → "Hello Alice, you are 30 years old"
|
|
29
|
+
*
|
|
30
|
+
* sprintf("%05d", 42)
|
|
31
|
+
* // → "00042"
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export function sprintf(format, ...args) {
|
|
35
|
+
const exp = /(%([%]|(-)?(\+|\x20)?(0)?(\d+)?(\.(\d)?)?([bcdfosxX])))/g;
|
|
36
|
+
const matches = [];
|
|
37
|
+
const strings = [];
|
|
38
|
+
let convCount = 0;
|
|
39
|
+
let matchPosEnd = 0;
|
|
40
|
+
let result;
|
|
41
|
+
while ((result = exp.exec(format)) !== null) {
|
|
42
|
+
if (result[9])
|
|
43
|
+
convCount++;
|
|
44
|
+
const stringPosStart = matchPosEnd;
|
|
45
|
+
const stringPosEnd = exp.lastIndex - result[0].length;
|
|
46
|
+
strings.push(format.substring(stringPosStart, stringPosEnd));
|
|
47
|
+
matchPosEnd = exp.lastIndex;
|
|
48
|
+
const argValue = args[convCount - 1];
|
|
49
|
+
matches.push({
|
|
50
|
+
match: result[0],
|
|
51
|
+
left: !!result[3],
|
|
52
|
+
sign: result[4] || '',
|
|
53
|
+
pad: result[5] || ' ',
|
|
54
|
+
min: result[6] ? parseInt(result[6]) : 0,
|
|
55
|
+
precision: result[8] !== undefined ? parseInt(result[8]) : undefined,
|
|
56
|
+
code: result[9] || '%',
|
|
57
|
+
negative: Number(argValue) < 0,
|
|
58
|
+
argument: String(argValue),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
strings.push(format.substring(matchPosEnd));
|
|
62
|
+
if (matches.length === 0)
|
|
63
|
+
return format;
|
|
64
|
+
if (args.length < convCount)
|
|
65
|
+
return format;
|
|
66
|
+
let output = '';
|
|
67
|
+
for (let i = 0; i < matches.length; i++) {
|
|
68
|
+
const m = matches[i];
|
|
69
|
+
let substitution;
|
|
70
|
+
switch (m.code) {
|
|
71
|
+
case '%':
|
|
72
|
+
substitution = '%';
|
|
73
|
+
break;
|
|
74
|
+
case 'b':
|
|
75
|
+
m.argument = Math.abs(parseInt(m.argument)).toString(2);
|
|
76
|
+
substitution = convert(m, true);
|
|
77
|
+
break;
|
|
78
|
+
case 'c':
|
|
79
|
+
m.argument = String.fromCharCode(Math.abs(parseInt(m.argument)));
|
|
80
|
+
substitution = convert(m, true);
|
|
81
|
+
break;
|
|
82
|
+
case 'd':
|
|
83
|
+
m.argument = String(Math.abs(parseInt(m.argument)));
|
|
84
|
+
substitution = convert(m);
|
|
85
|
+
break;
|
|
86
|
+
case 'f':
|
|
87
|
+
m.argument = Math.abs(parseFloat(m.argument)).toFixed(m.precision ?? 6);
|
|
88
|
+
substitution = convert(m);
|
|
89
|
+
break;
|
|
90
|
+
case 'o':
|
|
91
|
+
m.argument = Math.abs(parseInt(m.argument)).toString(8);
|
|
92
|
+
substitution = convert(m);
|
|
93
|
+
break;
|
|
94
|
+
case 's':
|
|
95
|
+
m.argument = m.precision
|
|
96
|
+
? m.argument.substring(0, m.precision)
|
|
97
|
+
: m.argument;
|
|
98
|
+
substitution = convert(m, true);
|
|
99
|
+
break;
|
|
100
|
+
case 'x':
|
|
101
|
+
m.argument = Math.abs(parseInt(m.argument)).toString(16);
|
|
102
|
+
substitution = convert(m);
|
|
103
|
+
break;
|
|
104
|
+
case 'X':
|
|
105
|
+
m.argument = Math.abs(parseInt(m.argument)).toString(16);
|
|
106
|
+
substitution = convert(m).toUpperCase();
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
substitution = m.match;
|
|
110
|
+
}
|
|
111
|
+
output += strings[i] + substitution;
|
|
112
|
+
}
|
|
113
|
+
output += strings[matches.length];
|
|
114
|
+
return output;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=sprintf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprintf.js","sourceRoot":"","sources":["../../src/utils/sprintf.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A constraint handler defines behavior that is attached to input elements
|
|
3
|
+
* bearing a matching `constraint` attribute value.
|
|
4
|
+
*
|
|
5
|
+
* Each handler is self-contained — it knows how to bind its own events
|
|
6
|
+
* and how to validate its own input.
|
|
7
|
+
*/
|
|
8
|
+
export interface ConstraintHandler {
|
|
9
|
+
/** The constraint keyword (e.g. `"date"`, `"number"`). */
|
|
10
|
+
name: string;
|
|
11
|
+
/**
|
|
12
|
+
* Called once per matching element to attach event listeners.
|
|
13
|
+
* This is the **Decorator** step — it augments the element's behavior.
|
|
14
|
+
*/
|
|
15
|
+
attach(element: HTMLInputElement | HTMLTextAreaElement): void;
|
|
16
|
+
}
|
|
17
|
+
export declare const dateConstraint: ConstraintHandler;
|
|
18
|
+
export declare const numberConstraint: ConstraintHandler;
|
|
19
|
+
export declare const timeConstraint: ConstraintHandler;
|
|
20
|
+
export declare const upperCaseConstraint: ConstraintHandler;
|
|
21
|
+
export declare const onlyEnConstraint: ConstraintHandler;
|
|
22
|
+
export declare const builtInConstraints: ConstraintHandler[];
|
|
23
|
+
//# sourceMappingURL=constraints.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraints.d.ts","sourceRoot":"","sources":["../../src/validation/constraints.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IAEb;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,gBAAgB,GAAG,mBAAmB,GAAG,IAAI,CAAC;CAC/D;AAID,eAAO,MAAM,cAAc,EAAE,iBAc5B,CAAC;AAIF,eAAO,MAAM,gBAAgB,EAAE,iBAkC9B,CAAC;AAIF,eAAO,MAAM,cAAc,EAAE,iBAmC5B,CAAC;AAIF,eAAO,MAAM,mBAAmB,EAAE,iBAgBjC,CAAC;AAIF,eAAO,MAAM,gBAAgB,EAAE,iBAQ9B,CAAC;AAIF,eAAO,MAAM,kBAAkB,EAAE,iBAAiB,EAMjD,CAAC"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Constraint handlers — individual input behavior decorators
|
|
3
|
+
//
|
|
4
|
+
// Design patterns used:
|
|
5
|
+
// - Strategy Pattern : each constraint is an independent strategy object
|
|
6
|
+
// - Decorator Pattern : constraints add behavior to plain HTML inputs
|
|
7
|
+
// via attribute-driven binding
|
|
8
|
+
// - Registry Pattern : constraints are registered by name and looked up
|
|
9
|
+
// from the `constraint` attribute at runtime
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
import { sprintf } from '../utils/sprintf.js';
|
|
12
|
+
import { isDateValid } from '../utils/dom.js';
|
|
13
|
+
// -- Date constraint --------------------------------------------------------
|
|
14
|
+
export const dateConstraint = {
|
|
15
|
+
name: 'date',
|
|
16
|
+
attach(element) {
|
|
17
|
+
element.addEventListener('change', () => {
|
|
18
|
+
if (element.value !== '' && !isDateValid(element.value)) {
|
|
19
|
+
element.value = '';
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
// Disable IME for date input
|
|
23
|
+
element.style['imeMode'] = 'disabled';
|
|
24
|
+
element.setAttribute('inputmode', 'numeric');
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
// -- Number constraint ------------------------------------------------------
|
|
28
|
+
export const numberConstraint = {
|
|
29
|
+
name: 'number',
|
|
30
|
+
attach(element) {
|
|
31
|
+
element.addEventListener('keydown', ((event) => {
|
|
32
|
+
// Allow: backspace, delete, tab, escape, enter, arrows, home, end
|
|
33
|
+
const allowedKeys = [
|
|
34
|
+
'Backspace', 'Delete', 'Tab', 'Escape', 'Enter',
|
|
35
|
+
'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown',
|
|
36
|
+
'Home', 'End',
|
|
37
|
+
];
|
|
38
|
+
if (allowedKeys.includes(event.key))
|
|
39
|
+
return;
|
|
40
|
+
// Allow Ctrl/Cmd + A/C/V/X
|
|
41
|
+
if ((event.ctrlKey || event.metaKey) && ['a', 'c', 'v', 'x'].includes(event.key))
|
|
42
|
+
return;
|
|
43
|
+
// Allow digits, dot, minus
|
|
44
|
+
if (/[\d.\-]/.test(event.key))
|
|
45
|
+
return;
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
}));
|
|
48
|
+
element.addEventListener('change', () => {
|
|
49
|
+
const val = element.value;
|
|
50
|
+
if (!/^-?[0-9]+(\.[0-9]+)?$/.test(val) || /^0\d+$/.test(val)) {
|
|
51
|
+
element.value = '0';
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// Default empty number fields to 0
|
|
55
|
+
if (element.value === '') {
|
|
56
|
+
element.value = '0';
|
|
57
|
+
}
|
|
58
|
+
element.style['imeMode'] = 'disabled';
|
|
59
|
+
element.setAttribute('inputmode', 'decimal');
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
// -- Time constraint --------------------------------------------------------
|
|
63
|
+
export const timeConstraint = {
|
|
64
|
+
name: 'time',
|
|
65
|
+
attach(element) {
|
|
66
|
+
element.addEventListener('blur', () => {
|
|
67
|
+
const input = element.value;
|
|
68
|
+
let hour = '00';
|
|
69
|
+
let minute = '00';
|
|
70
|
+
if (/^\d{1,4}$/.test(input)) {
|
|
71
|
+
hour = sprintf('%02s', input.substring(0, 2));
|
|
72
|
+
minute = sprintf('%02s', input.substring(2, 4));
|
|
73
|
+
}
|
|
74
|
+
else if (/^\d{0,2}:\d{0,2}$/.test(input)) {
|
|
75
|
+
const colonIdx = input.indexOf(':');
|
|
76
|
+
hour = sprintf('%02s', input.substring(0, colonIdx));
|
|
77
|
+
minute = sprintf('%02s', input.substring(colonIdx + 1));
|
|
78
|
+
}
|
|
79
|
+
element.value = `${hour}:${minute}`;
|
|
80
|
+
});
|
|
81
|
+
element.addEventListener('keydown', ((event) => {
|
|
82
|
+
const allowedKeys = [
|
|
83
|
+
'Backspace', 'Delete', 'Tab', 'Escape', 'Enter',
|
|
84
|
+
'ArrowLeft', 'ArrowRight', 'Home', 'End',
|
|
85
|
+
];
|
|
86
|
+
if (allowedKeys.includes(event.key))
|
|
87
|
+
return;
|
|
88
|
+
if ((event.ctrlKey || event.metaKey) && ['a', 'c', 'v', 'x'].includes(event.key))
|
|
89
|
+
return;
|
|
90
|
+
if (/[\d:]/.test(event.key))
|
|
91
|
+
return;
|
|
92
|
+
event.preventDefault();
|
|
93
|
+
}));
|
|
94
|
+
element.style['imeMode'] = 'disabled';
|
|
95
|
+
element.setAttribute('inputmode', 'numeric');
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
// -- UpperCase constraint ---------------------------------------------------
|
|
99
|
+
export const upperCaseConstraint = {
|
|
100
|
+
name: 'upperCase',
|
|
101
|
+
attach(element) {
|
|
102
|
+
let timeout;
|
|
103
|
+
element.addEventListener('keyup', () => {
|
|
104
|
+
clearTimeout(timeout);
|
|
105
|
+
timeout = setTimeout(() => {
|
|
106
|
+
const val = element.value;
|
|
107
|
+
if (/[a-z]/.test(val)) {
|
|
108
|
+
element.value = val.toUpperCase();
|
|
109
|
+
}
|
|
110
|
+
}, 500);
|
|
111
|
+
});
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
// -- OnlyEn constraint ------------------------------------------------------
|
|
115
|
+
export const onlyEnConstraint = {
|
|
116
|
+
name: 'onlyEn',
|
|
117
|
+
attach(element) {
|
|
118
|
+
element.style['imeMode'] = 'disabled';
|
|
119
|
+
element.setAttribute('inputmode', 'text');
|
|
120
|
+
element.setAttribute('lang', 'en');
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
// -- All built-in constraints -----------------------------------------------
|
|
124
|
+
export const builtInConstraints = [
|
|
125
|
+
dateConstraint,
|
|
126
|
+
numberConstraint,
|
|
127
|
+
timeConstraint,
|
|
128
|
+
upperCaseConstraint,
|
|
129
|
+
onlyEnConstraint,
|
|
130
|
+
];
|
|
131
|
+
//# sourceMappingURL=constraints.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../src/validation/constraints.ts"],"names":[],"mappings":"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"}
|