essor 0.0.6-beta.2 → 0.0.6-beta.4

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/dist/essor.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as csstype from 'csstype';
2
2
 
3
3
  type EffectFn = () => void;
4
- declare class Signal<T> {
4
+ declare class Signal$1<T> {
5
5
  private _value;
6
6
  constructor(value: T);
7
7
  valueOf(): T;
@@ -12,8 +12,8 @@ declare class Signal<T> {
12
12
  peek(): T;
13
13
  update(): void;
14
14
  }
15
- declare function useSignal<T>(value?: T): Signal<T>;
16
- declare function isSignal<T>(value: any): value is Signal<T>;
15
+ declare function useSignal<T>(value?: T): Signal$1<T>;
16
+ declare function isSignal<T>(value: any): value is Signal$1<T>;
17
17
  declare class Computed<T> {
18
18
  private readonly fn;
19
19
  private _value;
@@ -26,9 +26,27 @@ declare function useComputed<T>(fn: () => T): Computed<T>;
26
26
  declare function isComputed<T>(value: any): value is Computed<T>;
27
27
  declare function useEffect(fn: EffectFn): () => void;
28
28
  type SignalObject<T> = {
29
- [K in keyof T]: Signal<T[K]>;
29
+ [K in keyof T]: Signal$1<T[K]> | T[K];
30
30
  };
31
- declare function signalObject<T extends Object>(initialValues: T): SignalObject<T>;
31
+ /**
32
+ * Creates a SignalObject from the given initialValues, excluding specified keys.
33
+ *
34
+ * @param {T extends Object} initialValues - The initial values for the SignalObject.
35
+ * @param {(key: string) => boolean | string[]} exclude - A function that determines which keys to exclude from the SignalObject.
36
+ * @return {SignalObject<T>} The created SignalObject.
37
+ */
38
+ declare function signalObject<T extends object>(initialValues: T, exclude?: ((key: string) => boolean) | string[]): SignalObject<T>;
39
+ /**
40
+ * Returns the current value of a signal, signal object, or plain object, excluding specified keys.
41
+ *
42
+ * @param {SignalObject<T> | T | Signal<T>} signal - The signal, signal object, or plain object to unwrap.
43
+ * @param {(key: string) => boolean | string[]} [exclude] - A function that determines which keys to exclude from the unwrapped object.
44
+ * @return {T} The unwrapped value of the signal, signal object, or plain object.
45
+ */
46
+ declare function unSignal<T>(signal: SignalObject<T> | T | Signal$1<T>, exclude?: ((key: string) => boolean) | string[]): T;
47
+ declare function isReactive(obj: any): any;
48
+ declare function unReactive(obj: any): any;
49
+ declare function reactive(initialValue: any): any;
32
50
 
33
51
  type PatchPayload = Record<string, any>;
34
52
  type Callback = (value: any) => void;
@@ -40,13 +58,13 @@ interface StoreActions {
40
58
  reset$: () => void;
41
59
  }
42
60
  type Getters<S> = {
43
- [K in keyof S]: S[K] extends (...args: any[]) => any ? Signal<ReturnType<S[K]>> : Signal<S[K]>;
61
+ [K in keyof S]: S[K] extends (...args: any[]) => any ? ReturnType<S[K]> : S[K];
44
62
  };
45
63
  declare function createStore<S, G, A>(options: {
46
64
  state: S;
47
65
  getters?: G;
48
66
  actions?: A;
49
- } & ThisType<SignalObject<S> & Getters<G> & A>): () => S & Getters<G> & A & StoreActions & {
67
+ } & ThisType<S & Getters<G> & A>): () => S & Getters<G> & A & StoreActions & {
50
68
  state: S;
51
69
  };
52
70
 
@@ -226,7 +244,7 @@ declare global {
226
244
  ref?: unknown | ((e: unknown) => void);
227
245
  }
228
246
  interface CustomAttributes<T> {
229
- ref?: T | ((el: T) => void);
247
+ ref?: Signal<T> | ((el: T) => void);
230
248
  classList?: {
231
249
  [k: string]: boolean | undefined;
232
250
  };
@@ -2287,13 +2305,13 @@ declare class TemplateNode implements JSX.Element {
2287
2305
  type Hook = 'mounted' | 'destroy';
2288
2306
  declare class ComponentNode$1 implements JSX.Element {
2289
2307
  template: EssorComponent;
2290
- props: Record<string, unknown>;
2308
+ props: Record<string, any>;
2291
2309
  key?: string | undefined;
2292
- constructor(template: EssorComponent, props: Record<string, unknown>, key?: string | undefined);
2310
+ constructor(template: EssorComponent, props: Record<string, any>, key?: string | undefined);
2293
2311
  addEventListener(): void;
2294
2312
  removeEventListener(): void;
2295
2313
  static ref: ComponentNode$1 | null;
2296
- static context: Record<symbol, Signal<any>>;
2314
+ static context: Record<symbol, Signal$1<any>>;
2297
2315
  id?: string;
2298
2316
  private proxyProps;
2299
2317
  context: Record<symbol | string | number, any>;
@@ -2311,7 +2329,7 @@ declare class ComponentNode$1 implements JSX.Element {
2311
2329
  unmount(): void;
2312
2330
  mount(parent: Node, before?: Node | null): Node[];
2313
2331
  private getNodeTrack;
2314
- patchProps(props: Record<string, unknown>): void;
2332
+ patchProps(props: Record<string, any>): void;
2315
2333
  }
2316
2334
 
2317
2335
  declare function h(template: EssorComponent | HTMLTemplateElement, props: Record<string, any>, key?: string): JSX.Element;
@@ -2340,7 +2358,7 @@ declare function useRef<T>(): {
2340
2358
  current: T | null;
2341
2359
  };
2342
2360
 
2343
- declare const __essor_version = "0.0.6-beta.1";
2361
+ declare const __essor_version = "0.0.6-beta.3";
2344
2362
 
2345
2363
  interface TemplateMap {
2346
2364
  [key: number]: {
@@ -2356,4 +2374,4 @@ declare function hydrate(component: {
2356
2374
  mount: (root: HTMLElement) => void;
2357
2375
  }, root: HTMLElement): void;
2358
2376
 
2359
- export { ComponentNode$1 as ComponentNode, Computed, type EssorComponent, type EssorNode, Fragment, type Hook$1 as Hook, type InjectionKey, type NodeTrack, type Output, Signal, type StoreActions, TemplateNode, __essor_version, createStore, h, hydrate, isComputed, isJsxElement, isSignal, nextTick, onDestroy, onMount, renderToString, signalObject, ssr, ssrtmpl, template, useComputed, useEffect, useInject, useProvide, useRef, useSignal };
2377
+ export { ComponentNode$1 as ComponentNode, Computed, type EssorComponent, type EssorNode, Fragment, type Hook$1 as Hook, type InjectionKey, type NodeTrack, type Output, Signal$1 as Signal, type StoreActions, TemplateNode, __essor_version, createStore, h, hydrate, isComputed, isJsxElement, isReactive, isSignal, nextTick, onDestroy, onMount, reactive, renderToString, signalObject, ssr, ssrtmpl, template, unReactive, unSignal, useComputed, useEffect, useInject, useProvide, useRef, useSignal };
@@ -16,6 +16,7 @@ var __spreadValues = (a, b) => {
16
16
  }
17
17
  return a;
18
18
  };
19
+ var isFunction = (val) => typeof val === "function";
19
20
 
20
21
  // src/signal/signal.ts
21
22
  var activeEffect = null;
@@ -137,24 +138,67 @@ function useEffect(fn) {
137
138
  activeEffect = null;
138
139
  };
139
140
  }
140
- function signalObject(initialValues) {
141
+ function shouldExclude(key, exclude) {
142
+ return Array.isArray(exclude) ? exclude.includes(key) : isFunction(exclude) ? exclude(key) : false;
143
+ }
144
+ function signalObject(initialValues, exclude) {
141
145
  const signals = Object.entries(initialValues).reduce((acc, [key, value]) => {
142
- acc[key] = isSignal(value) ? value : useSignal(value);
146
+ acc[key] = shouldExclude(key, exclude) || isSignal(value) ? value : useSignal(value);
143
147
  return acc;
144
148
  }, {});
145
149
  return signals;
146
150
  }
147
- function signalToObject(signal) {
151
+ function unSignal(signal, exclude) {
148
152
  if (!signal)
149
153
  return {};
150
154
  if (isSignal(signal)) {
151
155
  return signal.peek();
152
156
  }
153
157
  return Object.entries(signal).reduce((acc, [key, value]) => {
154
- acc[key] = isSignal(value) ? value.peek() : value;
158
+ if (shouldExclude(key, exclude)) {
159
+ acc[key] = value;
160
+ } else {
161
+ acc[key] = isSignal(value) ? value.peek() : value;
162
+ }
155
163
  return acc;
156
164
  }, {});
157
165
  }
166
+ var REACTIVE_MARKER = Symbol("reactive");
167
+ function isReactive(obj) {
168
+ return obj && obj[REACTIVE_MARKER] === true;
169
+ }
170
+ function unReactive(obj) {
171
+ if (!isReactive(obj)) {
172
+ return obj;
173
+ }
174
+ const copy = Object.assign({}, obj);
175
+ delete copy[REACTIVE_MARKER];
176
+ return copy;
177
+ }
178
+ function reactive(initialValue) {
179
+ if (isReactive(initialValue)) {
180
+ return initialValue;
181
+ }
182
+ const signalObj = signalObject(initialValue);
183
+ const handler = {
184
+ get(target, key, receiver) {
185
+ track(target, key);
186
+ const value = Reflect.get(target, key, receiver);
187
+ return isSignal(value) ? value.value : value;
188
+ },
189
+ set(target, key, value, receiver) {
190
+ const oldValue = Reflect.get(target, key, receiver);
191
+ if (oldValue !== value) {
192
+ Reflect.set(target, key, useSignal(value), receiver);
193
+ trigger(target, key);
194
+ }
195
+ return true;
196
+ }
197
+ };
198
+ const reactiveProxy = new Proxy(signalObj, handler);
199
+ reactiveProxy[REACTIVE_MARKER] = true;
200
+ return reactiveProxy;
201
+ }
158
202
 
159
203
  // src/signal/store.ts
160
204
  var _id = 0;
@@ -162,14 +206,14 @@ var StoreMap = /* @__PURE__ */ new Map();
162
206
  function createOptionsStore(options) {
163
207
  const { state, getters, actions } = options;
164
208
  const initState = __spreadValues({}, state != null ? state : {});
165
- const signalState = signalObject(state != null ? state : {});
209
+ const reactiveState = reactive(state != null ? state : {});
166
210
  const subscriptions = [];
167
211
  const actionCallbacks = [];
168
212
  const default_actions = {
169
213
  patch$(payload) {
170
- Object.assign(signalState, signalObject(payload));
171
- subscriptions.forEach((callback) => callback(signalToObject(signalState)));
172
- actionCallbacks.forEach((callback) => callback(signalToObject(signalState)));
214
+ Object.assign(reactiveState, payload);
215
+ subscriptions.forEach((callback) => callback(reactiveState));
216
+ actionCallbacks.forEach((callback) => callback(reactiveState));
173
217
  },
174
218
  subscribe$(callback) {
175
219
  subscriptions.push(callback);
@@ -184,42 +228,44 @@ function createOptionsStore(options) {
184
228
  actionCallbacks.push(callback);
185
229
  },
186
230
  reset$() {
187
- default_actions.patch$(initState);
231
+ Object.assign(reactiveState, initState);
188
232
  }
189
233
  };
190
- const states = {
191
- _id: `store_${_id}`
192
- };
234
+ const gettersStates = {};
235
+ const actionStates = {};
193
236
  for (const key in getters) {
194
237
  const getter = getters[key];
195
238
  if (getter) {
196
- states[key] = useComputed(() => {
197
- return getter.call(signalState);
239
+ gettersStates[key] = useComputed(() => {
240
+ return getter.call(reactiveState, reactiveState);
198
241
  });
199
242
  }
200
243
  }
201
244
  for (const key in actions) {
202
245
  const action = actions[key];
203
246
  if (action) {
204
- states[key] = action.bind(signalState);
247
+ actionStates[key] = action.bind(reactiveState);
205
248
  }
206
249
  }
207
- StoreMap.set(_id, useSignal);
250
+ StoreMap.set(_id, reactiveState);
208
251
  ++_id;
209
252
  return new Proxy(
210
253
  {},
211
254
  {
212
255
  get(_, key) {
213
256
  if (key === "state") {
214
- return signalToObject(signalState);
257
+ return reactiveState;
258
+ }
259
+ if (key in gettersStates) {
260
+ return gettersStates[key].value;
215
261
  }
216
- if (key in states) {
217
- return states[key];
262
+ if (key in actionStates) {
263
+ return actionStates[key];
218
264
  }
219
265
  if (key in default_actions) {
220
266
  return default_actions[key];
221
267
  }
222
- return signalState[key].value;
268
+ return reactiveState[key];
223
269
  }
224
270
  }
225
271
  );
@@ -237,13 +283,16 @@ function createStore(options) {
237
283
  function coerceArray(data) {
238
284
  return Array.isArray(data) ? data.flat() : [data];
239
285
  }
240
- var isObject = (val) => val !== null && typeof val === "object";
241
- var isArray = Array.isArray;
242
- function isNil(x) {
286
+ function startsWith(str, searchString) {
287
+ return str.indexOf(searchString) === 0;
288
+ }
289
+ var isObject2 = (val) => val !== null && typeof val === "object";
290
+ var isArray2 = Array.isArray;
291
+ function isNil2(x) {
243
292
  return x === null || x === void 0;
244
293
  }
245
- var isFunction = (val) => typeof val === "function";
246
- function isFalsy(x) {
294
+ var isFunction2 = (val) => typeof val === "function";
295
+ function isFalsy2(x) {
247
296
  return x === false || x === null || x === void 0 || x === "";
248
297
  }
249
298
  var kebabCase = (string) => {
@@ -268,7 +317,10 @@ var _ComponentNode = class _ComponentNode {
268
317
  destroy: /* @__PURE__ */ new Set()
269
318
  };
270
319
  this.trackMap = /* @__PURE__ */ new Map();
271
- this.proxyProps = signalObject(props);
320
+ this.proxyProps = signalObject(
321
+ props,
322
+ (key2) => startsWith(key2, "on") || startsWith(key2, "update:")
323
+ );
272
324
  }
273
325
  addEventListener() {
274
326
  }
@@ -315,7 +367,7 @@ var _ComponentNode = class _ComponentNode {
315
367
  }
316
368
  mount(parent, before) {
317
369
  var _a, _b, _c, _d;
318
- if (!isFunction(this.template)) {
370
+ if (!isFunction2(this.template)) {
319
371
  throw new Error("Template must be a function");
320
372
  }
321
373
  if (this.isConnected) {
@@ -345,19 +397,19 @@ var _ComponentNode = class _ComponentNode {
345
397
  patchProps(props) {
346
398
  var _a, _b, _c, _d, _e;
347
399
  for (const [key, prop] of Object.entries(props)) {
348
- if (key.indexOf("on") === 0 && ((_a = this.rootNode) == null ? void 0 : _a.nodes)) {
400
+ if (startsWith(key, "on") && ((_a = this.rootNode) == null ? void 0 : _a.nodes)) {
349
401
  const event = key.slice(2).toLowerCase();
350
402
  const listener = prop;
351
403
  const cleanup = addEventListener(this.rootNode.nodes[0], event, listener);
352
404
  this.emitter.add(cleanup);
353
- } else if (key.indexOf("bind:") === 0) {
354
- this.proxyProps[key] = useSignal(prop);
355
405
  } else if (key === "ref") {
356
406
  if (isSignal(prop)) {
357
407
  props[key].value = (_b = this.rootNode) == null ? void 0 : _b.nodes[0];
358
- } else {
359
- props[key] = (_c = this.rootNode) == null ? void 0 : _c.nodes[0];
408
+ } else if (isFunction2(prop)) {
409
+ props[key]((_c = this.rootNode) == null ? void 0 : _c.nodes[0]);
360
410
  }
411
+ } else if (startsWith(key, "update:")) {
412
+ props[key] = isSignal(prop) ? prop.value : prop;
361
413
  } else {
362
414
  const newValue = (_e = (_d = this.proxyProps)[key]) != null ? _e : _d[key] = useSignal(prop);
363
415
  const track2 = this.getNodeTrack(key);
@@ -375,7 +427,7 @@ var ComponentNode = _ComponentNode;
375
427
 
376
428
  // src/template/template.ts
377
429
  function h(template2, props, key) {
378
- return isFunction(template2) ? new ComponentNode(template2, props, key) : new TemplateNode(template2, props, key);
430
+ return isFunction2(template2) ? new ComponentNode(template2, props, key) : new TemplateNode(template2, props, key);
379
431
  }
380
432
  function isJsxElement(node) {
381
433
  return node instanceof ComponentNode || node instanceof TemplateNode;
@@ -394,7 +446,7 @@ function coerceNode(data) {
394
446
  if (isJsxElement(data) || data instanceof Node) {
395
447
  return data;
396
448
  }
397
- const text = isFalsy(data) ? "" : String(data);
449
+ const text = isFalsy2(data) ? "" : String(data);
398
450
  return document.createTextNode(text);
399
451
  }
400
452
  function insertChild(parent, child, before = null) {
@@ -443,7 +495,7 @@ function setAttribute(element, attr, value) {
443
495
  }
444
496
  return;
445
497
  }
446
- if (isFalsy(value)) {
498
+ if (isFalsy2(value)) {
447
499
  element.removeAttribute(attr);
448
500
  } else if (value === true) {
449
501
  element.setAttribute(attr, "");
@@ -725,7 +777,7 @@ var TemplateNode = class _TemplateNode {
725
777
  patchNode(key, node, props, isRoot) {
726
778
  for (const attr in props) {
727
779
  if (attr === "children" && props.children) {
728
- if (!isArray(props.children)) {
780
+ if (!isArray2(props.children)) {
729
781
  const trackKey = `${key}:${attr}:${0}`;
730
782
  const track2 = this.getNodeTrack(trackKey, true, isRoot);
731
783
  patchChild(track2, node, props.children, null);
@@ -735,8 +787,8 @@ var TemplateNode = class _TemplateNode {
735
787
  if (!item) {
736
788
  return;
737
789
  }
738
- const [child, path] = isArray(item) ? item : [item, null];
739
- const before = isNil(path) ? null : (_a = this.treeMap.get(path)) != null ? _a : null;
790
+ const [child, path] = isArray2(item) ? item : [item, null];
791
+ const before = isNil2(path) ? null : (_a = this.treeMap.get(path)) != null ? _a : null;
740
792
  const trackKey = `${key}:${attr}:${index}`;
741
793
  const track2 = this.getNodeTrack(trackKey, true, isRoot);
742
794
  patchChild(track2, node, child, before);
@@ -745,31 +797,15 @@ var TemplateNode = class _TemplateNode {
745
797
  } else if (attr === "ref") {
746
798
  if (isSignal(props[attr])) {
747
799
  props[attr].value = node;
748
- } else {
749
- props[attr] = node;
800
+ } else if (isFunction2(props[attr])) {
801
+ props[attr](node);
750
802
  }
751
- } else if (attr.indexOf("on") === 0) {
803
+ } else if (startsWith(attr, "on")) {
752
804
  const eventName = attr.slice(2).toLocaleLowerCase();
753
805
  const track2 = this.getNodeTrack(`${key}:${attr}`);
754
806
  const listener = props[attr];
755
807
  track2.cleanup = addEventListener(node, eventName, listener);
756
- } else if (attr.indexOf("bind:") === 0) {
757
- const bindKey = attr.slice(5).toLocaleLowerCase();
758
- const val = props[attr];
759
- const track2 = this.getNodeTrack(`${key}:${attr}`);
760
- const triggerValue = isSignal(val) ? val : useSignal(val);
761
- const cleanup = useEffect(() => {
762
- triggerValue.value = isSignal(val) ? val.value : val;
763
- node[bindKey] = triggerValue.value;
764
- });
765
- const cleanupBind = binNode(node, (value) => {
766
- props[`update:${bindKey}`](value);
767
- });
768
- track2.cleanup = () => {
769
- cleanup == null ? void 0 : cleanup();
770
- cleanupBind == null ? void 0 : cleanupBind();
771
- };
772
- } else if (attr.indexOf("update:") !== 0) {
808
+ } else if (!startsWith(attr, "update:")) {
773
809
  const track2 = this.getNodeTrack(`${key}:${attr}`);
774
810
  const val = props[attr];
775
811
  const triggerValue = isSignal(val) ? val : useSignal(val);
@@ -777,8 +813,16 @@ var TemplateNode = class _TemplateNode {
777
813
  triggerValue.value = isSignal(val) ? val.value : val;
778
814
  patchAttribute(track2, node, attr, triggerValue.value);
779
815
  });
816
+ let cleanupBind;
817
+ const updateKey = `update:${attr}`;
818
+ if (props[updateKey]) {
819
+ cleanupBind = binNode(node, (value) => {
820
+ props[updateKey](value);
821
+ });
822
+ }
780
823
  track2.cleanup = () => {
781
- cleanup == null ? void 0 : cleanup();
824
+ cleanup && cleanup();
825
+ cleanupBind && cleanupBind();
782
826
  };
783
827
  }
784
828
  }
@@ -789,7 +833,7 @@ function patchAttribute(track2, node, attr, data) {
789
833
  if (!element.setAttribute) {
790
834
  return;
791
835
  }
792
- if (isFunction(data)) {
836
+ if (isFunction2(data)) {
793
837
  track2.cleanup = useEffect(() => {
794
838
  setAttribute(element, attr, data());
795
839
  });
@@ -798,7 +842,7 @@ function patchAttribute(track2, node, attr, data) {
798
842
  }
799
843
  }
800
844
  function patchChild(track2, parent, child, before) {
801
- if (isFunction(child)) {
845
+ if (isFunction2(child)) {
802
846
  track2.cleanup = useEffect(() => {
803
847
  const nextNodes = coerceArray(child()).map(coerceNode);
804
848
  track2.lastNodes = patchChildren(parent, track2.lastNodes, nextNodes, before);
@@ -862,7 +906,7 @@ function useRef() {
862
906
  }
863
907
 
864
908
  // src/version.ts
865
- var __essor_version = "0.0.6-beta.1";
909
+ var __essor_version = "0.0.6-beta.3";
866
910
 
867
911
  // src/server/index.ts
868
912
  function ssrtmpl(templates = []) {
@@ -875,17 +919,17 @@ function jsonToAttrs(json) {
875
919
  return Object.entries(json).map(([key, value]) => `${key}=${JSON.stringify(value)}`).join(" ");
876
920
  }
877
921
  function ssr(template2, props) {
878
- if (isFunction(template2)) {
922
+ if (isFunction2(template2)) {
879
923
  return template2(props);
880
924
  }
881
925
  const childrenMap = {};
882
926
  const newTemplate = {};
883
- if (isObject(template2)) {
927
+ if (isObject2(template2)) {
884
928
  Object.entries(template2).forEach(([key, tmpl]) => {
885
929
  const prop = props[key];
886
930
  if (prop) {
887
931
  Object.keys(prop).forEach((propKey) => {
888
- if (propKey.startsWith("on") && isFunction(prop[propKey])) {
932
+ if (startsWith(propKey, "on") && isFunction2(prop[propKey])) {
889
933
  delete prop[propKey];
890
934
  }
891
935
  });
@@ -927,15 +971,19 @@ exports.h = h;
927
971
  exports.hydrate = hydrate;
928
972
  exports.isComputed = isComputed;
929
973
  exports.isJsxElement = isJsxElement;
974
+ exports.isReactive = isReactive;
930
975
  exports.isSignal = isSignal;
931
976
  exports.nextTick = nextTick;
932
977
  exports.onDestroy = onDestroy;
933
978
  exports.onMount = onMount;
979
+ exports.reactive = reactive;
934
980
  exports.renderToString = renderToString;
935
981
  exports.signalObject = signalObject;
936
982
  exports.ssr = ssr;
937
983
  exports.ssrtmpl = ssrtmpl;
938
984
  exports.template = template;
985
+ exports.unReactive = unReactive;
986
+ exports.unSignal = unSignal;
939
987
  exports.useComputed = useComputed;
940
988
  exports.useEffect = useEffect;
941
989
  exports.useInject = useInject;