cotomy 0.1.70 → 0.1.72

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 CHANGED
@@ -1,20 +1,20 @@
1
- The MIT License (MIT)
2
- Copyright (c) 2025 Yasuhiro Arakawa
3
-
4
- Permission is hereby granted, free of charge, to any person obtaining a copy
5
- of this software and associated documentation files (the "Software"), to deal
6
- in the Software without restriction, including without limitation the rights
7
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
- copies of the Software, and to permit persons to whom the Software is
9
- furnished to do so, subject to the following conditions:
10
-
11
- The above copyright notice and this permission notice shall be included in all
12
- copies or substantial portions of the Software.
13
-
14
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
- SOFTWARE.
1
+ The MIT License (MIT)
2
+ Copyright (c) 2025 Yasuhiro Arakawa
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
package/README.md CHANGED
@@ -1,89 +1,296 @@
1
- # Cotomy
1
+ # Cotomy
2
+
3
+ > This library targets ES2020+.
4
+ > For older browsers (e.g. iOS 13 or IE), you will need a Polyfill such as `core-js`.
5
+
6
+ **Cotomy** is a lightweight framework for managing form behavior and page controllers in web applications.
7
+ It is suitable for both SPAs (Single Page Applications) and traditional web apps requiring dynamic form operations.
8
+
9
+ ⚠️ **Warning**: This project is in early development. APIs may change without notice until version 1.0.0.
10
+
11
+
12
+ To install Cotomy in your project, run the following command:
13
+
14
+ ```bash
15
+ npm i cotomy
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ Cotomy will continue to expand with more detailed usage instructions and code examples added to the README in the future.
21
+ For the latest updates, please check the official documentation or repository regularly.
22
+
23
+ ## View Reference
2
24
 
3
- > This library targets ES2020+.
4
- > For older browsers (e.g. iOS 13 or IE), you will need a Polyfill such as `core-js`.
25
+ The View layer provides thin wrappers around DOM elements and window events.
5
26
 
6
- **Cotomy** is a lightweight framework for managing form behavior and page controllers in web applications.
7
- It is suitable for both SPAs (Single Page Applications) and traditional web apps requiring dynamic form operations.
27
+ - `CotomyElement` A wrapper around `HTMLElement` with convenient utilities for scoped CSS, querying, attributes/styles, geometry, and event handling.
28
+ - `CotomyMetaElement` Convenience wrapper for `<meta>` tags.
29
+ - `CotomyWindow` — A singleton that exposes window-level events and helpers.
8
30
 
9
- ⚠️ **Warning**: This project is in early development. APIs may change without notice until version 1.0.0.
31
+ ### CotomyElement
10
32
 
33
+ - Constructor
34
+ - `new CotomyElement(element: HTMLElement)`
35
+ - `new CotomyElement(html: string)` — Creates an element from HTML (single root required)
36
+ - `new CotomyElement({ html, css? })` — Creates from HTML and injects scoped CSS
37
+ - `new CotomyElement({ tagname, text?, css? })`
38
+ - Scoped CSS
39
+ - `scopeId: string` — Unique attribute injected into the element for scoping
40
+ - `scopedSelector: string` — Selector string like `[__cotomy_scope__...]`
41
+ - `[scope]` placeholder in provided CSS is replaced by the element’s scope
42
+ - `stylable: boolean` — False for tags like `script`, `style`, `link`, `meta`
43
+ - Static helpers
44
+ - `CotomyElement.encodeHtml(text)`
45
+ - `CotomyElement.first(selector, type?)`
46
+ - `CotomyElement.find(selector, type?)`
47
+ - `CotomyElement.contains(selector)` / `CotomyElement.containsById(id)`
48
+ - `CotomyElement.byId(id, type?)`
49
+ - `CotomyElement.empty(type?)` — Creates a hidden placeholder element
50
+ - Identity & matching
51
+ - `id: string | null | undefined`
52
+ - `generateId(prefix = "__cotomy_elem__"): this`
53
+ - `is(selector: string): boolean` — Parent-aware matching helper
54
+ - `empty: boolean` — True for tags that cannot have children or have no content
55
+ - Attributes, classes, styles
56
+ - `attribute(name)` / `attribute(name, value | null): this`
57
+ - `hasAttribute(name): boolean`
58
+ - `addClass(name): this` / `removeClass(name): this` / `toggleClass(name, force?): this` / `hasClass(name): boolean`
59
+ - `style(name)` / `style(name, value | null): this`
60
+ - Content & value
61
+ - `text: string` (get/set)
62
+ - `html: string` (get/set)
63
+ - `value: string` — Works for inputs; falls back to `data-cotomy-value` otherwise
64
+ - `readonly: boolean` (get/set) — Uses native property if available, otherwise attribute
65
+ - `enabled: boolean` (get/set) — Toggles `disabled` attribute
66
+ - `setFocus(): void`
67
+ - Tree traversal & manipulation
68
+ - `parent: CotomyElement`
69
+ - `parents: CotomyElement[]`
70
+ - `children(selector = "*", type?): T[]` (direct children only)
71
+ - `firstChild(selector = "*", type?)`
72
+ - `lastChild(selector = "*", type?)`
73
+ - `closest(selector, type?)`
74
+ - `find(selector, type?)` / `first(selector = "*", type?)` / `contains(selector)`
75
+ - `append(child): this` / `prepend(child): this` / `appendAll(children): this`
76
+ - `insertBefore(sibling): this` / `insertAfter(sibling): this`
77
+ - `appendTo(target): this` / `prependTo(target): this`
78
+ - `clear(): this` — Removes all descendants and text
79
+ - `remove(): void`
80
+ - Geometry & visibility
81
+ - `visible: boolean`
82
+ - `width: number` (get/set px)
83
+ - `height: number` (get/set px)
84
+ - `innerWidth: number` / `innerHeight: number`
85
+ - `outerWidth: number` / `outerHeight: number` — Includes margins
86
+ - `scrollWidth: number` / `scrollHeight: number` / `scrollTop: number`
87
+ - `position(): { top, left }` — Relative to viewport
88
+ - `absolutePosition(): { top, left }` — Viewport + page scroll offset
89
+ - `screenPosition(): { top, left }`
90
+ - `rect(): { top, left, width, height }`
91
+ - `innerRect()` — Subtracts padding
92
+ - Events
93
+ - Generic: `on(event, handler, options?)`, `off(event, handler?, options?)`, `once(event, handler, options?)`, `trigger(event[, Event])`
94
+ - Delegation: `onChild(event, selector, handler, options?)`
95
+ - Mouse: `click`, `dblclick`, `mouseover`, `mouseout`, `mousedown`, `mouseup`, `mousemove`, `mouseenter`, `mouseleave`
96
+ - Keyboard: `keydown`, `keyup`, `keypress`
97
+ - Inputs: `change`, `input`
98
+ - Focus: `focus`, `blur`, `focusin`, `focusout`
99
+ - Viewport: `inview`, `outview` (uses `IntersectionObserver`)
100
+ - Layout (custom): `resize`, `scroll`, `changelayout` — requires `listenLayoutEvents()` on the element
101
+ - File: `filedrop(handler: (files: File[]) => void)`
11
102
 
12
- To install Cotomy in your project, run the following command:
103
+ Example (scoped CSS and events):
13
104
 
14
- ```bash
15
- npm i cotomy
105
+ ```ts
106
+ import { CotomyElement } from "cotomy";
107
+
108
+ const panel = new CotomyElement({
109
+ html: `<div class="panel"><button class="ok">OK</button></div>`,
110
+ css: `
111
+ [scope] .panel { padding: 8px; }
112
+ [scope] .ok { color: green; }
113
+ `,
114
+ });
115
+
116
+ panel.onChild("click", ".ok", () => console.log("clicked!"));
117
+ document.body.appendChild(panel.element);
16
118
  ```
17
119
 
18
- ## Usage
120
+ ### CotomyMetaElement
19
121
 
20
- Cotomy will continue to expand with more detailed usage instructions and code examples added to the README in the future.
21
- For the latest updates, please check the official documentation or repository regularly.
122
+ - `CotomyMetaElement.get(name): CotomyMetaElement`
123
+ - `content: string` Reads `content` attribute.
22
124
 
23
- ### Entity API forms
125
+ ### CotomyWindow
126
+
127
+ - Singleton
128
+ - `CotomyWindow.instance`
129
+ - `initialized: boolean` — Call `initialize()` once after DOM is ready
130
+ - `initialize(): void`
131
+ - DOM helpers
132
+ - `body: CotomyElement`
133
+ - `append(element: CotomyElement)`
134
+ - `moveNext(focused: CotomyElement, shift = false)` — Move focus to next/previous focusable
135
+ - Window events
136
+ - `on(event, handler)` / `off(event, handler?)` / `trigger(event)`
137
+ - `load(handler)` / `ready(handler)`
138
+ - `resize([handler])` / `scroll([handler])` / `changeLayout([handler])` / `pageshow([handler])`
139
+ - Window state
140
+ - `scrollTop`, `scrollLeft`, `width`, `height`, `documentWidth`, `documentHeight`
141
+ - `reload(): void` (sets internal `reloading` flag), `reloading: boolean`
142
+
143
+ Quick start:
144
+
145
+ ```ts
146
+ import { CotomyWindow, CotomyElement } from "cotomy";
24
147
 
25
- `CotomyEntityApiForm` targets REST endpoints that identify records with a single surrogate key.
26
- Attach `data-cotomy-entity-key="<id>"` to the form when editing an existing entity; omit the attribute (or leave it empty) to issue a `POST` to the base `action` URL.
27
- On `201 Created`, the form reads the `Location` header and stores the generated key back into `data-cotomy-entity-key`, enabling subsequent `PUT` submissions.
28
- Composite or natural keys are no longer supported—migrate any legacy markup that relied on `data-cotomy-keyindex` or multiple key inputs to the new surrogate-key flow.
29
- When you must integrate with endpoints that still expect natural identifiers, subclass `CotomyEntityApiForm`/`CotomyEntityFillApiForm`, override `canLoad()` to supply your own load condition, and adjust `loadActionUrl()` (plus any submission hooks) to build the appropriate URL fragments.
30
-
31
- The core of Cotomy is `CotomyElement`, which is constructed as a wrapper for `Element`.
32
- By passing HTML and CSS strings to the constructor, it is possible to generate Element designs with a limited scope.
33
-
34
- ```typescript
35
- const ce = new CotomyElement({
36
- html: /* html */`
37
- <div>
38
- <p>Text</p>
39
- </div>
40
- `,
41
- css: /* css */`
42
- [scope] {
43
- display: block;
44
- }
45
- [scope] > p {
46
- text-align: center;
47
- }
48
- `
49
- });
148
+ CotomyWindow.instance.initialize();
149
+ CotomyWindow.instance.ready(() => {
150
+ const el = new CotomyElement("<div>Hello</div>");
151
+ CotomyWindow.instance.append(el);
152
+ });
50
153
  ```
51
154
 
52
- - `"display HTML in character literals with color coding"` → `"syntax highlighting for embedded HTML"`
53
- - `"generate Element designs with a limited scope"` → `"generate scoped DOM elements with associated styles"`
155
+ ## Form Reference
54
156
 
55
- ## Development
157
+ The Form layer builds on `CotomyElement` for common form flows.
56
158
 
57
- Cotomy ships with both ESM (`dist/esm`) and CommonJS (`dist/cjs`) builds, plus generated type definitions in `dist/types`.
58
- For direct `<script>` usage, browser-ready bundles are available at `dist/browser/cotomy.js` and `dist/browser/cotomy.min.js` (also served via the npm `unpkg` entry).
59
- Include the minified build like so:
159
+ - `CotomyForm` Base class with submit lifecycle hooks
160
+ - `CotomyQueryForm` Submits to query string (GET)
161
+ - `CotomyApiForm` Submits via `CotomyApi` (handles `FormData`, errors, events)
162
+ - `CotomyEntityApiForm` — REST entity helper with surrogate key support
163
+ - `CotomyEntityFillApiForm` — Adds automatic field filling and simple view binding
60
164
 
61
- ```html
62
- <script src="https://unpkg.com/cotomy/dist/browser/cotomy.min.js"></script>
63
- <script>
64
- const el = new Cotomy.CotomyElement("<div>Hello</div>");
65
- document.body.appendChild(el.element);
66
- </script>
67
- ```
165
+ ### CotomyForm (base)
68
166
 
69
- Run the build to refresh every target bundle:
167
+ - Construction & basics
168
+ - Extends `CotomyElement` and expects a `<form>` element
169
+ - `initialize(): this` — Wires a `submit` listener that calls `submitAsync()`
170
+ - `initialized: boolean` — Set after `initialize()`
171
+ - `submitAsync(): Promise<void>` — Abstract in base
172
+ - Routing & reload
173
+ - `method(): string` — Defaults to `get` in base; specialized in subclasses
174
+ - `actionUrl(): string` — Defaults to `action` attribute or current path
175
+ - `reloadAsync(): Promise<void>` — Page reload using `CotomyWindow`
176
+ - `autoReload: boolean` — Backed by `data-cotomy-autoreload` (default true)
70
177
 
71
- ```bash
72
- npm install
73
- npm run build
74
- ```
178
+ ### CotomyQueryForm
75
179
 
76
- The Vitest-based test suite can be executed via:
180
+ - Always uses `GET`
181
+ - `submitAsync()` merges current query string with form inputs and navigates via `location.href`.
77
182
 
78
- ```bash
79
- npx vitest run
80
- ```
183
+ ### CotomyApiForm
184
+
185
+ - API integration
186
+ - `apiClient(): CotomyApi` — Override to inject a client; default creates a new one
187
+ - `actionUrl(): string` — Uses `action` attribute
188
+ - `method(): string` — Defaults to `post`
189
+ - `formData(): FormData` — Builds from form, converts `datetime-local` to ISO (UTC offset)
190
+ - `submitAsync()` — Calls `submitToApiAsync(formData)`
191
+ - `submitToApiAsync(formData): Promise<CotomyApiResponse>` — Uses `CotomyApi.submitAsync`
192
+ - Events
193
+ - `apiFailed(handler)` — Listens to `cotomy:apifailed`
194
+ - `submitFailed(handler)` — Listens to `cotomy:submitfailed`
195
+ - Both events bubble from the form element; payload is `CotomyApiFailedEvent`
196
+
197
+ ### CotomyEntityApiForm
81
198
 
82
- ## License
199
+ - Surrogate key flow
200
+ - `data-cotomy-entity-key` — Holds the entity identifier if present
201
+ - `data-cotomy-identify` — Defaults to true; when true and `201 Created` is returned, the form extracts the key from `Location` and stores it in `data-cotomy-entity-key`
202
+ - `actionUrl()` — Appends the key to the base `action` when present; otherwise normalizes trailing slash for collection URL
203
+ - `method()` — `put` when key exists; otherwise `post` (unless `method` attribute is explicitly set)
83
204
 
84
- This project is licensed under the [MIT License](LICENSE).
205
+ ### CotomyEntityFillApiForm
85
206
 
86
- ## Contact
207
+ - Data loading and field filling
208
+ - `initialize()` — Adds default fillers and triggers `loadAsync()` on `CotomyWindow.ready`
209
+ - `reloadAsync()` — Alias to `loadAsync()`
210
+ - `loadAsync(): Promise<CotomyApiResponse>` — Calls `CotomyApi.getAsync` when `canLoad()` is true
211
+ - `loadActionUrl(): string` — Defaults to `actionUrl()`; override for custom endpoints
212
+ - `canLoad(): boolean` — Defaults to `hasEntityKey`
213
+ - Naming & binding
214
+ - `bindNameGenerator(): ICotomyBindNameGenerator` — Defaults to `CotomyBracketBindNameGenerator` (`user[name]`)
215
+ - `renderer(): CotomyViewRenderer` — Applies `[data-cotomy-bind]` to view elements
216
+ - `filler(type, (input, value))` — Register fillers; defaults provided for `datetime-local`, `checkbox`, `radio`
217
+ - Fills non-array, non-object fields by matching input/select/textarea `name`
87
218
 
88
- You can reach out to me at: [yshr1920@gmail.com](mailto:yshr1920@gmail.com)
89
- GitHub repository: [https://github.com/yshr1920/cotomy](https://github.com/yshr1920/cotomy)
219
+ Example:
220
+
221
+ ```ts
222
+ import { CotomyEntityFillApiForm } from "cotomy";
223
+
224
+ const form = new CotomyEntityFillApiForm(document.querySelector("form")!);
225
+ form.initialize();
226
+ form.apiFailed(e => console.error("API failed", e.response.status));
227
+ form.submitFailed(e => console.warn("Submit failed", e.response.status));
228
+ ```
229
+
230
+ ### Entity API forms
231
+
232
+ `CotomyEntityApiForm` targets REST endpoints that identify records with a single surrogate key.
233
+ Attach `data-cotomy-entity-key="<id>"` to the form when editing an existing entity; omit the attribute (or leave it empty) to issue a `POST` to the base `action` URL.
234
+ On `201 Created`, the form reads the `Location` header and stores the generated key back into `data-cotomy-entity-key`, enabling subsequent `PUT` submissions.
235
+ Composite or natural keys are no longer supported—migrate any legacy markup that relied on `data-cotomy-keyindex` or multiple key inputs to the new surrogate-key flow.
236
+ When you must integrate with endpoints that still expect natural identifiers, subclass `CotomyEntityApiForm`/`CotomyEntityFillApiForm`, override `canLoad()` to supply your own load condition, and adjust `loadActionUrl()` (plus any submission hooks) to build the appropriate URL fragments.
237
+
238
+ The core of Cotomy is `CotomyElement`, which is constructed as a wrapper for `Element`.
239
+ By passing HTML and CSS strings to the constructor, it is possible to generate Element designs with a limited scope.
240
+
241
+ ```typescript
242
+ const ce = new CotomyElement({
243
+ html: /* html */`
244
+ <div>
245
+ <p>Text</p>
246
+ </div>
247
+ `,
248
+ css: /* css */`
249
+ [scope] {
250
+ display: block;
251
+ }
252
+ [scope] > p {
253
+ text-align: center;
254
+ }
255
+ `
256
+ });
257
+ ```
258
+
259
+ - `"display HTML in character literals with color coding"` → `"syntax highlighting for embedded HTML"`
260
+ - `"generate Element designs with a limited scope"` → `"generate scoped DOM elements with associated styles"`
261
+
262
+ ## Development
263
+
264
+ Cotomy ships with both ESM (`dist/esm`) and CommonJS (`dist/cjs`) builds, plus generated type definitions in `dist/types`.
265
+ For direct `<script>` usage, browser-ready bundles are available at `dist/browser/cotomy.js` and `dist/browser/cotomy.min.js` (also served via the npm `unpkg` entry).
266
+ Include the minified build like so:
267
+
268
+ ```html
269
+ <script src="https://unpkg.com/cotomy/dist/browser/cotomy.min.js"></script>
270
+ <script>
271
+ const el = new Cotomy.CotomyElement("<div>Hello</div>");
272
+ document.body.appendChild(el.element);
273
+ </script>
274
+ ```
275
+
276
+ Run the build to refresh every target bundle:
277
+
278
+ ```bash
279
+ npm install
280
+ npm run build
281
+ ```
282
+
283
+ The Vitest-based test suite can be executed via:
284
+
285
+ ```bash
286
+ npx vitest run
287
+ ```
288
+
289
+ ## License
290
+
291
+ This project is licensed under the [MIT License](LICENSE).
292
+
293
+ ## Contact
294
+
295
+ You can reach out to me at: [yshr1920@gmail.com](mailto:yshr1920@gmail.com)
296
+ GitHub repository: [https://github.com/yshr1920/cotomy](https://github.com/yshr1920/cotomy)
@@ -174,7 +174,7 @@ module.exports = cuid;
174
174
  /***/ 826:
175
175
  /***/ (function(module) {
176
176
 
177
- !function(t,i){ true?module.exports=i():0}(this,(function(){"use strict";var t="minute",i=/[+-]\d\d(?::?\d\d)?/g,e=/([+-]|\d\d)/g;return function(s,f,n){var u=f.prototype;n.utc=function(t){var i={date:t,utc:!0,args:arguments};return new f(i)},u.utc=function(i){var e=n(this.toDate(),{locale:this.$L,utc:!0});return i?e.add(this.utcOffset(),t):e},u.local=function(){return n(this.toDate(),{locale:this.$L,utc:!1})};var o=u.parse;u.parse=function(t){t.utc&&(this.$u=!0),this.$utils().u(t.$offset)||(this.$offset=t.$offset),o.call(this,t)};var r=u.init;u.init=function(){if(this.$u){var t=this.$d;this.$y=t.getUTCFullYear(),this.$M=t.getUTCMonth(),this.$D=t.getUTCDate(),this.$W=t.getUTCDay(),this.$H=t.getUTCHours(),this.$m=t.getUTCMinutes(),this.$s=t.getUTCSeconds(),this.$ms=t.getUTCMilliseconds()}else r.call(this)};var a=u.utcOffset;u.utcOffset=function(s,f){var n=this.$utils().u;if(n(s))return this.$u?0:n(this.$offset)?a.call(this):this.$offset;if("string"==typeof s&&(s=function(t){void 0===t&&(t="");var s=t.match(i);if(!s)return null;var f=(""+s[0]).match(e)||["-",0,0],n=f[0],u=60*+f[1]+ +f[2];return 0===u?0:"+"===n?u:-u}(s),null===s))return this;var u=Math.abs(s)<=16?60*s:s,o=this;if(f)return o.$offset=u,o.$u=0===s,o;if(0!==s){var r=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();(o=this.local().add(u+r,t)).$offset=u,o.$x.$localOffset=r}else o=this.utc();return o};var h=u.format;u.format=function(t){var i=t||(this.$u?"YYYY-MM-DDTHH:mm:ss[Z]":"");return h.call(this,i)},u.valueOf=function(){var t=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*t},u.isUTC=function(){return!!this.$u},u.toISOString=function(){return this.toDate().toISOString()},u.toString=function(){return this.toDate().toUTCString()};var l=u.toDate;u.toDate=function(t){return"s"===t&&this.$offset?n(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate():l.call(this)};var c=u.diff;u.diff=function(t,i,e){if(t&&this.$u===t.$u)return c.call(this,t,i,e);var s=this.local(),f=n(t).local();return c.call(s,f,i,e)}}}));
177
+ !function(t,i){ true?module.exports=i():0}(this,(function(){"use strict";var t="minute",i=/[+-]\d\d(?::?\d\d)?/g,e=/([+-]|\d\d)/g;return function(s,f,n){var u=f.prototype;n.utc=function(t){var i={date:t,utc:!0,args:arguments};return new f(i)},u.utc=function(i){var e=n(this.toDate(),{locale:this.$L,utc:!0});return i?e.add(this.utcOffset(),t):e},u.local=function(){return n(this.toDate(),{locale:this.$L,utc:!1})};var r=u.parse;u.parse=function(t){t.utc&&(this.$u=!0),this.$utils().u(t.$offset)||(this.$offset=t.$offset),r.call(this,t)};var o=u.init;u.init=function(){if(this.$u){var t=this.$d;this.$y=t.getUTCFullYear(),this.$M=t.getUTCMonth(),this.$D=t.getUTCDate(),this.$W=t.getUTCDay(),this.$H=t.getUTCHours(),this.$m=t.getUTCMinutes(),this.$s=t.getUTCSeconds(),this.$ms=t.getUTCMilliseconds()}else o.call(this)};var a=u.utcOffset;u.utcOffset=function(s,f){var n=this.$utils().u;if(n(s))return this.$u?0:n(this.$offset)?a.call(this):this.$offset;if("string"==typeof s&&(s=function(t){void 0===t&&(t="");var s=t.match(i);if(!s)return null;var f=(""+s[0]).match(e)||["-",0,0],n=f[0],u=60*+f[1]+ +f[2];return 0===u?0:"+"===n?u:-u}(s),null===s))return this;var u=Math.abs(s)<=16?60*s:s;if(0===u)return this.utc(f);var r=this.clone();if(f)return r.$offset=u,r.$u=!1,r;var o=this.$u?this.toDate().getTimezoneOffset():-1*this.utcOffset();return(r=this.local().add(u+o,t)).$offset=u,r.$x.$localOffset=o,r};var h=u.format;u.format=function(t){var i=t||(this.$u?"YYYY-MM-DDTHH:mm:ss[Z]":"");return h.call(this,i)},u.valueOf=function(){var t=this.$utils().u(this.$offset)?0:this.$offset+(this.$x.$localOffset||this.$d.getTimezoneOffset());return this.$d.valueOf()-6e4*t},u.isUTC=function(){return!!this.$u},u.toISOString=function(){return this.toDate().toISOString()},u.toString=function(){return this.toDate().toUTCString()};var l=u.toDate;u.toDate=function(t){return"s"===t&&this.$offset?n(this.format("YYYY-MM-DD HH:mm:ss:SSS")).toDate():l.call(this)};var c=u.diff;u.diff=function(t,i,e){if(t&&this.$u===t.$u)return c.call(this,t,i,e);var s=this.local(),f=n(t).local();return c.call(s,f,i,e)}}}));
178
178
 
179
179
  /***/ })
180
180
 
@@ -2583,7 +2583,7 @@ class CotomyEntityApiForm extends CotomyApiForm {
2583
2583
  this.attribute("data-cotomy-entity-key", addedParts[0]);
2584
2584
  }
2585
2585
  else {
2586
- const msg = `Location does not contain a single entity key segment.
2586
+ const msg = `Location does not contain a single entity key segment.
2587
2587
  action="${baseAction}", location="${locPath}", added=["${addedParts.join('","')}"]`;
2588
2588
  throw new Error(msg);
2589
2589
  }
@@ -2637,13 +2637,6 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
2637
2637
  }
2638
2638
  return this;
2639
2639
  }
2640
- async submitToApiAsync(formData) {
2641
- const response = await super.submitToApiAsync(formData);
2642
- if (response.ok) {
2643
- await this.fillAsync(response);
2644
- }
2645
- return response;
2646
- }
2647
2640
  async reloadAsync() {
2648
2641
  await this.loadAsync();
2649
2642
  }
@@ -2691,8 +2684,8 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
2691
2684
  await this.fillObjectAsync(bindNameGenerator, value, pname);
2692
2685
  continue;
2693
2686
  }
2694
- this.find(`input[name="${pname}" i]:not([data-cotomy-fill="false"]):not([multiple]),
2695
- textarea[name="${pname}" i]:not([data-cotomy-fill="false"]),
2687
+ this.find(`input[name="${pname}" i]:not([data-cotomy-fill="false"]):not([multiple]),
2688
+ textarea[name="${pname}" i]:not([data-cotomy-fill="false"]),
2696
2689
  select[name="${pname}" i]:not([data-cotomy-fill="false"]):not([multiple])`).forEach(input => {
2697
2690
  if (CotomyDebugSettings.isEnabled(CotomyDebugFeature.Fill)) {
2698
2691
  console.debug(`Filling input[name="${pname}"] with value:`, value);
@@ -2714,6 +2707,13 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
2714
2707
  }
2715
2708
  this.find("textarea").forEach(e => e.input());
2716
2709
  }
2710
+ async submitToApiAsync(formData) {
2711
+ const response = await super.submitToApiAsync(formData);
2712
+ if (response.ok) {
2713
+ await this.fillAsync(response);
2714
+ }
2715
+ return response;
2716
+ }
2717
2717
  }
2718
2718
 
2719
2719
  // EXTERNAL MODULE: ./node_modules/dayjs/plugin/timezone.js