@wcstack/state 1.3.17 → 1.3.18
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.ja.md +37 -6
- package/README.md +37 -6
- package/dist/index.esm.js +20 -16
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -8,6 +8,28 @@
|
|
|
8
8
|
|
|
9
9
|
CDNスクリプトはカスタム要素の定義を登録するだけ — ロード時にはそれ以外何も起きない。`<wcs-state>` 要素がDOMに接続されたとき、状態ソースを読み取り、兄弟要素の `data-wcs` バインディングを走査し、リアクティビティを構築する。すべての初期化は要素のライフサイクルが駆動する。あなたのコードではなく。
|
|
10
10
|
|
|
11
|
+
## 4ステップで動く
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<!-- 1. CDN を読み込む -->
|
|
15
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
16
|
+
|
|
17
|
+
<!-- 2. <wcs-state> タグを書く -->
|
|
18
|
+
<wcs-state>
|
|
19
|
+
<!-- 3. 状態オブジェクトを定義する -->
|
|
20
|
+
<script type="module">
|
|
21
|
+
export default {
|
|
22
|
+
message: "Hello, World!"
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
</wcs-state>
|
|
26
|
+
|
|
27
|
+
<!-- 4. data-wcs 属性でバインドする -->
|
|
28
|
+
<div data-wcs="textContent: message"></div>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
これだけ。ビルドなし、初期化コードなし、フレームワークなし。
|
|
32
|
+
|
|
11
33
|
## 特徴
|
|
12
34
|
|
|
13
35
|
- **宣言的データバインディング** — `data-wcs` 属性によるプロパティ / テキスト / イベント / 構造バインディング
|
|
@@ -1077,12 +1099,21 @@ bootstrapState();
|
|
|
1077
1099
|
|
|
1078
1100
|
```
|
|
1079
1101
|
bootstrapState()
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1102
|
+
└── registerComponents() // <wcs-state> カスタム要素を登録
|
|
1103
|
+
|
|
1104
|
+
<wcs-state> connectedCallback
|
|
1105
|
+
├── _initializeBindWebComponent() // bind-component: 親コンポーネントから状態を取得
|
|
1106
|
+
├── _initialize() // 状態をロード (state属性 / src / json / script / API)
|
|
1107
|
+
│ └── setStateElementByName() // WeakMap<Node, Map<name, element>> に登録
|
|
1108
|
+
│ └── (rootNode への初回登録時)
|
|
1109
|
+
│ └── queueMicrotask → buildBindings()
|
|
1110
|
+
├── _callStateConnectedCallback() // $connectedCallback が定義されていれば呼び出し
|
|
1111
|
+
|
|
1112
|
+
buildBindings(root)
|
|
1113
|
+
├── waitForStateInitialize() // 全 <wcs-state> の initializePromise を待機
|
|
1114
|
+
├── convertMustacheToComments() // {{ }} → コメントノードに変換
|
|
1115
|
+
├── collectStructuralFragments() // for/if テンプレートを収集
|
|
1116
|
+
└── initializeBindings() // DOM 走査、data-wcs 解析、バインディング設定
|
|
1086
1117
|
```
|
|
1087
1118
|
|
|
1088
1119
|
### リアクティビティフロー
|
package/README.md
CHANGED
|
@@ -8,6 +8,28 @@ That's what `<wcs-state>` and `data-wcs` explore. One CDN import, zero dependenc
|
|
|
8
8
|
|
|
9
9
|
The CDN script only registers the custom element definition — nothing else happens at load time. When a `<wcs-state>` element connects to the DOM, it reads its state source, scans sibling elements for `data-wcs` bindings, and wires up reactivity. All initialization is driven by the element's lifecycle, not by your code.
|
|
10
10
|
|
|
11
|
+
## 4 Steps to Reactive HTML
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<!-- 1. Load the CDN -->
|
|
15
|
+
<script type="module" src="https://esm.run/@wcstack/state/auto"></script>
|
|
16
|
+
|
|
17
|
+
<!-- 2. Write a <wcs-state> tag -->
|
|
18
|
+
<wcs-state>
|
|
19
|
+
<!-- 3. Define your state object -->
|
|
20
|
+
<script type="module">
|
|
21
|
+
export default {
|
|
22
|
+
message: "Hello, World!"
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
25
|
+
</wcs-state>
|
|
26
|
+
|
|
27
|
+
<!-- 4. Bind with data-wcs attributes -->
|
|
28
|
+
<div data-wcs="textContent: message"></div>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
That's it. No build, no bootstrap code, no framework.
|
|
32
|
+
|
|
11
33
|
## Features
|
|
12
34
|
|
|
13
35
|
- **Declarative data binding** — `data-wcs` attribute for property / text / event / structural binding
|
|
@@ -1077,12 +1099,21 @@ bootstrapState();
|
|
|
1077
1099
|
|
|
1078
1100
|
```
|
|
1079
1101
|
bootstrapState()
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1102
|
+
└── registerComponents() // Register <wcs-state> custom element
|
|
1103
|
+
|
|
1104
|
+
<wcs-state> connectedCallback
|
|
1105
|
+
├── _initializeBindWebComponent() // bind-component: get state from parent component
|
|
1106
|
+
├── _initialize() // Load state (state attr / src / json / script / API)
|
|
1107
|
+
│ └── setStateElementByName() // Register to WeakMap<Node, Map<name, element>>
|
|
1108
|
+
│ └── (first registration per rootNode)
|
|
1109
|
+
│ └── queueMicrotask → buildBindings()
|
|
1110
|
+
├── _callStateConnectedCallback() // Call $connectedCallback if defined
|
|
1111
|
+
|
|
1112
|
+
buildBindings(root)
|
|
1113
|
+
├── waitForStateInitialize() // Wait for all <wcs-state> initializePromise
|
|
1114
|
+
├── convertMustacheToComments() // {{ }} → comment nodes
|
|
1115
|
+
├── collectStructuralFragments() // Collect for/if templates
|
|
1116
|
+
└── initializeBindings() // Walk DOM, parse data-wcs, set up bindings
|
|
1086
1117
|
```
|
|
1087
1118
|
|
|
1088
1119
|
### Reactivity Flow
|
package/dist/index.esm.js
CHANGED
|
@@ -1910,28 +1910,31 @@ function clearAbsoluteStateAddressByBinding(binding) {
|
|
|
1910
1910
|
}
|
|
1911
1911
|
|
|
1912
1912
|
const cache = new WeakMap();
|
|
1913
|
-
function
|
|
1914
|
-
|
|
1915
|
-
if (
|
|
1916
|
-
return
|
|
1913
|
+
function getCustomElement(node) {
|
|
1914
|
+
const cached = cache.get(node);
|
|
1915
|
+
if (cached !== undefined) {
|
|
1916
|
+
return cached;
|
|
1917
1917
|
}
|
|
1918
|
+
let value = null;
|
|
1918
1919
|
try {
|
|
1919
1920
|
if (node.nodeType !== Node.ELEMENT_NODE) {
|
|
1920
|
-
return value
|
|
1921
|
+
return value;
|
|
1921
1922
|
}
|
|
1922
1923
|
const element = node;
|
|
1923
|
-
|
|
1924
|
-
|
|
1924
|
+
const tagName = element.tagName.toLowerCase();
|
|
1925
|
+
if (tagName.includes("-")) {
|
|
1926
|
+
return value = tagName;
|
|
1925
1927
|
}
|
|
1926
1928
|
if (element.hasAttribute("is")) {
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
+
const is = element.getAttribute("is");
|
|
1930
|
+
if (is.includes("-")) {
|
|
1931
|
+
return value = is;
|
|
1929
1932
|
}
|
|
1930
1933
|
}
|
|
1931
|
-
return value
|
|
1934
|
+
return value;
|
|
1932
1935
|
}
|
|
1933
1936
|
finally {
|
|
1934
|
-
cache.set(node, value
|
|
1937
|
+
cache.set(node, value);
|
|
1935
1938
|
}
|
|
1936
1939
|
}
|
|
1937
1940
|
|
|
@@ -2967,9 +2970,9 @@ function applyChange(binding, context) {
|
|
|
2967
2970
|
if (binding.bindingType === "event") {
|
|
2968
2971
|
return;
|
|
2969
2972
|
}
|
|
2970
|
-
|
|
2971
|
-
|
|
2972
|
-
if (customElements.get(
|
|
2973
|
+
const customTag = getCustomElement(binding.replaceNode);
|
|
2974
|
+
if (customTag) {
|
|
2975
|
+
if (customElements.get(customTag) === undefined) {
|
|
2973
2976
|
// cutomElement側の初期化を期待
|
|
2974
2977
|
return;
|
|
2975
2978
|
}
|
|
@@ -5494,7 +5497,8 @@ class State extends HTMLElement {
|
|
|
5494
5497
|
: parentNode instanceof Element
|
|
5495
5498
|
? parentNode
|
|
5496
5499
|
: null;
|
|
5497
|
-
|
|
5500
|
+
const customTagName = boundComponent ? getCustomElement(boundComponent) : null;
|
|
5501
|
+
if (boundComponent === null || customTagName === null) {
|
|
5498
5502
|
raiseError(`"bind-component" requires <${config.tagNames.state}> to be a direct child of a custom element.`);
|
|
5499
5503
|
}
|
|
5500
5504
|
// LightDOMの場合、名前空間が上位スコープと共有されるためnameが必須
|
|
@@ -5502,7 +5506,7 @@ class State extends HTMLElement {
|
|
|
5502
5506
|
raiseError(`"bind-component" in Light DOM requires a "name" attribute to avoid namespace conflicts with the parent scope.`);
|
|
5503
5507
|
}
|
|
5504
5508
|
const boundComponentStateProp = this.getAttribute("bind-component");
|
|
5505
|
-
await customElements.whenDefined(
|
|
5509
|
+
await customElements.whenDefined(customTagName.toLowerCase());
|
|
5506
5510
|
// data-wcs属性がある場合は、上位の状態によりbinding情報の設定が完了するまで待機する
|
|
5507
5511
|
if (boundComponent.hasAttribute(config.bindAttributeName)) {
|
|
5508
5512
|
await waitInitializeBinding(boundComponent);
|