vanilla_project 2.0.0 → 3.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.
@@ -136,13 +136,15 @@ const DOM_TYPES = {
136
136
  TEXT: 'text',
137
137
  ELEMENT: 'element',
138
138
  FRAGMENT: 'fragment',
139
+ COMPONENT: 'component',
139
140
  };
140
141
  function h(tag, props = {}, children = []) {
142
+ const type = typeof tag === 'string' ? DOM_TYPES.ELEMENT : DOM_TYPES.COMPONENT;
141
143
  return {
142
144
  tag,
143
145
  props,
146
+ type,
144
147
  children: mapTextNodes(withoutNulls(children)),
145
- type: DOM_TYPES.ELEMENT,
146
148
  }
147
149
  }
148
150
  function mapTextNodes(children) {
@@ -172,14 +174,17 @@ function extractChildren(v_dom){
172
174
  return children
173
175
  }
174
176
 
175
- function addEventListener(eventName, handler, el) {
176
- el.addEventListener(eventName, handler);
177
- return handler
177
+ function addEventListener(eventName, handler, el,hostComponent = null) {
178
+ function boundHandler() {
179
+ hostComponent ? handler.apply(hostComponent,arguments) : handler(...arguments);
180
+ }
181
+ el.addEventListener(eventName,boundHandler);
182
+ return boundHandler
178
183
  }
179
- function addEventListeners(listeners = {}, el) {
184
+ function addEventListeners(listeners = {}, el,hostComponent = null) {
180
185
  const addedListeners = {};
181
186
  Object.entries(listeners).forEach(([eventName, handler]) => {
182
- const listener = addEventListener(eventName, handler, el);
187
+ const listener = addEventListener(eventName, handler, el,hostComponent);
183
188
  addedListeners[eventName] = listener;
184
189
  });
185
190
  return addedListeners
@@ -205,6 +210,10 @@ function destroyDOM(v_dom) {
205
210
  removeFragmentNodes(v_dom);
206
211
  break
207
212
  }
213
+ case DOM_TYPES.COMPONENT: {
214
+ v_dom.component.unmount();
215
+ break
216
+ }
208
217
  default: {
209
218
  throw new Error(`Can't destroy DOM of type: ${type}`)
210
219
  }
@@ -230,7 +239,7 @@ function removeFragmentNodes(v_dom) {
230
239
  }
231
240
 
232
241
  function setAttributes(el, attrs) {
233
- const {class: className, style, ...otherAttrs} = attrs;
242
+ const {class: className, style,focus, ...otherAttrs} = attrs;
234
243
  if (className) {
235
244
  setClass(el, className);
236
245
  }
@@ -272,18 +281,28 @@ function removeAttribute(el, name) {
272
281
  el.removeAttribute(name);
273
282
  }
274
283
 
275
- function mountDOM(v_dom, parentEl,index) {
284
+ function extractPropsAndEvents(v_dom) {
285
+ const {on: events = {}, ...props} = v_dom.props;
286
+ delete props.key;
287
+ return {props, events}
288
+ }
289
+
290
+ function mountDOM(v_dom, parentEl, index = null, hostComponent = null) {
276
291
  switch (v_dom.type) {
277
292
  case DOM_TYPES.TEXT: {
278
- createTextNode(v_dom, parentEl,index);
293
+ createTextNode(v_dom, parentEl, index);
279
294
  break
280
295
  }
281
296
  case DOM_TYPES.ELEMENT: {
282
- createElementNode(v_dom, parentEl,index);
297
+ createElementNode(v_dom, parentEl, index, hostComponent);
283
298
  break
284
299
  }
285
300
  case DOM_TYPES.FRAGMENT: {
286
- createFragmentNodes(v_dom, parentEl,index);
301
+ createFragmentNodes(v_dom, parentEl, index, hostComponent);
302
+ break
303
+ }
304
+ case DOM_TYPES.COMPONENT: {
305
+ createComponentNode(v_dom, parentEl, index, hostComponent);
287
306
  break
288
307
  }
289
308
  default: {
@@ -291,79 +310,84 @@ function mountDOM(v_dom, parentEl,index) {
291
310
  }
292
311
  }
293
312
  }
294
- function createTextNode(v_dom, parentEl,index) {
295
- const { value } = v_dom;
313
+ function createTextNode(v_dom, parentEl, index) {
314
+ const {value} = v_dom;
296
315
  const textNode = document.createTextNode(value);
297
316
  v_dom.el = textNode;
298
- insert(textNode,parentEl,index);
317
+ insert(textNode, parentEl, index);
299
318
  }
300
- function createFragmentNodes(v_dom, parentEl,index) {
319
+ function createFragmentNodes(v_dom, parentEl, index, hostComponent) {
301
320
  const {children} = v_dom;
302
321
  v_dom.el = parentEl;
303
- children.forEach((child,i) => mountDOM(child, parentEl,index ? index + i : null));
322
+ children.forEach((child, i) => mountDOM(child, parentEl, index ? index + i : null, hostComponent));
304
323
  }
305
- function createElementNode(v_dom, parentEl,index) {
306
- const { tag, props, children } = v_dom;
324
+ function createElementNode(v_dom, parentEl, index, hostComponent) {
325
+ const {tag, children} = v_dom;
307
326
  const element = document.createElement(tag);
308
- addProps(element, props, v_dom);
327
+ addProps(element, v_dom, hostComponent);
309
328
  v_dom.el = element;
310
- children.forEach((child) => mountDOM(child, element));
311
- insert(element,parentEl,index);
312
- }
313
- function addProps(el, props, v_dom) {
314
- const { on: events, ...attrs } = props;
315
- v_dom.listeners = addEventListeners(events, el);
329
+ children.forEach((child) => mountDOM(child, element, null, hostComponent));
330
+ insert(element, parentEl, index);
331
+ const {props} = extractPropsAndEvents(v_dom);
332
+ if (props.focus && props.focus === true) {
333
+ element.focus();
334
+ element.select();
335
+ }
336
+ }
337
+ function createComponentNode(v_dom, parentEl, index, hostComponent) {
338
+ const Component = v_dom.tag;
339
+ const {props, events} = extractPropsAndEvents(v_dom);
340
+ const component = new Component(props, events, hostComponent);
341
+ component.mount(parentEl, index);
342
+ v_dom.component = component;
343
+ v_dom.el = component.firstElement;
344
+ }
345
+ function addProps(el, v_dom, hostComponent) {
346
+ const {props: attrs, events} = extractPropsAndEvents(v_dom);
347
+ v_dom.listeners = addEventListeners(events, el, hostComponent);
316
348
  setAttributes(el, attrs);
317
349
  }
318
- function insert(el,parentEl,index){
319
- if(index == null){
350
+ function insert(el, parentEl, index) {
351
+ if (index == null) {
320
352
  parentEl.append(el);
321
353
  return
322
354
  }
323
- if(index < 0 ){
355
+ if (index < 0) {
324
356
  throw new Error(`Index must be positive,got ${index}`)
325
357
  }
326
358
  const children = parentEl.childNodes;
327
- if(index >= children.length){
359
+ if (index >= children.length) {
328
360
  parentEl.append(el);
329
- }
330
- else {
331
- parentEl.insertBefore(el,children[index]);
361
+ } else {
362
+ parentEl.insertBefore(el, children[index]);
332
363
  }
333
364
  }
334
365
 
335
- class Dispatcher {
336
- #subs = new Map()
337
- #afterHandlers = []
338
- subscribe(commandName, handler) {
339
- if (!this.#subs.has(commandName)) {
340
- this.#subs.set(commandName, []);
341
- }
342
- const handlers = this.#subs.get(commandName);
343
- if (handlers.includes(handler)) {
344
- return () => {
345
- }
346
- }
347
- handlers.push(handler);
348
- return () => {
349
- const id = handlers.indexOf(handler);
350
- handlers.splice(id, 1);
351
- }
352
- }
353
- afterEveryCommand(handler) {
354
- this.#afterHandlers.push(handler);
355
- return () => {
356
- const id = this.#afterHandlers.indexOf(handler);
357
- this.#afterHandlers.splice(id, 1);
358
- }
366
+ function createApp(RootComponent, props = {}) {
367
+ let parentEl = null;
368
+ let isMounted = false;
369
+ let v_dom = null;
370
+ function reset() {
371
+ parentEl = null;
372
+ isMounted = false;
373
+ v_dom = null;
359
374
  }
360
- dispatch(commandName, payload) {
361
- if (this.#subs.has(commandName)) {
362
- this.#subs.get(commandName).forEach((handler) => handler(payload));
363
- } else {
364
- console.warn(`No handlers for command ${commandName}`);
375
+ return {
376
+ mount(_parentEl) {
377
+ if (isMounted) {
378
+ throw new Error("The application is already mounted");
379
+ }
380
+ parentEl = _parentEl;
381
+ v_dom = h(RootComponent, props);
382
+ mountDOM(v_dom, parentEl);
383
+ isMounted = true;
384
+ },
385
+ unmount() {
386
+ destroyDOM(v_dom);
387
+ v_dom = null;
388
+ destroyDOM(v_dom);
389
+ reset();
365
390
  }
366
- this.#afterHandlers.forEach((handler) => handler());
367
391
  }
368
392
  }
369
393
 
@@ -372,9 +396,14 @@ function areNodesEqual(nodeOne,nodeTwo){
372
396
  return false
373
397
  }
374
398
  if(nodeOne.type === DOM_TYPES.ELEMENT){
375
- const {tag: tagOne} = nodeOne;
376
- const {tag: tagTwo} = nodeTwo;
377
- return tagOne === tagTwo
399
+ const {tag: tagOne,props: {key: keyOne}} = nodeOne;
400
+ const {tag: tagTwo,props: {key: keyTwo}} = nodeTwo;
401
+ return tagOne === tagTwo && keyOne === keyTwo
402
+ }
403
+ if (nodeOne.type === DOM_TYPES.COMPONENT) {
404
+ const {tag: componentOne, props: {key: keyOne}} = nodeOne;
405
+ const {tag: componentTwo, props: {key: keyTwo}} = nodeOne;
406
+ return componentOne === componentTwo && keyOne === keyTwo
378
407
  }
379
408
  return true
380
409
  }
@@ -398,6 +427,9 @@ function objectsDiff(oldObj, newObj) {
398
427
  updated: updated
399
428
  }
400
429
  }
430
+ function hasOwnProperty(obj,prop){
431
+ return Object.prototype.hasOwnProperty.call(obj,prop)
432
+ }
401
433
 
402
434
  function isNotEmptyString(str){
403
435
  return str !== ''
@@ -406,11 +438,11 @@ function isNotBlankOrEmptyString(str){
406
438
  return isNotEmptyString(str.trim())
407
439
  }
408
440
 
409
- function patchDom(oldV_dom, newV_dom, parentEl) {
441
+ function patchDom(oldV_dom, newV_dom, parentEl, hostComponent = null) {
410
442
  if (!areNodesEqual(oldV_dom, newV_dom)) {
411
443
  const index = findIndexInParent(parentEl, oldV_dom.el);
412
444
  destroyDOM(oldV_dom);
413
- mountDOM(newV_dom, parentEl, index);
445
+ mountDOM(newV_dom, parentEl, index, hostComponent);
414
446
  return newV_dom
415
447
  }
416
448
  newV_dom.el = oldV_dom.el;
@@ -420,11 +452,15 @@ function patchDom(oldV_dom, newV_dom, parentEl) {
420
452
  return newV_dom
421
453
  }
422
454
  case DOM_TYPES.ELEMENT: {
423
- patchElement(oldV_dom, newV_dom);
455
+ patchElement(oldV_dom, newV_dom, hostComponent);
456
+ break
457
+ }
458
+ case DOM_TYPES.COMPONENT: {
459
+ patchComponent(oldV_dom, newV_dom);
424
460
  break
425
461
  }
426
462
  }
427
- patchChildren(oldV_dom,newV_dom);
463
+ patchChildren(oldV_dom, newV_dom, hostComponent);
428
464
  return newV_dom
429
465
  }
430
466
  function findIndexInParent(parentEl, el) {
@@ -442,7 +478,7 @@ function patchText(oldV_dom, newV_dom) {
442
478
  el.nodeValue = newText;
443
479
  }
444
480
  }
445
- function patchElement(oldV_dom, newV_dom) {
481
+ function patchElement(oldV_dom, newV_dom, hostComponent) {
446
482
  const el = oldV_dom.el;
447
483
  const {
448
484
  class: oldClass,
@@ -460,7 +496,14 @@ function patchElement(oldV_dom, newV_dom) {
460
496
  patchAttrs(el, oldAttrs, newAttrs);
461
497
  patchClasses(el, oldClass, newClass);
462
498
  patchStyles(el, oldStyle, newStyle);
463
- newV_dom.listeners = patchEvents(el, oldListeners, oldEvents, newEvents);
499
+ newV_dom.listeners = patchEvents(el, oldListeners, oldEvents, newEvents, hostComponent);
500
+ }
501
+ function patchComponent(oldV_dom, newV_dom) {
502
+ const {component} = oldV_dom;
503
+ const {props} = extractPropsAndEvents(newV_dom);
504
+ component.updateProps(props);
505
+ newV_dom.component = component;
506
+ newV_dom.el = component.firstElement;
464
507
  }
465
508
  function patchAttrs(el, oldAttrs, newAttrs) {
466
509
  const {added, removed, updated} = objectsDiff(oldAttrs, newAttrs);
@@ -488,36 +531,36 @@ function toClassList(classes = '') {
488
531
  classes.split("/(\s+)/").filter(isNotBlankOrEmptyString)
489
532
  }
490
533
  function patchStyles(el, oldStyle = {}, newStyle = {}) {
491
- const {added,removed,updated} = objectsDiff(oldStyle,newStyle);
492
- for (const style of removed){
493
- removeStyle(el,style);
534
+ const {added, removed, updated} = objectsDiff(oldStyle, newStyle);
535
+ for (const style of removed) {
536
+ removeStyle(el, style);
494
537
  }
495
- for(const style of added.concat(updated)){
496
- setStyle(el,style,newStyle[style]);
538
+ for (const style of added.concat(updated)) {
539
+ setStyle(el, style, newStyle[style]);
497
540
  }
498
541
  }
499
- function patchEvents(el, oldListeners = {}, oldEvents = {}, newEvents = {}) {
500
- const {removed, added, updated} = objectsDiff(oldEvents,newEvents);
501
- for(const eventName of removed.concat(updated)){
502
- el.removeEventListener(eventName,oldListeners[eventName]);
542
+ function patchEvents(el, oldListeners = {}, oldEvents = {}, newEvents = {}, hostComponent) {
543
+ const {removed, added, updated} = objectsDiff(oldEvents, newEvents);
544
+ for (const eventName of removed.concat(updated)) {
545
+ el.removeEventListener(eventName, oldListeners[eventName]);
503
546
  }
504
547
  const addedListeners = {};
505
- for(const eventName of added.concat(updated)){
506
- const listener = addEventListener(eventName,newEvents[eventName],el);
507
- addedListeners[eventName] = listener;
548
+ for (const eventName of added.concat(updated)) {
549
+ addedListeners[eventName] = addEventListener(eventName, newEvents[eventName], el, hostComponent);
508
550
  }
509
551
  return addedListeners
510
552
  }
511
- function patchChildren(oldV_dom, newV_dom) {
553
+ function patchChildren(oldV_dom, newV_dom, hostComponent) {
512
554
  const oldChildren = extractChildren(oldV_dom);
513
555
  const newChildren = extractChildren(newV_dom);
514
556
  const parentEl = oldV_dom.el;
515
- const diffSeq = arraysDiffSequence(oldChildren,newChildren,areNodesEqual);
516
- for(const operation of diffSeq){
557
+ const diffSeq = arraysDiffSequence(oldChildren, newChildren, areNodesEqual);
558
+ for (const operation of diffSeq) {
517
559
  const {originalIndex, index, item} = operation;
560
+ const offset = hostComponent?.offset ?? 0;
518
561
  switch (operation.op) {
519
562
  case ARRAY_DIFF_OP.ADD: {
520
- mountDOM(item,parentEl,index);
563
+ mountDOM(item, parentEl, index + offset, hostComponent);
521
564
  break
522
565
  }
523
566
  case ARRAY_DIFF_OP.REMOVE: {
@@ -528,57 +571,204 @@ function patchChildren(oldV_dom, newV_dom) {
528
571
  const oldChild = oldChildren[originalIndex];
529
572
  const newChild = newChildren[index];
530
573
  const el = oldChild.el;
531
- const elAtTargetIndex = parentEl.childNodes[index];
532
- parentEl.insertBefore(el,elAtTargetIndex);
533
- patchDom(oldChild,newChild,parentEl);
574
+ const elAtTargetIndex = parentEl.childNodes[index + offset];
575
+ parentEl.insertBefore(el, elAtTargetIndex);
576
+ patchDom(oldChild, newChild, parentEl, hostComponent);
534
577
  break
535
578
  }
536
579
  case ARRAY_DIFF_OP.NOOP: {
537
- patchDom(oldChildren[originalIndex],newChildren[index],parentEl);
580
+ patchDom(oldChildren[originalIndex], newChildren[index], parentEl, hostComponent);
538
581
  break
539
582
  }
540
583
  }
541
584
  }
542
585
  }
543
586
 
544
- function createApp({state, view, reducers = {}}) {
545
- let parentEl = null;
546
- let v_dom = null;
547
- let isMounted = false;
548
- const dispatcher = new Dispatcher();
549
- const subscriptions = [dispatcher.afterEveryCommand(renderApp)];
550
- function emit(eventName, payload) {
551
- dispatcher.dispatch(eventName, payload);
552
- }
553
- for (const actionName in reducers) {
554
- const reducer = reducers[actionName];
555
- const subs = dispatcher.subscribe(actionName, (payload) => {
556
- state = reducer(state, payload);
557
- });
558
- subscriptions.push(subs);
587
+ function getDefaultExportFromCjs (x) {
588
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
589
+ }
590
+
591
+ var fastDeepEqual;
592
+ var hasRequiredFastDeepEqual;
593
+ function requireFastDeepEqual () {
594
+ if (hasRequiredFastDeepEqual) return fastDeepEqual;
595
+ hasRequiredFastDeepEqual = 1;
596
+ fastDeepEqual = function equal(a, b) {
597
+ if (a === b) return true;
598
+ if (a && b && typeof a == 'object' && typeof b == 'object') {
599
+ if (a.constructor !== b.constructor) return false;
600
+ var length, i, keys;
601
+ if (Array.isArray(a)) {
602
+ length = a.length;
603
+ if (length != b.length) return false;
604
+ for (i = length; i-- !== 0;)
605
+ if (!equal(a[i], b[i])) return false;
606
+ return true;
607
+ }
608
+ if (a.constructor === RegExp) return a.source === b.source && a.flags === b.flags;
609
+ if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
610
+ if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
611
+ keys = Object.keys(a);
612
+ length = keys.length;
613
+ if (length !== Object.keys(b).length) return false;
614
+ for (i = length; i-- !== 0;)
615
+ if (!Object.prototype.hasOwnProperty.call(b, keys[i])) return false;
616
+ for (i = length; i-- !== 0;) {
617
+ var key = keys[i];
618
+ if (!equal(a[key], b[key])) return false;
619
+ }
620
+ return true;
621
+ }
622
+ return a!==a && b!==b;
623
+ };
624
+ return fastDeepEqual;
625
+ }
626
+
627
+ var fastDeepEqualExports = requireFastDeepEqual();
628
+ var equal = /*@__PURE__*/getDefaultExportFromCjs(fastDeepEqualExports);
629
+
630
+ class Dispatcher {
631
+ #subs = new Map()
632
+ #afterHandlers = []
633
+ subscribe(commandName, handler) {
634
+ if (!this.#subs.has(commandName)) {
635
+ this.#subs.set(commandName, []);
636
+ }
637
+ const handlers = this.#subs.get(commandName);
638
+ if (handlers.includes(handler)) {
639
+ return () => {
640
+ }
641
+ }
642
+ handlers.push(handler);
643
+ return () => {
644
+ const id = handlers.indexOf(handler);
645
+ handlers.splice(id, 1);
646
+ }
559
647
  }
560
- function renderApp() {
561
- console.log("App rendered");
562
- const newV_dom = view(state, emit);
563
- v_dom = patchDom(v_dom,newV_dom,parentEl);
648
+ afterEveryCommand(handler) {
649
+ this.#afterHandlers.push(handler);
650
+ return () => {
651
+ const id = this.#afterHandlers.indexOf(handler);
652
+ this.#afterHandlers.splice(id, 1);
653
+ }
564
654
  }
565
- return {
566
- mount(_parentEl) {
567
- if (isMounted) {
568
- throw new Error("The application is already mounted");
655
+ dispatch(commandName, payload) {
656
+ if (this.#subs.has(commandName)) {
657
+ this.#subs.get(commandName).forEach((handler) => handler(payload));
658
+ } else {
659
+ console.warn(`No handlers for command ${commandName}`);
660
+ }
661
+ this.#afterHandlers.forEach((handler) => handler());
662
+ }
663
+ }
664
+
665
+ function defineComponent({render, state, ...methods}) {
666
+ class Component {
667
+ #isMounted = false
668
+ #v_dom = null
669
+ #hostEl = null
670
+ #eventHandlers = null
671
+ #parentComponent = null
672
+ #dispatcher = new Dispatcher()
673
+ #subscriptions = []
674
+ constructor(props = {}, eventHandlers = {}, parentComponent = {}) {
675
+ this.props = props;
676
+ this.state = state ? state(props) : {};
677
+ this.#eventHandlers = eventHandlers;
678
+ this.#parentComponent = parentComponent;
679
+ }
680
+ #wireEventHandlers() {
681
+ this.#subscriptions = Object.entries(this.#eventHandlers)
682
+ .map(
683
+ ([eventName, handler]) => this.#wireEventHandler(eventName, handler)
684
+ );
685
+ }
686
+ #wireEventHandler(eventName, handler) {
687
+ return this.#dispatcher.subscribe(eventName, (payload) => {
688
+ if (this.#parentComponent) {
689
+ handler.call(this.#parentComponent, payload);
690
+ } else {
691
+ handler(payload);
692
+ }
693
+ });
694
+ }
695
+ emit(eventName,payload){
696
+ this.#dispatcher.dispatch(eventName,payload);
697
+ }
698
+ get elements() {
699
+ if (this.#v_dom == null) {
700
+ return []
569
701
  }
570
- parentEl = _parentEl;
571
- v_dom = view(state, emit);
572
- mountDOM(v_dom, parentEl);
573
- isMounted = true;
574
- },
702
+ if (this.#v_dom.type === DOM_TYPES.FRAGMENT) {
703
+ return extractChildren(this.#v_dom).flatMap((child) => {
704
+ if (child.type === DOM_TYPES.COMPONENT) {
705
+ return child.component.elements
706
+ }
707
+ return [child.el]
708
+ })
709
+ }
710
+ return [this.#v_dom.el]
711
+ }
712
+ get firstElement() {
713
+ return this.elements[0]
714
+ }
715
+ get offset() {
716
+ if (this.#v_dom.type === DOM_TYPES.FRAGMENT) {
717
+ return Array.from(this.#hostEl.children).indexOf(this.firstElement)
718
+ }
719
+ return 0
720
+ }
721
+ updateState(state) {
722
+ this.state = {...this.state, ...state};
723
+ this.#patch();
724
+ }
725
+ updateProps(props) {
726
+ const newProps = {...this.props, ...props};
727
+ if (equal(this.props, newProps)) {
728
+ return
729
+ }
730
+ this.props = newProps;
731
+ this.#patch();
732
+ }
733
+ render() {
734
+ return render.call(this)
735
+ }
736
+ mount(hostEl, index = null) {
737
+ if (this.#isMounted) {
738
+ throw new Error("Component is already mounted")
739
+ }
740
+ this.#v_dom = this.render();
741
+ mountDOM(this.#v_dom, hostEl, index, this);
742
+ this.#wireEventHandlers();
743
+ this.#hostEl = hostEl;
744
+ this.#isMounted = true;
745
+ }
575
746
  unmount() {
576
- destroyDOM(v_dom);
577
- v_dom = null;
578
- subscriptions.forEach((unsubscribe) => unsubscribe());
579
- isMounted = false;
747
+ if (!this.#isMounted) {
748
+ throw new Error('Component is not mounted')
749
+ }
750
+ destroyDOM(this.#v_dom);
751
+ this.#subscriptions.forEach((unsubscribe) => unsubscribe());
752
+ this.#v_dom = null;
753
+ this.#hostEl = null;
754
+ this.#isMounted = false;
755
+ this.#subscriptions = [];
756
+ }
757
+ #patch() {
758
+ if (!this.#isMounted) {
759
+ throw new Error('Component is not mounted')
760
+ }
761
+ const v_dom = this.render();
762
+ this.#v_dom = patchDom(this.#v_dom, v_dom, this.#hostEl, this);
763
+ }
764
+ }
765
+ for (const methodName in methods) {
766
+ if (hasOwnProperty(Component, methodName)) {
767
+ throw new Error(`Method ${methodName} already exists in the component`)
580
768
  }
769
+ Component.prototype[methodName] = methods[methodName];
581
770
  }
771
+ return Component
582
772
  }
583
773
 
584
- export { createApp, h, hFragment, hString };
774
+ export { createApp, defineComponent, h, hFragment, hString };
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "vanilla_project",
3
- "version": "2.0.0",
3
+ "version": "3.0.0",
4
4
  "main": "dist/vanilla_project.js",
5
5
  "files": [
6
6
  "dist/vanilla_project.js"
7
7
  ],
8
8
  "devDependencies": {
9
+ "@rollup/plugin-commonjs": "^29.0.0",
10
+ "@rollup/plugin-node-resolve": "^16.0.3",
9
11
  "eslint": "^9.39.2",
10
12
  "jsdom": "^27.4.0",
11
13
  "rollup": "^4.55.1",
@@ -21,10 +23,10 @@
21
23
  "test": "vitest",
22
24
  "test:run": "vitest run"
23
25
  },
24
- "type": "commonjs",
25
26
  "dependencies": {
26
27
  "@eslint/eslintrc": "^3.3.3",
27
28
  "@eslint/js": "^9.39.2",
29
+ "fast-deep-equal": "^3.1.3",
28
30
  "globals": "^14.0.0"
29
31
  }
30
32
  }