mithril-mobs 0.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/package.json +23 -0
- package/src/mobs/index.js +133 -0
package/package.json
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
{
|
2
|
+
"name": "mithril-mobs",
|
3
|
+
"private": false,
|
4
|
+
"version": "0.0.0",
|
5
|
+
"type": "module",
|
6
|
+
"scripts": {
|
7
|
+
"dev": "vite",
|
8
|
+
"build": "vite build",
|
9
|
+
"preview": "vite preview"
|
10
|
+
},
|
11
|
+
"exports": {
|
12
|
+
".": "./src/mobs/index.js"
|
13
|
+
},
|
14
|
+
"files": [
|
15
|
+
"./src/mobs/"
|
16
|
+
],
|
17
|
+
"devDependencies": {
|
18
|
+
"vite": "^6.3.5"
|
19
|
+
},
|
20
|
+
"dependencies": {
|
21
|
+
"mithril": "^2.3.1"
|
22
|
+
}
|
23
|
+
}
|
@@ -0,0 +1,133 @@
|
|
1
|
+
import m from "mithril"
|
2
|
+
|
3
|
+
export function if_(firstCondition) {
|
4
|
+
const conditions = [firstCondition];
|
5
|
+
const vnodes = [];
|
6
|
+
|
7
|
+
const ctx = {
|
8
|
+
then(v) {
|
9
|
+
vnodes.push(v);
|
10
|
+
return prepare(ctx);
|
11
|
+
},
|
12
|
+
elseIf(newCondition) {
|
13
|
+
conditions.push(newCondition); // <- fixed
|
14
|
+
return prepare(ctx);
|
15
|
+
},
|
16
|
+
else(v) {
|
17
|
+
conditions.push(true); // the default branch
|
18
|
+
vnodes.push(v);
|
19
|
+
return prepare(ctx);
|
20
|
+
},
|
21
|
+
view() { // evaluate
|
22
|
+
for (let i = 0; i < conditions.length; i++) {
|
23
|
+
if (conditions[i]) return vnodes[i] || null;
|
24
|
+
}
|
25
|
+
return null;
|
26
|
+
}
|
27
|
+
};
|
28
|
+
|
29
|
+
return prepare(ctx)
|
30
|
+
}
|
31
|
+
|
32
|
+
function prepare(ctx) {
|
33
|
+
const n = m(ctx)
|
34
|
+
n.then = ctx.then
|
35
|
+
n.elseIf = ctx.elseIf
|
36
|
+
n.else = ctx.else
|
37
|
+
n.view = ctx.view
|
38
|
+
return n
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
const Component = {
|
47
|
+
_counter: 0,
|
48
|
+
|
49
|
+
create(def) {
|
50
|
+
const compId = `comp-${Component._counter++}`;
|
51
|
+
|
52
|
+
// Convert SASS-like staticStyles object to CSS string
|
53
|
+
function stylesToCss(styles, prefix = `[data-comp-id="${compId}"]`) {
|
54
|
+
let css = "";
|
55
|
+
let props = [];
|
56
|
+
|
57
|
+
for (const key in styles) {
|
58
|
+
if (key.startsWith("/")) {
|
59
|
+
// Nested selector, replace "/" with space for nesting
|
60
|
+
const selector = prefix + key.replace(/\//g, " ");
|
61
|
+
css += stylesToCss(styles[key], selector);
|
62
|
+
} else {
|
63
|
+
// Style property
|
64
|
+
props.push(`${key}: ${styles[key]};`);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
if (props.length > 0) {
|
69
|
+
css = `${prefix} { ${props.join(" ")} }\n` + css;
|
70
|
+
}
|
71
|
+
|
72
|
+
return css;
|
73
|
+
}
|
74
|
+
|
75
|
+
// Automatically add <style id="component-styles"> if missing
|
76
|
+
let styleTag = document.getElementById("component-styles");
|
77
|
+
if (!styleTag) {
|
78
|
+
styleTag = document.createElement("style");
|
79
|
+
styleTag.id = "component-styles";
|
80
|
+
document.head.appendChild(styleTag);
|
81
|
+
}
|
82
|
+
|
83
|
+
// Use a Set to track injected components
|
84
|
+
styleTag.__injectedComponents = styleTag.__injectedComponents || new Set();
|
85
|
+
|
86
|
+
if (!styleTag.__injectedComponents.has(compId)) {
|
87
|
+
styleTag.appendChild(document.createTextNode(stylesToCss(def.staticStyles || {})));
|
88
|
+
styleTag.__injectedComponents.add(compId);
|
89
|
+
}
|
90
|
+
|
91
|
+
return {
|
92
|
+
...def,
|
93
|
+
view(vnode) {
|
94
|
+
const v = def.view.call(this, vnode);
|
95
|
+
|
96
|
+
if (Array.isArray(v)) {
|
97
|
+
return m("div", { "data-comp-id": compId }, v);
|
98
|
+
}
|
99
|
+
|
100
|
+
if (v && typeof v === "object" && v.tag) {
|
101
|
+
v.attrs = v.attrs || {};
|
102
|
+
v.attrs["data-comp-id"] = compId;
|
103
|
+
return v;
|
104
|
+
}
|
105
|
+
|
106
|
+
return m("div", { "data-comp-id": compId }, v);
|
107
|
+
},
|
108
|
+
};
|
109
|
+
},
|
110
|
+
};
|
111
|
+
|
112
|
+
export const createComponent = (def) => Component.create(def);
|
113
|
+
|
114
|
+
|
115
|
+
export function obs(initialValue) {
|
116
|
+
let value = initialValue;
|
117
|
+
const listeners = new Set();
|
118
|
+
|
119
|
+
return {
|
120
|
+
get() {
|
121
|
+
return value;
|
122
|
+
},
|
123
|
+
set(newValue) {
|
124
|
+
value = newValue
|
125
|
+
listeners.forEach((listener) => listener(value))
|
126
|
+
},
|
127
|
+
subscribe(listener) {
|
128
|
+
listeners.add(listener);
|
129
|
+
// Return an unsubscribe function
|
130
|
+
return () => listeners.delete(listener);
|
131
|
+
}
|
132
|
+
};
|
133
|
+
}
|