cotomy 1.0.3 → 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/README.md +29 -5
- package/dist/browser/cotomy.js +50 -23
- package/dist/browser/cotomy.js.map +1 -1
- package/dist/browser/cotomy.min.js +1 -1
- package/dist/browser/cotomy.min.js.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/api.js +36 -16
- package/dist/esm/api.js.map +1 -1
- package/dist/esm/form.js +2 -2
- package/dist/esm/form.js.map +1 -1
- package/dist/esm/page.js +7 -0
- package/dist/esm/page.js.map +1 -1
- package/dist/types/api.d.ts +6 -3
- package/dist/types/page.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -243,7 +243,7 @@ The Form layer builds on `CotomyElement` for common form flows.
|
|
|
243
243
|
- `loadActionUrl: string` — Defaults to `actionUrl`; override or set for custom endpoints
|
|
244
244
|
- `canLoad: boolean` — Defaults to `hasEntityKey`
|
|
245
245
|
- Naming & binding
|
|
246
|
-
- `bindNameGenerator(): ICotomyBindNameGenerator` — Defaults to `
|
|
246
|
+
- `bindNameGenerator(): ICotomyBindNameGenerator` — Defaults to `CotomyViewRenderer.defaultBindNameGenerator` (initial value: `CotomyBracketBindNameGenerator`, `user[name]`)
|
|
247
247
|
- `renderer(): CotomyViewRenderer` — Applies `[data-cotomy-bind]` to view elements
|
|
248
248
|
- `filler(type, (input, value))` — Register fillers; defaults provided for `datetime-local`, `checkbox`, `radio`
|
|
249
249
|
- Fills non-array, non-object fields by matching input/select/textarea `name`
|
|
@@ -255,15 +255,21 @@ The Form layer builds on `CotomyElement` for common form flows.
|
|
|
255
255
|
- `mail`, `tel`, `url` — Wrap the value in a corresponding anchor tag.
|
|
256
256
|
- `number` — Uses `Intl.NumberFormat` with `data-cotomy-locale`/`data-cotomy-currency` inheritance.
|
|
257
257
|
- `data-cotomy-fraction-digits="2"` — Forces fixed fraction digits (sets both `minimumFractionDigits` and `maximumFractionDigits`). Works with or without `data-cotomy-currency` (e.g. `0` → `0.00`).
|
|
258
|
-
- `utc` — Treats the value as UTC (or appends `Z` when missing) and formats with `data-cotomy-format` (default `YYYY/MM/DD HH:mm`).
|
|
259
|
-
- `date` — Renders local dates with `data-cotomy-format` (default `YYYY/MM/DD`) when the input is a valid `Date` value.
|
|
258
|
+
- `utc` — Treats the value as UTC (or appends `Z` when missing) and formats with `data-cotomy-format` (default `YYYY/MM/DD HH:mm`). By default it renders in local time; set `data-cotomy-timezone` (element or ancestor) to render in a specific IANA timezone.
|
|
259
|
+
- `date` — Renders local dates with `data-cotomy-format` (default `YYYY/MM/DD`) when the input is a valid `Date` value. By default it renders in local time; set `data-cotomy-timezone` (element or ancestor) to render in a specific IANA timezone.
|
|
260
|
+
|
|
261
|
+
### UTC Renderer
|
|
262
|
+
|
|
263
|
+
- Supports ISO 8601 offsets (`+09:00`, `-05:00`)
|
|
264
|
+
- Explicitly supports `Z` (UTC indicator)
|
|
265
|
+
- Offset-less timestamps are treated as UTC (internally appends "Z" before parsing)
|
|
266
|
+
- `data-cotomy-timezone` is optional. When omitted, output stays local; when set, output is converted to the specified IANA timezone (supports ancestor inheritance).
|
|
260
267
|
|
|
261
268
|
Example:
|
|
262
269
|
|
|
263
270
|
```ts
|
|
264
271
|
const view = new CotomyViewRenderer(
|
|
265
|
-
new CotomyElement(document.querySelector("#profile")!)
|
|
266
|
-
new CotomyBracketBindNameGenerator()
|
|
272
|
+
new CotomyElement(document.querySelector("#profile")!)
|
|
267
273
|
);
|
|
268
274
|
|
|
269
275
|
await view.applyAsync(apiResponse); // apiResponse is CotomyApiResponse from CotomyApi
|
|
@@ -289,6 +295,24 @@ form.apiFailed(e => console.error("API failed", e.response.status));
|
|
|
289
295
|
form.submitFailed(e => console.warn("Submit failed", e.response.status));
|
|
290
296
|
```
|
|
291
297
|
|
|
298
|
+
To switch the default bind naming style for a page, set it from your page controller:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
import {
|
|
302
|
+
CotomyDotBindNameGenerator,
|
|
303
|
+
CotomyEntityFillApiForm,
|
|
304
|
+
CotomyPageController
|
|
305
|
+
} from "cotomy";
|
|
306
|
+
|
|
307
|
+
CotomyPageController.set(class extends CotomyPageController {
|
|
308
|
+
protected override async initializeAsync(): Promise<void> {
|
|
309
|
+
this.defaultBindNameGenerator = new CotomyDotBindNameGenerator();
|
|
310
|
+
|
|
311
|
+
this.setForm(CotomyEntityFillApiForm.byId("profile-form", CotomyEntityFillApiForm)!);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
```
|
|
315
|
+
|
|
292
316
|
### Entity API forms
|
|
293
317
|
|
|
294
318
|
`CotomyEntityApiForm` targets REST endpoints that identify records with a single surrogate key.
|
package/dist/browser/cotomy.js
CHANGED
|
@@ -289,6 +289,12 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
289
289
|
// EXTERNAL MODULE: ./node_modules/dayjs/dayjs.min.js
|
|
290
290
|
var dayjs_min = __webpack_require__(353);
|
|
291
291
|
var dayjs_min_default = /*#__PURE__*/__webpack_require__.n(dayjs_min);
|
|
292
|
+
// EXTERNAL MODULE: ./node_modules/dayjs/plugin/timezone.js
|
|
293
|
+
var timezone = __webpack_require__(569);
|
|
294
|
+
var timezone_default = /*#__PURE__*/__webpack_require__.n(timezone);
|
|
295
|
+
// EXTERNAL MODULE: ./node_modules/dayjs/plugin/utc.js
|
|
296
|
+
var utc = __webpack_require__(826);
|
|
297
|
+
var utc_default = /*#__PURE__*/__webpack_require__.n(utc);
|
|
292
298
|
;// ./node_modules/http-status-codes/build/es/status-codes.js
|
|
293
299
|
// Generated file. Do not edit
|
|
294
300
|
var StatusCodes;
|
|
@@ -2257,6 +2263,10 @@ CotomyWindow._instance = null;
|
|
|
2257
2263
|
|
|
2258
2264
|
|
|
2259
2265
|
|
|
2266
|
+
|
|
2267
|
+
|
|
2268
|
+
dayjs_min_default().extend((utc_default()));
|
|
2269
|
+
dayjs_min_default().extend((timezone_default()));
|
|
2260
2270
|
class CotomyApiException extends Error {
|
|
2261
2271
|
constructor(status, message, response, bodyText = "") {
|
|
2262
2272
|
super(message);
|
|
@@ -2452,19 +2462,20 @@ class CotomyDotBindNameGenerator {
|
|
|
2452
2462
|
}
|
|
2453
2463
|
}
|
|
2454
2464
|
class CotomyViewRenderer {
|
|
2455
|
-
|
|
2465
|
+
static get defaultBindNameGenerator() {
|
|
2466
|
+
return this._defaultBindNameGenerator ?? new CotomyBracketBindNameGenerator();
|
|
2467
|
+
}
|
|
2468
|
+
static set defaultBindNameGenerator(generator) {
|
|
2469
|
+
this._defaultBindNameGenerator = generator;
|
|
2470
|
+
}
|
|
2471
|
+
static resetDefaultBindNameGenerator() {
|
|
2472
|
+
this._defaultBindNameGenerator = null;
|
|
2473
|
+
}
|
|
2474
|
+
constructor(element, bindNameGenerator = CotomyViewRenderer.defaultBindNameGenerator) {
|
|
2456
2475
|
this.element = element;
|
|
2457
2476
|
this.bindNameGenerator = bindNameGenerator;
|
|
2458
2477
|
this._renderers = {};
|
|
2459
|
-
this.
|
|
2460
|
-
}
|
|
2461
|
-
get locale() {
|
|
2462
|
-
const languages = (navigator.languages && navigator.languages.length ? navigator.languages : [navigator.language]).filter(Boolean);
|
|
2463
|
-
let locale = this.element.attribute("data-cotomy-locale")
|
|
2464
|
-
|| this.element.closest("[data-cotomy-locale]")?.attribute("data-cotomy-locale")
|
|
2465
|
-
|| languages[0]
|
|
2466
|
-
|| 'en-US';
|
|
2467
|
-
return locale.includes("-") ? locale.split("-")[0] : locale;
|
|
2478
|
+
this._initialized = false;
|
|
2468
2479
|
}
|
|
2469
2480
|
renderer(type, callback) {
|
|
2470
2481
|
this._renderers[type] = callback;
|
|
@@ -2475,7 +2486,7 @@ class CotomyViewRenderer {
|
|
|
2475
2486
|
return this._renderers;
|
|
2476
2487
|
}
|
|
2477
2488
|
get initialized() {
|
|
2478
|
-
return this.
|
|
2489
|
+
return this._initialized;
|
|
2479
2490
|
}
|
|
2480
2491
|
initialize() {
|
|
2481
2492
|
if (!this.initialized) {
|
|
@@ -2507,16 +2518,27 @@ class CotomyViewRenderer {
|
|
|
2507
2518
|
...(currency ? { style: "currency", currency } : {}),
|
|
2508
2519
|
...(hasFractionDigits ? { minimumFractionDigits: fractionDigits, maximumFractionDigits: fractionDigits } : {}),
|
|
2509
2520
|
};
|
|
2510
|
-
|
|
2521
|
+
const languages = (navigator.languages && navigator.languages.length ? navigator.languages : [navigator.language]).filter(Boolean);
|
|
2522
|
+
const localeAttribute = element.attribute("data-cotomy-locale")
|
|
2523
|
+
|| element.closest("[data-cotomy-locale]")?.attribute("data-cotomy-locale")
|
|
2524
|
+
|| this.element.attribute("data-cotomy-locale")
|
|
2525
|
+
|| this.element.closest("[data-cotomy-locale]")?.attribute("data-cotomy-locale")
|
|
2526
|
+
|| languages[0]
|
|
2527
|
+
|| "en-US";
|
|
2528
|
+
const locale = localeAttribute.includes("-") ? localeAttribute.split("-")[0] : localeAttribute;
|
|
2529
|
+
element.text = new Intl.NumberFormat(locale, options).format(value);
|
|
2511
2530
|
}
|
|
2512
2531
|
});
|
|
2513
2532
|
this.renderer("utc", (element, value) => {
|
|
2514
2533
|
if (value) {
|
|
2515
|
-
const hasOffset = /[+-]\d{2}:\d{2}$/.test(value);
|
|
2534
|
+
const hasOffset = /([+-]\d{2}:\d{2}|Z)$/.test(value);
|
|
2516
2535
|
const date = hasOffset ? new Date(value) : new Date(`${value}Z`);
|
|
2517
2536
|
if (!isNaN(date.getTime())) {
|
|
2518
2537
|
const format = element.attribute("data-cotomy-format") ?? "YYYY/MM/DD HH:mm";
|
|
2519
|
-
|
|
2538
|
+
const timezone = element.attribute("data-cotomy-timezone")
|
|
2539
|
+
|| element.closest("[data-cotomy-timezone]")?.attribute("data-cotomy-timezone");
|
|
2540
|
+
const dt = dayjs_min_default()(date);
|
|
2541
|
+
element.text = timezone && timezone.trim() !== "" ? dt.tz(timezone).format(format) : dt.format(format);
|
|
2520
2542
|
}
|
|
2521
2543
|
}
|
|
2522
2544
|
});
|
|
@@ -2525,11 +2547,14 @@ class CotomyViewRenderer {
|
|
|
2525
2547
|
const date = new Date(value);
|
|
2526
2548
|
if (!isNaN(date.getTime())) {
|
|
2527
2549
|
const format = element.attribute("data-cotomy-format") ?? "YYYY/MM/DD";
|
|
2528
|
-
|
|
2550
|
+
const timezone = element.attribute("data-cotomy-timezone")
|
|
2551
|
+
|| element.closest("[data-cotomy-timezone]")?.attribute("data-cotomy-timezone");
|
|
2552
|
+
const dt = dayjs_min_default()(date);
|
|
2553
|
+
element.text = timezone && timezone.trim() !== "" ? dt.tz(timezone).format(format) : dt.format(format);
|
|
2529
2554
|
}
|
|
2530
2555
|
}
|
|
2531
2556
|
});
|
|
2532
|
-
this.
|
|
2557
|
+
this._initialized = true;
|
|
2533
2558
|
}
|
|
2534
2559
|
return this;
|
|
2535
2560
|
}
|
|
@@ -2587,6 +2612,7 @@ class CotomyViewRenderer {
|
|
|
2587
2612
|
return this;
|
|
2588
2613
|
}
|
|
2589
2614
|
}
|
|
2615
|
+
CotomyViewRenderer._defaultBindNameGenerator = null;
|
|
2590
2616
|
class CotomyApi {
|
|
2591
2617
|
constructor(_options = {
|
|
2592
2618
|
baseUrl: null, headers: null, credentials: null, redirect: null,
|
|
@@ -3048,7 +3074,7 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
|
|
|
3048
3074
|
return this.actionUrl;
|
|
3049
3075
|
}
|
|
3050
3076
|
bindNameGenerator() {
|
|
3051
|
-
return
|
|
3077
|
+
return CotomyViewRenderer.defaultBindNameGenerator;
|
|
3052
3078
|
}
|
|
3053
3079
|
renderer() {
|
|
3054
3080
|
return new CotomyViewRenderer(this, this.bindNameGenerator());
|
|
@@ -3140,18 +3166,13 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
|
|
|
3140
3166
|
}
|
|
3141
3167
|
}
|
|
3142
3168
|
|
|
3143
|
-
// EXTERNAL MODULE: ./node_modules/dayjs/plugin/timezone.js
|
|
3144
|
-
var timezone = __webpack_require__(569);
|
|
3145
|
-
var timezone_default = /*#__PURE__*/__webpack_require__.n(timezone);
|
|
3146
|
-
// EXTERNAL MODULE: ./node_modules/dayjs/plugin/utc.js
|
|
3147
|
-
var utc = __webpack_require__(826);
|
|
3148
|
-
var utc_default = /*#__PURE__*/__webpack_require__.n(utc);
|
|
3149
3169
|
;// ./src/page.ts
|
|
3150
3170
|
|
|
3151
3171
|
|
|
3152
3172
|
|
|
3153
3173
|
|
|
3154
3174
|
|
|
3175
|
+
|
|
3155
3176
|
dayjs_min_default().extend((utc_default()));
|
|
3156
3177
|
dayjs_min_default().extend((timezone_default()));
|
|
3157
3178
|
class CotomyUrl {
|
|
@@ -3213,6 +3234,12 @@ class CotomyPageController {
|
|
|
3213
3234
|
}
|
|
3214
3235
|
return this._instance;
|
|
3215
3236
|
}
|
|
3237
|
+
get defaultBindNameGenerator() {
|
|
3238
|
+
return CotomyViewRenderer.defaultBindNameGenerator;
|
|
3239
|
+
}
|
|
3240
|
+
set defaultBindNameGenerator(value) {
|
|
3241
|
+
CotomyViewRenderer.defaultBindNameGenerator = value;
|
|
3242
|
+
}
|
|
3216
3243
|
setForm(form) {
|
|
3217
3244
|
if (!form.id) {
|
|
3218
3245
|
form.generateId();
|