@ailuracode/alpine-child 0.1.0 → 1.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 +6 -6
- package/dist/global.d.ts +29 -7
- package/dist/index.d.ts +151 -11
- package/dist/index.js +1 -232
- package/package.json +13 -5
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -5,18 +5,18 @@ Alpine.js directive for **asChild-style** composition: transfer attributes, clas
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
pnpm add @ailuracode/alpine-child @alpinejs/morph alpinejs
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
|
-
```
|
|
13
|
+
```ts
|
|
14
14
|
import Alpine from "alpinejs";
|
|
15
15
|
import morph from "@alpinejs/morph";
|
|
16
|
-
import
|
|
16
|
+
import { childPlugin } from "@ailuracode/alpine-child";
|
|
17
17
|
|
|
18
18
|
Alpine.plugin(morph);
|
|
19
|
-
Alpine.plugin(
|
|
19
|
+
Alpine.plugin(childPlugin());
|
|
20
20
|
Alpine.start();
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -89,7 +89,7 @@ Programmatic listeners attached to the wrapper at runtime are **not** transferre
|
|
|
89
89
|
|
|
90
90
|
## Blade components
|
|
91
91
|
|
|
92
|
-
```
|
|
92
|
+
```html
|
|
93
93
|
{{-- resources/views/components/button.blade.php --}}
|
|
94
94
|
<span
|
|
95
95
|
x-child
|
|
@@ -99,7 +99,7 @@ Programmatic listeners attached to the wrapper at runtime are **not** transferre
|
|
|
99
99
|
</span>
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
```
|
|
102
|
+
```html
|
|
103
103
|
<x-button>
|
|
104
104
|
<a href="{{ route('docs') }}">Docs</a>
|
|
105
105
|
</x-button>
|
package/dist/global.d.ts
CHANGED
|
@@ -1,9 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Ambient type surface for `@ailuracode/alpine-child`.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the public type surface so consumers can include this
|
|
5
|
+
* file via the triple-slash directive and typecheck `x-child`
|
|
6
|
+
* references without pulling the runtime entrypoint.
|
|
7
|
+
*
|
|
8
|
+
* Per core's `global.d.ts` convention, this package does NOT augment
|
|
9
|
+
* external modules — the `x-child` directive is identified by its
|
|
10
|
+
* attribute name, not by an `Alpine.*` namespace entry. Consumers that
|
|
11
|
+
* need typed access to the unwrap machinery should import the types
|
|
12
|
+
* from `@ailuracode/alpine-child` directly:
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* import type {
|
|
16
|
+
* ChildDirectiveConfig,
|
|
17
|
+
* ChildMergeMode,
|
|
18
|
+
* ChildPluginOptions,
|
|
19
|
+
* } from "@ailuracode/alpine-child";
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
2
22
|
|
|
3
|
-
|
|
23
|
+
/// <reference types="@types/alpinejs" />
|
|
4
24
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
25
|
+
export type {
|
|
26
|
+
ChildDirectiveConfig,
|
|
27
|
+
ChildMergeMode,
|
|
28
|
+
ChildMorphOptions,
|
|
29
|
+
ChildPluginCallback,
|
|
30
|
+
ChildPluginOptions,
|
|
31
|
+
} from "./types.js";
|
package/dist/index.d.ts
CHANGED
|
@@ -1,20 +1,160 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Alpine, PluginCallback } from '@ailuracode/alpine-core';
|
|
2
|
+
import { Alpine as Alpine$1 } from 'alpinejs';
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Public type contracts for `@ailuracode/alpine-child`.
|
|
6
|
+
*
|
|
7
|
+
* Per `.cursor/rules/formatting.mdc`, every public type
|
|
8
|
+
* lives in a `types.ts` module so consumers can import them without pulling
|
|
9
|
+
* the implementation. The shape IS the contract — renaming a field or
|
|
10
|
+
* changing a variant is a breaking change.
|
|
11
|
+
*
|
|
12
|
+
* The directive is intentionally minimal: one merge mode per element,
|
|
13
|
+
* no events, no state. The types here document the entire public surface
|
|
14
|
+
* besides the runtime functions in `./controller` and the Alpine glue
|
|
15
|
+
* in `./plugin`.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* How wrapper attributes interact with the first element child during the
|
|
20
|
+
* unwrap pass.
|
|
21
|
+
*
|
|
22
|
+
* - `'default'` — `class` and `style` merge token/property lists with
|
|
23
|
+
* child tokens winning on conflict; other attributes copy only when
|
|
24
|
+
* missing on the child. Existing child `id`, `aria-*`, and `data-*`
|
|
25
|
+
* attributes always win.
|
|
26
|
+
* - `'merge'` — explicit alias for `'default'`. Surfaced via the
|
|
27
|
+
* `.merge` modifier; reserved as a distinct variant so future
|
|
28
|
+
* semantics (e.g. deep attribute merging) can branch on it without
|
|
29
|
+
* breaking the modifier contract.
|
|
30
|
+
* - `'replace'` — wrapper values overwrite child values on conflict.
|
|
31
|
+
* `class` and `style` still merge token/property lists.
|
|
32
|
+
*/
|
|
3
33
|
type ChildMergeMode = "default" | "merge" | "replace";
|
|
34
|
+
/**
|
|
35
|
+
* Parsed `x-child` directive configuration extracted from the wrapper's
|
|
36
|
+
* attributes. Produced by `parseChildDirective` in `./controller`.
|
|
37
|
+
*/
|
|
38
|
+
interface ChildDirectiveConfig {
|
|
39
|
+
readonly mode: ChildMergeMode;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Options accepted by {@link childPlugin}. The directive currently has
|
|
43
|
+
* no runtime knobs beyond what the modifiers express, so the options
|
|
44
|
+
* surface is empty by design — reserved as the public seam for future
|
|
45
|
+
* cross-cutting configuration (e.g. warning sinks, scoped mutation
|
|
46
|
+
* observers, debug logging).
|
|
47
|
+
*/
|
|
48
|
+
interface ChildPluginOptions {
|
|
49
|
+
readonly id?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Typed view of `Alpine` the child plugin uses internally.
|
|
53
|
+
*
|
|
54
|
+
* Adds the `morph(el, html, options)` helper from `@alpinejs/morph` on
|
|
55
|
+
* top of the toolkit's {@link Alpine} generic. The morph function is
|
|
56
|
+
* only present when consumers register `Alpine.plugin(morph)` before
|
|
57
|
+
* `childPlugin(...)`; the plugin runtime-checks its presence and warns
|
|
58
|
+
* otherwise. The toolkit's `Alpine<Stores>` only ADDS overloads, so a
|
|
59
|
+
* real `Alpine` runtime is assignable to this view without a cast.
|
|
60
|
+
*/
|
|
61
|
+
type ChildAlpine = Alpine<Record<string, never>> & {
|
|
62
|
+
/**
|
|
63
|
+
* Forwarded from `@alpinejs/morph`. The plugin reads this property at
|
|
64
|
+
* runtime and falls back with a warning when it is absent.
|
|
65
|
+
*/
|
|
66
|
+
morph?(el: Element, newHtml: string | Element, options?: ChildMorphOptions): Element;
|
|
67
|
+
};
|
|
68
|
+
/** Subset of `Alpine.morph` options the plugin reads. */
|
|
69
|
+
interface ChildMorphOptions {
|
|
70
|
+
readonly added?: (node: Node) => void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* `Alpine.plugin()` callback signature.
|
|
74
|
+
*
|
|
75
|
+
* Typed against the base `Alpine` via the toolkit's `PluginCallback`
|
|
76
|
+
* generic so `childPlugin(...)` drops straight into `Alpine.plugin(...)`
|
|
77
|
+
* without a cast.
|
|
78
|
+
*/
|
|
79
|
+
type ChildPluginCallback = PluginCallback<Alpine$1>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Internal merge helpers for `@ailuracode/alpine-child`.
|
|
83
|
+
*
|
|
84
|
+
* Pure DOM utilities used by `controller.ts` to apply the wrapper → child
|
|
85
|
+
* attribute transfer. Lives under `internal/` so the public surface stays
|
|
86
|
+
* small — every helper here is consumed by the controller facade.
|
|
87
|
+
*
|
|
88
|
+
* Construction rules (per
|
|
89
|
+
* `.cursor/rules/new-package.mdc`):
|
|
90
|
+
*
|
|
91
|
+
* - No `window` / `document` access — these run on whatever `Element`
|
|
92
|
+
* instances the controller hands them.
|
|
93
|
+
* - No Alpine APIs, no scope reads, no event subscriptions.
|
|
94
|
+
*
|
|
95
|
+
* The merge rules are documented in the package README under
|
|
96
|
+
* "Attribute rules" — keep this file in sync when the public rules
|
|
97
|
+
* change.
|
|
98
|
+
*/
|
|
99
|
+
|
|
4
100
|
/** Returns the first element child, skipping text and comment nodes. */
|
|
5
101
|
declare function findFirstElementChild(parent: Element): Element | null;
|
|
6
102
|
/** Counts element children (excluding text/comment nodes). */
|
|
7
103
|
declare function countElementChildren(parent: Element): number;
|
|
8
|
-
/**
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
104
|
+
/**
|
|
105
|
+
* Parses `x-child` directive modifiers from element attributes.
|
|
106
|
+
*
|
|
107
|
+
* Returns `null` when the directive is absent, so the plugin can skip
|
|
108
|
+
* elements without `x-child` quickly without extra branching. Returns a
|
|
109
|
+
* config with `mode: 'default'` when the attribute is present without
|
|
110
|
+
* any modifier.
|
|
111
|
+
*/
|
|
112
|
+
declare function parseChildDirective(el: Element): ChildDirectiveConfig | null;
|
|
113
|
+
/**
|
|
114
|
+
* Applies the wrapper attributes onto the child following the active
|
|
115
|
+
* {@link ChildMergeMode}.
|
|
116
|
+
*
|
|
117
|
+
* Public from the controller's perspective — `internal/` re-export
|
|
118
|
+
* is internal-by-convention, not strict.
|
|
119
|
+
*/
|
|
120
|
+
declare function transferAttributes(wrapper: Element, child: Element, mode: ChildMergeMode): void;
|
|
121
|
+
/**
|
|
122
|
+
* Removes every attribute from the wrapper.
|
|
123
|
+
*
|
|
124
|
+
* After `Alpine.morph()` swaps the wrapper out of the document, this
|
|
125
|
+
* is mostly defensive — the wrapper is already detached. Kept exported
|
|
126
|
+
* so tests can verify the scrub step in isolation, and so consumers
|
|
127
|
+
* that wire `x-child` into a custom Alpine adapter can run the same
|
|
128
|
+
* cleanup themselves.
|
|
129
|
+
*/
|
|
15
130
|
declare function clearTransferredAttributes(wrapper: Element): void;
|
|
16
131
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
132
|
+
/**
|
|
133
|
+
* Alpine.js integration for `@ailuracode/alpine-child`.
|
|
134
|
+
*
|
|
135
|
+
* Thin adapter that registers the `x-child` directive. The unwrap pass
|
|
136
|
+
* runs in `Alpine.interceptInit` so the wrapper is hidden before its
|
|
137
|
+
* own descendants init, and the morph swap is deferred to the next
|
|
138
|
+
* tick so sibling components (e.g. `x-show` on a sidebar) init first.
|
|
139
|
+
*
|
|
140
|
+
* Two ways to consume the package:
|
|
141
|
+
*
|
|
142
|
+
* 1. Standalone — import any of the helpers in `./controller` directly
|
|
143
|
+
* for tests, custom directives, or non-Alpine adapters.
|
|
144
|
+
* 2. Alpine — `childPlugin({ id? })` returns the `Alpine.plugin()`
|
|
145
|
+
* callback that registers the directive.
|
|
146
|
+
*
|
|
147
|
+
* The framework-agnostic logic lives in `./controller` and
|
|
148
|
+
* `./internal/transfer`. This file is the only place that imports
|
|
149
|
+
* Alpine APIs.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Plugin factory — returns the `Alpine.plugin()` callback. Pass
|
|
154
|
+
* {@link ChildPluginOptions} to configure future cross-cutting knobs,
|
|
155
|
+
* or `{}` for the package defaults. See `AGENTS.md` for the
|
|
156
|
+
* integration contract.
|
|
157
|
+
*/
|
|
158
|
+
declare function childPlugin(options?: ChildPluginOptions): ChildPluginCallback;
|
|
19
159
|
|
|
20
|
-
export { type ChildMergeMode, clearTransferredAttributes, countElementChildren, childPlugin as default, findFirstElementChild, parseChildDirective, transferAttributes };
|
|
160
|
+
export { type ChildAlpine, type ChildDirectiveConfig, type ChildMergeMode, type ChildMorphOptions, type ChildPluginCallback, type ChildPluginOptions, childPlugin, clearTransferredAttributes, countElementChildren, childPlugin as default, findFirstElementChild, parseChildDirective, transferAttributes };
|
package/dist/index.js
CHANGED
|
@@ -1,232 +1 @@
|
|
|
1
|
-
|
|
2
|
-
var CHILD_DIRECTIVE_PREFIX = "x-child";
|
|
3
|
-
var NEVER_TRANSFER = /* @__PURE__ */ new Set([
|
|
4
|
-
CHILD_DIRECTIVE_PREFIX,
|
|
5
|
-
"x-ignore",
|
|
6
|
-
"x-ignore.self",
|
|
7
|
-
"x-teleport",
|
|
8
|
-
"x-cloak"
|
|
9
|
-
]);
|
|
10
|
-
var NEVER_TRANSFER_PREFIXES = ["x-child.", "x-teleport.", "x-transition", "x-effect"];
|
|
11
|
-
var SCOPE_ATTRS = /* @__PURE__ */ new Set(["x-data", "x-init", "x-ref"]);
|
|
12
|
-
function isNeverTransfer(name) {
|
|
13
|
-
if (NEVER_TRANSFER.has(name)) {
|
|
14
|
-
return true;
|
|
15
|
-
}
|
|
16
|
-
return NEVER_TRANSFER_PREFIXES.some((prefix) => name.startsWith(prefix));
|
|
17
|
-
}
|
|
18
|
-
function findFirstElementChild(parent) {
|
|
19
|
-
for (const node of parent.childNodes) {
|
|
20
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
21
|
-
return node;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
function countElementChildren(parent) {
|
|
27
|
-
let count = 0;
|
|
28
|
-
for (const node of parent.childNodes) {
|
|
29
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
30
|
-
count += 1;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return count;
|
|
34
|
-
}
|
|
35
|
-
function parseChildDirective(el) {
|
|
36
|
-
for (const { name } of el.attributes) {
|
|
37
|
-
if (name === CHILD_DIRECTIVE_PREFIX) {
|
|
38
|
-
return { mode: "default" };
|
|
39
|
-
}
|
|
40
|
-
if (!name.startsWith(`${CHILD_DIRECTIVE_PREFIX}.`)) {
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
const modifiers = name.slice(CHILD_DIRECTIVE_PREFIX.length + 1).split(".");
|
|
44
|
-
if (modifiers.includes("replace")) {
|
|
45
|
-
return { mode: "replace" };
|
|
46
|
-
}
|
|
47
|
-
if (modifiers.includes("merge")) {
|
|
48
|
-
return { mode: "merge" };
|
|
49
|
-
}
|
|
50
|
-
return { mode: "default" };
|
|
51
|
-
}
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
function mergeClassTokens(...values) {
|
|
55
|
-
const tokens = /* @__PURE__ */ new Set();
|
|
56
|
-
for (const value of values) {
|
|
57
|
-
for (const token of value.split(/\s+/)) {
|
|
58
|
-
if (token) {
|
|
59
|
-
tokens.add(token);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
return [...tokens].join(" ");
|
|
64
|
-
}
|
|
65
|
-
function parseInlineStyle(style) {
|
|
66
|
-
const map = /* @__PURE__ */ new Map();
|
|
67
|
-
for (const part of style.split(";")) {
|
|
68
|
-
const trimmed = part.trim();
|
|
69
|
-
if (!trimmed) {
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const colon = trimmed.indexOf(":");
|
|
73
|
-
if (colon === -1) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
const property = trimmed.slice(0, colon).trim().toLowerCase();
|
|
77
|
-
const value = trimmed.slice(colon + 1).trim();
|
|
78
|
-
map.set(property, value);
|
|
79
|
-
}
|
|
80
|
-
return map;
|
|
81
|
-
}
|
|
82
|
-
function serializeInlineStyle(map) {
|
|
83
|
-
return [...map.entries()].map(([property, value]) => `${property}: ${value}`).join("; ");
|
|
84
|
-
}
|
|
85
|
-
function mergeInlineStyle(wrapperStyle, childStyle, childWins) {
|
|
86
|
-
const wrapperMap = parseInlineStyle(wrapperStyle);
|
|
87
|
-
const childMap = parseInlineStyle(childStyle);
|
|
88
|
-
const merged = childWins ? new Map([...wrapperMap, ...childMap]) : new Map([...childMap, ...wrapperMap]);
|
|
89
|
-
return serializeInlineStyle(merged);
|
|
90
|
-
}
|
|
91
|
-
function childHasAttribute(el, name) {
|
|
92
|
-
return el.hasAttribute(name);
|
|
93
|
-
}
|
|
94
|
-
function shouldCopyAttribute(name, wrapper, child, mode) {
|
|
95
|
-
if (isNeverTransfer(name)) {
|
|
96
|
-
return false;
|
|
97
|
-
}
|
|
98
|
-
if (name === "id" && childHasAttribute(child, "id")) {
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
if (SCOPE_ATTRS.has(name) && childHasAttribute(child, name)) {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
if (mode === "replace") {
|
|
105
|
-
return wrapper.hasAttribute(name);
|
|
106
|
-
}
|
|
107
|
-
if (mode === "default" || mode === "merge") {
|
|
108
|
-
if (name === "class" || name === "style") {
|
|
109
|
-
return wrapper.hasAttribute(name);
|
|
110
|
-
}
|
|
111
|
-
return wrapper.hasAttribute(name) && !childHasAttribute(child, name);
|
|
112
|
-
}
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
function applyAttribute(wrapper, child, name, mode) {
|
|
116
|
-
const wrapperValue = wrapper.getAttribute(name) ?? "";
|
|
117
|
-
const childValue = child.getAttribute(name) ?? "";
|
|
118
|
-
if (name === "class") {
|
|
119
|
-
if (mode === "replace") {
|
|
120
|
-
child.setAttribute("class", mergeClassTokens(wrapperValue, childValue));
|
|
121
|
-
return;
|
|
122
|
-
}
|
|
123
|
-
child.setAttribute("class", mergeClassTokens(childValue, wrapperValue));
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
if (name === "style") {
|
|
127
|
-
const merged = mergeInlineStyle(wrapperValue, childValue, mode !== "replace");
|
|
128
|
-
if (merged) {
|
|
129
|
-
child.setAttribute("style", merged);
|
|
130
|
-
}
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
if (mode === "replace" || !childHasAttribute(child, name)) {
|
|
134
|
-
child.setAttribute(name, wrapperValue);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
function transferAttributes(wrapper, child, mode = "default") {
|
|
138
|
-
const names = /* @__PURE__ */ new Set();
|
|
139
|
-
for (const { name } of wrapper.attributes) {
|
|
140
|
-
names.add(name);
|
|
141
|
-
}
|
|
142
|
-
for (const name of names) {
|
|
143
|
-
if (!shouldCopyAttribute(name, wrapper, child, mode)) {
|
|
144
|
-
continue;
|
|
145
|
-
}
|
|
146
|
-
applyAttribute(wrapper, child, name, mode);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
function clearTransferredAttributes(wrapper) {
|
|
150
|
-
const toRemove = [];
|
|
151
|
-
for (const { name } of wrapper.attributes) {
|
|
152
|
-
if (isNeverTransfer(name)) {
|
|
153
|
-
toRemove.push(name);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
toRemove.push(name);
|
|
157
|
-
}
|
|
158
|
-
for (const name of toRemove) {
|
|
159
|
-
wrapper.removeAttribute(name);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// src/index.ts
|
|
164
|
-
var processedWrappers = /* @__PURE__ */ new WeakSet();
|
|
165
|
-
function warnChild(message) {
|
|
166
|
-
console.warn(message);
|
|
167
|
-
}
|
|
168
|
-
function childPlugin(Alpine) {
|
|
169
|
-
Alpine.addInitSelector(() => `[${Alpine.prefixed("child")}]`);
|
|
170
|
-
Alpine.interceptInit((el, skip) => {
|
|
171
|
-
const config = parseChildDirective(el);
|
|
172
|
-
if (!config) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
if (processedWrappers.has(el)) {
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
const target = findFirstElementChild(el);
|
|
179
|
-
if (!target) {
|
|
180
|
-
warnChild("[x-child] No element child found; directive ignored.");
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
if (countElementChildren(el) > 1) {
|
|
184
|
-
warnChild("[x-child] Multiple element children; only the first is used.");
|
|
185
|
-
}
|
|
186
|
-
const morph = Alpine.morph;
|
|
187
|
-
if (typeof morph !== "function") {
|
|
188
|
-
warnChild(
|
|
189
|
-
"[x-child] @alpinejs/morph is required \u2014 register Alpine.plugin(morph) before x-child."
|
|
190
|
-
);
|
|
191
|
-
return;
|
|
192
|
-
}
|
|
193
|
-
processedWrappers.add(el);
|
|
194
|
-
el._x_ignoreSelf = true;
|
|
195
|
-
target._x_ignore = true;
|
|
196
|
-
skip();
|
|
197
|
-
Alpine.nextTick(() => {
|
|
198
|
-
if (!(el.isConnected || target.isConnected)) {
|
|
199
|
-
return;
|
|
200
|
-
}
|
|
201
|
-
transferAttributes(el, target, config.mode);
|
|
202
|
-
let promoted = null;
|
|
203
|
-
Alpine.mutateDom(() => {
|
|
204
|
-
morph(el, target.outerHTML, {
|
|
205
|
-
added(node) {
|
|
206
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
207
|
-
promoted = node;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
const result = promoted ?? (el.isConnected ? el : null);
|
|
213
|
-
if (result) {
|
|
214
|
-
processedWrappers.add(result);
|
|
215
|
-
result._x_ignore = void 0;
|
|
216
|
-
Alpine.initTree(result);
|
|
217
|
-
}
|
|
218
|
-
clearTransferredAttributes(el);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
Alpine.directive("child", () => {
|
|
222
|
-
}).before("ignore");
|
|
223
|
-
}
|
|
224
|
-
export {
|
|
225
|
-
clearTransferredAttributes,
|
|
226
|
-
countElementChildren,
|
|
227
|
-
childPlugin as default,
|
|
228
|
-
findFirstElementChild,
|
|
229
|
-
parseChildDirective,
|
|
230
|
-
transferAttributes
|
|
231
|
-
};
|
|
232
|
-
//# sourceMappingURL=index.js.map
|
|
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};
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ailuracode/alpine-child",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.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",
|
|
7
7
|
"author": "ailuracode",
|
|
8
|
+
"sideEffects": false,
|
|
8
9
|
"publishConfig": {
|
|
9
10
|
"access": "public"
|
|
10
11
|
},
|
|
@@ -32,8 +33,8 @@
|
|
|
32
33
|
},
|
|
33
34
|
"types": "./dist/global.d.ts",
|
|
34
35
|
"peerDependencies": {
|
|
36
|
+
"@ailuracode/alpine-core": "^0.2.0",
|
|
35
37
|
"@alpinejs/morph": "^3.0.0",
|
|
36
|
-
"@types/alpinejs": "^3.13.11",
|
|
37
38
|
"alpinejs": "^3.0.0"
|
|
38
39
|
},
|
|
39
40
|
"peerDependenciesMeta": {
|
|
@@ -42,7 +43,11 @@
|
|
|
42
43
|
}
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
|
-
"@alpinejs/morph": "^3.15.12"
|
|
46
|
+
"@alpinejs/morph": "^3.15.12",
|
|
47
|
+
"@types/alpinejs": "^3.13.10",
|
|
48
|
+
"@types/node": "^26.1.0",
|
|
49
|
+
"tsup": "^8.5.0",
|
|
50
|
+
"@ailuracode/alpine-core": "0.2.0"
|
|
46
51
|
},
|
|
47
52
|
"keywords": [
|
|
48
53
|
"alpinejs",
|
|
@@ -53,7 +58,10 @@
|
|
|
53
58
|
"headless"
|
|
54
59
|
],
|
|
55
60
|
"scripts": {
|
|
56
|
-
"
|
|
57
|
-
"
|
|
61
|
+
"clean": "rm -rf dist",
|
|
62
|
+
"build": "tsup --config tsup.config.ts && cp src/global.d.ts dist/global.d.ts",
|
|
63
|
+
"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"
|
|
58
66
|
}
|
|
59
67
|
}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transfer.ts","../src/index.ts"],"sourcesContent":["export type ChildMergeMode = \"default\" | \"merge\" | \"replace\";\n\nconst CHILD_DIRECTIVE_PREFIX = \"x-child\";\n\nconst NEVER_TRANSFER = new Set([\n CHILD_DIRECTIVE_PREFIX,\n \"x-ignore\",\n \"x-ignore.self\",\n \"x-teleport\",\n \"x-cloak\",\n]);\n\nconst NEVER_TRANSFER_PREFIXES = [\"x-child.\", \"x-teleport.\", \"x-transition\", \"x-effect\"];\n\nconst SCOPE_ATTRS = new Set([\"x-data\", \"x-init\", \"x-ref\"]);\n\nfunction isNeverTransfer(name: string): boolean {\n if (NEVER_TRANSFER.has(name)) {\n return true;\n }\n\n return NEVER_TRANSFER_PREFIXES.some((prefix) => name.startsWith(prefix));\n}\n\n/** Returns the first element child, skipping text and comment nodes. */\nexport function findFirstElementChild(parent: Element): Element | null {\n for (const node of parent.childNodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n return node as Element;\n }\n }\n\n return null;\n}\n\n/** Counts element children (excluding text/comment nodes). */\nexport function countElementChildren(parent: Element): number {\n let count = 0;\n\n for (const node of parent.childNodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n count += 1;\n }\n }\n\n return count;\n}\n\n/** Parses `x-child` directive modifiers from element attributes. */\nexport function parseChildDirective(el: Element): { mode: ChildMergeMode } | null {\n for (const { name } of el.attributes) {\n if (name === CHILD_DIRECTIVE_PREFIX) {\n return { mode: \"default\" };\n }\n\n if (!name.startsWith(`${CHILD_DIRECTIVE_PREFIX}.`)) {\n continue;\n }\n\n const modifiers = name.slice(CHILD_DIRECTIVE_PREFIX.length + 1).split(\".\");\n\n if (modifiers.includes(\"replace\")) {\n return { mode: \"replace\" };\n }\n\n if (modifiers.includes(\"merge\")) {\n return { mode: \"merge\" };\n }\n\n return { mode: \"default\" };\n }\n\n return null;\n}\n\nfunction mergeClassTokens(...values: string[]): string {\n const tokens = new Set<string>();\n\n for (const value of values) {\n for (const token of value.split(/\\s+/)) {\n if (token) {\n tokens.add(token);\n }\n }\n }\n\n return [...tokens].join(\" \");\n}\n\nfunction parseInlineStyle(style: string): Map<string, string> {\n const map = new Map<string, string>();\n\n for (const part of style.split(\";\")) {\n const trimmed = part.trim();\n if (!trimmed) {\n continue;\n }\n\n const colon = trimmed.indexOf(\":\");\n if (colon === -1) {\n continue;\n }\n\n const property = trimmed.slice(0, colon).trim().toLowerCase();\n const value = trimmed.slice(colon + 1).trim();\n map.set(property, value);\n }\n\n return map;\n}\n\nfunction serializeInlineStyle(map: Map<string, string>): string {\n return [...map.entries()].map(([property, value]) => `${property}: ${value}`).join(\"; \");\n}\n\nfunction mergeInlineStyle(wrapperStyle: string, childStyle: string, childWins: boolean): string {\n const wrapperMap = parseInlineStyle(wrapperStyle);\n const childMap = parseInlineStyle(childStyle);\n const merged = childWins\n ? new Map([...wrapperMap, ...childMap])\n : new Map([...childMap, ...wrapperMap]);\n\n return serializeInlineStyle(merged);\n}\n\nfunction childHasAttribute(el: Element, name: string): boolean {\n return el.hasAttribute(name);\n}\n\nfunction shouldCopyAttribute(\n name: string,\n wrapper: Element,\n child: Element,\n mode: ChildMergeMode\n): boolean {\n if (isNeverTransfer(name)) {\n return false;\n }\n\n if (name === \"id\" && childHasAttribute(child, \"id\")) {\n return false;\n }\n\n if (SCOPE_ATTRS.has(name) && childHasAttribute(child, name)) {\n return false;\n }\n\n if (mode === \"replace\") {\n return wrapper.hasAttribute(name);\n }\n\n if (mode === \"default\" || mode === \"merge\") {\n if (name === \"class\" || name === \"style\") {\n return wrapper.hasAttribute(name);\n }\n\n return wrapper.hasAttribute(name) && !childHasAttribute(child, name);\n }\n\n return false;\n}\n\nfunction applyAttribute(\n wrapper: Element,\n child: Element,\n name: string,\n mode: ChildMergeMode\n): void {\n const wrapperValue = wrapper.getAttribute(name) ?? \"\";\n const childValue = child.getAttribute(name) ?? \"\";\n\n if (name === \"class\") {\n if (mode === \"replace\") {\n child.setAttribute(\"class\", mergeClassTokens(wrapperValue, childValue));\n return;\n }\n\n child.setAttribute(\"class\", mergeClassTokens(childValue, wrapperValue));\n return;\n }\n\n if (name === \"style\") {\n const merged = mergeInlineStyle(wrapperValue, childValue, mode !== \"replace\");\n if (merged) {\n child.setAttribute(\"style\", merged);\n }\n return;\n }\n\n if (mode === \"replace\" || !childHasAttribute(child, name)) {\n child.setAttribute(name, wrapperValue);\n }\n}\n\n/** Transfers wrapper attributes onto the first element child. */\nexport function transferAttributes(\n wrapper: Element,\n child: Element,\n mode: ChildMergeMode = \"default\"\n): void {\n const names = new Set<string>();\n\n for (const { name } of wrapper.attributes) {\n names.add(name);\n }\n\n for (const name of names) {\n if (!shouldCopyAttribute(name, wrapper, child, mode)) {\n continue;\n }\n\n applyAttribute(wrapper, child, name, mode);\n }\n}\n\n/** Removes transferable attributes from the wrapper after unwrapping. */\nexport function clearTransferredAttributes(wrapper: Element): void {\n const toRemove: string[] = [];\n\n for (const { name } of wrapper.attributes) {\n if (isNeverTransfer(name)) {\n toRemove.push(name);\n continue;\n }\n\n toRemove.push(name);\n }\n\n for (const name of toRemove) {\n wrapper.removeAttribute(name);\n }\n}\n","import type AlpineType from \"alpinejs\";\nimport {\n clearTransferredAttributes,\n countElementChildren,\n findFirstElementChild,\n parseChildDirective,\n transferAttributes,\n} from \"./transfer.js\";\n\nexport type { ChildMergeMode } from \"./transfer.js\";\nexport {\n clearTransferredAttributes,\n countElementChildren,\n findFirstElementChild,\n parseChildDirective,\n transferAttributes,\n} from \"./transfer.js\";\n\nconst processedWrappers = new WeakSet<Element>();\n\ntype AlpineElement = Element & {\n _x_ignore?: boolean;\n _x_ignoreSelf?: boolean;\n};\n\ntype MorphOptions = {\n added?: (node: Node) => void;\n};\n\ntype AlpineWithMorph = AlpineType.Alpine & {\n morph?: (el: Element, newHtml: string | Element, options?: MorphOptions) => Element;\n};\n\nfunction warnChild(message: string): void {\n // biome-ignore lint/suspicious/noConsole: intentional developer warnings for invalid markup\n console.warn(message);\n}\n\n/** Alpine.js plugin. Registers the `x-child` directive (asChild-style unwrapping). */\nexport default function childPlugin(Alpine: AlpineType.Alpine): void {\n Alpine.addInitSelector(() => `[${Alpine.prefixed(\"child\")}]`);\n\n Alpine.interceptInit((el: Element, skip: () => void) => {\n const config = parseChildDirective(el);\n if (!config) {\n return;\n }\n\n if (processedWrappers.has(el)) {\n return;\n }\n\n const target = findFirstElementChild(el);\n if (!target) {\n warnChild(\"[x-child] No element child found; directive ignored.\");\n return;\n }\n\n if (countElementChildren(el) > 1) {\n warnChild(\"[x-child] Multiple element children; only the first is used.\");\n }\n\n const morph = (Alpine as AlpineWithMorph).morph;\n if (typeof morph !== \"function\") {\n warnChild(\n \"[x-child] @alpinejs/morph is required — register Alpine.plugin(morph) before x-child.\"\n );\n return;\n }\n\n // Defer unwrap until after the current initTree pass so DOM mutations from\n // morph do not corrupt scope for siblings initialized later (e.g. sidebar).\n processedWrappers.add(el);\n (el as AlpineElement)._x_ignoreSelf = true;\n (target as AlpineElement)._x_ignore = true;\n skip();\n\n Alpine.nextTick(() => {\n if (!(el.isConnected || target.isConnected)) {\n return;\n }\n\n transferAttributes(el, target, config.mode);\n\n let promoted: Element | null = null;\n\n Alpine.mutateDom(() => {\n morph(el, target.outerHTML, {\n added(node) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n promoted = node as Element;\n }\n },\n });\n });\n\n const result = promoted ?? (el.isConnected ? el : null);\n if (result) {\n processedWrappers.add(result);\n (result as AlpineElement)._x_ignore = undefined;\n Alpine.initTree(result as HTMLElement);\n }\n\n clearTransferredAttributes(el);\n });\n });\n\n Alpine.directive(\"child\", () => {\n // Unwrap runs in interceptInit before other directives on the wrapper.\n }).before(\"ignore\");\n}\n"],"mappings":"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","names":[]}
|