@maihcx/super-date 0.3.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/LICENSE +21 -0
- package/README.md +191 -0
- package/dist/super-date.css +86 -0
- package/dist/super-date.css.map +1 -0
- package/dist/super-date.esm.js +1083 -0
- package/dist/super-date.esm.js.map +1 -0
- package/dist/super-date.esm.min.js +2 -0
- package/dist/super-date.esm.min.js.br +0 -0
- package/dist/super-date.min.css +1 -0
- package/dist/super-date.min.css.br +0 -0
- package/dist/super-date.min.js +2 -0
- package/dist/super-date.min.js.br +0 -0
- package/dist/super-date.umd.js +1094 -0
- package/dist/super-date.umd.js.map +1 -0
- package/package.json +68 -0
- package/src/css/index.css +84 -0
- package/src/ts/core/format.ts +452 -0
- package/src/ts/core/instance.ts +605 -0
- package/src/ts/core/overlay.ts +127 -0
- package/src/ts/core/registry.ts +141 -0
- package/src/ts/global.ts +33 -0
- package/src/ts/index.ts +26 -0
- package/src/ts/types/bind-entry.type.ts +6 -0
- package/src/ts/types/css.d.ts +1 -0
- package/src/ts/types/date-token.type.ts +9 -0
- package/src/ts/types/segment.type.ts +8 -0
- package/src/ts/types/super-date.type.ts +14 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 maihcx
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# SuperDate
|
|
2
|
+
|
|
3
|
+
TypeScript date/time input enhancer. Replaces the native browser date-picker chrome with a fully custom, format-aware overlay — while still delegating the actual popup to the OS so you never re-implement a calendar or clock widget.
|
|
4
|
+
|
|
5
|
+
Supports `input[type="date"]`, `input[type="time"]`, and `input[type="datetime-local"]`.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
| Feature | Detail |
|
|
10
|
+
|---|---|
|
|
11
|
+
| **3 input types** | `date`, `time`, and `datetime-local` all supported |
|
|
12
|
+
| **Auto-observe** | `SuperDate.bind('.selector')` watches the DOM via `MutationObserver` — inputs added later are automatically enhanced |
|
|
13
|
+
| **Custom format** | Global default or per-element via `data-date-format`, `data-time-format`, `data-date-time-delimiter` |
|
|
14
|
+
| **Keyboard editing** | `↑ ↓` step values, `← →` move segments, `0–9` type digits, auto-advance on completion |
|
|
15
|
+
| **Copy / Paste** | Parses pasted text against configured format + common fallbacks |
|
|
16
|
+
| **Native picker** | Calendar / clock icon opens the OS picker; `input.value` stays as ISO string |
|
|
17
|
+
| **Zero dependencies** | Plain TypeScript, no runtime deps |
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install superdate # if published
|
|
23
|
+
# or copy dist/ into your project
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Build
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install
|
|
30
|
+
npm run build
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Outputs:
|
|
34
|
+
|
|
35
|
+
| File | Format |
|
|
36
|
+
|---|---|
|
|
37
|
+
| `dist/super-date.esm.js` | ES Module |
|
|
38
|
+
| `dist/super-date.esm.min.js` | ES Module (minified) |
|
|
39
|
+
| `dist/super-date.umd.js` | UMD (browser global `SuperDate`) |
|
|
40
|
+
| `dist/super-date.min.js` | UMD (minified) |
|
|
41
|
+
|
|
42
|
+
## Usage
|
|
43
|
+
|
|
44
|
+
### Via `<script>` tag
|
|
45
|
+
|
|
46
|
+
```html
|
|
47
|
+
<link rel="stylesheet" href="dist/super-date.min.css" />
|
|
48
|
+
<script src="dist/super-date.umd.js"></script>
|
|
49
|
+
<script>
|
|
50
|
+
SuperDate.bind('.sd', { format: 'dd/MM/yyyy' });
|
|
51
|
+
</script>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### ES Module
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import SuperDate from './dist/super-date.esm.js';
|
|
58
|
+
SuperDate.bind('.sd', { format: 'dd/MM/yyyy' });
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### TypeScript / bundler
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import SuperDate from 'superdate';
|
|
65
|
+
SuperDate.bind('.sd');
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## API
|
|
69
|
+
|
|
70
|
+
### `SuperDate.bind(selector, options?)`
|
|
71
|
+
|
|
72
|
+
Enhances all current **and future** `<input type="date">`, `<input type="time">`, and `<input type="datetime-local">` elements matching `selector`.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
SuperDate.bind('.sd', {
|
|
76
|
+
format: 'dd/MM/yyyy', // date display format
|
|
77
|
+
timeFormat: 'HH:mm', // time display format
|
|
78
|
+
dateTimeDelimiter: ' ', // separator between date and time parts
|
|
79
|
+
locale: 'vi-VN', // locale (reserved for future i18n)
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Returns `this` for chaining.
|
|
84
|
+
|
|
85
|
+
### `SuperDate.init(el, options?)`
|
|
86
|
+
|
|
87
|
+
Manually enhance a single element. Returns the `SuperDateInstance`.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
const el = document.querySelector('#my-input') as HTMLInputElement;
|
|
91
|
+
SuperDate.init(el, { format: 'yyyy/MM/dd' });
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `SuperDate.destroy(el)`
|
|
95
|
+
|
|
96
|
+
Remove the overlay and restore the original native input.
|
|
97
|
+
|
|
98
|
+
## Options
|
|
99
|
+
|
|
100
|
+
| Option | Type | Default | Description |
|
|
101
|
+
|---|---|---|---|
|
|
102
|
+
| `format` | `string` | `'dd/MM/yyyy'` | Display format for `date` and the date part of `datetime-local` inputs |
|
|
103
|
+
| `timeFormat` | `string` | `'HH:mm'` | Display format for `time` and the time part of `datetime-local` inputs |
|
|
104
|
+
| `dateTimeDelimiter` | `string` | `' '` | String inserted between date and time parts in `datetime-local` inputs |
|
|
105
|
+
| `locale` | `string` | `navigator.language` | Locale (reserved) |
|
|
106
|
+
|
|
107
|
+
## Per-element overrides (data attributes)
|
|
108
|
+
|
|
109
|
+
```html
|
|
110
|
+
<!-- date -->
|
|
111
|
+
<input type="date" data-date-format="yyyy/MM/dd" />
|
|
112
|
+
|
|
113
|
+
<!-- time -->
|
|
114
|
+
<input type="time" data-time-format="HH:mm:ss" />
|
|
115
|
+
|
|
116
|
+
<!-- datetime-local — all three can be combined -->
|
|
117
|
+
<input type="datetime-local"
|
|
118
|
+
data-date-format="dd/MM/yyyy"
|
|
119
|
+
data-time-format="HH:mm:ss"
|
|
120
|
+
data-date-time-delimiter=" | " />
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Per-element attributes always take priority over `bind()` options.
|
|
124
|
+
|
|
125
|
+
## Supported tokens
|
|
126
|
+
|
|
127
|
+
### Date tokens
|
|
128
|
+
|
|
129
|
+
| Token | Description | Example |
|
|
130
|
+
|---|---|---|
|
|
131
|
+
| `yyyy` | 4-digit year | `2025` |
|
|
132
|
+
| `yy` | 2-digit year | `25` |
|
|
133
|
+
| `MM` | Month, zero-padded | `03` |
|
|
134
|
+
| `M` | Month, no padding | `3` |
|
|
135
|
+
| `dd` | Day, zero-padded | `07` |
|
|
136
|
+
| `d` | Day, no padding | `7` |
|
|
137
|
+
|
|
138
|
+
### Time tokens
|
|
139
|
+
|
|
140
|
+
| Token | Description | Example |
|
|
141
|
+
|---|---|---|
|
|
142
|
+
| `HH` | Hours 24h, zero-padded | `09`, `23` |
|
|
143
|
+
| `H` | Hours 24h, no padding | `9`, `23` |
|
|
144
|
+
| `hh` | Hours 12h, zero-padded | `09`, `11` |
|
|
145
|
+
| `h` | Hours 12h, no padding | `9`, `11` |
|
|
146
|
+
| `mm` | Minutes, zero-padded | `05`, `59` |
|
|
147
|
+
| `ss` | Seconds, zero-padded | `00`, `59` |
|
|
148
|
+
|
|
149
|
+
> **Note:** `MM` = months (uppercase), `mm` = minutes (lowercase).
|
|
150
|
+
|
|
151
|
+
## CSS variables
|
|
152
|
+
|
|
153
|
+
Override the overlay appearance per-element or globally:
|
|
154
|
+
|
|
155
|
+
```css
|
|
156
|
+
.superdate-overlay {
|
|
157
|
+
--superdate-active-bg: #2563eb; /* active segment background */
|
|
158
|
+
--superdate-active-color: #fff; /* active segment text */
|
|
159
|
+
--superdate-placeholder-color: #9ca3af; /* empty segment placeholder */
|
|
160
|
+
--superdate-sep-color: inherit; /* separator / literal color */
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Keyboard shortcuts
|
|
165
|
+
|
|
166
|
+
| Key | Action |
|
|
167
|
+
|---|---|
|
|
168
|
+
| `0–9` | Type digit into active segment, auto-advance when full |
|
|
169
|
+
| `↑` / `↓` | Increment / decrement active segment value |
|
|
170
|
+
| `←` / `→` | Move to previous / next segment |
|
|
171
|
+
| `Tab` / `Shift+Tab` | Move to next / previous segment |
|
|
172
|
+
| `Backspace` | Erase last typed digit in buffer |
|
|
173
|
+
| `Escape` | Deactivate / clear selection |
|
|
174
|
+
| `Ctrl+A` | Select all segments |
|
|
175
|
+
| `Ctrl+C` | Copy selected segments as formatted text |
|
|
176
|
+
| Click & drag | Multi-segment selection |
|
|
177
|
+
| Double-click | Select all segments |
|
|
178
|
+
|
|
179
|
+
## Input value
|
|
180
|
+
|
|
181
|
+
The underlying `input.value` always stays in native ISO format — SuperDate only changes the **visual overlay**:
|
|
182
|
+
|
|
183
|
+
| Input type | `input.value` format |
|
|
184
|
+
|---|---|
|
|
185
|
+
| `date` | `yyyy-MM-dd` |
|
|
186
|
+
| `time` | `HH:mm:ss` |
|
|
187
|
+
| `datetime-local` | `yyyy-MM-ddTHH:mm:ss` |
|
|
188
|
+
|
|
189
|
+
## License
|
|
190
|
+
|
|
191
|
+
MIT
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
input.superdate-input::-webkit-datetime-edit,
|
|
2
|
+
input.superdate-input::-webkit-inner-spin-button,
|
|
3
|
+
input.superdate-input::-webkit-clear-button,
|
|
4
|
+
input.superdate-input::-webkit-calendar-picker-indicator {
|
|
5
|
+
display: none !important;
|
|
6
|
+
opacity: 0 !important;
|
|
7
|
+
width: 0 !important;
|
|
8
|
+
}
|
|
9
|
+
input.superdate-input {
|
|
10
|
+
caret-color: transparent;
|
|
11
|
+
color: transparent !important;
|
|
12
|
+
position: relative;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/* Overlay wrapper */
|
|
16
|
+
.superdate-wrapper {
|
|
17
|
+
position: relative;
|
|
18
|
+
display: inline-block;
|
|
19
|
+
width: fit-content;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/* The visible overlay */
|
|
23
|
+
.superdate-overlay {
|
|
24
|
+
position: absolute;
|
|
25
|
+
inset: 0;
|
|
26
|
+
display: flex;
|
|
27
|
+
align-items: center;
|
|
28
|
+
padding: 0 8px;
|
|
29
|
+
pointer-events: none;
|
|
30
|
+
font: inherit;
|
|
31
|
+
letter-spacing: inherit;
|
|
32
|
+
white-space: nowrap;
|
|
33
|
+
overflow: hidden;
|
|
34
|
+
box-sizing: border-box;
|
|
35
|
+
gap: 0;
|
|
36
|
+
/* prevent browser text selection interfering with drag */
|
|
37
|
+
user-select: none;
|
|
38
|
+
-webkit-user-select: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.superdate-seg {
|
|
42
|
+
position: relative;
|
|
43
|
+
display: inline-block;
|
|
44
|
+
border-radius: 2px;
|
|
45
|
+
transition: background 0.1s;
|
|
46
|
+
white-space: pre;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.superdate-seg[data-token] {
|
|
50
|
+
pointer-events: auto;
|
|
51
|
+
cursor: text;
|
|
52
|
+
min-width: 1ch;
|
|
53
|
+
text-align: center;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Single-seg focus OR multi-seg drag selection — same colour, same class */
|
|
57
|
+
.superdate-seg[data-token].active {
|
|
58
|
+
background: var(--superdate-active-bg, #2563eb);
|
|
59
|
+
color: var(--superdate-active-color, #fff);
|
|
60
|
+
border-radius: 3px;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.superdate-seg[data-token].empty {
|
|
64
|
+
color: var(--superdate-placeholder-color, #9ca3af);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.superdate-seg:not([data-token]) {
|
|
68
|
+
color: var(--superdate-sep-color, inherit);
|
|
69
|
+
pointer-events: none;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/* Calendar icon area */
|
|
73
|
+
.superdate-icon {
|
|
74
|
+
pointer-events: auto;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
margin-left: auto;
|
|
79
|
+
padding-left: 6px;
|
|
80
|
+
opacity: 0.5;
|
|
81
|
+
transition: opacity 0.15s;
|
|
82
|
+
flex-shrink: 0;
|
|
83
|
+
}
|
|
84
|
+
.superdate-icon:hover { opacity: 1; }
|
|
85
|
+
|
|
86
|
+
/*# sourceMappingURL=super-date.css.map */
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["index.css"],"names":[],"mappings":"AAAA;;;;EAIE,wBAAwB;EACxB,qBAAqB;EACrB,mBAAmB;AACrB;AACA;EACE,wBAAwB;EACxB,6BAA6B;EAC7B,kBAAkB;AACpB;;AAEA,oBAAoB;AACpB;EACE,kBAAkB;EAClB,qBAAqB;EACrB,kBAAkB;AACpB;;AAEA,wBAAwB;AACxB;EACE,kBAAkB;EAClB,QAAQ;EACR,aAAa;EACb,mBAAmB;EACnB,cAAc;EACd,oBAAoB;EACpB,aAAa;EACb,uBAAuB;EACvB,mBAAmB;EACnB,gBAAgB;EAChB,sBAAsB;EACtB,MAAM;EACN,yDAAyD;EACzD,iBAAiB;EACjB,yBAAyB;AAC3B;;AAEA;EACE,kBAAkB;EAClB,qBAAqB;EACrB,kBAAkB;EAClB,2BAA2B;EAC3B,gBAAgB;AAClB;;AAEA;EACE,oBAAoB;EACpB,YAAY;EACZ,cAAc;EACd,kBAAkB;AACpB;;AAEA,2EAA2E;AAC3E;EACE,+CAA+C;EAC/C,0CAA0C;EAC1C,kBAAkB;AACpB;;AAEA;EACE,kDAAkD;AACpD;;AAEA;EACE,0CAA0C;EAC1C,oBAAoB;AACtB;;AAEA,uBAAuB;AACvB;EACE,oBAAoB;EACpB,eAAe;EACf,aAAa;EACb,mBAAmB;EACnB,iBAAiB;EACjB,iBAAiB;EACjB,YAAY;EACZ,yBAAyB;EACzB,cAAc;AAChB;AACA,wBAAwB,UAAU,EAAE","file":"super-date.css","sourcesContent":["input.superdate-input::-webkit-datetime-edit,\ninput.superdate-input::-webkit-inner-spin-button,\ninput.superdate-input::-webkit-clear-button,\ninput.superdate-input::-webkit-calendar-picker-indicator {\n display: none !important;\n opacity: 0 !important;\n width: 0 !important;\n}\ninput.superdate-input {\n caret-color: transparent;\n color: transparent !important;\n position: relative;\n}\n\n/* Overlay wrapper */\n.superdate-wrapper {\n position: relative;\n display: inline-block;\n width: fit-content;\n}\n\n/* The visible overlay */\n.superdate-overlay {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n padding: 0 8px;\n pointer-events: none;\n font: inherit;\n letter-spacing: inherit;\n white-space: nowrap;\n overflow: hidden;\n box-sizing: border-box;\n gap: 0;\n /* prevent browser text selection interfering with drag */\n user-select: none;\n -webkit-user-select: none;\n}\n\n.superdate-seg {\n position: relative;\n display: inline-block;\n border-radius: 2px;\n transition: background 0.1s;\n white-space: pre;\n}\n\n.superdate-seg[data-token] {\n pointer-events: auto;\n cursor: text;\n min-width: 1ch;\n text-align: center;\n}\n\n/* Single-seg focus OR multi-seg drag selection — same colour, same class */\n.superdate-seg[data-token].active {\n background: var(--superdate-active-bg, #2563eb);\n color: var(--superdate-active-color, #fff);\n border-radius: 3px;\n}\n\n.superdate-seg[data-token].empty {\n color: var(--superdate-placeholder-color, #9ca3af);\n}\n\n.superdate-seg:not([data-token]) {\n color: var(--superdate-sep-color, inherit);\n pointer-events: none;\n}\n\n/* Calendar icon area */\n.superdate-icon {\n pointer-events: auto;\n cursor: pointer;\n display: flex;\n align-items: center;\n margin-left: auto;\n padding-left: 6px;\n opacity: 0.5;\n transition: opacity 0.15s;\n flex-shrink: 0;\n}\n.superdate-icon:hover { opacity: 1; }\n"]}
|