Skip to content

Commit

Permalink
Ajustes no bind...
Browse files Browse the repository at this point in the history
  • Loading branch information
djalmajr committed Aug 11, 2023
1 parent ebcea6e commit 04486ad
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 25 deletions.
26 changes: 26 additions & 0 deletions examples/counter.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.counter {
align-items: center;
display: flex;
padding: 1rem;
}

.counter span,
.counter button {
font-size: 200%;
}

.counter span {
display: inline-block;
margin: auto 0.5rem;
min-width: 4rem;
text-align: center;
}

.counter button {
width: 4rem;
height: 4rem;
border: none;
border-radius: 10px;
background-color: seagreen;
color: white;
}
9 changes: 9 additions & 0 deletions examples/counter.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<script type="importmap">
{ "imports": { "help-es": "../lib/index.js", "help-es/": "../lib/" } }
</script>
<script type="esms-options">
{ "polyfillEnable": ["css-modules", "json-modules"] }
</script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
<script type="module" src="./counter.js"></script>
24 changes: 24 additions & 0 deletions examples/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { addStyle, createState, html, render } from 'help-es';
import styles from './counter.css' assert { type: 'css' };

addStyle(styles);

const store = createState({
counter: 0,
increment() { this.counter++ },
decrement() { this.counter-- },
});

function App() {
return html`
<div class="counter">
<button @click=${store.decrement}></button>
<span>${store.counter}</span>
<button @click=${store.increment}>+</button>
</div>
`;
}

const update = () => render(document.body, App());
store.observe(update);
update();
25 changes: 19 additions & 6 deletions src/bind.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import { Fn } from './types';

type Callback = Fn<[...any[]], any>; // eslint-disable-line

type Callback = Fn<[...any[]], any>;
const _ = new WeakMap();
const { defineProperty, getOwnPropertyDescriptor } = Object;

export function bind<T extends object>(ctx: T, arg?: Callback | keyof T) {
if (arg) {
const fn = typeof arg === 'function' ? arg : <Callback>ctx[arg as never];
const fns = _.get(ctx) || _.set(ctx, new Map()).get(ctx);
return fns.get(fn) || fns.set(fn, fn.bind(ctx)).get(fn);
}

for (const key in ctx) {
const d = getOwnPropertyDescriptor(ctx, key);
if (d?.get && d?.configurable) {
defineProperty(ctx, key, { get: d.get.bind(ctx) });
} else if (typeof ctx[key] === 'function') {
defineProperty(ctx, key, { value: (ctx[key] as any).bind(ctx) });
}
}

export function bind<T extends object>(ctx: T, cb: Callback | keyof T) {
const fn = typeof cb === 'function' ? cb : <Callback>ctx[cb as never];
const fns = _.get(ctx) || _.set(ctx, new Map()).get(ctx);
return fns.get(fn) || fns.set(fn, fn.bind(ctx)).get(fn);
return ctx;
}
25 changes: 6 additions & 19 deletions src/createState.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { bind } from './bind';
import { clone } from './clone';
import { createEmitter } from './createEmitter';
import { isFunction } from './isFunction';
import { isObject } from './isObject';
import { omit } from './omit';
import { guid } from './random';
import { Obj } from './types';

type Store<T> = T & {
type State<T> = T & {
dispose(fn: (s: T) => void): void;
observe(fn: (s: T) => void): () => void;
};
Expand Down Expand Up @@ -39,7 +39,7 @@ type Options = {
immediate?: boolean;
};

export function createState<T extends object>(data?: T, opts?: Options): Store<T> {
export function createState<T extends object>(data?: T, opts?: Options): State<T> {
const { immediate } = opts || {};
const fns = <Function[]>[];
const init = clone(data || {}) as Obj;
Expand All @@ -60,26 +60,13 @@ export function createState<T extends object>(data?: T, opts?: Options): Store<T
});

let nextTickId = 0;
const store = new Proxy(init, handler(uid));
const state = new Proxy(init, handler(uid));
on(`update:${uid}`, () => {
const data = omit(['dispose', 'observe'], store);
const data = omit(['dispose', 'observe'], state);
if (immediate) return fns.forEach((fn) => fn(data));
if (nextTickId) cancelAnimationFrame(nextTickId);
nextTickId = requestAnimationFrame(() => fns.forEach((fn) => fn(data)));
});

for (const prop in init) {
const d = getOwnPropertyDescriptor(init, prop);
if (d?.get && d?.configurable) {
defineProperty(init, prop, {
get: d.get.bind(store),
});
} else if (isFunction(init[prop])) {
defineProperty(init, prop, {
value: (init[prop] as any).bind(store),
});
}
}

return store as Store<T>;
return bind(state);
}

0 comments on commit 04486ad

Please sign in to comment.