cotomy 0.3.17 → 0.4.1

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 CHANGED
@@ -37,7 +37,9 @@ The View layer provides thin wrappers around DOM elements and window events.
37
37
  - `new CotomyElement({ tagname, text?, css? })`
38
38
  - Scoped CSS
39
39
  - `scopeId: string` - Returns the value stored in the element's `data-cotomy-scopeid` attribute
40
- - `[scope]` placeholder in provided CSS is replaced by `[data-cotomy-scopeid="..."]`
40
+ - `[root]` placeholder in provided CSS is replaced by `[data-cotomy-scopeid="..."]`
41
+ - `[scope]` is deprecated and will be removed in a future release (use `[root]` instead)
42
+ - If neither `[root]` nor `[scope]` is present, `[root]` is treated as if it were prefixed automatically
41
43
  - Scoped CSS text is kept on the instance; if the `<style id="css-${scopeId}">` is missing when the element is attached, it will be re-generated automatically
42
44
  - `stylable: boolean` - False for tags like `script`, `style`, `link`, `meta`
43
45
  - Static helpers
@@ -119,8 +121,8 @@ import { CotomyElement } from "cotomy";
119
121
  const panel = new CotomyElement({
120
122
  html: `<div class="panel"><button class="ok">OK</button></div>`,
121
123
  css: `
122
- [scope] .panel { padding: 8px; }
123
- [scope] .ok { color: green; }
124
+ [root] .panel { padding: 8px; }
125
+ [root] .ok { color: green; }
124
126
  `,
125
127
  });
126
128
 
@@ -143,7 +145,7 @@ npm test -- --run tests/view.spec.ts -t "throws when cloning an invalidated elem
143
145
  npm test -- --run tests/view.spec.ts -t "compares document order with comesBefore/comesAfter"
144
146
  ```
145
147
 
146
- 普段は `npm test` で全体を実行できます。上記のコマンドでは `[scope]` 展開、スコープID共有のクローン挙動、インスタンス単位のイベント隔離、クローン後のスコープCSS再生成、移動フラグの除去、無効化要素のクローン拒否、DOM順序判定などをピンポイントで確認できます。
148
+ 普段は `npm test` で全体を実行できます。上記のコマンドでは `[root]/[scope]` 展開、スコープID共有のクローン挙動、インスタンス単位のイベント隔離、クローン後のスコープCSS再生成、移動フラグの除去、無効化要素のクローン拒否、DOM順序判定などをピンポイントで確認できます。
147
149
 
148
150
  ### CotomyMetaElement
149
151
 
@@ -237,9 +239,9 @@ The Form layer builds on `CotomyElement` for common form flows.
237
239
  - Data loading and field filling
238
240
  - `initialize()` — Adds default fillers and triggers `loadAsync()` on `CotomyWindow.ready`
239
241
  - `reloadAsync()` — Alias to `loadAsync()`
240
- - `loadAsync(): Promise<CotomyApiResponse>` — Calls `CotomyApi.getAsync` when `canLoad()` is true
241
- - `loadActionUrl(): string` — Defaults to `actionUrl`; override for custom endpoints
242
- - `canLoad(): boolean` — Defaults to `hasEntityKey`
242
+ - `loadAsync(): Promise<CotomyApiResponse>` — Calls `CotomyApi.getAsync` when `canLoad` is true
243
+ - `loadActionUrl: string` — Defaults to `actionUrl`; override or set for custom endpoints
244
+ - `canLoad: boolean` — Defaults to `hasEntityKey`
243
245
  - Naming & binding
244
246
  - `bindNameGenerator(): ICotomyBindNameGenerator` — Defaults to `CotomyBracketBindNameGenerator` (`user[name]`)
245
247
  - `renderer(): CotomyViewRenderer` — Applies `[data-cotomy-bind]` to view elements
@@ -293,7 +295,7 @@ form.submitFailed(e => console.warn("Submit failed", e.response.status));
293
295
  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.
294
296
  On `201 Created`, the form reads the `Location` header and stores the generated key back into `data-cotomy-entity-key`, enabling subsequent `PUT` submissions.
295
297
  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.
296
- 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.
298
+ 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.
297
299
 
298
300
  The core of Cotomy is `CotomyElement`, which is constructed as a wrapper for `Element`.
299
301
  By passing HTML and CSS strings to the constructor, it is possible to generate Element designs with a limited scope.
@@ -306,10 +308,10 @@ By passing HTML and CSS strings to the constructor, it is possible to generate E
306
308
  </div>
307
309
  `,
308
310
  css: /* css */`
309
- [scope] {
311
+ [root] {
310
312
  display: block;
311
313
  }
312
- [scope] > p {
314
+ [root] > p {
313
315
  text-align: center;
314
316
  }
315
317
  `
@@ -856,7 +856,7 @@ class CotomyScrollOptions {
856
856
  if (init.inline !== undefined)
857
857
  this.inline = init.inline;
858
858
  }
859
- resolveBehavior() {
859
+ get resolveBehavior() {
860
860
  return this.behavior;
861
861
  }
862
862
  static from(options) {
@@ -1008,7 +1008,9 @@ class CotomyElement {
1008
1008
  const cssid = this.scopedCssElementId;
1009
1009
  CotomyElement.find(`#${cssid}`).forEach(e => e.remove());
1010
1010
  const element = document.createElement("style");
1011
- const writeCss = css.replace(/\[scope\]/g, `[data-cotomy-scopeid="${this.scopeId}"]`);
1011
+ const hasScopeOrRoot = /\[(?:scope|root)\]/.test(css);
1012
+ const normalizedCss = hasScopeOrRoot ? css : `[root] ${css}`;
1013
+ const writeCss = normalizedCss.replace(/\[(?:scope|root)\]/g, `[data-cotomy-scopeid="${this.scopeId}"]`);
1012
1014
  const node = document.createTextNode(writeCss);
1013
1015
  element.appendChild(node);
1014
1016
  element.id = cssid;
@@ -1404,7 +1406,7 @@ class CotomyElement {
1404
1406
  if (!this.attached)
1405
1407
  return this;
1406
1408
  const resolved = CotomyScrollOptions.from(options);
1407
- const behavior = resolved.resolveBehavior();
1409
+ const behavior = resolved.resolveBehavior;
1408
1410
  const onlyIfNeeded = resolved.onlyIfNeeded;
1409
1411
  const block = resolved.block;
1410
1412
  const inline = resolved.inline;
@@ -3009,7 +3011,7 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
3009
3011
  async reloadAsync() {
3010
3012
  await this.loadAsync();
3011
3013
  }
3012
- loadActionUrl() {
3014
+ get loadActionUrl() {
3013
3015
  return this.actionUrl;
3014
3016
  }
3015
3017
  bindNameGenerator() {
@@ -3018,16 +3020,16 @@ class CotomyEntityFillApiForm extends CotomyEntityApiForm {
3018
3020
  renderer() {
3019
3021
  return new CotomyViewRenderer(this, this.bindNameGenerator());
3020
3022
  }
3021
- canLoad() {
3023
+ get canLoad() {
3022
3024
  return this.hasEntityKey;
3023
3025
  }
3024
3026
  async loadAsync() {
3025
- if (!this.canLoad()) {
3027
+ if (!this.canLoad) {
3026
3028
  return new CotomyApiResponse();
3027
3029
  }
3028
3030
  const api = this.apiClient();
3029
3031
  try {
3030
- const response = await api.getAsync(this.loadActionUrl());
3032
+ const response = await api.getAsync(this.loadActionUrl);
3031
3033
  await this.fillAsync(response);
3032
3034
  return response;
3033
3035
  }
@@ -3197,11 +3199,11 @@ class CotomyPageController {
3197
3199
  }
3198
3200
  return form;
3199
3201
  }
3200
- forms() {
3202
+ get forms() {
3201
3203
  return Object.values(this._forms);
3202
3204
  }
3203
3205
  async restoreAsync() {
3204
- for (const f of this.forms()) {
3206
+ for (const f of this.forms) {
3205
3207
  if (CotomyWindow.instance.reloading) {
3206
3208
  break;
3207
3209
  }