@trunkjs/form 1.0.0 → 1.0.5
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/CHANGELOG.md +33 -0
- package/components/tj-form/tj-form.d.ts +2 -0
- package/index.js +55 -31
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,36 @@
|
|
|
1
|
+
## 1.0.5 (2026-09-10)
|
|
2
|
+
|
|
3
|
+
This was a version bump only for form to align it with other projects, there were no code changes.
|
|
4
|
+
|
|
5
|
+
## 1.0.4 (2026-09-09)
|
|
6
|
+
|
|
7
|
+
This was a version bump only for form to align it with other projects, there were no code changes.
|
|
8
|
+
|
|
9
|
+
## 1.0.3 (2026-09-09)
|
|
10
|
+
|
|
11
|
+
This was a version bump only for form to align it with other projects, there were no code changes.
|
|
12
|
+
|
|
13
|
+
## 1.0.2 (2026-09-07)
|
|
14
|
+
|
|
15
|
+
### 🧱 Updated Dependencies
|
|
16
|
+
|
|
17
|
+
- Updated vite-demo-viewer to 1.0.12
|
|
18
|
+
|
|
19
|
+
## 1.0.1 (2026-09-01)
|
|
20
|
+
|
|
21
|
+
### 🚀 Features
|
|
22
|
+
|
|
23
|
+
- **form:** compose global form presets ([d94865c](https://github.com/trunkjs/trunkjs-monorepo/commit/d94865c))
|
|
24
|
+
- **form:** add ajax form element and remote controls ([0d75fd1](https://github.com/trunkjs/trunkjs-monorepo/commit/0d75fd1))
|
|
25
|
+
|
|
26
|
+
### 🩹 Fixes
|
|
27
|
+
|
|
28
|
+
- **form:** select a single preset ([cda92d5](https://github.com/trunkjs/trunkjs-monorepo/commit/cda92d5))
|
|
29
|
+
|
|
30
|
+
### ❤️ Thank You
|
|
31
|
+
|
|
32
|
+
- Matthias Leuffen
|
|
33
|
+
|
|
1
34
|
# Changelog
|
|
2
35
|
|
|
3
36
|
## Unreleased
|
|
@@ -24,6 +24,8 @@ export declare class TjForm extends HTMLElement {
|
|
|
24
24
|
requestSubmit(submitter?: HTMLElement | null, sourceEvent?: Event | null): Promise<unknown>;
|
|
25
25
|
private readonly handleClick;
|
|
26
26
|
private isSubmitter;
|
|
27
|
+
private validateControls;
|
|
28
|
+
private isVisibleControl;
|
|
27
29
|
private createContext;
|
|
28
30
|
private watchPreset;
|
|
29
31
|
private activatePreset;
|
package/index.js
CHANGED
|
@@ -5,12 +5,12 @@ class h {
|
|
|
5
5
|
this.presets = /* @__PURE__ */ new Map(), this.listeners = /* @__PURE__ */ new Map();
|
|
6
6
|
}
|
|
7
7
|
register(t, e) {
|
|
8
|
-
const
|
|
9
|
-
return this.presets.set(
|
|
8
|
+
const i = this.normalizeName(t);
|
|
9
|
+
return this.presets.set(i, e), this.notify(i, e), this;
|
|
10
10
|
}
|
|
11
11
|
unregister(t) {
|
|
12
|
-
const e = t.trim(),
|
|
13
|
-
return
|
|
12
|
+
const e = t.trim(), i = this.presets.delete(e);
|
|
13
|
+
return i && this.notify(e, void 0), i;
|
|
14
14
|
}
|
|
15
15
|
get(t) {
|
|
16
16
|
return t ? this.presets.get(t.trim()) : void 0;
|
|
@@ -19,9 +19,9 @@ class h {
|
|
|
19
19
|
return this.presets.has(t.trim());
|
|
20
20
|
}
|
|
21
21
|
subscribe(t, e) {
|
|
22
|
-
const
|
|
23
|
-
return
|
|
24
|
-
|
|
22
|
+
const i = this.normalizeName(t), s = this.listeners.get(i) ?? /* @__PURE__ */ new Set();
|
|
23
|
+
return s.add(e), this.listeners.set(i, s), () => {
|
|
24
|
+
s.delete(e), s.size === 0 && this.listeners.delete(i);
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
normalizeName(t) {
|
|
@@ -31,12 +31,12 @@ class h {
|
|
|
31
31
|
return e;
|
|
32
32
|
}
|
|
33
33
|
notify(t, e) {
|
|
34
|
-
for (const
|
|
35
|
-
|
|
34
|
+
for (const i of this.listeners.get(t) ?? [])
|
|
35
|
+
i(e);
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
const c = globalThis.__trunkjsFormRegistry ?? (globalThis.__trunkjsFormRegistry = new h());
|
|
39
|
-
function
|
|
39
|
+
function b(n, t) {
|
|
40
40
|
if (typeof n == "string") {
|
|
41
41
|
if (!t)
|
|
42
42
|
throw new Error("A named form preset requires a preset definition.");
|
|
@@ -47,8 +47,8 @@ function g(n, t) {
|
|
|
47
47
|
class d extends HTMLElement {
|
|
48
48
|
constructor(t = c) {
|
|
49
49
|
super(), this.registry = t, this.dataAccessor = new l(this), this.unsubscribeRegistry = null, this.pluginCleanups = [], this.handleClick = (e) => {
|
|
50
|
-
const
|
|
51
|
-
!
|
|
50
|
+
const i = e.target instanceof Element ? e.target : null, s = i == null ? void 0 : i.closest('button, input, [type="submit"]');
|
|
51
|
+
!s || s.closest("tj-form") !== this || !this.isSubmitter(s) || (e.preventDefault(), this.requestSubmit(s, e));
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
static get observedAttributes() {
|
|
@@ -91,20 +91,44 @@ class d extends HTMLElement {
|
|
|
91
91
|
}
|
|
92
92
|
async requestSubmit(t = null, e = null) {
|
|
93
93
|
var r, o;
|
|
94
|
-
|
|
94
|
+
if (!this.validateControls())
|
|
95
|
+
return;
|
|
96
|
+
const i = this.createContext(t, e);
|
|
95
97
|
if (this.dispatchEvent(
|
|
96
98
|
new CustomEvent("tj-form-submit", {
|
|
97
99
|
bubbles: !0,
|
|
98
100
|
cancelable: !0,
|
|
99
|
-
detail:
|
|
101
|
+
detail: i
|
|
100
102
|
})
|
|
101
103
|
))
|
|
102
|
-
return (o = (r = this.activePreset) == null ? void 0 : r.onSubmit) == null ? void 0 : o.call(r,
|
|
104
|
+
return (o = (r = this.activePreset) == null ? void 0 : r.onSubmit) == null ? void 0 : o.call(r, i);
|
|
103
105
|
}
|
|
104
106
|
isSubmitter(t) {
|
|
105
107
|
var e;
|
|
106
108
|
return t instanceof HTMLButtonElement ? (t.getAttribute("type") ?? "submit").toLowerCase() === "submit" : t instanceof HTMLInputElement ? ["submit", "image"].includes(t.type.toLowerCase()) : ((e = t.getAttribute("type")) == null ? void 0 : e.toLowerCase()) === "submit";
|
|
107
109
|
}
|
|
110
|
+
// Validates native and form-associated custom controls before dispatching the submit event.
|
|
111
|
+
validateControls() {
|
|
112
|
+
var e, i;
|
|
113
|
+
const t = [];
|
|
114
|
+
for (const s of this.getElements()) {
|
|
115
|
+
const r = s;
|
|
116
|
+
!this.isVisibleControl(r) || typeof r.checkValidity != "function" || r.checkValidity() || t.push(r);
|
|
117
|
+
}
|
|
118
|
+
return t.forEach((s) => {
|
|
119
|
+
var r;
|
|
120
|
+
return (r = s.reportValidity) == null ? void 0 : r.call(s);
|
|
121
|
+
}), (i = (e = t[0]) == null ? void 0 : e.focus) == null || i.call(e), t.length === 0;
|
|
122
|
+
}
|
|
123
|
+
// Uses the browser visibility API where available and falls back to the relevant HTML visibility states.
|
|
124
|
+
isVisibleControl(t) {
|
|
125
|
+
if (t.hidden || t.closest("[hidden]"))
|
|
126
|
+
return !1;
|
|
127
|
+
if (typeof t.checkVisibility == "function")
|
|
128
|
+
return t.checkVisibility({ checkOpacity: !1, checkVisibilityCSS: !0 });
|
|
129
|
+
const e = window.getComputedStyle(t);
|
|
130
|
+
return e.display !== "none" && e.visibility !== "hidden";
|
|
131
|
+
}
|
|
108
132
|
createContext(t, e) {
|
|
109
133
|
return {
|
|
110
134
|
form: this,
|
|
@@ -122,8 +146,8 @@ class d extends HTMLElement {
|
|
|
122
146
|
if (this.disconnectPlugins(), this.activePreset = t, !!t) {
|
|
123
147
|
t.value && (this.value = t.value);
|
|
124
148
|
for (const e of t.plugins ?? []) {
|
|
125
|
-
const
|
|
126
|
-
|
|
149
|
+
const i = e.connect(this);
|
|
150
|
+
i && this.pluginCleanups.push(i);
|
|
127
151
|
}
|
|
128
152
|
}
|
|
129
153
|
}
|
|
@@ -132,26 +156,26 @@ class d extends HTMLElement {
|
|
|
132
156
|
}
|
|
133
157
|
}
|
|
134
158
|
typeof customElements < "u" && !customElements.get("tj-form") && customElements.define("tj-form", d);
|
|
135
|
-
class
|
|
159
|
+
class f {
|
|
136
160
|
constructor(t = {}) {
|
|
137
161
|
this.options = t;
|
|
138
162
|
}
|
|
139
163
|
connect(t) {
|
|
140
|
-
const e = (
|
|
141
|
-
if (
|
|
164
|
+
const e = (i) => {
|
|
165
|
+
if (i.key !== "Enter" || i.defaultPrevented || i.isComposing)
|
|
142
166
|
return;
|
|
143
|
-
const
|
|
144
|
-
if (!
|
|
167
|
+
const s = i.target instanceof HTMLElement ? i.target : null;
|
|
168
|
+
if (!s || s.closest("tj-form") !== t || this.isMultiline(s))
|
|
145
169
|
return;
|
|
146
|
-
const r = t.getElements().filter((a) => !this.isDisabled(a)), o = r.find((a) => a ===
|
|
147
|
-
o && (
|
|
170
|
+
const r = t.getElements().filter((a) => !this.isDisabled(a)), o = r.find((a) => a === s || a.contains(s));
|
|
171
|
+
o && (i.preventDefault(), this.moveNext(t, o, r));
|
|
148
172
|
};
|
|
149
173
|
return t.addEventListener("keydown", e), () => t.removeEventListener("keydown", e);
|
|
150
174
|
}
|
|
151
|
-
async moveNext(t, e,
|
|
175
|
+
async moveNext(t, e, i) {
|
|
152
176
|
if (!(this.options.validate ? await this.options.validate(e, t) : this.validate(e)))
|
|
153
177
|
return;
|
|
154
|
-
const r =
|
|
178
|
+
const r = i[i.indexOf(e) + 1];
|
|
155
179
|
r && (this.options.focus ?? ((o) => o.focus()))(r);
|
|
156
180
|
}
|
|
157
181
|
validate(t) {
|
|
@@ -165,15 +189,15 @@ class m {
|
|
|
165
189
|
return t instanceof HTMLTextAreaElement || t.getAttribute("contenteditable") === "true";
|
|
166
190
|
}
|
|
167
191
|
}
|
|
168
|
-
function
|
|
169
|
-
return new
|
|
192
|
+
function g(n = {}) {
|
|
193
|
+
return new f(n);
|
|
170
194
|
}
|
|
171
195
|
export {
|
|
172
196
|
u as DEFAULT_FORM_PRESET,
|
|
173
|
-
|
|
197
|
+
f as EnterNextPlugin,
|
|
174
198
|
d as TjForm,
|
|
175
199
|
h as TjFormRegistry,
|
|
176
|
-
|
|
177
|
-
|
|
200
|
+
g as enterNextPlugin,
|
|
201
|
+
b as registerFormPreset,
|
|
178
202
|
c as tjFormRegistry
|
|
179
203
|
};
|
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trunkjs/form",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"main": "./index.js",
|
|
5
5
|
"repository": {
|
|
6
6
|
"directory": "packages/form",
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "git+https://github.com/trunkjs/trunkjs-monorepo.git"
|
|
9
9
|
},
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"@trunkjs/browser-utils": "*"
|
|
12
|
-
},
|
|
13
10
|
"devDependencies": {
|
|
14
11
|
"@trunkjs/demo-viewer": "*",
|
|
15
12
|
"@trunkjs/vite-demo-viewer": "*"
|
|
16
13
|
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@trunkjs/browser-utils": "^1.0.55"
|
|
16
|
+
},
|
|
17
17
|
"type": "module",
|
|
18
18
|
"types": "./index.d.ts"
|
|
19
19
|
}
|