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.
Files changed (2) hide show
  1. package/package.json +23 -0
  2. 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
+ }