@ailuracode/alpine-child 1.0.0 → 2.0.0

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
@@ -5,10 +5,10 @@ Alpine.js directive for **asChild-style** composition: transfer attributes, clas
5
5
  ## Install
6
6
 
7
7
  ```bash
8
- pnpm add @ailuracode/alpine-child @alpinejs/morph alpinejs
8
+ pnpm add @ailuracode/alpine-child @ailuracode/alpine-core @alpinejs/morph alpinejs
9
9
  ```
10
10
 
11
- ## Setup
11
+ ## Quick start
12
12
 
13
13
  ```ts
14
14
  import Alpine from "alpinejs";
@@ -22,7 +22,7 @@ Alpine.start();
22
22
 
23
23
  Unwrapping uses [`Alpine.morph()`](https://alpinejs.dev/plugins/morph) — register Morph before `x-child`.
24
24
 
25
- ## Usage
25
+ ## Quick start
26
26
 
27
27
  ```html
28
28
  <span
@@ -126,6 +126,16 @@ This package registers a single directive:
126
126
 
127
127
  No stores or magics are added.
128
128
 
129
+ ### Avoiding name collisions
130
+
131
+ If your application already owns an `x-child` directive — or another toolkit plugin registers on that name — rename the integration surface without touching the unwrap pass:
132
+
133
+ ```ts
134
+ Alpine.plugin(childPlugin({ directiveKey: "unwrap" })); // → x-unwrap
135
+ ```
136
+
137
+ The exposed constant `DEFAULT_CHILD_DIRECTIVE_KEY` keeps the rename discoverable from TypeScript.
138
+
129
139
  ## License
130
140
 
131
141
  MIT
package/dist/index.d.ts CHANGED
@@ -47,7 +47,17 @@ interface ChildDirectiveConfig {
47
47
  */
48
48
  interface ChildPluginOptions {
49
49
  readonly id?: string;
50
+ /**
51
+ * `x-child` directive key the Alpine plugin registers under. Defaults
52
+ * to {@link DEFAULT_CHILD_DIRECTIVE_KEY}. Set when the host already
53
+ * owns a `child` directive or another toolkit plugin would collide
54
+ * on that name — the rename avoids the collision without touching
55
+ * the unwrap pass or attribute transfer helpers.
56
+ */
57
+ readonly directiveKey?: string;
50
58
  }
59
+ /** Default `x-child` directive key registered by {@link childPlugin}. */
60
+ declare const DEFAULT_CHILD_DIRECTIVE_KEY = "child";
51
61
  /**
52
62
  * Typed view of `Alpine` the child plugin uses internally.
53
63
  *
@@ -157,4 +167,4 @@ declare function clearTransferredAttributes(wrapper: Element): void;
157
167
  */
158
168
  declare function childPlugin(options?: ChildPluginOptions): ChildPluginCallback;
159
169
 
160
- export { type ChildAlpine, type ChildDirectiveConfig, type ChildMergeMode, type ChildMorphOptions, type ChildPluginCallback, type ChildPluginOptions, childPlugin, clearTransferredAttributes, countElementChildren, childPlugin as default, findFirstElementChild, parseChildDirective, transferAttributes };
170
+ export { type ChildAlpine, type ChildDirectiveConfig, type ChildMergeMode, type ChildMorphOptions, type ChildPluginCallback, type ChildPluginOptions, DEFAULT_CHILD_DIRECTIVE_KEY, childPlugin, clearTransferredAttributes, countElementChildren, childPlugin as default, findFirstElementChild, parseChildDirective, transferAttributes };
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- var f="x-child",T=new Set([f,"x-ignore","x-ignore.self","x-teleport","x-cloak"]),_=["x-child.","x-teleport.","x-transition","x-effect"],v=new Set(["x-data","x-init","x-ref"]);function S(e){return T.has(e)?!0:_.some(t=>e.startsWith(t))}function N(e,t,r,n){return S(e)||e==="id"&&r.hasAttribute("id")||v.has(e)&&r.hasAttribute(e)?!1:n==="replace"?t.hasAttribute(e):n==="default"||n==="merge"?e==="class"||e==="style"?t.hasAttribute(e):t.hasAttribute(e)&&!r.hasAttribute(e):!1}function d(e){for(let t of e.childNodes)if(t.nodeType===Node.ELEMENT_NODE)return t;return null}function c(e){let t=0;for(let r of e.childNodes)r.nodeType===Node.ELEMENT_NODE&&(t+=1);return t}function a(e){for(let{name:t}of e.attributes){if(t===f)return{mode:"default"};if(!t.startsWith(`${f}.`))continue;let r=t.slice(f.length+1).split(".");return r.includes("replace")?{mode:"replace"}:r.includes("merge")?{mode:"merge"}:{mode:"default"}}return null}function p(e,t,r){for(let{name:n}of e.attributes)N(n,e,t,r)&&R(e,t,n,r)}function g(e){for(let{name:t}of e.attributes)e.removeAttribute(t)}function b(...e){let t=new Set;for(let r of e)for(let n of r.split(/\s+/))n&&t.add(n);return[...t].join(" ")}function A(e){let t=new Map;for(let r of e.split(";")){let n=r.trim();if(!n)continue;let o=n.indexOf(":");if(o===-1)continue;let i=n.slice(0,o).trim().toLowerCase(),s=n.slice(o+1).trim();t.set(i,s)}return t}function D(e){return[...e.entries()].map(([t,r])=>`${t}: ${r}`).join("; ")}function I(e,t,r){let n=A(e),o=A(t),i=r?new Map([...n,...o]):new Map([...o,...n]);return D(i)}function R(e,t,r,n){let o=e.getAttribute(r)??"",i=t.getAttribute(r)??"";if(r==="class"){if(n==="replace"){t.setAttribute("class",b(o,i));return}t.setAttribute("class",b(i,o));return}if(r==="style"){let s=I(o,i,n!=="replace");s&&t.setAttribute("style",s);return}(n==="replace"||!t.hasAttribute(r))&&t.setAttribute(r,o)}var x="child";function M(e={}){return function(r){let n=r,o=new WeakSet;n.addInitSelector(()=>`[${n.prefixed(x)}]`),n.interceptInit((i,s)=>{let E=a(i);if(!E||o.has(i))return;let l=d(i);if(!l)return;c(i)>1;let h=n.morph;typeof h=="function"&&(o.add(i),i._x_ignoreSelf=!0,l._x_ignore=!0,s(),n.nextTick(()=>{if(!(i.isConnected||l.isConnected))return;p(i,l,E.mode);let m=null;n.mutateDom(()=>{let y={added(C){C.nodeType===Node.ELEMENT_NODE&&(m=C)}};h(i,l.outerHTML,y)});let u=m??(i.isConnected?i:null);u&&(o.add(u),u._x_ignore=void 0,n.initTree(u)),g(i)}))}),n.directive(x,()=>{}).before("ignore")}}var O=M;export{M as childPlugin,g as clearTransferredAttributes,c as countElementChildren,O as default,d as findFirstElementChild,a as parseChildDirective,p as transferAttributes};
1
+ var f="x-child",v=new Set([f,"x-ignore","x-ignore.self","x-teleport","x-cloak"]),D=["x-child.","x-teleport.","x-transition","x-effect"],I=new Set(["x-data","x-init","x-ref"]);function N(t){return v.has(t)?!0:D.some(e=>t.startsWith(e))}function S(t,e,n,r){return N(t)||t==="id"&&n.hasAttribute("id")||I.has(t)&&n.hasAttribute(t)?!1:r==="replace"?e.hasAttribute(t):r==="default"||r==="merge"?t==="class"||t==="style"?e.hasAttribute(t):e.hasAttribute(t)&&!n.hasAttribute(t):!1}function a(t){for(let e of t.childNodes)if(e.nodeType===Node.ELEMENT_NODE)return e;return null}function c(t){let e=0;for(let n of t.childNodes)n.nodeType===Node.ELEMENT_NODE&&(e+=1);return e}function p(t){for(let{name:e}of t.attributes){if(e===f)return{mode:"default"};if(!e.startsWith(`${f}.`))continue;let n=e.slice(f.length+1).split(".");return n.includes("replace")?{mode:"replace"}:n.includes("merge")?{mode:"merge"}:{mode:"default"}}return null}function g(t,e,n){for(let{name:r}of t.attributes)S(r,t,e,n)&&O(t,e,r,n)}function m(t){for(let{name:e}of t.attributes)t.removeAttribute(e)}function x(...t){let e=new Set;for(let n of t)for(let r of n.split(/\s+/))r&&e.add(r);return[...e].join(" ")}function y(t){let e=new Map;for(let n of t.split(";")){let r=n.trim();if(!r)continue;let i=r.indexOf(":");if(i===-1)continue;let l=r.slice(0,i).trim().toLowerCase(),s=r.slice(i+1).trim();e.set(l,s)}return e}function R(t){return[...t.entries()].map(([e,n])=>`${e}: ${n}`).join("; ")}function k(t,e,n){let r=y(t),i=y(e),l=n?new Map([...r,...i]):new Map([...i,...r]);return R(l)}function O(t,e,n,r){let i=t.getAttribute(n)??"",l=e.getAttribute(n)??"";if(n==="class"){if(r==="replace"){e.setAttribute("class",x(i,l));return}e.setAttribute("class",x(l,i));return}if(n==="style"){let s=k(i,l,r!=="replace");s&&e.setAttribute("style",s);return}(r==="replace"||!e.hasAttribute(n))&&e.setAttribute(n,i)}import{guardDirective as P}from"@ailuracode/alpine-core";var E="child";function M(t={}){let e=t.directiveKey??E;return function(r){let i=r,l=new WeakSet;i.addInitSelector(()=>`[${i.prefixed(e)}]`),i.interceptInit((o,_)=>{let h=p(o);if(!h||l.has(o))return;let d=a(o);if(!d)return;c(o)>1;let C=i.morph;typeof C=="function"&&(l.add(o),o._x_ignoreSelf=!0,d._x_ignore=!0,_(),i.nextTick(()=>{if(!(o.isConnected||d.isConnected))return;g(o,d,h.mode);let A=null;i.mutateDom(()=>{let T={added(b){b.nodeType===Node.ELEMENT_NODE&&(A=b)}};C(o,d.outerHTML,T)});let u=A??(o.isConnected?o:null);u&&(l.add(u),u._x_ignore=void 0,i.initTree(u)),m(o)}))});let s=P(i,e,()=>({}),"child");s&&typeof s.before=="function"&&s.before("ignore")}}var L=M;export{E as DEFAULT_CHILD_DIRECTIVE_KEY,M as childPlugin,m as clearTransferredAttributes,c as countElementChildren,L as default,a as findFirstElementChild,p as parseChildDirective,g as transferAttributes};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ailuracode/alpine-child",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Alpine.js x-child directive — asChild-style attribute transfer to the first child element",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -33,7 +33,7 @@
33
33
  },
34
34
  "types": "./dist/global.d.ts",
35
35
  "peerDependencies": {
36
- "@ailuracode/alpine-core": "^0.2.0",
36
+ "@ailuracode/alpine-core": "^0.3.0",
37
37
  "@alpinejs/morph": "^3.0.0",
38
38
  "alpinejs": "^3.0.0"
39
39
  },
@@ -47,7 +47,8 @@
47
47
  "@types/alpinejs": "^3.13.10",
48
48
  "@types/node": "^26.1.0",
49
49
  "tsup": "^8.5.0",
50
- "@ailuracode/alpine-core": "0.2.0"
50
+ "alpinejs": "^3.15.12",
51
+ "@ailuracode/alpine-core": "0.3.0"
51
52
  },
52
53
  "keywords": [
53
54
  "alpinejs",
@@ -57,11 +58,33 @@
57
58
  "as-child",
58
59
  "headless"
59
60
  ],
61
+ "toolkit": {
62
+ "bundleBudget": {
63
+ "category": "small-feature"
64
+ }
65
+ },
66
+ "size-limit": [
67
+ {
68
+ "name": "full surface",
69
+ "path": "dist/index.js",
70
+ "import": "*",
71
+ "ignore": [
72
+ "alpinejs",
73
+ "@ailuracode/alpine-core",
74
+ "@alpinejs/morph"
75
+ ],
76
+ "gzip": true,
77
+ "brotli": true,
78
+ "limit": "1.5 kB"
79
+ }
80
+ ],
60
81
  "scripts": {
61
- "clean": "rm -rf dist",
62
82
  "build": "tsup --config tsup.config.ts && cp src/global.d.ts dist/global.d.ts",
83
+ "clean": "rm -rf dist",
84
+ "size": "size-limit",
85
+ "test": "vitest run --config ../../vitest.config.ts packages/child",
86
+ "test:watch": "vitest --config ../../vitest.config.ts",
63
87
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
64
- "test": "vitest run --config ../../vitest.config.ts test",
65
- "test:watch": "vitest --config ../../vitest.config.ts"
88
+ "test:e2e": "playwright test --config playwright.config.ts"
66
89
  }
67
90
  }