olova 2.0.10 → 2.0.11

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.
@@ -1,18 +1,18 @@
1
- name: Publish to NPM
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
-
7
- jobs:
8
- publish:
9
- runs-on: ubuntu-latest
10
- steps:
11
- - uses: actions/checkout@v2
12
- - uses: actions/setup-node@v2
13
- with:
14
- node-version: '14'
15
- registry-url: 'https://registry.npmjs.org'
16
- - run: yarn publish
17
- env:
18
- NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
1
+ name: Publish to NPM
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+
7
+ jobs:
8
+ publish:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - uses: actions/checkout@v2
12
+ - uses: actions/setup-node@v2
13
+ with:
14
+ node-version: '14'
15
+ registry-url: 'https://registry.npmjs.org'
16
+ - run: yarn publish
17
+ env:
18
+ NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
package/README.md CHANGED
@@ -1,54 +1,54 @@
1
- # Olova JavaScript Framework
2
-
3
- Olova is a lightweight and reactive JavaScript framework that simplifies UI
4
- development with a clean, intuitive syntax. It provides a reactivity system and
5
- hooks to manage state and side effects, allowing developers to build modern web
6
- applications with ease.
7
-
8
- ## Features
9
-
10
- - **State Management**: Use the `State` hook to manage reactive state in your
11
- components.
12
- - **Side Effects**: Use the `Effect` hook to run side effects in response to
13
- state changes.
14
- - **JSX-style Syntax**: Write UI components using a simple, declarative
15
- JSX-style syntax.
16
- - **Reactivity**: Automatically re-render components when state changes.
17
-
18
- ## Installation
19
-
20
- To get started with Olova, first install the core library via npm or yarn.
21
-
22
- ```bash
23
- npm install olova
24
- ```
25
-
26
- or
27
-
28
- ```bash
29
- yarn add olova
30
- ```
31
-
32
- ## Example Usage
33
-
34
- Here is an example of a basic component in Olova:
35
-
36
- ```js
37
- import Olova, { State, Effect } from "olova";
38
-
39
- export default function Home() {
40
- const [count, setCount] = State(0);
41
-
42
- Effect(() => {
43
- console.log("Home is rendered");
44
- console.log(count);
45
- }, [count]);
46
-
47
- return (
48
- <>
49
- <h1>{count}</h1>
50
- <button onClick={() => setCount(count + 1)}>Increment</button>
51
- </>
52
- );
53
- }
54
- ```
1
+ # Olova JavaScript Framework
2
+
3
+ Olova is a lightweight and reactive JavaScript framework that simplifies UI
4
+ development with a clean, intuitive syntax. It provides a reactivity system and
5
+ hooks to manage state and side effects, allowing developers to build modern web
6
+ applications with ease.
7
+
8
+ ## Features
9
+
10
+ - **State Management**: Use the `State` hook to manage reactive state in your
11
+ components.
12
+ - **Side Effects**: Use the `Effect` hook to run side effects in response to
13
+ state changes.
14
+ - **JSX-style Syntax**: Write UI components using a simple, declarative
15
+ JSX-style syntax.
16
+ - **Reactivity**: Automatically re-render components when state changes.
17
+
18
+ ## Installation
19
+
20
+ To get started with Olova, first install the core library via npm or yarn.
21
+
22
+ ```bash
23
+ npm install olova
24
+ ```
25
+
26
+ or
27
+
28
+ ```bash
29
+ yarn add olova
30
+ ```
31
+
32
+ ## Example Usage
33
+
34
+ Here is an example of a basic component in Olova:
35
+
36
+ ```js
37
+ import Olova, { State, Effect } from "olova";
38
+
39
+ export default function Home() {
40
+ const [count, setCount] = State(0);
41
+
42
+ Effect(() => {
43
+ console.log("Home is rendered");
44
+ console.log(count);
45
+ }, [count]);
46
+
47
+ return (
48
+ <>
49
+ <h1>{count}</h1>
50
+ <button onClick={() => setCount(count + 1)}>Increment</button>
51
+ </>
52
+ );
53
+ }
54
+ ```
@@ -0,0 +1,14 @@
1
+ import { currentEffect, setCurrentEffect } from "./createSignal";
2
+ function createEffect(t) {
3
+ const e = () => {
4
+ f(), setCurrentEffect(e);
5
+ try {
6
+ f = t() || (() => {});
7
+ } finally {
8
+ setCurrentEffect(null);
9
+ }
10
+ };
11
+ let f = () => {};
12
+ e();
13
+ }
14
+ export { createEffect };
@@ -0,0 +1,21 @@
1
+ import { $state, $effect } from "../olova.js";
2
+ function createMemo(t, e = []) {
3
+ const [o, s] = $state(void 0),
4
+ [c, a] = $state(e),
5
+ [i, r] = $state(void 0);
6
+ return (
7
+ $effect(() => {
8
+ if (
9
+ void 0 === i ||
10
+ ((f = c),
11
+ (o = e).length !== f.length || o.some((t, e) => !Object.is(t, f[e])))
12
+ ) {
13
+ const o = t();
14
+ Object.is(o, i) || (r(o), s(o)), a(e);
15
+ }
16
+ var o, f;
17
+ }),
18
+ o
19
+ );
20
+ }
21
+ export { createMemo };
@@ -0,0 +1,13 @@
1
+ import { createSignal } from "./createSignal";
2
+ function createRef(e = null) {
3
+ const [r, t] = createSignal({ current: e });
4
+ return {
5
+ get current() {
6
+ return r().current;
7
+ },
8
+ set current(e) {
9
+ t({ current: e });
10
+ },
11
+ };
12
+ }
13
+ export { createRef };
@@ -0,0 +1,13 @@
1
+ let currentEffect = null;
2
+ const setCurrentEffect = (t) => {
3
+ currentEffect = t;
4
+ };
5
+ function createSignal(t) {
6
+ let e = t;
7
+ const r = new Set();
8
+ return [
9
+ () => (currentEffect && r.add(currentEffect), e),
10
+ (t) => ((e = "function" == typeof t ? t(e) : t), r.forEach((t) => t()), e),
11
+ ];
12
+ }
13
+ export { createSignal, currentEffect, setCurrentEffect };
package/dist/olova.d.ts CHANGED
@@ -1 +1 @@
1
- declare module "olova";
1
+ declare module "olova";
package/dist/olova.js CHANGED
@@ -1 +1 @@
1
- import{createStateHook}from"./hooks/state";import{createEffectHook}from"./hooks/effect";import{createMemoHook}from"./hooks/memo";import{createRefHook}from"./hooks/ref";import{createCallbackHook}from"./hooks/callback";import{createContextHook}from"./hooks/context";class ReactLite{constructor(){this.rootElement=null,this.components=new Map,this.componentStack=[],this.componentInstances=new Map,this.pendingUpdates=[],this.pendingEffects=[],this.contextSubscriptions=new WeakMap,this.isBatchingUpdates=!1,this.hasScheduledFlush=!1,this.dirtyInstances=null,this.mountedComponents=new Map,this.$state=createStateHook(this),this.$effect=createEffectHook(this),this.$memo=createMemoHook(this),this.$ref=createRefHook(this),this.$callback=createCallbackHook(this),this.$context=createContextHook(this)}createElement(e,t,...n){if(null==e)return console.error("Element type cannot be null or undefined"),null;const o=n.flat(),r=[];return o.forEach((e=>{"string"==typeof e||"number"==typeof e?r.length>0&&("string"==typeof r[r.length-1]||"number"==typeof r[r.length-1])?r[r.length-1]=String(r[r.length-1])+String(e):r.push(e):null!=e&&r.push(e)})),e===Fragment?{type:Fragment,props:{...t,children:r}}:{type:e,props:{...t,children:r}}}render(e,t){try{if(null==e)return;if("string"==typeof e||"number"==typeof e)return void t.appendChild(document.createTextNode(e));if(Array.isArray(e))return void e.forEach((e=>this.render(e,t)));if(!e.type)return void console.error("Invalid element:",e);if(e.type===Fragment)return void(e.props?.children||[]).forEach((e=>this.render(e,t)));if("function"==typeof e.type){const n=e.type,o=this.getComponentInstance(n);this.componentStack.push(o),o.currentHook=0,o.lastProps=e.props;const r=n(e.props);return o.lastResult=r,this.componentStack.pop(),void this.render(r,t)}if("string"==typeof e.type){const n=document.createElement(e.type);return this.applyProps(n,e.props),(e.props?.children||[]).forEach((e=>this.render(e,n))),void t.appendChild(n)}console.error("Unhandled element type:",e.type)}catch(t){console.error("Render error:",t),console.error("Element:",e)}}applyProps(e,t){Object.keys(t||{}).forEach((n=>{if("ref"===n&&t[n])t[n].current=e;else if(n.startsWith("on")){const o=n.toLowerCase().substring(2);e.addEventListener(o,t[n])}else"children"!==n&&("className"===n?e.setAttribute("class",t[n]):e[n]=t[n])}))}getComponentInstance(e){return this.componentInstances.has(e)||this.componentInstances.set(e,{hooks:[],currentHook:0,effects:new Map,cleanups:new Set,pendingEffects:[],contextSubscriptions:new Set,lastProps:null,lastResult:null}),this.componentInstances.get(e)}renderComponent(e,t){const n=this.getComponentInstance(e);this.componentStack.push(n),n.currentHook=0;const o=e();n.lastResult=o,this.render(o,t),this.componentStack.pop()}scheduleUpdate(){this.isBatchingUpdates||(this.isBatchingUpdates=!0,queueMicrotask((()=>{const e=new Set(this.dirtyInstances);this.dirtyInstances=new Set,e.forEach((e=>{const t=Array.from(this.components.keys()).find((t=>this.componentInstances.get(t)===e));if(t){this.componentStack.push(e),e.currentHook=0;const n=t(),o=e.lastResult;this.areNodesEqual(n,o)||(e.lastResult=n,this.rootElement&&this.updateDOM(this.rootElement,o,n)),this.componentStack.pop()}})),this.isBatchingUpdates=!1})))}updateDOM(e,t,n){if(this.areNodesEqual(t,n))return;const o=(e,t,n,r=0)=>{if("string"==typeof t||"number"==typeof t){const n=e.childNodes[r];return void(n?3===n.nodeType?n.textContent!==String(t)&&(n.textContent=String(t)):e.replaceChild(document.createTextNode(String(t)),n):e.appendChild(document.createTextNode(String(t))))}if(n&&this.areNodesEqual(n,t))return;if(!t)return void(e.childNodes[r]&&e.removeChild(e.childNodes[r]));if(!n||n.type!==t.type){const n=this.createElementFromVNode(t);return void(e.childNodes[r]?e.replaceChild(n,e.childNodes[r]):e.appendChild(n))}const s=e.childNodes[r];"string"==typeof t.type&&this.updateProps(s,n.props||{},t.props||{});const i=Array.isArray(t.props?.children)?t.props.children:[t.props?.children].filter(Boolean),c=Array.isArray(n.props?.children)?n.props.children:[n.props?.children].filter(Boolean),a=Math.max(i.length,c.length);for(let e=0;e<a;e++)o(s,i[e],c[e],e)};o(e,n,t)}updateProps(e,t,n){Object.keys(t).forEach((o=>{if("children"!==o&&!(o in n))if(o.startsWith("on")){const n=o.toLowerCase().substring(2);e.removeEventListener(n,t[o])}else"className"===o?e.removeAttribute("class"):e.removeAttribute(o)})),Object.keys(n).forEach((o=>{if("children"!==o&&n[o]!==t[o])if(o.startsWith("on")){const r=o.toLowerCase().substring(2);t[o]&&e.removeEventListener(r,t[o]),e.addEventListener(r,n[o])}else"className"===o?e.setAttribute("class",n[o]):o in e?e[o]=n[o]:e.setAttribute(o,n[o])}))}flushUpdates(){for(;this.pendingUpdates.length>0;){this.pendingUpdates.shift()()}this.hasScheduledFlush=!1}mount(e,t){this.rootElement=t,this.components.set(e,e),this.mountedComponents.has(t)&&this.unmount(t),t.innerHTML="",this.mountedComponents.set(t,new Set),this.renderComponent(e,t)}unmount(e){console.log("Unmounting component...");Array.from(this.componentInstances.values()).forEach((e=>{e.cleanups&&(e.cleanups.forEach((e=>{try{console.log("Running cleanup on unmount"),e()}catch(e){console.error("Error in unmount cleanup:",e)}})),e.cleanups.clear())})),this.componentInstances.clear(),e.innerHTML=""}createElementFromVNode(e){if("string"==typeof e||"number"==typeof e)return document.createTextNode(e);if(e.type===Fragment){const t=document.createDocumentFragment();return(e.props&&e.props.children?e.props.children:[]).forEach((e=>{t.appendChild(this.createElementFromVNode(e))})),t}if("string"==typeof e.type){const t=document.createElement(e.type);if(e.props){Object.keys(e.props).forEach((n=>{if("children"!==n)if("className"===n)t.setAttribute("class",e.props[n]);else if(n.startsWith("on")){const o=n.toLowerCase().substring(2);t.addEventListener(o,e.props[n])}else t[n]=e.props[n]}));(e.props.children||[]).forEach((e=>{t.appendChild(this.createElementFromVNode(e))}))}return t}return document.createTextNode("")}createContext(e){const t={currentValue:e,defaultValue:e,subscribers:new Map,version:0,Provider:({value:e,children:n})=>{const o=this.getCurrentInstance(),r=o.currentHook++,s=o.hooks[r];return this.shallowEqual(s,e)||(t._currentValue=e,t._version++,t.subscribers.forEach((t=>{t.instance.hooks[t.hookIndex]=e,this.dirtyInstances=this.dirtyInstances||new Set,this.dirtyInstances.add(t.instance),this.scheduleUpdate()}))),o.hooks[r]=e,n},Consumer:({children:e})=>{if("function"!=typeof e)throw new Error("Context.Consumer expects a function as a child");return e(t._currentValue)}};return t}memo(e){const t=t=>{const n=this.getCurrentInstance();if(!n)return e(t);const o=n.currentHook++,r=n.hooks[o]||{props:null,result:null},s=!r.props||!this.deepEqual(t,r.props);if(!r.result||s){const r=e(t);return n.hooks[o]={props:t,result:r},r}return r.result};return t.__isMemoized=!0,t.__original=e,t}shallowEqual(e,t){if(e===t)return!0;if(!e||!t)return!1;if("object"!=typeof e||"object"!=typeof t)return e===t;const n=Object.keys(e),o=Object.keys(t);return n.length===o.length&&n.every((n=>t.hasOwnProperty(n)&&e[n]===t[n]))}deepEqual(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if("object"!=typeof e||null===e||null===t)return!1;const n=Object.keys(e),o=Object.keys(t);return n.length===o.length&&n.every((n=>this.deepEqual(e[n],t[n])))}areArraysEqual(e,t){return e===t||!(!e||!t)&&(e.length===t.length&&e.every(((e,n)=>e===t[n])))}areNodesEqual(e,t){return e===t||!(!e||!t)&&(typeof e==typeof t&&("string"==typeof e||"number"==typeof e?e===t:e.type===t.type&&this.areObjectsEqual(e.props,t.props)))}areObjectsEqual(e,t){if(e===t)return!0;if(!e||!t)return!1;const n=Object.keys(e),o=Object.keys(t);return n.length===o.length&&n.every((n=>"children"===n?this.areChildrenEqual(e[n],t[n]):e[n]===t[n]))}areChildrenEqual(e,t){if(e===t)return!0;if(!e||!t)return!1;const n=Array.isArray(e)?e:[e],o=Array.isArray(t)?t:[t];return n.length===o.length&&n.every(((e,t)=>this.areNodesEqual(e,o[t])))}getCurrentInstance(){const e=this.componentStack[this.componentStack.length-1];if(!e)throw new Error("Hooks can only be called inside function components");return e}}const Olova=new ReactLite;export const h=Olova.createElement.bind(Olova);export const Fragment=Symbol("Fragment");export const $state=Olova.$state.bind(Olova);export const $effect=Olova.$effect.bind(Olova);export const $ref=Olova.$ref.bind(Olova);export const $memo=Olova.$memo.bind(Olova);export const $callback=Olova.$callback.bind(Olova);export const $context=Olova.$context.bind(Olova);export const createContext=Olova.createContext.bind(Olova);export const memo=Olova.memo.bind(Olova);export default Olova;function isFunctionComponent(e){return"function"==typeof e}function renderComponent(e,t){try{return"function"==typeof e.type?e.type(e.props):"string"==typeof e?e:Array.isArray(e)?e.map((e=>renderComponent(e,t))):null==e?"":"object"==typeof e?e:String(e)}catch(e){return console.error("Error rendering component:",e),null}}
1
+ import{createSignal as $state}from"./hooks/createSignal";import{createEffect as $effect}from"./hooks/createEffect";import{createMemo as $memo}from"./hooks/createMemo";import{createRef as $ref}from"./hooks/createRef";function h(e,t={},...n){if(e===h.Fragment){const e=document.createDocumentFragment(),t=n.flat();for(let n=0;n<t.length;n++){const o=t[n];if("function"==typeof o){const t=document.createTextNode("");$effect((()=>{const n=o();if(Array.isArray(n)){const o=t.previousSibling;o&&o.remove();const r=document.createDocumentFragment();for(let e=0;e<n.length;e++){const t=n[e];r.appendChild(t instanceof Node?t:document.createTextNode(String(t)))}e.insertBefore(r,t)}else t.textContent=String(n)})),e.appendChild(t)}else o instanceof Node?e.appendChild(o):null!=o&&e.appendChild(document.createTextNode(String(o)))}return e}const o="function"==typeof e?e(t):document.createElement(e);if("function"!=typeof e){if(t){const e=Object.entries(t);for(let t=0;t<e.length;t++){const[n,r]=e[t];"ref"===n?queueMicrotask((()=>{r&&"object"==typeof r&&(r.current=o)})):n.startsWith("on")?o.addEventListener(n.slice(2).toLowerCase(),r):"style"===n&&"object"==typeof r?Object.assign(o.style,r):"className"===n?o.className=r:o.setAttribute(n,r)}}const e=document.createTextNode(""),r=n.flat();for(let t=0;t<r.length;t++){const n=r[t];if("function"==typeof n)$effect((()=>{const t=n();if(Array.isArray(t)){o.textContent="";const e=document.createDocumentFragment();for(let n=0;n<t.length;n++){const o=t[n];e.appendChild(o instanceof Node?o:document.createTextNode(String(o)))}o.appendChild(e)}else e.textContent=String(t),e.parentNode||o.appendChild(e)}));else if(Array.isArray(n)){const e=document.createDocumentFragment();for(let t=0;t<n.length;t++){const o=n[t];o instanceof Node?e.appendChild(o):null!=o&&e.appendChild(document.createTextNode(String(o)))}o.appendChild(e)}else n instanceof Node?o.appendChild(n):null!=n&&o.appendChild(document.createTextNode(String(n)))}}return o}h.Fragment=Symbol("Fragment");const Fragment=h.Fragment;export{h,$state,$effect,$memo,Fragment,$ref};
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
- {
2
- "name": "olova",
3
- "version": "2.0.10",
4
- "description": "A lightweight JavaScript framework for building reactive applications.",
5
- "main": "dist/olova.js",
6
- "keywords": [
7
- "javascript",
8
- "framework",
9
- "reactive",
10
- "olova",
11
- "olovajs"
12
- ],
13
- "author": "Nazmul Hossain",
14
- "license": "MIT"
15
- }
1
+ {
2
+ "name": "olova",
3
+ "version": "2.0.11",
4
+ "description": "A lightweight JavaScript framework for building reactive applications.",
5
+ "main": "dist/olova.js",
6
+ "keywords": [
7
+ "javascript",
8
+ "framework",
9
+ "reactive",
10
+ "olova",
11
+ "olovajs"
12
+ ],
13
+ "author": "Nazmul Hossain",
14
+ "license": "MIT"
15
+ }
@@ -1,6 +0,0 @@
1
- import { createMemoHook } from "./memo.js";
2
- export function createCallbackHook(o) {
3
- return function (e, r) {
4
- return o.$memo(() => e, r);
5
- };
6
- }
@@ -1,25 +0,0 @@
1
- export function createContextHook(e) {
2
- return function (n) {
3
- const s = e.getCurrentInstance(),
4
- t = s.currentHook++;
5
- if (!s.hooks[t]) {
6
- s.hooks[t] = n._currentValue;
7
- const e = { instance: s, hookIndex: t, version: n._version };
8
- n.subscribers.set(s, e),
9
- s.contextSubscriptions.add(() => {
10
- n.subscribers.delete(s);
11
- });
12
- }
13
- const r = n.subscribers.get(s);
14
- return (
15
- r &&
16
- r.version !== n._version &&
17
- ((s.hooks[t] = n._currentValue),
18
- (r.version = n._version),
19
- (e.dirtyInstances = e.dirtyInstances || new Set()),
20
- e.dirtyInstances.add(s),
21
- e.scheduleUpdate()),
22
- n._currentValue
23
- );
24
- };
25
- }
@@ -1,20 +0,0 @@
1
- export function createEffectHook(n) {
2
- return function (e, t) {
3
- const o = n.getCurrentInstance(),
4
- u = o.currentHook++;
5
- o.hooks[u] ||
6
- (o.hooks[u] = { deps: null, cleanup: null, effect: e, lastRun: 0 });
7
- const c = o.hooks[u];
8
- (t
9
- ? c.deps &&
10
- n.areArraysEqual(
11
- t.map((n) => ("function" == typeof n ? n() : n)),
12
- c.deps
13
- )
14
- : 0 !== c.lastRun) ||
15
- ("function" == typeof c.cleanup && c.cleanup(),
16
- (c.cleanup = e()),
17
- (c.deps = t?.map((n) => ("function" == typeof n ? n() : n))),
18
- (c.lastRun = Date.now()));
19
- };
20
- }
@@ -1,17 +0,0 @@
1
- export function createMemoHook(o) {
2
- return function (n, t) {
3
- const e = o.getCurrentInstance(),
4
- r = e.currentHook++,
5
- [u, c] = e.hooks[r] || [void 0, void 0];
6
- if (
7
- !c ||
8
- !t ||
9
- t.length !== c.length ||
10
- t.some((n, t) => !o.shallowEqual(n, c[t]))
11
- ) {
12
- const o = n();
13
- return (e.hooks[r] = [o, t]), o;
14
- }
15
- return u;
16
- };
17
- }
@@ -1,21 +0,0 @@
1
- export function createReducerHook(t) {
2
- return function (s, e, o) {
3
- const n = t.getCurrentInstance(),
4
- c = n.currentHook++;
5
- if (!n.hooks[c]) {
6
- const a = o ? o(e) : e;
7
- n.hooks[c] = {
8
- state: a,
9
- dispatch: (e) => {
10
- const o = s(n.hooks[c].state, e);
11
- o !== n.hooks[c].state &&
12
- ((n.hooks[c].state = o),
13
- t.dirtyInstances || (t.dirtyInstances = new Set()),
14
- t.dirtyInstances.add(n),
15
- t.scheduleUpdate());
16
- },
17
- };
18
- }
19
- return [n.hooks[c].state, n.hooks[c].dispatch];
20
- };
21
- }
package/dist/hooks/ref.js DELETED
@@ -1,7 +0,0 @@
1
- export function createRefHook(o) {
2
- return function (n) {
3
- const r = o.getCurrentInstance(),
4
- t = r.currentHook++;
5
- return r.hooks[t] || (r.hooks[t] = { current: n }), r.hooks[t];
6
- };
7
- }
@@ -1,21 +0,0 @@
1
- export function createStateHook(e) {
2
- return function (t) {
3
- const o = e.getCurrentInstance(),
4
- n = o.currentHook++;
5
- return (
6
- o.hooks[n] ||
7
- (o.hooks[n] = {
8
- value: t,
9
- setValue: (t) => {
10
- const s = "function" == typeof t ? t(o.hooks[n].value) : t;
11
- s !== o.hooks[n].value &&
12
- ((o.hooks[n].value = s),
13
- e.dirtyInstances || (e.dirtyInstances = new Set()),
14
- e.dirtyInstances.add(o),
15
- e.scheduleUpdate());
16
- },
17
- }),
18
- [() => o.hooks[n].value, o.hooks[n].setValue]
19
- );
20
- };
21
- }