@vortexm/vjt 0.1.4 → 0.1.6

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.
@@ -6,6 +6,8 @@ export type ActionExecutionContext = {
6
6
  x: number;
7
7
  y: number;
8
8
  } | null;
9
+ currentList?: unknown[];
10
+ currentIndex?: number;
9
11
  };
10
12
  type ActionRuntimeOptions = {
11
13
  debugLogging: boolean;
@@ -13,6 +15,7 @@ type ActionRuntimeOptions = {
13
15
  actionFunctions: Record<string, () => unknown>;
14
16
  nodeById: Map<string, DescriptionNode>;
15
17
  stateById: Map<string, WidgetState>;
18
+ stateByKey: Map<string, WidgetState>;
16
19
  rerenderRoot: () => Promise<void>;
17
20
  dispatchWidgetEvent: (node: DescriptionNode, eventName: WidgetEventName, key: string, inputValue?: unknown, pointer?: {
18
21
  x: number;
@@ -27,6 +30,17 @@ type ActionRuntimeOptions = {
27
30
  resolveMappedValue: (template: unknown, currentValue: unknown, responseValue: unknown) => unknown;
28
31
  setWidgetEnabled: (widgetId: string, enabled: boolean) => void;
29
32
  clearWidget: (widgetId: string) => void;
33
+ clearListElementState: (listKey: string) => void;
34
+ focusWidget: (reference: string) => void;
35
+ playAudio: (value: unknown) => Promise<void>;
36
+ stopPlaying: () => Promise<void>;
37
+ copyToClipboard: (value: unknown) => Promise<void>;
38
+ selectFile: (options: unknown) => Promise<unknown>;
39
+ confirmModal: (options: unknown, inputValue: unknown) => Promise<boolean>;
40
+ startRecording: () => Promise<void>;
41
+ stopRecording: () => Promise<void>;
42
+ startListening: () => Promise<void>;
43
+ stopListening: () => Promise<void>;
30
44
  setUiReference: (widgetId: string, resourceRef: string) => void;
31
45
  refreshWidgetTree: (widgetId: string) => Promise<void>;
32
46
  renderWidgetTree: (widgetId: string) => Promise<void>;
@@ -42,6 +56,8 @@ type ActionRuntimeOptions = {
42
56
  id: string;
43
57
  x: number;
44
58
  y: number;
59
+ currentValue?: unknown;
60
+ openPath?: number[];
45
61
  } | null) => void;
46
62
  setActiveModalId: (modalId: string | null) => void;
47
63
  closeModal: (modalId?: string | null) => void;
@@ -54,6 +70,7 @@ export declare class ActionRuntime {
54
70
  private readonly actionFunctions;
55
71
  private readonly nodeById;
56
72
  private readonly stateById;
73
+ private readonly stateByKey;
57
74
  private readonly rerenderRoot;
58
75
  private readonly dispatchWidgetEventImpl;
59
76
  private readonly executeRequest;
@@ -63,6 +80,17 @@ export declare class ActionRuntime {
63
80
  private readonly resolveMappedValue;
64
81
  private readonly setWidgetEnabled;
65
82
  private readonly clearWidget;
83
+ private readonly clearListElementState;
84
+ private readonly focusWidget;
85
+ private readonly playAudio;
86
+ private readonly stopPlaying;
87
+ private readonly copyToClipboard;
88
+ private readonly selectFile;
89
+ private readonly confirmModal;
90
+ private readonly startRecording;
91
+ private readonly stopRecording;
92
+ private readonly startListening;
93
+ private readonly stopListening;
66
94
  private readonly setUiReference;
67
95
  private readonly refreshWidgetTree;
68
96
  private readonly renderWidgetTree;
@@ -82,5 +110,10 @@ export declare class ActionRuntime {
82
110
  getInlineActionsForNode(node: DescriptionNode): ActionDefinition[] | undefined;
83
111
  private runSingleAction;
84
112
  private executeAction;
113
+ private unwrapListValue;
114
+ private getCurrentListState;
115
+ private cloneValue;
116
+ private stringifyValue;
117
+ private isCurrentScopedReference;
85
118
  }
86
119
  export {};
@@ -15,16 +15,20 @@ export type PreservedElementState = {
15
15
  }>;
16
16
  };
17
17
  export declare function isElementInsidePendingResetModal(element: HTMLElement, pendingResetModalIds: Set<string>): boolean;
18
- export declare function captureElementState(root: HTMLElement, pendingResetModalIds: Set<string>, stateByKey: Map<string, WidgetState>): PreservedElementState;
19
- export declare function restoreElementState(root: HTMLElement, state: PreservedElementState): void;
18
+ export declare function captureElementState(root: HTMLElement, pendingResetModalIds: Set<string>): PreservedElementState;
19
+ export declare function restoreElementState(root: HTMLElement, state: PreservedElementState, stateByKey: Map<string, WidgetState>): void;
20
20
  export declare function adjustContextMenuPosition(root: HTMLElement, activeContextMenu: {
21
21
  id: string;
22
22
  x: number;
23
23
  y: number;
24
+ currentValue?: unknown;
25
+ openPath?: number[];
24
26
  } | null): {
25
27
  id: string;
26
28
  x: number;
27
29
  y: number;
30
+ currentValue?: unknown;
31
+ openPath?: number[];
28
32
  } | null;
29
33
  export declare function updatePointerFromMouseEvent(event: MouseEvent): {
30
34
  x: number;
@@ -25,6 +25,8 @@ export declare class NetworkRuntime {
25
25
  executeRequest(requestName: string, currentValue: unknown): Promise<unknown>;
26
26
  buildSchemaValue(schema: RequestSchema, currentValue: unknown, responseValue: unknown): Promise<unknown>;
27
27
  private stringifyPrimitive;
28
+ private createRequestError;
29
+ private toRequestErrorPayload;
28
30
  coercePrimitiveSchemaValue(type: PrimitiveRequestType, value: unknown): unknown;
29
31
  private handleSseEvent;
30
32
  }
@@ -6,6 +6,8 @@ type ReferenceRuntimeHost = {
6
6
  readonly nodeByKey: Map<string, DescriptionNode>;
7
7
  getAppValue: (name: string) => unknown;
8
8
  setAppValue: (name: string, value: unknown) => void;
9
+ getVarValue: (name: string) => unknown;
10
+ setVarValue: (name: string, value: unknown) => void;
9
11
  ensureWidgetState: (node: DescriptionNode, key: string) => WidgetState;
10
12
  resolveItemNodeKey: (node: DescriptionNode, listKey: string, index: number, fallbackPath: string) => string;
11
13
  indexListElementNodes: (listNode: ListNode | GridViewNode, element: DescriptionNode, index: number) => void;
@@ -4,7 +4,7 @@ export type TextAlign = 'left' | 'center' | 'right';
4
4
  export type VerticalAlign = 'top' | 'center' | 'bottom';
5
5
  export type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
6
6
  export type WidgetEventName = 'onClick' | 'onUserValueChange' | 'onRefresh' | 'onEnter' | 'onShiftEnter' | 'onControlEnter';
7
- export type SystemEventName = 'onBeforeRender' | 'onAfterRender' | 'onBeforeNavigate' | 'onAfterNavigate';
7
+ export type SystemEventName = 'onBeforeRender' | 'onAfterRender' | 'onBeforeNavigate' | 'onAfterNavigate' | 'onSpeechDetected' | 'onRecordingStarted' | 'onRecordingStopped' | 'onRecordingError' | 'onListeningError' | 'onListeringError' | 'onPlayFinished' | 'onPlayingStopped';
8
8
  export type PrimitiveRequestType = 'int' | 'float' | 'boolean' | 'string';
9
9
  export type ActionDefinition = {
10
10
  action: string;
@@ -34,6 +34,7 @@ export type RequestDefinition = {
34
34
  request: RequestSchema;
35
35
  response?: RequestSchema;
36
36
  onResponse?: ActionDefinition[];
37
+ onError?: ActionDefinition[];
37
38
  };
38
39
  export type SseEventDefinition = {
39
40
  name: string;
@@ -114,6 +115,7 @@ export type WidgetState = {
114
115
  };
115
116
  export type RuntimeSnapshot = {
116
117
  stateByKey: Array<[string, WidgetState]>;
118
+ vars: Array<[string, unknown]>;
117
119
  activeModalId: string | null;
118
120
  activeContextMenu: {
119
121
  id: string;
@@ -0,0 +1,48 @@
1
+ import type { SystemEventName } from './types.js';
2
+ type VoiceRuntimeOptions = {
3
+ debugLogging: boolean;
4
+ triggerSystemEvent: (eventName: SystemEventName, inputValue: unknown) => Promise<void>;
5
+ };
6
+ export declare class VoiceRuntime {
7
+ private readonly debugLogging;
8
+ private readonly triggerSystemEvent;
9
+ private readonly activePlayers;
10
+ private mediaStream;
11
+ private mediaRecorder;
12
+ private recordingChunks;
13
+ private recordingTimeoutId;
14
+ private listening;
15
+ private listenContext;
16
+ private listenAnalyser;
17
+ private listenSource;
18
+ private listenFrameId;
19
+ private lastSpeechAt;
20
+ private listeningStartedAt;
21
+ private recordingStartedFromListening;
22
+ private speechEventTriggered;
23
+ private readonly visibilityHandler;
24
+ private readonly pageHideHandler;
25
+ constructor(options: VoiceRuntimeOptions);
26
+ play(value: unknown): Promise<void>;
27
+ stopPlaying(): Promise<void>;
28
+ startRecording(): Promise<void>;
29
+ stopRecording(): void;
30
+ startListening(): Promise<void>;
31
+ stopListening(): Promise<void>;
32
+ dispose(): void;
33
+ private startRecordingInternal;
34
+ private handleRecorderStop;
35
+ private handleRecordingError;
36
+ private handleListeningError;
37
+ private normalizePlayablePayload;
38
+ private getPreferredRecordingMimeType;
39
+ private ensureInputStream;
40
+ private clearRecordingTimeout;
41
+ private releaseInputStreamIfIdle;
42
+ private stopStreamTracks;
43
+ private normalizeErrorMessage;
44
+ private detachPlayer;
45
+ private finishPlayback;
46
+ private handlePageDeactivation;
47
+ }
48
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { WidgetRenderEnvironment } from './context.js';
2
+ export type ConfirmModalState = {
3
+ caption: string;
4
+ yes: string;
5
+ no: string;
6
+ };
7
+ export declare function renderConfirmModalOverlay(env: WidgetRenderEnvironment, modal: ConfirmModalState): string;
@@ -1,14 +1,20 @@
1
1
  import type { ActionDefinition, BaseNode } from '../types.js';
2
2
  import type { WidgetRenderEnvironment } from './context.js';
3
+ export type ContextMenuItem = {
4
+ name: string;
5
+ actions?: ActionDefinition[];
6
+ items?: ContextMenuItem[];
7
+ };
3
8
  export type ContextMenuNode = BaseNode & {
4
9
  widget: 'context-menu';
5
- items?: Array<{
6
- name: string;
7
- actions?: ActionDefinition[];
8
- }>;
10
+ items?: ContextMenuItem[];
9
11
  };
10
- export declare function renderContextMenuOverlay(env: WidgetRenderEnvironment, menu: {
12
+ export type ActiveContextMenuState = {
11
13
  id: string;
12
14
  x: number;
13
15
  y: number;
14
- }): string;
16
+ currentValue?: unknown;
17
+ openPath?: number[];
18
+ };
19
+ export declare function getContextMenuItemAtPath(items: ContextMenuItem[] | undefined, path: number[]): ContextMenuItem | null;
20
+ export declare function renderContextMenuOverlay(env: WidgetRenderEnvironment, menu: ActiveContextMenuState): string;
@@ -5,7 +5,7 @@ import type { CheckboxNode } from './checkbox.js';
5
5
  import type { ComboboxNode } from './combobox.js';
6
6
  import type { ConditionalContainerNode } from './conditional-container.js';
7
7
  import type { ContainerCell, ContainerLayoutNode } from './container-layout.js';
8
- import type { ContextMenuNode } from './context-menu.js';
8
+ import type { ActiveContextMenuState, ContextMenuNode } from './context-menu.js';
9
9
  import type { GridViewNode } from './grid-view.js';
10
10
  import type { ImageNode } from './image.js';
11
11
  import type { LinkNode } from './link.js';
@@ -23,11 +23,7 @@ import type { TabsNode } from './tabs.js';
23
23
  import type { TextareaNode } from './textarea.js';
24
24
  import type { UiReferenceNode } from './ui-reference.js';
25
25
  export type WidgetRenderEnvironment = {
26
- readonly activeContextMenu: {
27
- id: string;
28
- x: number;
29
- y: number;
30
- } | null;
26
+ readonly activeContextMenu: ActiveContextMenuState | null;
31
27
  readonly activeModalId: string | null;
32
28
  readonly nodeById: Map<string, DescriptionNode>;
33
29
  escapeHtml: (value: unknown) => string;
@@ -7,10 +7,19 @@ type DelegationEnvironment = {
7
7
  x: number;
8
8
  y: number;
9
9
  };
10
+ getActiveContextMenu: () => {
11
+ id: string;
12
+ x: number;
13
+ y: number;
14
+ currentValue?: unknown;
15
+ openPath?: number[];
16
+ } | null;
10
17
  setActiveContextMenu: (menu: {
11
18
  id: string;
12
19
  x: number;
13
20
  y: number;
21
+ currentValue?: unknown;
22
+ openPath?: number[];
14
23
  } | null) => void;
15
24
  isWidgetEnabled: (node: DescriptionNode, key: string) => boolean;
16
25
  startSplitterDrag: (layoutKey: string, axis: 'horizontal' | 'vertical', splitterIndex: number, startPointer: number) => void;
@@ -18,6 +27,7 @@ type DelegationEnvironment = {
18
27
  updateSplitterDrag: (clientPosition: number) => void;
19
28
  stopSplitterDrag: () => void;
20
29
  hasSplitterDrag: () => boolean;
30
+ resolveConfirmModal: (confirmed: boolean) => void;
21
31
  closeModal: (modalId: string | null) => void;
22
32
  rerenderRoot: () => Promise<void>;
23
33
  redispatchUnderlyingClick: (clientX: number, clientY: number) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vortexm/vjt",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
package/vjt-styles.css CHANGED
@@ -685,12 +685,21 @@ body {
685
685
  }
686
686
 
687
687
  .vjt-modal-backdrop,
688
- .vjt-context-menu-backdrop {
688
+ .vjt-context-menu-backdrop,
689
+ .vjt-confirm-backdrop {
689
690
  position: fixed;
690
691
  inset: 0;
692
+ }
693
+
694
+ .vjt-modal-backdrop,
695
+ .vjt-context-menu-backdrop {
691
696
  z-index: 1000;
692
697
  }
693
698
 
699
+ .vjt-confirm-backdrop {
700
+ z-index: 1100;
701
+ }
702
+
694
703
  .vjt-modal-backdrop {
695
704
  display: flex;
696
705
  align-items: center;
@@ -759,16 +768,20 @@ body {
759
768
  }
760
769
 
761
770
  .vjt-context-menu {
762
- position: fixed;
763
- min-width: 180px;
764
- padding: 8px;
765
- border-radius: 14px;
771
+ position: fixed;
772
+ box-sizing: border-box;
773
+ width: 220px;
774
+ padding: 8px;
775
+ border-radius: 14px;
766
776
  border: 1px solid var(--vjt-border);
767
777
  background: var(--vjt-surface);
768
778
  box-shadow: var(--vjt-shadow);
769
779
  }
770
780
 
771
781
  .vjt-context-menu-item {
782
+ display: flex;
783
+ align-items: center;
784
+ justify-content: space-between;
772
785
  width: 100%;
773
786
  padding: 10px 12px;
774
787
  text-align: left;
@@ -781,3 +794,48 @@ body {
781
794
  .vjt-context-menu-item:hover {
782
795
  background: color-mix(in srgb, var(--vjt-accent) 14%, transparent);
783
796
  }
797
+
798
+ .vjt-context-menu-item--parent {
799
+ font-weight: 500;
800
+ }
801
+
802
+ .vjt-context-menu-chevron {
803
+ margin-left: 16px;
804
+ opacity: 0.7;
805
+ }
806
+
807
+ .vjt-confirm-backdrop {
808
+ display: flex;
809
+ align-items: center;
810
+ justify-content: center;
811
+ background: rgba(7, 10, 15, 0.42);
812
+ padding: 24px;
813
+ }
814
+
815
+ .vjt-confirm-window {
816
+ width: min(420px, calc(100vw - 32px));
817
+ display: flex;
818
+ flex-direction: column;
819
+ gap: 18px;
820
+ padding: 22px;
821
+ border-radius: 18px;
822
+ border: 1px solid var(--vjt-border);
823
+ background: var(--vjt-modal-surface);
824
+ color: var(--vjt-text);
825
+ box-shadow: var(--vjt-shadow);
826
+ }
827
+
828
+ .vjt-confirm-caption {
829
+ line-height: 1.45;
830
+ white-space: pre-wrap;
831
+ }
832
+
833
+ .vjt-confirm-actions {
834
+ display: flex;
835
+ justify-content: flex-end;
836
+ gap: 10px;
837
+ }
838
+
839
+ .vjt-confirm-actions .vjt-button {
840
+ min-width: 120px;
841
+ }