veles 1.0.0-alpha.1 → 1.0.0-alpha.2

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.
@@ -171,9 +171,9 @@ function parseChildren({ children, htmlElement, velesNode, portal }) {
171
171
  //#region src/create-element/assign-attributes.ts
172
172
  function assignAttributes({ props, htmlElement, velesNode }) {
173
173
  Object.entries(props).forEach(([key, value]) => {
174
- if (typeof value === "function" && value.velesAttribute === true) assignAttribute({
174
+ if (value && typeof value === "object" && value.velesAttribute === true) assignAttribute({
175
175
  key,
176
- value: value(htmlElement, key, velesNode),
176
+ value: value.getValue(htmlElement, key, velesNode),
177
177
  htmlElement
178
178
  });
179
179
  else assignAttribute({
@@ -238,14 +238,14 @@ function createElement(element, props = {}) {
238
238
  });
239
239
  else portal.append(childComponent.html);
240
240
  else if ("velesStringElement" in childComponent) portal.append(childComponent.html);
241
- else appendComponentToPortal(getExecutedComponentVelesNode(childComponent.executedVersion), portal);
241
+ else appendComponentToPortal(getExecutedComponentVelesNode(getMountedNodeExecutedVersion(childComponent, "Portal child component is not mounted")), portal);
242
242
  });
243
243
  });
244
244
  velesNode._privateMethods._addUnmountHandler(function removeNodeOnUnmount() {
245
245
  velesNode.childComponents.forEach((childComponent) => {
246
246
  if ("velesNode" in childComponent) childComponent.html.remove();
247
247
  else if ("velesStringElement" in childComponent) childComponent.html.remove();
248
- else cleanupComponentFromPortal(getExecutedComponentVelesNode(childComponent.executedVersion));
248
+ else cleanupComponentFromPortal(getExecutedComponentVelesNode(getMountedNodeExecutedVersion(childComponent, "Portal child component is not mounted")));
249
249
  });
250
250
  });
251
251
  }
@@ -309,8 +309,8 @@ function createContext() {
309
309
  addContext,
310
310
  readContext: () => {
311
311
  const currentContext = publicContextStack[publicContextStack.length - 1];
312
- if (!currentContext) console.error("no Context currently available");
313
- else return currentContext[contextId];
312
+ if (!currentContext) throw new Error("no Context currently available");
313
+ return currentContext[contextId];
314
314
  }
315
315
  };
316
316
  }
@@ -374,21 +374,29 @@ function renderTree(component, { parentVelesElement } = {}) {
374
374
  */
375
375
  if (parentVelesElement) newNode.parentVelesElement = parentVelesElement;
376
376
  } else if (parentVelesElement) {
377
- if (component.insertAfter) if ("velesComponentObject" in component.insertAfter) component.html = insertNode({
378
- velesElement: newNode,
379
- adjacentNode: component.insertAfter.html,
380
- parentVelesElement
381
- });
382
- else component.html = insertNode({
383
- velesElement: newNode,
384
- adjacentNode: component.insertAfter,
385
- parentVelesElement
386
- });
387
- else component.html = insertNode({
388
- velesElement: newNode,
389
- adjacentNode: null,
390
- parentVelesElement
391
- });
377
+ if (component.insertAfter) if ("velesComponentObject" in component.insertAfter) {
378
+ const lastNode = insertNode({
379
+ velesElement: newNode,
380
+ adjacentNode: component.insertAfter.html ?? null,
381
+ parentVelesElement
382
+ });
383
+ if (lastNode) component.html = lastNode;
384
+ } else {
385
+ const lastNode = insertNode({
386
+ velesElement: newNode,
387
+ adjacentNode: component.insertAfter,
388
+ parentVelesElement
389
+ });
390
+ if (lastNode) component.html = lastNode;
391
+ }
392
+ else {
393
+ const lastNode = insertNode({
394
+ velesElement: newNode,
395
+ adjacentNode: null,
396
+ parentVelesElement
397
+ });
398
+ if (lastNode) component.html = lastNode;
399
+ }
392
400
  newNode.parentVelesElement = parentVelesElement;
393
401
  }
394
402
  if (component.needExecutedVersion || component.portal) component.executedVersion = executedComponent;
@@ -405,6 +413,7 @@ function renderTree(component, { parentVelesElement } = {}) {
405
413
  if (component.needExecutedVersion) component.executedVersion = executedNode;
406
414
  return executedNode;
407
415
  }
416
+ throw new Error("Unknown component type in renderTree");
408
417
  }
409
418
  function insertNode({ velesElement, adjacentNode, parentVelesElement }) {
410
419
  if (velesElement.phantom) {
@@ -440,6 +449,10 @@ function insertNode({ velesElement, adjacentNode, parentVelesElement }) {
440
449
  return velesElement.html;
441
450
  }
442
451
  }
452
+ function getMountedNodeExecutedVersion(node, errorMessage) {
453
+ if (!node.executedVersion) throw new Error(errorMessage || "Expected node to have executedVersion by this point");
454
+ return node.executedVersion;
455
+ }
443
456
  function callMountHandlers(component) {
444
457
  component._privateMethods._callMountHandlers();
445
458
  if ("executedVelesStringElement" in component) return;
@@ -519,6 +532,12 @@ Object.defineProperty(exports, "getExecutedComponentVelesNode", {
519
532
  return getExecutedComponentVelesNode;
520
533
  }
521
534
  });
535
+ Object.defineProperty(exports, "getMountedNodeExecutedVersion", {
536
+ enumerable: true,
537
+ get: function() {
538
+ return getMountedNodeExecutedVersion;
539
+ }
540
+ });
522
541
  Object.defineProperty(exports, "hasCurrentLifecycleContext", {
523
542
  enumerable: true,
524
543
  get: function() {
@@ -171,9 +171,9 @@ function parseChildren({ children, htmlElement, velesNode, portal }) {
171
171
  //#region src/create-element/assign-attributes.ts
172
172
  function assignAttributes({ props, htmlElement, velesNode }) {
173
173
  Object.entries(props).forEach(([key, value]) => {
174
- if (typeof value === "function" && value.velesAttribute === true) assignAttribute({
174
+ if (value && typeof value === "object" && value.velesAttribute === true) assignAttribute({
175
175
  key,
176
- value: value(htmlElement, key, velesNode),
176
+ value: value.getValue(htmlElement, key, velesNode),
177
177
  htmlElement
178
178
  });
179
179
  else assignAttribute({
@@ -238,14 +238,14 @@ function createElement(element, props = {}) {
238
238
  });
239
239
  else portal.append(childComponent.html);
240
240
  else if ("velesStringElement" in childComponent) portal.append(childComponent.html);
241
- else appendComponentToPortal(getExecutedComponentVelesNode(childComponent.executedVersion), portal);
241
+ else appendComponentToPortal(getExecutedComponentVelesNode(getMountedNodeExecutedVersion(childComponent, "Portal child component is not mounted")), portal);
242
242
  });
243
243
  });
244
244
  velesNode._privateMethods._addUnmountHandler(function removeNodeOnUnmount() {
245
245
  velesNode.childComponents.forEach((childComponent) => {
246
246
  if ("velesNode" in childComponent) childComponent.html.remove();
247
247
  else if ("velesStringElement" in childComponent) childComponent.html.remove();
248
- else cleanupComponentFromPortal(getExecutedComponentVelesNode(childComponent.executedVersion));
248
+ else cleanupComponentFromPortal(getExecutedComponentVelesNode(getMountedNodeExecutedVersion(childComponent, "Portal child component is not mounted")));
249
249
  });
250
250
  });
251
251
  }
@@ -309,8 +309,8 @@ function createContext() {
309
309
  addContext,
310
310
  readContext: () => {
311
311
  const currentContext = publicContextStack[publicContextStack.length - 1];
312
- if (!currentContext) console.error("no Context currently available");
313
- else return currentContext[contextId];
312
+ if (!currentContext) throw new Error("no Context currently available");
313
+ return currentContext[contextId];
314
314
  }
315
315
  };
316
316
  }
@@ -374,21 +374,29 @@ function renderTree(component, { parentVelesElement } = {}) {
374
374
  */
375
375
  if (parentVelesElement) newNode.parentVelesElement = parentVelesElement;
376
376
  } else if (parentVelesElement) {
377
- if (component.insertAfter) if ("velesComponentObject" in component.insertAfter) component.html = insertNode({
378
- velesElement: newNode,
379
- adjacentNode: component.insertAfter.html,
380
- parentVelesElement
381
- });
382
- else component.html = insertNode({
383
- velesElement: newNode,
384
- adjacentNode: component.insertAfter,
385
- parentVelesElement
386
- });
387
- else component.html = insertNode({
388
- velesElement: newNode,
389
- adjacentNode: null,
390
- parentVelesElement
391
- });
377
+ if (component.insertAfter) if ("velesComponentObject" in component.insertAfter) {
378
+ const lastNode = insertNode({
379
+ velesElement: newNode,
380
+ adjacentNode: component.insertAfter.html ?? null,
381
+ parentVelesElement
382
+ });
383
+ if (lastNode) component.html = lastNode;
384
+ } else {
385
+ const lastNode = insertNode({
386
+ velesElement: newNode,
387
+ adjacentNode: component.insertAfter,
388
+ parentVelesElement
389
+ });
390
+ if (lastNode) component.html = lastNode;
391
+ }
392
+ else {
393
+ const lastNode = insertNode({
394
+ velesElement: newNode,
395
+ adjacentNode: null,
396
+ parentVelesElement
397
+ });
398
+ if (lastNode) component.html = lastNode;
399
+ }
392
400
  newNode.parentVelesElement = parentVelesElement;
393
401
  }
394
402
  if (component.needExecutedVersion || component.portal) component.executedVersion = executedComponent;
@@ -405,6 +413,7 @@ function renderTree(component, { parentVelesElement } = {}) {
405
413
  if (component.needExecutedVersion) component.executedVersion = executedNode;
406
414
  return executedNode;
407
415
  }
416
+ throw new Error("Unknown component type in renderTree");
408
417
  }
409
418
  function insertNode({ velesElement, adjacentNode, parentVelesElement }) {
410
419
  if (velesElement.phantom) {
@@ -440,6 +449,10 @@ function insertNode({ velesElement, adjacentNode, parentVelesElement }) {
440
449
  return velesElement.html;
441
450
  }
442
451
  }
452
+ function getMountedNodeExecutedVersion(node, errorMessage) {
453
+ if (!node.executedVersion) throw new Error(errorMessage || "Expected node to have executedVersion by this point");
454
+ return node.executedVersion;
455
+ }
443
456
  function callMountHandlers(component) {
444
457
  component._privateMethods._callMountHandlers();
445
458
  if ("executedVelesStringElement" in component) return;
@@ -465,4 +478,4 @@ function unique(arr) {
465
478
  return resultArr;
466
479
  }
467
480
  //#endregion
468
- export { renderTree as a, createContext as c, Fragment as d, createElement as f, onUnmount as g, onMount as h, identity as i, getCurrentContext as l, hasCurrentLifecycleContext as m, callUnmountHandlers as n, unique as o, createTextElement as p, getExecutedComponentVelesNode as r, addPublicContext as s, callMountHandlers as t, popPublicContext as u };
481
+ export { onUnmount as _, identity as a, addPublicContext as c, popPublicContext as d, Fragment as f, onMount as g, hasCurrentLifecycleContext as h, getMountedNodeExecutedVersion as i, createContext as l, createTextElement as m, callUnmountHandlers as n, renderTree as o, createElement as p, getExecutedComponentVelesNode as r, unique as s, callMountHandlers as t, getCurrentContext as u };
@@ -353,8 +353,9 @@ declare namespace JSX {
353
353
  z?: number | string | undefined | AttributeHelper<number | string | undefined>;
354
354
  zoomAndPan?: string | undefined | AttributeHelper<string | undefined>;
355
355
  }
356
- export type TargetedEvent<Target extends EventTarget = EventTarget, TypedEvent extends Event = Event> = Omit<TypedEvent, "currentTarget"> & {
356
+ export type TargetedEvent<Target extends EventTarget = EventTarget, TypedEvent extends Event = Event> = Omit<TypedEvent, "currentTarget" | "target"> & {
357
357
  readonly currentTarget: Target;
358
+ readonly target: Target;
358
359
  };
359
360
  export type TargetedAnimationEvent<Target extends EventTarget> = TargetedEvent<Target, AnimationEvent>;
360
361
  export type TargetedClipboardEvent<Target extends EventTarget> = TargetedEvent<Target, ClipboardEvent>;
@@ -1494,33 +1495,33 @@ type ExecutedVelesComponent = {
1494
1495
  };
1495
1496
  // all supported child options
1496
1497
  type velesChild = string | number | VelesElement | VelesComponentObject | VelesStringElement;
1497
- type VelesChildren = velesChild | velesChild[] | undefined | null;
1498
- type VelesElementProps = {
1498
+ type VelesMaybeChild = velesChild | undefined | null;
1499
+ type VelesChildren = VelesMaybeChild | VelesMaybeChild[];
1500
+ type VelesBaseProps = {
1499
1501
  children?: VelesChildren;
1500
1502
  ref?: {
1501
1503
  velesRef: true;
1502
1504
  current: any;
1503
1505
  };
1504
- portal?: HTMLElement; // event handlers + any html properties
1505
- // the value can be either a string value
1506
- // or a function in case we support reactivity
1507
- // TODO: we can improve these types
1508
- [htmlAttribute: string]: any;
1509
- } & JSX.HTMLAttributes;
1506
+ portal?: HTMLElement;
1507
+ phantom?: boolean; // Custom data-* attributes used widely in tests/apps.
1508
+ [dataAttribute: `data-${string}`]: unknown;
1509
+ };
1510
+ type VelesElementProps = VelesBaseProps & JSX.HTMLAttributes;
1510
1511
  type ComponentAPI = {
1511
1512
  // You can return a function from the mount callback, and it will be
1512
1513
  // automatically registered as `onUnmount` callback
1513
1514
  onMount: (cb: Function) => void | Function;
1514
1515
  onUnmount: (cb: Function) => void;
1515
1516
  };
1516
- type ComponentFunction = (props: VelesElementProps, componentAPI: ComponentAPI) => VelesElement | VelesComponentObject | VelesStringElement | string | null;
1517
+ type ComponentFunction<Props extends object = VelesElementProps> = (props: Props, componentAPI: ComponentAPI) => VelesElement | VelesComponentObject | VelesStringElement | string | null;
1517
1518
  type AttributeHelper<T> = {
1518
- (htmlElement: HTMLElement, attributeName: string, node: VelesElement): T;
1519
- velesAttribute: boolean;
1519
+ velesAttribute: true;
1520
+ getValue: (htmlElement: HTMLElement, attributeName: string, node: VelesElement) => T;
1520
1521
  };
1521
1522
  type VelesComponentObject = {
1522
1523
  velesComponentObject: true;
1523
- element: ComponentFunction;
1524
+ element: ComponentFunction<any>;
1524
1525
  props: VelesElementProps;
1525
1526
  insertAfter?: VelesComponentObject | HTMLElement | Text | null;
1526
1527
  html?: HTMLElement | Text;
@@ -1537,13 +1538,14 @@ type VelesComponentObject = {
1537
1538
  };
1538
1539
  //#endregion
1539
1540
  //#region src/create-element/create-element.d.ts
1540
- declare function createElement(element: string | ComponentFunction, props?: VelesElementProps): VelesElement | VelesComponentObject;
1541
+ declare function createElement<Tag extends keyof JSX.IntrinsicElements>(element: Tag, props?: VelesBaseProps & JSX.IntrinsicElements[Tag]): VelesElement;
1542
+ declare function createElement<Props extends object>(element: ComponentFunction<Props>, props?: Props): VelesComponentObject;
1541
1543
  //#endregion
1542
1544
  //#region src/fragment.d.ts
1543
1545
  declare function Fragment({
1544
1546
  children
1545
1547
  }: {
1546
1548
  children?: VelesChildren;
1547
- }): VelesElement | VelesComponentObject;
1549
+ }): VelesElement;
1548
1550
  //#endregion
1549
1551
  export { VelesComponentObject as a, JSX as c, VelesChildren as i, createElement as n, VelesElement as o, AttributeHelper as r, VelesStringElement as s, Fragment as t };
@@ -353,8 +353,9 @@ declare namespace JSX {
353
353
  z?: number | string | undefined | AttributeHelper<number | string | undefined>;
354
354
  zoomAndPan?: string | undefined | AttributeHelper<string | undefined>;
355
355
  }
356
- export type TargetedEvent<Target extends EventTarget = EventTarget, TypedEvent extends Event = Event> = Omit<TypedEvent, "currentTarget"> & {
356
+ export type TargetedEvent<Target extends EventTarget = EventTarget, TypedEvent extends Event = Event> = Omit<TypedEvent, "currentTarget" | "target"> & {
357
357
  readonly currentTarget: Target;
358
+ readonly target: Target;
358
359
  };
359
360
  export type TargetedAnimationEvent<Target extends EventTarget> = TargetedEvent<Target, AnimationEvent>;
360
361
  export type TargetedClipboardEvent<Target extends EventTarget> = TargetedEvent<Target, ClipboardEvent>;
@@ -1494,33 +1495,33 @@ type ExecutedVelesComponent = {
1494
1495
  };
1495
1496
  // all supported child options
1496
1497
  type velesChild = string | number | VelesElement | VelesComponentObject | VelesStringElement;
1497
- type VelesChildren = velesChild | velesChild[] | undefined | null;
1498
- type VelesElementProps = {
1498
+ type VelesMaybeChild = velesChild | undefined | null;
1499
+ type VelesChildren = VelesMaybeChild | VelesMaybeChild[];
1500
+ type VelesBaseProps = {
1499
1501
  children?: VelesChildren;
1500
1502
  ref?: {
1501
1503
  velesRef: true;
1502
1504
  current: any;
1503
1505
  };
1504
- portal?: HTMLElement; // event handlers + any html properties
1505
- // the value can be either a string value
1506
- // or a function in case we support reactivity
1507
- // TODO: we can improve these types
1508
- [htmlAttribute: string]: any;
1509
- } & JSX.HTMLAttributes;
1506
+ portal?: HTMLElement;
1507
+ phantom?: boolean; // Custom data-* attributes used widely in tests/apps.
1508
+ [dataAttribute: `data-${string}`]: unknown;
1509
+ };
1510
+ type VelesElementProps = VelesBaseProps & JSX.HTMLAttributes;
1510
1511
  type ComponentAPI = {
1511
1512
  // You can return a function from the mount callback, and it will be
1512
1513
  // automatically registered as `onUnmount` callback
1513
1514
  onMount: (cb: Function) => void | Function;
1514
1515
  onUnmount: (cb: Function) => void;
1515
1516
  };
1516
- type ComponentFunction = (props: VelesElementProps, componentAPI: ComponentAPI) => VelesElement | VelesComponentObject | VelesStringElement | string | null;
1517
+ type ComponentFunction<Props extends object = VelesElementProps> = (props: Props, componentAPI: ComponentAPI) => VelesElement | VelesComponentObject | VelesStringElement | string | null;
1517
1518
  type AttributeHelper<T> = {
1518
- (htmlElement: HTMLElement, attributeName: string, node: VelesElement): T;
1519
- velesAttribute: boolean;
1519
+ velesAttribute: true;
1520
+ getValue: (htmlElement: HTMLElement, attributeName: string, node: VelesElement) => T;
1520
1521
  };
1521
1522
  type VelesComponentObject = {
1522
1523
  velesComponentObject: true;
1523
- element: ComponentFunction;
1524
+ element: ComponentFunction<any>;
1524
1525
  props: VelesElementProps;
1525
1526
  insertAfter?: VelesComponentObject | HTMLElement | Text | null;
1526
1527
  html?: HTMLElement | Text;
@@ -1537,13 +1538,14 @@ type VelesComponentObject = {
1537
1538
  };
1538
1539
  //#endregion
1539
1540
  //#region src/create-element/create-element.d.ts
1540
- declare function createElement(element: string | ComponentFunction, props?: VelesElementProps): VelesElement | VelesComponentObject;
1541
+ declare function createElement<Tag extends keyof JSX.IntrinsicElements>(element: Tag, props?: VelesBaseProps & JSX.IntrinsicElements[Tag]): VelesElement;
1542
+ declare function createElement<Props extends object>(element: ComponentFunction<Props>, props?: Props): VelesComponentObject;
1541
1543
  //#endregion
1542
1544
  //#region src/fragment.d.ts
1543
1545
  declare function Fragment({
1544
1546
  children
1545
1547
  }: {
1546
1548
  children?: VelesChildren;
1547
- }): VelesElement | VelesComponentObject;
1549
+ }): VelesElement;
1548
1550
  //#endregion
1549
1551
  export { VelesComponentObject as a, JSX as c, VelesChildren as i, createElement as n, VelesElement as o, AttributeHelper as r, VelesStringElement as s, Fragment as t };
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require__utils = require("./_utils-gPluq0AT.cjs");
2
+ const require__utils = require("./_utils-Bhfy2AFV.cjs");
3
3
  //#region src/attach-component.ts
4
4
  /**
5
5
  * Attach Veles component tree to a regular HTML node.
@@ -204,11 +204,7 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
204
204
  console.error("there is no wrapper component for the iterator");
205
205
  return;
206
206
  }
207
- if (!wrapperComponent.executedVersion) {
208
- console.error("it seems the wrapper component was not mounted");
209
- return;
210
- }
211
- const wrapperVelesElementNode = require__utils.getExecutedComponentVelesNode(wrapperComponent.executedVersion);
207
+ const wrapperVelesElementNode = require__utils.getExecutedComponentVelesNode(require__utils.getMountedNodeExecutedVersion(wrapperComponent, "Iterator wrapper is expected to be mounted"));
212
208
  const parentVelesElement = wrapperVelesElementNode.parentVelesElement;
213
209
  if (!parentVelesElement) {
214
210
  console.error("there is no parent Veles node for the iterator wrapper");
@@ -273,13 +269,13 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
273
269
  let offset = 0;
274
270
  let currentElement = null;
275
271
  newRenderedElements.forEach((newRenderedElement, index) => {
276
- newChildRenderedComponents.push(newRenderedElement[0].executedVersion);
272
+ newChildRenderedComponents.push(require__utils.getMountedNodeExecutedVersion(newRenderedElement[0], "Iterator child is expected to be mounted"));
277
273
  newChildComponents.push(newRenderedElement[0]);
278
274
  if (positioningOffset[index]) offset = offset + positioningOffset[index];
279
275
  const [newNode, calculatedKey, newState] = newRenderedElement;
280
276
  const existingElement = elementsByKey[calculatedKey];
281
277
  if (existingElement) {
282
- const existingElementNode = require__utils.getExecutedComponentVelesNode(existingElement.node.executedVersion);
278
+ const existingElementNode = require__utils.getExecutedComponentVelesNode(require__utils.getMountedNodeExecutedVersion(existingElement.node, "Existing iterator node is expected to be mounted"));
283
279
  if (existingElement.indexValue + offset === index) {
284
280
  currentElement = existingElementNode.html;
285
281
  return;
@@ -306,7 +302,8 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
306
302
  offset = offset - 1;
307
303
  }
308
304
  } else {
309
- const newNodeVelesElement = require__utils.getExecutedComponentVelesNode(newNode.executedVersion);
305
+ const newNodeExecutedVersion = require__utils.getMountedNodeExecutedVersion(newNode, "New iterator node is expected to be mounted");
306
+ const newNodeVelesElement = require__utils.getExecutedComponentVelesNode(newNodeExecutedVersion);
310
307
  newNodeVelesElement.parentVelesElement = parentVelesElement;
311
308
  if (currentElement) currentElement.after(newNodeVelesElement.html);
312
309
  else {
@@ -317,15 +314,16 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
317
314
  offset = offset + 1;
318
315
  currentElement = newNodeVelesElement.html;
319
316
  newElementsCount = newElementsCount + 1;
320
- require__utils.callMountHandlers(newNode.executedVersion);
317
+ require__utils.callMountHandlers(newNodeExecutedVersion);
321
318
  }
322
319
  });
323
320
  if (renderedElements.length === newRenderedElements.length + newElementsCount) {} else renderedElements.forEach(([oldNode, calculatedKey]) => {
324
321
  if (renderedExistingElements[calculatedKey] === true) return;
325
322
  else {
326
- require__utils.getExecutedComponentVelesNode(oldNode.executedVersion).html.remove();
327
- require__utils.callUnmountHandlers(oldNode.executedVersion);
328
- if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = wrapperVelesElementNode.childComponents.filter((childComponent) => childComponent !== oldNode.executedVersion);
323
+ const oldNodeExecutedVersion = require__utils.getMountedNodeExecutedVersion(oldNode, "Removed iterator node is expected to be mounted");
324
+ require__utils.getExecutedComponentVelesNode(oldNodeExecutedVersion).html.remove();
325
+ require__utils.callUnmountHandlers(oldNodeExecutedVersion);
326
+ if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = wrapperVelesElementNode.childComponents.filter((childComponent) => childComponent !== oldNodeExecutedVersion);
329
327
  else throw new Error("Wrapper iterator element is a string");
330
328
  if ("velesNode" in wrapperComponent) wrapperComponent.childComponents = wrapperComponent.childComponents.filter((childComponent) => childComponent !== oldNode);
331
329
  }
@@ -608,7 +606,7 @@ function createStateFromCore(core, subscribeCallback) {
608
606
  });
609
607
  const result = {
610
608
  track: (cb, options = {}) => {
611
- result.trackSelected(void 0, cb, options);
609
+ result.trackSelected((value) => value, cb, options);
612
610
  },
613
611
  trackSelected(selector, cb, options = {}) {
614
612
  const selectedCore = selector ? core.map(selector, { equality: createCoreEquality(options.comparator) }) : options.comparator ? core.map((value) => value, { equality: createCoreEquality(options.comparator) }) : core;
@@ -712,28 +710,29 @@ function createStateFromCore(core, subscribeCallback) {
712
710
  const originalValue = core.get();
713
711
  let wasMounted = false;
714
712
  const attributeValue = cb ? cb(originalValue) : originalValue;
715
- const attributeHelper = (htmlElement, attributeName, node) => {
716
- const trackingElement = {
717
- cb,
718
- htmlElement,
719
- attributeName,
720
- attributeValue
721
- };
722
- node._privateMethods._addMountHandler(() => {
723
- trackers.trackingAttributes.push(trackingElement);
724
- if (!wasMounted && core.get() === originalValue) {} else updateUseAttributeValue({
725
- element: trackingElement,
726
- value: core.get()
727
- });
728
- if (!wasMounted) wasMounted = true;
729
- node._privateMethods._addUnmountHandler(() => {
730
- trackers.trackingAttributes = trackers.trackingAttributes.filter((trackingAttribute) => trackingAttribute !== trackingElement);
713
+ return {
714
+ velesAttribute: true,
715
+ getValue(htmlElement, attributeName, node) {
716
+ const trackingElement = {
717
+ cb,
718
+ htmlElement,
719
+ attributeName,
720
+ attributeValue
721
+ };
722
+ node._privateMethods._addMountHandler(() => {
723
+ trackers.trackingAttributes.push(trackingElement);
724
+ if (!wasMounted && core.get() === originalValue) {} else updateUseAttributeValue({
725
+ element: trackingElement,
726
+ value: core.get()
727
+ });
728
+ if (!wasMounted) wasMounted = true;
729
+ node._privateMethods._addUnmountHandler(() => {
730
+ trackers.trackingAttributes = trackers.trackingAttributes.filter((trackingAttribute) => trackingAttribute !== trackingElement);
731
+ });
731
732
  });
732
- });
733
- return attributeValue;
733
+ return attributeValue;
734
+ }
734
735
  };
735
- attributeHelper.velesAttribute = true;
736
- return attributeHelper;
737
736
  },
738
737
  dispose: () => {
739
738
  core.dispose();
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-D252pobF.cjs";
1
+ import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-C16zCm8L.cjs";
2
2
 
3
3
  //#region src/attach-component.d.ts
4
4
  /**
@@ -23,6 +23,7 @@ declare function onUnmount(cb: Function): void;
23
23
  //#region src/create-state/types.d.ts
24
24
  type StateEquality<ValueType> = (value1: ValueType, value2: ValueType) => boolean;
25
25
  type StateLike<ValueType> = State<ValueType>;
26
+ type ArrayElement<T> = T extends ReadonlyArray<infer Element> ? Element : never;
26
27
  type State<ValueType> = {
27
28
  track(cb: (value: ValueType) => void | Function, options?: {
28
29
  callOnMount?: boolean;
@@ -40,16 +41,26 @@ type State<ValueType> = {
40
41
  <SelectorValueType>(selector: (value: ValueType) => SelectorValueType, cb?: (value: SelectorValueType) => VelesElement | VelesComponentObject | string | undefined | null, comparator?: (value1: SelectorValueType, value2: SelectorValueType) => boolean): VelesElement | VelesComponentObject | VelesStringElement;
41
42
  };
42
43
  attribute(cb?: (value: ValueType) => any): AttributeHelper<any>;
43
- renderEach<Element>(options: {
44
+ renderEach<Element extends ArrayElement<ValueType> = ArrayElement<ValueType>>(options: ValueType extends ReadonlyArray<any> ? {
44
45
  key: string | ((options: {
45
46
  element: Element;
46
47
  index: number;
47
48
  }) => string);
48
- selector?: (value: ValueType) => Element[];
49
+ selector?: undefined;
50
+ } : never, cb: (props: {
51
+ elementState: State<Element>;
52
+ indexState: State<number>;
53
+ }) => VelesElement | VelesComponentObject): VelesComponentObject | VelesElement;
54
+ renderEach<SelectorValueType extends ReadonlyArray<any>, Element extends ArrayElement<SelectorValueType> = ArrayElement<SelectorValueType>>(options: {
55
+ key: string | ((options: {
56
+ element: Element;
57
+ index: number;
58
+ }) => string);
59
+ selector: (value: ValueType) => SelectorValueType;
49
60
  }, cb: (props: {
50
61
  elementState: State<Element>;
51
62
  indexState: State<number>;
52
- }) => VelesElement | VelesComponentObject): VelesComponentObject | VelesElement | null;
63
+ }) => VelesElement | VelesComponentObject): VelesComponentObject | VelesElement;
53
64
  map<SelectorValueType>(selector: (value: ValueType) => SelectorValueType, options?: {
54
65
  equality?: StateEquality<SelectorValueType>;
55
66
  }): State<SelectorValueType>;
@@ -101,7 +112,7 @@ declare function createContext<T>(): {
101
112
  }: {
102
113
  value: T;
103
114
  children?: VelesChildren;
104
- }) => VelesElement | VelesComponentObject;
115
+ }) => VelesComponentObject;
105
116
  addContext: (value: T) => void;
106
117
  readContext: () => T;
107
118
  };
@@ -113,6 +124,6 @@ declare function Portal({
113
124
  }: {
114
125
  children?: VelesChildren;
115
126
  portalNode: HTMLElement;
116
- }): VelesElement | VelesComponentObject;
127
+ }): VelesElement;
117
128
  //#endregion
118
129
  export { Fragment, Portal, type State, attachComponent, createContext, createElement, createRef, createState, onMount, onUnmount };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-BdtgAtEr.js";
1
+ import { a as VelesComponentObject, i as VelesChildren, n as createElement, o as VelesElement, r as AttributeHelper, s as VelesStringElement, t as Fragment } from "./fragment-yC0-T2O-.js";
2
2
 
3
3
  //#region src/attach-component.d.ts
4
4
  /**
@@ -23,6 +23,7 @@ declare function onUnmount(cb: Function): void;
23
23
  //#region src/create-state/types.d.ts
24
24
  type StateEquality<ValueType> = (value1: ValueType, value2: ValueType) => boolean;
25
25
  type StateLike<ValueType> = State<ValueType>;
26
+ type ArrayElement<T> = T extends ReadonlyArray<infer Element> ? Element : never;
26
27
  type State<ValueType> = {
27
28
  track(cb: (value: ValueType) => void | Function, options?: {
28
29
  callOnMount?: boolean;
@@ -40,16 +41,26 @@ type State<ValueType> = {
40
41
  <SelectorValueType>(selector: (value: ValueType) => SelectorValueType, cb?: (value: SelectorValueType) => VelesElement | VelesComponentObject | string | undefined | null, comparator?: (value1: SelectorValueType, value2: SelectorValueType) => boolean): VelesElement | VelesComponentObject | VelesStringElement;
41
42
  };
42
43
  attribute(cb?: (value: ValueType) => any): AttributeHelper<any>;
43
- renderEach<Element>(options: {
44
+ renderEach<Element extends ArrayElement<ValueType> = ArrayElement<ValueType>>(options: ValueType extends ReadonlyArray<any> ? {
44
45
  key: string | ((options: {
45
46
  element: Element;
46
47
  index: number;
47
48
  }) => string);
48
- selector?: (value: ValueType) => Element[];
49
+ selector?: undefined;
50
+ } : never, cb: (props: {
51
+ elementState: State<Element>;
52
+ indexState: State<number>;
53
+ }) => VelesElement | VelesComponentObject): VelesComponentObject | VelesElement;
54
+ renderEach<SelectorValueType extends ReadonlyArray<any>, Element extends ArrayElement<SelectorValueType> = ArrayElement<SelectorValueType>>(options: {
55
+ key: string | ((options: {
56
+ element: Element;
57
+ index: number;
58
+ }) => string);
59
+ selector: (value: ValueType) => SelectorValueType;
49
60
  }, cb: (props: {
50
61
  elementState: State<Element>;
51
62
  indexState: State<number>;
52
- }) => VelesElement | VelesComponentObject): VelesComponentObject | VelesElement | null;
63
+ }) => VelesElement | VelesComponentObject): VelesComponentObject | VelesElement;
53
64
  map<SelectorValueType>(selector: (value: ValueType) => SelectorValueType, options?: {
54
65
  equality?: StateEquality<SelectorValueType>;
55
66
  }): State<SelectorValueType>;
@@ -101,7 +112,7 @@ declare function createContext<T>(): {
101
112
  }: {
102
113
  value: T;
103
114
  children?: VelesChildren;
104
- }) => VelesElement | VelesComponentObject;
115
+ }) => VelesComponentObject;
105
116
  addContext: (value: T) => void;
106
117
  readContext: () => T;
107
118
  };
@@ -113,6 +124,6 @@ declare function Portal({
113
124
  }: {
114
125
  children?: VelesChildren;
115
126
  portalNode: HTMLElement;
116
- }): VelesElement | VelesComponentObject;
127
+ }): VelesElement;
117
128
  //#endregion
118
129
  export { Fragment, Portal, type State, attachComponent, createContext, createElement, createRef, createState, onMount, onUnmount };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as renderTree, c as createContext, d as Fragment, f as createElement, g as onUnmount, h as onMount, i as identity, l as getCurrentContext, m as hasCurrentLifecycleContext, n as callUnmountHandlers, o as unique, p as createTextElement, r as getExecutedComponentVelesNode, s as addPublicContext, t as callMountHandlers, u as popPublicContext } from "./_utils-BZ1SMqm2.js";
1
+ import { _ as onUnmount, a as identity, c as addPublicContext, d as popPublicContext, f as Fragment, g as onMount, h as hasCurrentLifecycleContext, i as getMountedNodeExecutedVersion, l as createContext, m as createTextElement, n as callUnmountHandlers, o as renderTree, p as createElement, r as getExecutedComponentVelesNode, s as unique, t as callMountHandlers, u as getCurrentContext } from "./_utils-kYa7oewT.js";
2
2
  //#region src/attach-component.ts
3
3
  /**
4
4
  * Attach Veles component tree to a regular HTML node.
@@ -203,11 +203,7 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
203
203
  console.error("there is no wrapper component for the iterator");
204
204
  return;
205
205
  }
206
- if (!wrapperComponent.executedVersion) {
207
- console.error("it seems the wrapper component was not mounted");
208
- return;
209
- }
210
- const wrapperVelesElementNode = getExecutedComponentVelesNode(wrapperComponent.executedVersion);
206
+ const wrapperVelesElementNode = getExecutedComponentVelesNode(getMountedNodeExecutedVersion(wrapperComponent, "Iterator wrapper is expected to be mounted"));
211
207
  const parentVelesElement = wrapperVelesElementNode.parentVelesElement;
212
208
  if (!parentVelesElement) {
213
209
  console.error("there is no parent Veles node for the iterator wrapper");
@@ -272,13 +268,13 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
272
268
  let offset = 0;
273
269
  let currentElement = null;
274
270
  newRenderedElements.forEach((newRenderedElement, index) => {
275
- newChildRenderedComponents.push(newRenderedElement[0].executedVersion);
271
+ newChildRenderedComponents.push(getMountedNodeExecutedVersion(newRenderedElement[0], "Iterator child is expected to be mounted"));
276
272
  newChildComponents.push(newRenderedElement[0]);
277
273
  if (positioningOffset[index]) offset = offset + positioningOffset[index];
278
274
  const [newNode, calculatedKey, newState] = newRenderedElement;
279
275
  const existingElement = elementsByKey[calculatedKey];
280
276
  if (existingElement) {
281
- const existingElementNode = getExecutedComponentVelesNode(existingElement.node.executedVersion);
277
+ const existingElementNode = getExecutedComponentVelesNode(getMountedNodeExecutedVersion(existingElement.node, "Existing iterator node is expected to be mounted"));
282
278
  if (existingElement.indexValue + offset === index) {
283
279
  currentElement = existingElementNode.html;
284
280
  return;
@@ -305,7 +301,8 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
305
301
  offset = offset - 1;
306
302
  }
307
303
  } else {
308
- const newNodeVelesElement = getExecutedComponentVelesNode(newNode.executedVersion);
304
+ const newNodeExecutedVersion = getMountedNodeExecutedVersion(newNode, "New iterator node is expected to be mounted");
305
+ const newNodeVelesElement = getExecutedComponentVelesNode(newNodeExecutedVersion);
309
306
  newNodeVelesElement.parentVelesElement = parentVelesElement;
310
307
  if (currentElement) currentElement.after(newNodeVelesElement.html);
311
308
  else {
@@ -316,15 +313,16 @@ function updateUseValueIteratorValue({ value, trackingIterator, createState }) {
316
313
  offset = offset + 1;
317
314
  currentElement = newNodeVelesElement.html;
318
315
  newElementsCount = newElementsCount + 1;
319
- callMountHandlers(newNode.executedVersion);
316
+ callMountHandlers(newNodeExecutedVersion);
320
317
  }
321
318
  });
322
319
  if (renderedElements.length === newRenderedElements.length + newElementsCount) {} else renderedElements.forEach(([oldNode, calculatedKey]) => {
323
320
  if (renderedExistingElements[calculatedKey] === true) return;
324
321
  else {
325
- getExecutedComponentVelesNode(oldNode.executedVersion).html.remove();
326
- callUnmountHandlers(oldNode.executedVersion);
327
- if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = wrapperVelesElementNode.childComponents.filter((childComponent) => childComponent !== oldNode.executedVersion);
322
+ const oldNodeExecutedVersion = getMountedNodeExecutedVersion(oldNode, "Removed iterator node is expected to be mounted");
323
+ getExecutedComponentVelesNode(oldNodeExecutedVersion).html.remove();
324
+ callUnmountHandlers(oldNodeExecutedVersion);
325
+ if ("executedVelesNode" in wrapperVelesElementNode) wrapperVelesElementNode.childComponents = wrapperVelesElementNode.childComponents.filter((childComponent) => childComponent !== oldNodeExecutedVersion);
328
326
  else throw new Error("Wrapper iterator element is a string");
329
327
  if ("velesNode" in wrapperComponent) wrapperComponent.childComponents = wrapperComponent.childComponents.filter((childComponent) => childComponent !== oldNode);
330
328
  }
@@ -607,7 +605,7 @@ function createStateFromCore(core, subscribeCallback) {
607
605
  });
608
606
  const result = {
609
607
  track: (cb, options = {}) => {
610
- result.trackSelected(void 0, cb, options);
608
+ result.trackSelected((value) => value, cb, options);
611
609
  },
612
610
  trackSelected(selector, cb, options = {}) {
613
611
  const selectedCore = selector ? core.map(selector, { equality: createCoreEquality(options.comparator) }) : options.comparator ? core.map((value) => value, { equality: createCoreEquality(options.comparator) }) : core;
@@ -711,28 +709,29 @@ function createStateFromCore(core, subscribeCallback) {
711
709
  const originalValue = core.get();
712
710
  let wasMounted = false;
713
711
  const attributeValue = cb ? cb(originalValue) : originalValue;
714
- const attributeHelper = (htmlElement, attributeName, node) => {
715
- const trackingElement = {
716
- cb,
717
- htmlElement,
718
- attributeName,
719
- attributeValue
720
- };
721
- node._privateMethods._addMountHandler(() => {
722
- trackers.trackingAttributes.push(trackingElement);
723
- if (!wasMounted && core.get() === originalValue) {} else updateUseAttributeValue({
724
- element: trackingElement,
725
- value: core.get()
726
- });
727
- if (!wasMounted) wasMounted = true;
728
- node._privateMethods._addUnmountHandler(() => {
729
- trackers.trackingAttributes = trackers.trackingAttributes.filter((trackingAttribute) => trackingAttribute !== trackingElement);
712
+ return {
713
+ velesAttribute: true,
714
+ getValue(htmlElement, attributeName, node) {
715
+ const trackingElement = {
716
+ cb,
717
+ htmlElement,
718
+ attributeName,
719
+ attributeValue
720
+ };
721
+ node._privateMethods._addMountHandler(() => {
722
+ trackers.trackingAttributes.push(trackingElement);
723
+ if (!wasMounted && core.get() === originalValue) {} else updateUseAttributeValue({
724
+ element: trackingElement,
725
+ value: core.get()
726
+ });
727
+ if (!wasMounted) wasMounted = true;
728
+ node._privateMethods._addUnmountHandler(() => {
729
+ trackers.trackingAttributes = trackers.trackingAttributes.filter((trackingAttribute) => trackingAttribute !== trackingElement);
730
+ });
730
731
  });
731
- });
732
- return attributeValue;
732
+ return attributeValue;
733
+ }
733
734
  };
734
- attributeHelper.velesAttribute = true;
735
- return attributeHelper;
736
735
  },
737
736
  dispose: () => {
738
737
  core.dispose();
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require__utils = require("./_utils-gPluq0AT.cjs");
2
+ const require__utils = require("./_utils-Bhfy2AFV.cjs");
3
3
  exports.Fragment = require__utils.Fragment;
4
4
  exports.jsx = require__utils.createElement;
5
5
  exports.jsxDEV = require__utils.createElement;
@@ -1,2 +1,2 @@
1
- import { c as JSX, n as createElement, t as Fragment } from "./fragment-D252pobF.cjs";
1
+ import { c as JSX, n as createElement, t as Fragment } from "./fragment-C16zCm8L.cjs";
2
2
  export { Fragment, type JSX, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,2 +1,2 @@
1
- import { c as JSX, n as createElement, t as Fragment } from "./fragment-BdtgAtEr.js";
1
+ import { c as JSX, n as createElement, t as Fragment } from "./fragment-yC0-T2O-.js";
2
2
  export { Fragment, type JSX, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
@@ -1,2 +1,2 @@
1
- import { d as Fragment, f as createElement } from "./_utils-BZ1SMqm2.js";
1
+ import { f as Fragment, p as createElement } from "./_utils-kYa7oewT.js";
2
2
  export { Fragment, createElement as jsx, createElement as jsxDEV, createElement as jsxs };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "veles",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.2",
4
4
  "description": "UI library with main focus on performance",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",