@zcomponent/core 1.14.1-beta → 1.14.3-beta

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.
@@ -34,7 +34,7 @@ export declare class Animation {
34
34
  private _spotlightLayer?;
35
35
  timeSource: (() => number) | undefined;
36
36
  private _entityPaths;
37
- private _defaultValues;
37
+ private _defaultValuesByPath;
38
38
  /** @internal */
39
39
  _pendingEvents: {
40
40
  evt: AnimationEvents;
@@ -49,17 +49,15 @@ export declare class Animation {
49
49
  removeLayer(l: Layer): void;
50
50
  initialize(): void;
51
51
  tick(): void;
52
- registerEntityPath(path: string, entity: any, pathParts: (string | number)[]): void;
52
+ registerEntityProperty(path: string, entity: any, property: string | number): void;
53
53
  evaluateTouchedPaths(paths: string[], t?: number): void;
54
- private _evaluateLayer;
55
54
  get spotlightLayer(): Layer | undefined;
56
55
  set spotlightLayer(l: Layer | undefined);
57
56
  clearCachedDefault(entityID: string, prop: string): void;
58
57
  private _emitPendingEvents;
59
- private _resolvePath;
60
58
  start(): void;
61
59
  }
62
60
  export interface EntityPath {
63
61
  entity: any;
64
- pathParts: (string | number)[];
62
+ property: string | number;
65
63
  }
@@ -22,7 +22,7 @@ export class Animation {
22
22
  this.hasLayers = new Observable(false);
23
23
  this._layers = [];
24
24
  this._entityPaths = new Map();
25
- this._defaultValues = new Map();
25
+ this._defaultValuesByPath = new Map();
26
26
  /** @internal */
27
27
  this._pendingEvents = [];
28
28
  }
@@ -87,7 +87,7 @@ export class Animation {
87
87
  tick() {
88
88
  if (!this._initialize)
89
89
  return;
90
- const t = this.timeSource?.() ?? performance.now();
90
+ const t = Math.floor(this.timeSource?.() ?? performance.now());
91
91
  const touchedPaths = [];
92
92
  if (this._spotlightLayer) {
93
93
  this._spotlightLayer.tick(t, touchedPaths);
@@ -100,66 +100,40 @@ export class Animation {
100
100
  this.evaluateTouchedPaths(touchedPaths, t);
101
101
  this.onTick.emit();
102
102
  }
103
- registerEntityPath(path, entity, pathParts) {
104
- this._entityPaths.set(path, { entity, pathParts });
103
+ registerEntityProperty(path, entity, property) {
104
+ this._entityPaths.set(path, { entity, property });
105
105
  }
106
106
  evaluateTouchedPaths(paths, t) {
107
107
  if (!this._initialize)
108
108
  return;
109
- t = t ?? this.timeSource?.() ?? performance.now();
109
+ t = t ?? Math.floor(this.timeSource?.() ?? performance.now());
110
110
  const unique = new Set([...paths]);
111
111
  const uniqueAsArray = unique.values();
112
- const resolvedPaths = [...uniqueAsArray].map(entry => this._resolvePath(entry));
113
- for (const entry of resolvedPaths) {
114
- if (!entry)
112
+ for (const entry of uniqueAsArray) {
113
+ const entityPath = this._entityPaths.get(entry);
114
+ if (!entityPath)
115
115
  continue;
116
- let byEntity = this._defaultValues.get(entry[0]);
117
- if (!byEntity) {
118
- byEntity = new Map();
119
- this._defaultValues.set(entry[0], byEntity);
116
+ const prop = entityPath.entity[entityPath.property];
117
+ const propIsObservable = prop instanceof Observable;
118
+ let def = this._defaultValuesByPath.get(entry);
119
+ if (!def) {
120
+ const val = propIsObservable ? prop.value : prop;
121
+ def = new Observable(val);
122
+ this._defaultValuesByPath.set(entry, def);
120
123
  }
121
- let observable = byEntity.get(entry[1][0]);
122
- if (!observable) {
123
- let val = entry[0][entry[1][0]];
124
- if (val instanceof Observable)
125
- val = val.value;
126
- observable = new Observable(val);
127
- byEntity.set(entry[1][0], observable);
124
+ let val = def.value;
125
+ for (const layer of this._layers) {
126
+ if (!layer.influencedPaths.has(entry))
127
+ continue;
128
+ val = layer.computePathProperty(t, entry, val);
128
129
  }
129
- entry[2] = observable;
130
- }
131
- // Reset our working values to default
132
- for (const p of resolvedPaths) {
133
- if (p?.[2])
134
- p[2].value = undefined;
135
- }
136
- if (this._spotlightLayer)
137
- this._evaluateLayer(t, this._spotlightLayer, resolvedPaths);
138
- else {
139
- for (const layer of this._layers)
140
- this._evaluateLayer(t, layer, resolvedPaths);
141
- }
142
- for (const entry of resolvedPaths) {
143
- if (!entry?.[2])
144
- continue;
145
- if (entry[0][entry[1][0]] instanceof Observable)
146
- entry[0][entry[1][0]].value = entry[2].value;
130
+ if (propIsObservable)
131
+ prop.value = val;
147
132
  else
148
- entry[0][entry[1][0]] = entry[2].value;
133
+ entityPath.entity[entityPath.property] = val;
149
134
  }
150
135
  this._emitPendingEvents();
151
136
  }
152
- _evaluateLayer(t, layer, paths) {
153
- for (const p of paths) {
154
- if (!p?.[2])
155
- continue;
156
- if (!layer.influencedPaths.has(p[3]))
157
- continue;
158
- let val = getResolved(p[2], p[1]);
159
- val = layer.computePathProperty(t, p[3], val);
160
- setResolved(p[2], p[1], val);
161
- }
162
- }
163
137
  get spotlightLayer() {
164
138
  return this._spotlightLayer;
165
139
  }
@@ -181,11 +155,7 @@ export class Animation {
181
155
  this.hasLayers.value = hasLayers;
182
156
  }
183
157
  clearCachedDefault(entityID, prop) {
184
- const prefix = entityID + '.' + prop;
185
- for (const entityPath of this._defaultValues.keys()) {
186
- if (entityPath.indexOf(prefix) === 0)
187
- this._defaultValues.delete(entityPath);
188
- }
158
+ this._defaultValuesByPath.delete(entityID + '.' + prop);
189
159
  }
190
160
  _emitPendingEvents() {
191
161
  while (this._pendingEvents.length > 0) {
@@ -195,12 +165,6 @@ export class Animation {
195
165
  this[entry.evt].emit(...entry.args);
196
166
  }
197
167
  }
198
- _resolvePath(p) {
199
- const path = this._entityPaths.get(p);
200
- if (!path || path.pathParts.length === 0)
201
- return;
202
- return [path.entity, path.pathParts, undefined, p];
203
- }
204
168
  start() {
205
169
  for (const layer of this._layers) {
206
170
  for (const clip of Object.values(layer.clips)) {
@@ -210,18 +174,3 @@ export class Animation {
210
174
  }
211
175
  }
212
176
  }
213
- function getResolved(o, pathParts) {
214
- let current = o.value;
215
- for (let i = 1; i < pathParts.length; i++)
216
- current = current[pathParts[i]];
217
- return current;
218
- }
219
- function setResolved(o, pathParts, val) {
220
- let target = o;
221
- let key = 'value';
222
- for (let i = 1; i < pathParts.length; i++) {
223
- target = target[key];
224
- key = pathParts[i];
225
- }
226
- target[key] = val;
227
- }
@@ -99,7 +99,7 @@ export class LayerClip {
99
99
  return t1 - t;
100
100
  }
101
101
  _getTime() {
102
- return this.timeSource?.() ?? this.animation?.timeSource?.() ?? performance.now();
102
+ return Math.floor(this.timeSource?.() ?? this.animation.timeSource?.() ?? performance.now());
103
103
  }
104
104
  queue(opts) {
105
105
  this.layer.queue(this, opts);
@@ -7,6 +7,7 @@ export declare class PropertyTrack extends Track {
7
7
  private _entity;
8
8
  path: string;
9
9
  private _property;
10
+ private _path;
10
11
  private _keyframes;
11
12
  private _keyframesById;
12
13
  private _keyframesDirty;
@@ -30,4 +31,5 @@ export declare class PropertyTrack extends Track {
30
31
  get sortedWeights(): Keyframe[];
31
32
  getFadeLengthForPath(path: string): number;
32
33
  computePathProperty(t: number, p: string, valueBefore: any, parentWeight?: number): any;
34
+ private _computePathProperty;
33
35
  }
@@ -1,5 +1,7 @@
1
+ import { Observable } from '../../observable';
1
2
  import { addBlend, interpolate } from '../interpolate';
2
3
  import { resolveKeyframes, resolveKeyframeValue, Track } from './track';
4
+ const _scratch = new Observable(undefined);
3
5
  export class PropertyTrack extends Track {
4
6
  constructor(anim, _entityID, _entity, property, id) {
5
7
  super(anim, id);
@@ -12,13 +14,17 @@ export class PropertyTrack extends Track {
12
14
  this._weightsById = {};
13
15
  this._weightsDirty = false;
14
16
  this.blend = 'overlay';
15
- if (Array.isArray(property))
17
+ if (Array.isArray(property)) {
18
+ this._property = property[0];
19
+ this._path = property.slice(1);
20
+ }
21
+ else {
16
22
  this._property = property;
17
- else
18
- this._property = [property];
19
- this.path = [this._entityID, ...this._property].join('.');
23
+ this._path = [];
24
+ }
25
+ this.path = this._entityID + '.' + this._property;
20
26
  this.influencedPaths = [this.path];
21
- anim.registerEntityPath(this.path, this._entity, this._property);
27
+ anim.registerEntityProperty(this.path, _entity, this._property);
22
28
  }
23
29
  addKeyframe(k) {
24
30
  this._keyframesById[k.id] = k;
@@ -59,6 +65,18 @@ export class PropertyTrack extends Track {
59
65
  return this.fadeParameters?.time ?? 0;
60
66
  }
61
67
  computePathProperty(t, p, valueBefore, parentWeight) {
68
+ if (this._path.length === 0) {
69
+ return this._computePathProperty(t, p, valueBefore, parentWeight);
70
+ }
71
+ else {
72
+ _scratch.value = valueBefore;
73
+ const v = _scratch.getValueAtPath(this._path);
74
+ const computed = this._computePathProperty(t, p, v, parentWeight);
75
+ _scratch.setValueAtPath(this._path, computed);
76
+ return _scratch.value;
77
+ }
78
+ }
79
+ _computePathProperty(t, p, valueBefore, parentWeight) {
62
80
  const keyframes = this.sortedKeyframes;
63
81
  const [before, after] = resolveKeyframes(keyframes, t);
64
82
  if (!before)
@@ -0,0 +1,58 @@
1
+ import { Context, ContextManager, Event, Observable } from '../index';
2
+ export declare enum GestureMode {
3
+ ScaleOnly = "Scale Only",
4
+ RotateOnly = "Rotate Only",
5
+ ScaleRotate = "Scale Rotate"
6
+ }
7
+ interface ConstructionProps {
8
+ /**
9
+ * The HTML element to which touch event listeners are attached.
10
+ * Defaults to canvas.
11
+ */
12
+ element?: HTMLElement;
13
+ }
14
+ /** @zcontext */
15
+ export declare class GestureContext extends Context<ConstructionProps> {
16
+ private element;
17
+ private canScale;
18
+ private gestureMode;
19
+ private canRotate;
20
+ private initialDistance;
21
+ private initialAngle;
22
+ private oneFingerRotateMode;
23
+ private initialTouchX;
24
+ rotation: Observable<number, never>;
25
+ scale: Observable<number, never>;
26
+ onRotate: Event<[number]>;
27
+ onScale: Event<[number]>;
28
+ /**
29
+ * Defaults to true.
30
+ */
31
+ enabled: Observable<boolean, never>;
32
+ /**
33
+ * Defaults to 0.5;
34
+ */
35
+ minScale: number;
36
+ /**
37
+ * Defaults to 2.
38
+ */
39
+ maxScale: number;
40
+ /**
41
+ * Defaults to 1.
42
+ */
43
+ rotationSensitivity: number;
44
+ constructor(contextManager: ContextManager, constructorProps: ConstructionProps);
45
+ private onTouchStart;
46
+ private onTouchMove;
47
+ private handleOneFingerRotate;
48
+ private handleTwoFingerGestures;
49
+ private handleScale;
50
+ private handleRotate;
51
+ private onTouchEnd;
52
+ private getDistanceBetweenTouches;
53
+ private getAngleBetweenTouches;
54
+ private attachEventListeners;
55
+ private detachEventListeners;
56
+ dispose(): never;
57
+ }
58
+ export {};
@@ -0,0 +1,140 @@
1
+ import { Context, Event, Observable, useCanvas } from '../index';
2
+ export var GestureMode;
3
+ (function (GestureMode) {
4
+ GestureMode["ScaleOnly"] = "Scale Only";
5
+ GestureMode["RotateOnly"] = "Rotate Only";
6
+ GestureMode["ScaleRotate"] = "Scale Rotate";
7
+ })(GestureMode || (GestureMode = {}));
8
+ /** @zcontext */
9
+ export class GestureContext extends Context {
10
+ constructor(contextManager, constructorProps) {
11
+ super(contextManager, constructorProps);
12
+ this.canScale = true;
13
+ this.gestureMode = GestureMode.ScaleRotate;
14
+ this.canRotate = true;
15
+ this.initialDistance = null;
16
+ this.initialAngle = null;
17
+ this.oneFingerRotateMode = true;
18
+ this.initialTouchX = null;
19
+ this.rotation = new Observable(0);
20
+ this.scale = new Observable(0);
21
+ this.onRotate = new Event();
22
+ this.onScale = new Event();
23
+ /**
24
+ * Defaults to true.
25
+ */
26
+ this.enabled = new Observable(true);
27
+ /**
28
+ * Defaults to 0.5;
29
+ */
30
+ this.minScale = 0.5;
31
+ /**
32
+ * Defaults to 2.
33
+ */
34
+ this.maxScale = 2;
35
+ /**
36
+ * Defaults to 1.
37
+ */
38
+ this.rotationSensitivity = 1;
39
+ this.onTouchStart = (event) => {
40
+ if (this.oneFingerRotateMode && event.touches.length === 1) {
41
+ this.initialTouchX = event.touches[0].pageX;
42
+ }
43
+ else if (event.touches.length === 2) {
44
+ this.initialDistance = this.getDistanceBetweenTouches(event.touches);
45
+ this.initialAngle = this.getAngleBetweenTouches(event.touches);
46
+ }
47
+ };
48
+ this.onTouchMove = (event) => {
49
+ switch (this.gestureMode) {
50
+ case GestureMode.ScaleOnly:
51
+ if (event.touches.length === 2) {
52
+ this.handleScale(event);
53
+ }
54
+ break;
55
+ case GestureMode.RotateOnly:
56
+ if (this.oneFingerRotateMode && event.touches.length === 1) {
57
+ this.handleOneFingerRotate(event);
58
+ }
59
+ else if (event.touches.length === 2) {
60
+ this.handleRotate(event);
61
+ }
62
+ break;
63
+ case GestureMode.ScaleRotate:
64
+ if (this.oneFingerRotateMode && event.touches.length === 1) {
65
+ this.handleOneFingerRotate(event);
66
+ }
67
+ else if (event.touches.length === 2) {
68
+ this.handleTwoFingerGestures(event);
69
+ }
70
+ break;
71
+ }
72
+ };
73
+ this.onTouchEnd = (event) => {
74
+ this.initialDistance = null;
75
+ this.initialAngle = null;
76
+ };
77
+ this.element = constructorProps.element ?? useCanvas(contextManager);
78
+ this.enabled.addListener(enabled => {
79
+ if (enabled) {
80
+ this.attachEventListeners();
81
+ }
82
+ else {
83
+ this.detachEventListeners();
84
+ }
85
+ }, undefined, true);
86
+ }
87
+ handleOneFingerRotate(event) {
88
+ if (this.initialTouchX !== null) {
89
+ const currentTouchX = event.touches[0].pageX;
90
+ const rotateAmount = (currentTouchX - this.initialTouchX) * this.rotationSensitivity;
91
+ this.onRotate.emit(rotateAmount);
92
+ this.rotation.value = rotateAmount;
93
+ }
94
+ }
95
+ handleTwoFingerGestures(event) {
96
+ this.handleScale(event);
97
+ this.handleRotate(event);
98
+ }
99
+ handleScale(event) {
100
+ if (this.canScale && this.initialDistance !== null) {
101
+ const currentDistance = this.getDistanceBetweenTouches(event.touches);
102
+ let scaleAmount = currentDistance / this.initialDistance;
103
+ scaleAmount = Math.max(this.minScale, Math.min(scaleAmount, this.maxScale));
104
+ this.onScale.emit(scaleAmount);
105
+ this.scale.value = scaleAmount;
106
+ }
107
+ }
108
+ handleRotate(event) {
109
+ if (this.canRotate && this.initialAngle !== null) {
110
+ const currentAngle = this.getAngleBetweenTouches(event.touches);
111
+ const rotateAmount = currentAngle - this.initialAngle;
112
+ this.onRotate.emit(-rotateAmount);
113
+ this.rotation.value = -rotateAmount;
114
+ }
115
+ }
116
+ getDistanceBetweenTouches(touches) {
117
+ const dx = touches[0].pageX - touches[1].pageX;
118
+ const dy = touches[0].pageY - touches[1].pageY;
119
+ return Math.sqrt(dx * dx + dy * dy);
120
+ }
121
+ getAngleBetweenTouches(touches) {
122
+ const dx = touches[1].pageX - touches[0].pageX;
123
+ const dy = touches[1].pageY - touches[0].pageY;
124
+ return (Math.atan2(dy, dx) * 180) / Math.PI;
125
+ }
126
+ attachEventListeners() {
127
+ this.element.addEventListener('touchstart', this.onTouchStart, { passive: true });
128
+ this.element.addEventListener('touchmove', this.onTouchMove, { passive: true });
129
+ this.element.addEventListener('touchend', this.onTouchEnd);
130
+ }
131
+ detachEventListeners() {
132
+ this.element.removeEventListener('touchstart', this.onTouchStart);
133
+ this.element.removeEventListener('touchmove', this.onTouchMove);
134
+ this.element.removeEventListener('touchend', this.onTouchEnd);
135
+ }
136
+ dispose() {
137
+ this.detachEventListeners();
138
+ return super.dispose();
139
+ }
140
+ }
@@ -0,0 +1,51 @@
1
+ import { ContextManager, Context } from '../context';
2
+ import { Event } from '../event';
3
+ import { Observable } from '../observable';
4
+ export declare enum Orientation {
5
+ Portrait = "portrait",
6
+ Landscape = "landscape",
7
+ PortraitSecondary = "portrait-secondary",
8
+ LandscapeSecondary = "landscape-secondary"
9
+ }
10
+ /**
11
+ * @zcontext
12
+ */
13
+ export declare class OrientationContext extends Context {
14
+ /**
15
+ * @zui
16
+ */
17
+ readonly isPortrait: Observable<boolean>;
18
+ /**
19
+ * @zui
20
+ */
21
+ readonly isLandscape: Observable<boolean>;
22
+ /**
23
+ * @zui
24
+ */
25
+ readonly isPortraitSecondary: Observable<boolean>;
26
+ /**
27
+ * @zui
28
+ */
29
+ readonly isLandscapeSecondary: Observable<boolean>;
30
+ readonly onOrientationChange: Event<[Orientation]>;
31
+ readonly orientation: Observable<Orientation>;
32
+ readonly onPortrait: Event<[void]>;
33
+ readonly onLandscape: Event<[void]>;
34
+ readonly onPortraitSecondary: Event<[void]>;
35
+ readonly onLandscapeSecondary: Event<[void]>;
36
+ constructor(contextManager: ContextManager);
37
+ private attachListeners;
38
+ private _onOrientationChange;
39
+ private orientationChangeHandler;
40
+ private getOrientation;
41
+ private getOrientationFromScreen;
42
+ private getOrientationFromWindow;
43
+ private getOrientationFromDimensions;
44
+ dispose: () => never;
45
+ }
46
+ export declare function useOnOrientationChange(mgr: ContextManager): Event<[Orientation]>;
47
+ export declare function getOrientation(mgr: ContextManager): Orientation;
48
+ export declare function isPortrait(mgr: ContextManager): boolean;
49
+ export declare function isLandscape(mgr: ContextManager): boolean;
50
+ export declare function isPortraitSecondary(mgr: ContextManager): boolean;
51
+ export declare function isLandscapeSecondary(mgr: ContextManager): boolean;
@@ -0,0 +1,124 @@
1
+ import { Context } from '../context';
2
+ import { Event } from '../event';
3
+ import { Observable } from '../observable';
4
+ export var Orientation;
5
+ (function (Orientation) {
6
+ Orientation["Portrait"] = "portrait";
7
+ Orientation["Landscape"] = "landscape";
8
+ Orientation["PortraitSecondary"] = "portrait-secondary";
9
+ Orientation["LandscapeSecondary"] = "landscape-secondary";
10
+ })(Orientation || (Orientation = {}));
11
+ /**
12
+ * @zcontext
13
+ */
14
+ export class OrientationContext extends Context {
15
+ constructor(contextManager) {
16
+ super(contextManager, {});
17
+ this.onOrientationChange = new Event();
18
+ this.onPortrait = new Event();
19
+ this.onLandscape = new Event();
20
+ this.onPortraitSecondary = new Event();
21
+ this.onLandscapeSecondary = new Event();
22
+ this.attachListeners = () => {
23
+ this.orientation.addListener(this._onOrientationChange);
24
+ window.addEventListener('resize', this.orientationChangeHandler);
25
+ if ('orientation' in screen && screen.orientation) {
26
+ screen.orientation.addEventListener('change', this.orientationChangeHandler);
27
+ }
28
+ };
29
+ this._onOrientationChange = (orientation) => {
30
+ this.onOrientationChange.emit(orientation);
31
+ this.isPortrait.value = orientation === Orientation.Portrait;
32
+ this.isLandscape.value = orientation === Orientation.Landscape;
33
+ this.isPortraitSecondary.value = orientation === Orientation.PortraitSecondary;
34
+ this.isLandscapeSecondary.value = orientation === Orientation.LandscapeSecondary;
35
+ switch (orientation) {
36
+ case Orientation.Portrait:
37
+ this.onPortrait.emit();
38
+ break;
39
+ case Orientation.Landscape:
40
+ this.onLandscape.emit();
41
+ break;
42
+ case Orientation.PortraitSecondary:
43
+ this.onPortraitSecondary.emit();
44
+ break;
45
+ case Orientation.LandscapeSecondary:
46
+ this.onLandscapeSecondary.emit();
47
+ break;
48
+ }
49
+ };
50
+ this.orientationChangeHandler = () => {
51
+ const newOrientation = this.getOrientation();
52
+ if (this.orientation.value === newOrientation)
53
+ return;
54
+ this.orientation.value = newOrientation;
55
+ };
56
+ this.dispose = () => {
57
+ window.removeEventListener('resize', this.orientationChangeHandler);
58
+ if ('orientation' in screen && screen.orientation)
59
+ screen.orientation.removeEventListener('change', this.orientationChangeHandler);
60
+ this.orientation.removeListener(this._onOrientationChange);
61
+ return super.dispose();
62
+ };
63
+ const currentOrientation = this.getOrientation();
64
+ this.orientation = new Observable(currentOrientation);
65
+ this.isPortrait = new Observable(currentOrientation === Orientation.Portrait);
66
+ this.isLandscape = new Observable(currentOrientation === Orientation.Landscape);
67
+ this.isPortraitSecondary = new Observable(currentOrientation === Orientation.PortraitSecondary);
68
+ this.isLandscapeSecondary = new Observable(currentOrientation === Orientation.LandscapeSecondary);
69
+ this.attachListeners();
70
+ }
71
+ getOrientation() {
72
+ const orientation = this.getOrientationFromScreen() ?? this.getOrientationFromWindow() ?? this.getOrientationFromDimensions();
73
+ return orientation;
74
+ }
75
+ getOrientationFromScreen() {
76
+ const orientationType = screen?.orientation?.type;
77
+ if (orientationType) {
78
+ if (orientationType.includes('portrait')) {
79
+ return orientationType.includes('secondary') ? Orientation.PortraitSecondary : Orientation.Portrait;
80
+ }
81
+ else {
82
+ return orientationType.includes('secondary') ? Orientation.LandscapeSecondary : Orientation.Landscape;
83
+ }
84
+ }
85
+ return null;
86
+ }
87
+ getOrientationFromWindow() {
88
+ const windowOrientation = window?.orientation;
89
+ if (typeof windowOrientation === 'number') {
90
+ switch (windowOrientation) {
91
+ case 0:
92
+ return Orientation.Portrait;
93
+ case 90:
94
+ return Orientation.Landscape;
95
+ case 180:
96
+ return Orientation.PortraitSecondary;
97
+ case -90:
98
+ return Orientation.LandscapeSecondary;
99
+ }
100
+ }
101
+ return null;
102
+ }
103
+ getOrientationFromDimensions() {
104
+ return window.innerWidth > window.innerHeight ? Orientation.Landscape : Orientation.Portrait;
105
+ }
106
+ }
107
+ export function useOnOrientationChange(mgr) {
108
+ return mgr.get(OrientationContext).onOrientationChange;
109
+ }
110
+ export function getOrientation(mgr) {
111
+ return mgr.get(OrientationContext).orientation.value;
112
+ }
113
+ export function isPortrait(mgr) {
114
+ return mgr.get(OrientationContext).isPortrait.value;
115
+ }
116
+ export function isLandscape(mgr) {
117
+ return mgr.get(OrientationContext).isLandscape.value;
118
+ }
119
+ export function isPortraitSecondary(mgr) {
120
+ return mgr.get(OrientationContext).isPortraitSecondary.value;
121
+ }
122
+ export function isLandscapeSecondary(mgr) {
123
+ return mgr.get(OrientationContext).isLandscapeSecondary.value;
124
+ }
@@ -56,5 +56,7 @@ export declare class Observable<Type = never, TypeInternal extends any[] | [] |
56
56
  set value(v: Resolved<Type, TypeInternal> | undefined);
57
57
  addListener(fn: (v: Resolved<Type, TypeInternal>) => void, priority?: number, callImmediately?: boolean): void;
58
58
  private _emitValue;
59
+ setValueAtPath(path: (string | number)[], val: any): void;
60
+ getValueAtPath(path: (string | number)[]): any;
59
61
  }
60
62
  export {};
package/lib/observable.js CHANGED
@@ -113,6 +113,21 @@ export class Observable extends Emitter {
113
113
  _emitValue() {
114
114
  this._emit(this._value.proxy);
115
115
  }
116
+ setValueAtPath(path, val) {
117
+ let target = this;
118
+ let key = 'value';
119
+ for (let i = 0; i < path.length; i++) {
120
+ target = target[key];
121
+ key = path[i];
122
+ }
123
+ target[key] = val;
124
+ }
125
+ getValueAtPath(path) {
126
+ let current = this.value;
127
+ for (let i = 0; i < path.length; i++)
128
+ current = current[path[i]];
129
+ return current;
130
+ }
116
131
  }
117
132
  function clone(a, deep) {
118
133
  if (!deep) {
package/lib/types.d.ts CHANGED
@@ -83,7 +83,9 @@ export declare enum TypeHint {
83
83
  'angle-radians' = "angle-radians",
84
84
  'time-seconds' = "time-seconds",
85
85
  'time-milliseconds' = "time-milliseconds",
86
- 'time-hertz' = "time-hertz"
86
+ 'time-hertz' = "time-hertz",
87
+ 'emailaddress' = "emailaddress",
88
+ 'url' = "url"
87
89
  }
88
90
  export declare enum ValuesType {
89
91
  'files' = "files",
package/lib/types.js CHANGED
@@ -31,6 +31,8 @@ export var TypeHint;
31
31
  TypeHint["time-seconds"] = "time-seconds";
32
32
  TypeHint["time-milliseconds"] = "time-milliseconds";
33
33
  TypeHint["time-hertz"] = "time-hertz";
34
+ TypeHint["emailaddress"] = "emailaddress";
35
+ TypeHint["url"] = "url";
34
36
  })(TypeHint || (TypeHint = {}));
35
37
  export var ValuesType;
36
38
  (function (ValuesType) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zcomponent/core",
3
- "version": "1.14.1-beta",
3
+ "version": "1.14.3-beta",
4
4
  "description": "The core component model and built-in functionality for Mattercraft.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",