rask-ui 0.3.4 → 0.4.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 (61) hide show
  1. package/README.md +251 -79
  2. package/dist/batch.d.ts +4 -0
  3. package/dist/batch.d.ts.map +1 -0
  4. package/dist/batch.js +86 -0
  5. package/dist/component.d.ts +9 -1
  6. package/dist/component.d.ts.map +1 -1
  7. package/dist/component.js +15 -7
  8. package/dist/createComputed.d.ts +4 -0
  9. package/dist/createComputed.d.ts.map +1 -0
  10. package/dist/createComputed.js +34 -0
  11. package/dist/createEffect.d.ts +2 -0
  12. package/dist/createEffect.d.ts.map +1 -0
  13. package/dist/createEffect.js +19 -0
  14. package/dist/index.d.ts +4 -1
  15. package/dist/index.d.ts.map +1 -1
  16. package/dist/index.js +11 -1
  17. package/dist/observation.d.ts.map +1 -1
  18. package/dist/observation.js +4 -3
  19. package/dist/plugin.d.ts +8 -0
  20. package/dist/plugin.d.ts.map +1 -0
  21. package/dist/plugin.js +195 -0
  22. package/dist/scheduler.d.ts +4 -0
  23. package/dist/scheduler.d.ts.map +1 -0
  24. package/dist/scheduler.js +107 -0
  25. package/package.json +1 -1
  26. package/dist/createRef.d.ts +0 -5
  27. package/dist/createRef.d.ts.map +0 -1
  28. package/dist/createRef.js +0 -7
  29. package/dist/test-setup.d.ts +0 -16
  30. package/dist/test-setup.d.ts.map +0 -1
  31. package/dist/test-setup.js +0 -40
  32. package/dist/vdom/AbstractVNode.d.ts +0 -44
  33. package/dist/vdom/AbstractVNode.d.ts.map +0 -1
  34. package/dist/vdom/AbstractVNode.js +0 -256
  35. package/dist/vdom/ComponentVNode.d.ts +0 -48
  36. package/dist/vdom/ComponentVNode.d.ts.map +0 -1
  37. package/dist/vdom/ComponentVNode.js +0 -221
  38. package/dist/vdom/ElementVNode.d.ts +0 -27
  39. package/dist/vdom/ElementVNode.d.ts.map +0 -1
  40. package/dist/vdom/ElementVNode.js +0 -220
  41. package/dist/vdom/FragmentVNode.d.ts +0 -13
  42. package/dist/vdom/FragmentVNode.d.ts.map +0 -1
  43. package/dist/vdom/FragmentVNode.js +0 -49
  44. package/dist/vdom/RootVNode.d.ts +0 -25
  45. package/dist/vdom/RootVNode.d.ts.map +0 -1
  46. package/dist/vdom/RootVNode.js +0 -79
  47. package/dist/vdom/TextVNode.d.ts +0 -11
  48. package/dist/vdom/TextVNode.d.ts.map +0 -1
  49. package/dist/vdom/TextVNode.js +0 -35
  50. package/dist/vdom/dom-utils.d.ts +0 -14
  51. package/dist/vdom/dom-utils.d.ts.map +0 -1
  52. package/dist/vdom/dom-utils.js +0 -103
  53. package/dist/vdom/index.d.ts +0 -10
  54. package/dist/vdom/index.d.ts.map +0 -1
  55. package/dist/vdom/index.js +0 -26
  56. package/dist/vdom/types.d.ts +0 -20
  57. package/dist/vdom/types.d.ts.map +0 -1
  58. package/dist/vdom/types.js +0 -1
  59. package/dist/vdom/utils.d.ts +0 -6
  60. package/dist/vdom/utils.d.ts.map +0 -1
  61. package/dist/vdom/utils.js +0 -63
@@ -0,0 +1,19 @@
1
+ import { getCurrentComponent, onCleanup } from "./component";
2
+ import { Observer } from "./observation";
3
+ export function createEffect(cb) {
4
+ const currentComponent = getCurrentComponent();
5
+ const observer = new Observer(() => {
6
+ // We trigger effects on micro task as synchronous observer notifications
7
+ // (Like when components sets props) should not synchronously trigger effects
8
+ queueMicrotask(runEffect);
9
+ });
10
+ const runEffect = () => {
11
+ const stopObserving = observer.observe();
12
+ cb();
13
+ stopObserving();
14
+ };
15
+ if (currentComponent) {
16
+ onCleanup(() => observer.dispose());
17
+ }
18
+ runEffect();
19
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { render } from "inferno";
1
+ import { render as infernoRender } from "inferno";
2
2
  export { onCleanup, onMount } from "./component";
3
3
  export { createContext } from "./createContext";
4
4
  export { createState } from "./createState";
@@ -8,4 +8,7 @@ export { createQuery } from "./createQuery";
8
8
  export { createMutation } from "./createMutation";
9
9
  export { createRef } from "inferno";
10
10
  export { createView } from "./createView";
11
+ export { createEffect } from "./createEffect";
12
+ export { createComputed } from "./createComputed";
13
+ export declare function render(...params: Parameters<typeof infernoRender>): void;
11
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,SAAS,CAAC;AAElD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,wBAAgB,MAAM,CAAC,GAAG,MAAM,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,QAMjE"}
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
- export { render } from "inferno";
1
+ import { render as infernoRender } from "inferno";
2
+ import { installEventBatching } from "./batch";
2
3
  export { onCleanup, onMount } from "./component";
3
4
  export { createContext } from "./createContext";
4
5
  export { createState } from "./createState";
@@ -8,3 +9,12 @@ export { createQuery } from "./createQuery";
8
9
  export { createMutation } from "./createMutation";
9
10
  export { createRef } from "inferno";
10
11
  export { createView } from "./createView";
12
+ export { createEffect } from "./createEffect";
13
+ export { createComputed } from "./createComputed";
14
+ export function render(...params) {
15
+ if (!params[1]) {
16
+ throw new Error("You need a target container");
17
+ }
18
+ installEventBatching(params[1]);
19
+ return infernoRender(...params);
20
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAEA,wBAAgB,kBAAkB,aAEjC;AAKD,qBAAa,MAAM;IACjB,OAAO,CAAC,WAAW,CAAyB;IAC5C,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAOxB,MAAM;CAIP;AAED,qBAAa,QAAQ;IACnB,UAAU,UAAS;IACnB,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,QAAQ,CAAa;gBACjB,QAAQ,EAAE,MAAM,IAAI;IAGhC,eAAe,CAAC,MAAM,EAAE,MAAM;IAG9B,OAAO;IAOP,OAAO;CAIR"}
1
+ {"version":3,"file":"observation.d.ts","sourceRoot":"","sources":["../src/observation.ts"],"names":[],"mappings":"AAIA,wBAAgB,kBAAkB,aAEjC;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,WAAW,CAAyB;IAC5C,SAAS,CAAC,EAAE,EAAE,MAAM,IAAI;IAOxB,MAAM;CAIP;AAED,qBAAa,QAAQ;IACnB,UAAU,UAAS;IACnB,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,QAAQ,CAAa;gBACjB,QAAQ,EAAE,MAAM,IAAI;IAKhC,eAAe,CAAC,MAAM,EAAE,MAAM;IAG9B,OAAO;IAOP,OAAO;CAIR"}
@@ -1,9 +1,8 @@
1
+ import { queue } from "./batch";
1
2
  const observerStack = [];
2
3
  export function getCurrentObserver() {
3
4
  return observerStack[0];
4
5
  }
5
- let isQueuingNotify = false;
6
- let notifyQueue = [];
7
6
  export class Signal {
8
7
  subscribers = new Set();
9
8
  subscribe(cb) {
@@ -26,7 +25,9 @@ export class Observer {
26
25
  }
27
26
  onNotify;
28
27
  constructor(onNotify) {
29
- this.onNotify = onNotify;
28
+ this.onNotify = () => {
29
+ queue(onNotify);
30
+ };
30
31
  }
31
32
  subscribeSignal(signal) {
32
33
  this.signalDisposers.add(signal.subscribe(this.onNotify));
@@ -0,0 +1,8 @@
1
+ import type { Plugin } from 'vite';
2
+ interface RaskPluginOptions {
3
+ include?: RegExp;
4
+ exclude?: RegExp;
5
+ }
6
+ export declare function raskPlugin(options?: RaskPluginOptions): Plugin;
7
+ export {};
8
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAMnC,UAAU,iBAAiB;IACzB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAyDD,wBAAgB,UAAU,CAAC,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAsPlE"}
package/dist/plugin.js ADDED
@@ -0,0 +1,195 @@
1
+ import { parse } from '@babel/parser';
2
+ import _traverse from '@babel/traverse';
3
+ import _generate from '@babel/generator';
4
+ import * as t from '@babel/types';
5
+ // Handle ESM/CJS interop
6
+ const traverse = _traverse.default || _traverse;
7
+ const generate = _generate.default || _generate;
8
+ function isJSXReturnStatement(node) {
9
+ if (t.isJSXElement(node) || t.isJSXFragment(node)) {
10
+ return true;
11
+ }
12
+ if (t.isReturnStatement(node)) {
13
+ return node.argument ? isJSXReturnStatement(node.argument) : false;
14
+ }
15
+ if (t.isBlockStatement(node)) {
16
+ return node.body.some(isJSXReturnStatement);
17
+ }
18
+ if (t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {
19
+ // For arrow functions, check the body
20
+ return isJSXReturnStatement(node.body);
21
+ }
22
+ if (t.isConditionalExpression(node)) {
23
+ return isJSXReturnStatement(node.consequent) || isJSXReturnStatement(node.alternate);
24
+ }
25
+ if (t.isLogicalExpression(node)) {
26
+ return isJSXReturnStatement(node.right);
27
+ }
28
+ return false;
29
+ }
30
+ function isComponentFunction(node) {
31
+ // Check if function returns a function that returns JSX
32
+ if (t.isFunctionDeclaration(node) || t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {
33
+ // Handle arrow function with implicit return
34
+ if ((t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) &&
35
+ (t.isArrowFunctionExpression(node.body) || t.isFunctionExpression(node.body))) {
36
+ return isJSXReturnStatement(node.body);
37
+ }
38
+ // Handle functions with block body
39
+ if (t.isBlockStatement(node.body)) {
40
+ const returnStatements = node.body.body.filter(s => t.isReturnStatement(s));
41
+ return returnStatements.some(ret => {
42
+ if (!ret.argument)
43
+ return false;
44
+ if (t.isArrowFunctionExpression(ret.argument) || t.isFunctionExpression(ret.argument)) {
45
+ return isJSXReturnStatement(ret.argument);
46
+ }
47
+ return false;
48
+ });
49
+ }
50
+ }
51
+ return false;
52
+ }
53
+ export function raskPlugin(options = {}) {
54
+ const { include = /\.(jsx|tsx)$/, exclude = /node_modules/, } = options;
55
+ return {
56
+ name: 'rask-transform',
57
+ enforce: 'pre',
58
+ transform(code, id) {
59
+ // Skip if doesn't match include/exclude patterns
60
+ if (!include.test(id) || exclude.test(id)) {
61
+ return null;
62
+ }
63
+ try {
64
+ const ast = parse(code, {
65
+ sourceType: 'module',
66
+ plugins: ['jsx', 'typescript'],
67
+ });
68
+ let hasChanges = false;
69
+ let hasRaskComponentImport = false;
70
+ traverse(ast, {
71
+ ImportDeclaration(path) {
72
+ // Check if RaskComponent is already imported
73
+ if (path.node.source.value === 'rask-ui') {
74
+ const specifiers = path.node.specifiers;
75
+ hasRaskComponentImport = specifiers.some(s => t.isImportSpecifier(s) &&
76
+ t.isIdentifier(s.imported) &&
77
+ s.imported.name === 'RaskComponent');
78
+ }
79
+ },
80
+ ExportNamedDeclaration(path) {
81
+ const declaration = path.node.declaration;
82
+ if (!declaration)
83
+ return;
84
+ // Handle export function
85
+ if (t.isFunctionDeclaration(declaration)) {
86
+ if (!declaration.id)
87
+ return;
88
+ const isComponent = isComponentFunction(declaration);
89
+ if (!isComponent) {
90
+ return;
91
+ }
92
+ hasChanges = true;
93
+ const className = declaration.id.name;
94
+ const setupMethod = t.classProperty(t.identifier('setup'), t.functionExpression(t.identifier(className), declaration.params, declaration.body, declaration.generator, declaration.async));
95
+ const classDeclaration = t.classDeclaration(t.identifier(className), t.identifier('RaskComponent'), t.classBody([setupMethod]), []);
96
+ path.replaceWith(t.exportNamedDeclaration(classDeclaration, []));
97
+ path.skip();
98
+ }
99
+ // Handle export const/let/var
100
+ if (t.isVariableDeclaration(declaration)) {
101
+ const declarator = declaration.declarations[0];
102
+ if (!declarator || !t.isIdentifier(declarator.id))
103
+ return;
104
+ const init = declarator.init;
105
+ if (!init || !isComponentFunction(init))
106
+ return;
107
+ hasChanges = true;
108
+ const componentName = declarator.id.name;
109
+ let functionExpr;
110
+ if (t.isArrowFunctionExpression(init) || t.isFunctionExpression(init)) {
111
+ functionExpr = t.functionExpression(t.identifier(componentName), init.params, t.isExpression(init.body)
112
+ ? t.blockStatement([t.returnStatement(init.body)])
113
+ : init.body, init.generator, init.async);
114
+ }
115
+ else {
116
+ return;
117
+ }
118
+ const setupMethod = t.classProperty(t.identifier('setup'), functionExpr);
119
+ const classDeclaration = t.classDeclaration(t.identifier(componentName), t.identifier('RaskComponent'), t.classBody([setupMethod]), []);
120
+ path.replaceWith(t.exportNamedDeclaration(classDeclaration, []));
121
+ path.skip();
122
+ }
123
+ },
124
+ FunctionDeclaration(path) {
125
+ const node = path.node;
126
+ // Skip if not a component function or if it's part of an export
127
+ if (!node.id || !isComponentFunction(node) || path.parent.type === 'ExportNamedDeclaration') {
128
+ return;
129
+ }
130
+ hasChanges = true;
131
+ // Create the class declaration
132
+ const className = node.id.name;
133
+ const setupMethod = t.classProperty(t.identifier('setup'), t.functionExpression(t.identifier(className), node.params, node.body, node.generator, node.async));
134
+ const classDeclaration = t.classDeclaration(t.identifier(className), t.identifier('RaskComponent'), t.classBody([setupMethod]), []);
135
+ path.replaceWith(classDeclaration);
136
+ path.skip();
137
+ },
138
+ VariableDeclarator(path) {
139
+ const node = path.node;
140
+ // Check if it's a function component assigned to a variable
141
+ if (!t.isIdentifier(node.id))
142
+ return;
143
+ const init = node.init;
144
+ if (!init || !isComponentFunction(init))
145
+ return;
146
+ // Skip if it's part of an export
147
+ if (path.parentPath.parent?.type === 'ExportNamedDeclaration') {
148
+ return;
149
+ }
150
+ hasChanges = true;
151
+ const componentName = node.id.name;
152
+ // Create function expression from arrow function or function expression
153
+ let functionExpr;
154
+ if (t.isArrowFunctionExpression(init) || t.isFunctionExpression(init)) {
155
+ functionExpr = t.functionExpression(t.identifier(componentName), init.params, t.isExpression(init.body)
156
+ ? t.blockStatement([t.returnStatement(init.body)])
157
+ : init.body, init.generator, init.async);
158
+ }
159
+ else {
160
+ return;
161
+ }
162
+ const setupMethod = t.classProperty(t.identifier('setup'), functionExpr);
163
+ const classDeclaration = t.classDeclaration(t.identifier(componentName), t.identifier('RaskComponent'), t.classBody([setupMethod]), []);
164
+ // Replace the entire variable declaration with class declaration
165
+ const parentPath = path.parentPath;
166
+ if (t.isVariableDeclaration(parentPath.node) && parentPath.node.declarations.length === 1) {
167
+ parentPath.replaceWith(classDeclaration);
168
+ parentPath.skip();
169
+ }
170
+ },
171
+ });
172
+ // Add import if we made changes and RaskComponent wasn't imported
173
+ if (hasChanges && !hasRaskComponentImport) {
174
+ const importDecl = t.importDeclaration([t.importSpecifier(t.identifier('RaskComponent'), t.identifier('RaskComponent'))], t.stringLiteral('rask-ui'));
175
+ ast.program.body.unshift(importDecl);
176
+ }
177
+ if (!hasChanges) {
178
+ return null;
179
+ }
180
+ const output = generate(ast, {
181
+ retainLines: false,
182
+ compact: false,
183
+ }, code);
184
+ return {
185
+ code: output.code,
186
+ map: output.map,
187
+ };
188
+ }
189
+ catch (error) {
190
+ console.error('Error in rask-transform plugin:', error);
191
+ return null;
192
+ }
193
+ },
194
+ };
195
+ }
@@ -0,0 +1,4 @@
1
+ export declare function markDirty(): void;
2
+ export declare function enqueueUpdateFromSetter(): void;
3
+ export declare function installGlobalBatching(target?: EventTarget): () => void;
4
+ //# sourceMappingURL=scheduler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,SAExB;AAeD,wBAAgB,uBAAuB,SAWtC;AAmED,wBAAgB,qBAAqB,CAAC,MAAM,GAAE,WAAoB,cAoBjE"}
@@ -0,0 +1,107 @@
1
+ let depth = 0; // batching scope nesting
2
+ let dirty = false; // has any state update been enqueued?
3
+ let scheduled = false; // async flush scheduled?
4
+ export function markDirty() {
5
+ dirty = true;
6
+ }
7
+ function performWork() {
8
+ // TODO: call your Inferno render/commit once.
9
+ // infernoRender(vnode, container);
10
+ }
11
+ function flushNow() {
12
+ scheduled = false;
13
+ if (!dirty)
14
+ return;
15
+ dirty = false;
16
+ performWork();
17
+ }
18
+ // Called by setters after enqueueing their state change
19
+ export function enqueueUpdateFromSetter() {
20
+ dirty = true;
21
+ if (depth > 0) {
22
+ // We're inside a batched input event; we'll flush on exit (same frame).
23
+ return;
24
+ }
25
+ if (!scheduled) {
26
+ scheduled = true;
27
+ queueMicrotask(flushNow); // one flush per task
28
+ }
29
+ }
30
+ // Batch-scope control used by the global capture listeners
31
+ function enter() {
32
+ depth++;
33
+ }
34
+ function exit() {
35
+ if (--depth === 0) {
36
+ // End of the event propagation; commit now (before next paint).
37
+ flushNow();
38
+ }
39
+ }
40
+ // eventBatching.ts
41
+ const INTERACTIVE_EVENTS = [
42
+ // Pointer + mouse
43
+ "click",
44
+ "dblclick",
45
+ "contextmenu",
46
+ "mousedown",
47
+ "mouseup",
48
+ "mousemove",
49
+ "pointerdown",
50
+ "pointerup",
51
+ "pointermove",
52
+ "touchstart",
53
+ "touchmove",
54
+ "touchend",
55
+ "touchcancel",
56
+ "dragstart",
57
+ "drag",
58
+ "dragend",
59
+ "dragenter",
60
+ "dragleave",
61
+ "dragover",
62
+ "drop",
63
+ "wheel",
64
+ // Keyboard
65
+ "keydown",
66
+ "keypress",
67
+ "keyup",
68
+ // Focus & input
69
+ "focus",
70
+ "blur",
71
+ "focusin",
72
+ "focusout",
73
+ "input",
74
+ "beforeinput",
75
+ "change",
76
+ "compositionstart",
77
+ "compositionupdate",
78
+ "compositionend",
79
+ // Forms
80
+ "submit",
81
+ "reset",
82
+ // Selection / clipboard
83
+ "select",
84
+ "selectionchange",
85
+ "copy",
86
+ "cut",
87
+ "paste",
88
+ ];
89
+ export function installGlobalBatching(target = window) {
90
+ const handlers = [];
91
+ INTERACTIVE_EVENTS.forEach((type) => {
92
+ const onCapture = () => {
93
+ enter();
94
+ // Close the scope after all handlers (capture→target→bubble) have run.
95
+ queueMicrotask(exit);
96
+ };
97
+ target.addEventListener(type, onCapture, { capture: true });
98
+ handlers.push([onCapture, { capture: true }]);
99
+ });
100
+ // Return a disposer so you can remove on unmount
101
+ return () => {
102
+ INTERACTIVE_EVENTS.forEach((type, i) => {
103
+ const [fn, opts] = handlers[i];
104
+ target.removeEventListener(type, fn, opts);
105
+ });
106
+ };
107
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rask-ui",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -1,5 +0,0 @@
1
- export declare function createRef<T>(): {
2
- (node: T | null): void;
3
- current: T | null;
4
- };
5
- //# sourceMappingURL=createRef.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"createRef.d.ts","sourceRoot":"","sources":["../src/createRef.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,CAAC;WACN,CAAC,GAAG,IAAI;;EAO5B"}
package/dist/createRef.js DELETED
@@ -1,7 +0,0 @@
1
- export function createRef() {
2
- function ref(node) {
3
- ref.current = node;
4
- }
5
- ref.current = null;
6
- return ref;
7
- }
@@ -1,16 +0,0 @@
1
- import { VNode } from "inferno";
2
- /**
3
- * Test helper to render a component and provide easy cleanup
4
- *
5
- * @example
6
- * const { container, unmount } = renderComponent(<MyComponent />);
7
- * expect(container.textContent).toBe('hello');
8
- * unmount();
9
- */
10
- export declare function renderComponent(vnode: VNode): {
11
- container: HTMLElement;
12
- vnode: void;
13
- unmount: () => void;
14
- rerender: (newVnode: VNode) => void;
15
- };
16
- //# sourceMappingURL=test-setup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../src/test-setup.ts"],"names":[],"mappings":"AAGA,OAAO,EAAU,KAAK,EAAE,MAAM,SAAS,CAAC;AAUxC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK;;;;yBAoBnB,KAAK;EAI7B"}
@@ -1,40 +0,0 @@
1
- // Test setup file for vitest
2
- import { afterEach } from "vitest";
3
- import { render } from "inferno";
4
- // Clean up after each test
5
- afterEach(() => {
6
- document.body.innerHTML = "";
7
- // Remove any style tags added by render function
8
- document.querySelectorAll("style").forEach((style) => style.remove());
9
- });
10
- /**
11
- * Test helper to render a component and provide easy cleanup
12
- *
13
- * @example
14
- * const { container, unmount } = renderComponent(<MyComponent />);
15
- * expect(container.textContent).toBe('hello');
16
- * unmount();
17
- */
18
- export function renderComponent(vnode) {
19
- const container = document.createElement("div");
20
- document.body.appendChild(container);
21
- let currentVnode = render(vnode, container);
22
- // @ts-ignore
23
- const actualElement = currentVnode.elm;
24
- return {
25
- // The actual rendered DOM element (after patch replaces container)
26
- container: actualElement,
27
- // The vnode returned by render
28
- vnode: currentVnode,
29
- // Cleanup function
30
- unmount: () => {
31
- if (actualElement && actualElement.parentNode) {
32
- actualElement.parentNode.removeChild(actualElement);
33
- }
34
- },
35
- // Re-render with new vnode
36
- rerender: (newVnode) => {
37
- currentVnode.patch(newVnode);
38
- },
39
- };
40
- }
@@ -1,44 +0,0 @@
1
- import { RootVNode } from "./RootVNode";
2
- import { VNode } from "./types";
3
- export type PatchOperation = {
4
- type: "add";
5
- elm: Node | Node[];
6
- } | {
7
- type: "replace";
8
- oldElm: Node | Node[];
9
- newElm: Node | Node[];
10
- } | {
11
- type: "remove";
12
- elm: Node | Node[];
13
- };
14
- export declare abstract class AbstractVNode {
15
- key?: string;
16
- parent?: VNode;
17
- root?: RootVNode;
18
- elm?: Node;
19
- children?: VNode[];
20
- abstract mount(parent?: VNode): Node | Node[];
21
- abstract patch(oldNode: VNode): void;
22
- abstract unmount(): void;
23
- abstract rerender(operations?: PatchOperation[]): void;
24
- protected getHTMLElement(): HTMLElement;
25
- /**
26
- * A VNode can represent multiple elements (fragment of component)
27
- */
28
- getElements(): Node[];
29
- getParentElement(): HTMLElement;
30
- protected canPatch(oldNode: VNode, newNode: VNode): boolean;
31
- patchChildren(newChildren: VNode[]): {
32
- children: VNode[];
33
- hasChangedStructure: boolean;
34
- operations?: PatchOperation[];
35
- };
36
- applyPatchOperations(target: HTMLElement, operations: PatchOperation[]): void;
37
- /**
38
- * Intelligently sync DOM to match children VNode order.
39
- * Only performs DOM operations when elements are out of position.
40
- * This is used by both patch() and rerender() to efficiently update children.
41
- */
42
- protected syncDOMChildren(): void;
43
- }
44
- //# sourceMappingURL=AbstractVNode.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AbstractVNode.d.ts","sourceRoot":"","sources":["../../src/vdom/AbstractVNode.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACpB,GACD;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;IACtB,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACvB,GACD;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,GAAG,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;CACpB,CAAC;AAEN,8BAAsB,aAAa;IACjC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,KAAK,CAAC;IACf,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IACnB,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,IAAI,EAAE;IAC7C,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI;IACpC,QAAQ,CAAC,OAAO,IAAI,IAAI;IACxB,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,cAAc,EAAE,GAAG,IAAI;IACtD,SAAS,CAAC,cAAc;IAOxB;;OAEG;IACH,WAAW,IAAI,IAAI,EAAE;IAmBrB,gBAAgB,IAAI,WAAW;IAiB/B,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,GAAG,OAAO;IAoB3D,aAAa,CAAC,WAAW,EAAE,KAAK,EAAE,GAAG;QACnC,QAAQ,EAAE,KAAK,EAAE,CAAC;QAClB,mBAAmB,EAAE,OAAO,CAAC;QAC7B,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC;KAC/B;IAqJD,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE;IAqCtE;;;;OAIG;IACH,SAAS,CAAC,eAAe;CA6B1B"}