uiconfig-blueprint 0.1.0-dev.13 → 0.1.0-dev.15

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.
Files changed (167) hide show
  1. package/dist/ConfigObject.d.ts +3 -1
  2. package/dist/{allPaths-Dbwyd6G0.js → allPaths-vhUhWron.js} +5 -5
  3. package/dist/{allPaths-Dbwyd6G0.js.map → allPaths-vhUhWron.js.map} +1 -1
  4. package/dist/{allPathsLoader-B9DtnPQs.js → allPathsLoader-BeDEFia4.js} +4 -4
  5. package/dist/{allPathsLoader-B9DtnPQs.js.map → allPathsLoader-BeDEFia4.js.map} +1 -1
  6. package/dist/bpComponents/BPColorInputComponent.d.ts +1 -0
  7. package/dist/bpComponents/BPComponent.d.ts +2 -0
  8. package/dist/bpComponents/BPContainerComponent.d.ts +10 -2
  9. package/dist/bpComponents/BPDropdownInputComponent.d.ts +1 -0
  10. package/dist/bpComponents/BPFileComponent.d.ts +12 -10
  11. package/dist/bpComponents/BPFolderComponent.d.ts +13 -4
  12. package/dist/bpComponents/BPPanelComponent.d.ts +3 -3
  13. package/dist/bpComponents/BPTextInputComponent.d.ts +4 -0
  14. package/dist/bpComponents/BPValueComponent.d.ts +2 -2
  15. package/dist/bpComponents/BPVectorInputComponent.d.ts +11 -5
  16. package/dist/bpComponents/InputGroup2.d.ts +25 -0
  17. package/dist/components/DialogContext.d.ts +10 -3
  18. package/dist/components/DraggableIcon.d.ts +4 -3
  19. package/dist/components/FileComponent.d.ts +13 -6
  20. package/dist/components/FormGroupComponent.d.ts +3 -2
  21. package/dist/components/InspectorStackComponent.d.ts +11 -2
  22. package/dist/index-BaIbKicL.js +695 -0
  23. package/dist/index-BaIbKicL.js.map +1 -0
  24. package/dist/index-Bh4sHBxX.js +695 -0
  25. package/dist/index-Bh4sHBxX.js.map +1 -0
  26. package/dist/index-C8ABKThN.js +13501 -0
  27. package/dist/index-C8ABKThN.js.map +1 -0
  28. package/dist/index.js +28 -41
  29. package/dist/index.js.map +1 -1
  30. package/dist/index.mjs +2 -2
  31. package/dist/lib.d.ts +2 -3
  32. package/dist/{splitPathsBySizeLoader-Dii-Xb62.js → splitPathsBySizeLoader-CYAuGCeX.js} +5 -5
  33. package/dist/{splitPathsBySizeLoader-Dii-Xb62.js.map → splitPathsBySizeLoader-CYAuGCeX.js.map} +1 -1
  34. package/dist/utils/pointerLock.d.ts +44 -0
  35. package/docs/classes/UI.html +3 -3
  36. package/docs/classes/UiConfigRendererBlueprint.html +3 -3
  37. package/lib/css/renderer.css +35 -103
  38. package/lib/css/renderer.css.map +1 -1
  39. package/lib/esm/ConfigObject.d.ts +3 -1
  40. package/lib/esm/ConfigObject.js +5 -4
  41. package/lib/esm/ConfigObject.js.map +1 -1
  42. package/lib/esm/UiConfigRendererBlueprint.js +2 -1
  43. package/lib/esm/UiConfigRendererBlueprint.js.map +1 -1
  44. package/lib/esm/bpComponents/BPButtonComponent.js +1 -1
  45. package/lib/esm/bpComponents/BPButtonComponent.js.map +1 -1
  46. package/lib/esm/bpComponents/BPColorInputComponent.d.ts +1 -0
  47. package/lib/esm/bpComponents/BPColorInputComponent.js +17 -4
  48. package/lib/esm/bpComponents/BPColorInputComponent.js.map +1 -1
  49. package/lib/esm/bpComponents/BPComponent.d.ts +2 -0
  50. package/lib/esm/bpComponents/BPComponent.js +4 -4
  51. package/lib/esm/bpComponents/BPComponent.js.map +1 -1
  52. package/lib/esm/bpComponents/BPContainerComponent.d.ts +10 -2
  53. package/lib/esm/bpComponents/BPContainerComponent.js +4 -1
  54. package/lib/esm/bpComponents/BPContainerComponent.js.map +1 -1
  55. package/lib/esm/bpComponents/BPDropdownInputComponent.d.ts +1 -0
  56. package/lib/esm/bpComponents/BPDropdownInputComponent.js +5 -4
  57. package/lib/esm/bpComponents/BPDropdownInputComponent.js.map +1 -1
  58. package/lib/esm/bpComponents/BPFileComponent.d.ts +12 -10
  59. package/lib/esm/bpComponents/BPFileComponent.js +10 -8
  60. package/lib/esm/bpComponents/BPFileComponent.js.map +1 -1
  61. package/lib/esm/bpComponents/BPFolderComponent.d.ts +13 -4
  62. package/lib/esm/bpComponents/BPFolderComponent.js +58 -13
  63. package/lib/esm/bpComponents/BPFolderComponent.js.map +1 -1
  64. package/lib/esm/bpComponents/BPInputComponent.js +1 -1
  65. package/lib/esm/bpComponents/BPInputComponent.js.map +1 -1
  66. package/lib/esm/bpComponents/BPPanelComponent.d.ts +3 -3
  67. package/lib/esm/bpComponents/BPPanelComponent.js +1 -1
  68. package/lib/esm/bpComponents/BPPanelComponent.js.map +1 -1
  69. package/lib/esm/bpComponents/BPTextInputComponent.d.ts +4 -0
  70. package/lib/esm/bpComponents/BPTextInputComponent.js +34 -3
  71. package/lib/esm/bpComponents/BPTextInputComponent.js.map +1 -1
  72. package/lib/esm/bpComponents/BPTreeComponent.d.ts +4 -4
  73. package/lib/esm/bpComponents/BPTreeComponent.js +2 -2
  74. package/lib/esm/bpComponents/BPTreeComponent.js.map +1 -1
  75. package/lib/esm/bpComponents/BPValueComponent.d.ts +2 -2
  76. package/lib/esm/bpComponents/BPValueComponent.js +5 -4
  77. package/lib/esm/bpComponents/BPValueComponent.js.map +1 -1
  78. package/lib/esm/bpComponents/BPVectorInputComponent.d.ts +11 -5
  79. package/lib/esm/bpComponents/BPVectorInputComponent.js +47 -6
  80. package/lib/esm/bpComponents/BPVectorInputComponent.js.map +1 -1
  81. package/lib/esm/bpComponents/InputGroup2.d.ts +25 -0
  82. package/lib/esm/bpComponents/InputGroup2.js +93 -0
  83. package/lib/esm/bpComponents/InputGroup2.js.map +1 -0
  84. package/lib/esm/components/ConfigurationPanelComponent.js +1 -1
  85. package/lib/esm/components/ConfigurationPanelComponent.js.map +1 -1
  86. package/lib/esm/components/DialogContext.d.ts +10 -3
  87. package/lib/esm/components/DialogContext.js +14 -13
  88. package/lib/esm/components/DialogContext.js.map +1 -1
  89. package/lib/esm/components/DraggableIcon.d.ts +4 -3
  90. package/lib/esm/components/DraggableIcon.js +41 -39
  91. package/lib/esm/components/DraggableIcon.js.map +1 -1
  92. package/lib/esm/components/ExtendedNumericInput.js +1 -1
  93. package/lib/esm/components/ExtendedNumericInput.js.map +1 -1
  94. package/lib/esm/components/FileComponent.d.ts +13 -6
  95. package/lib/esm/components/FileComponent.js +15 -6
  96. package/lib/esm/components/FileComponent.js.map +1 -1
  97. package/lib/esm/components/FormGroupComponent.d.ts +3 -2
  98. package/lib/esm/components/FormGroupComponent.js +1 -6
  99. package/lib/esm/components/FormGroupComponent.js.map +1 -1
  100. package/lib/esm/components/InspectorStackComponent.d.ts +11 -2
  101. package/lib/esm/components/InspectorStackComponent.js +14 -4
  102. package/lib/esm/components/InspectorStackComponent.js.map +1 -1
  103. package/lib/esm/components/NumericInput.js +3 -2
  104. package/lib/esm/components/NumericInput.js.map +1 -1
  105. package/lib/esm/components/TreeNode2.d.ts +1 -1
  106. package/lib/esm/components/TreeNode2.js +4 -2
  107. package/lib/esm/components/TreeNode2.js.map +1 -1
  108. package/lib/esm/components/treeTypes.d.ts +2 -1
  109. package/lib/esm/lib.d.ts +2 -3
  110. package/lib/esm/lib.js +2 -3
  111. package/lib/esm/lib.js.map +1 -1
  112. package/lib/esm/renderer.css.js +1 -1
  113. package/lib/esm/utils/pointerLock.d.ts +44 -0
  114. package/lib/esm/utils/pointerLock.js +215 -0
  115. package/lib/esm/utils/pointerLock.js.map +1 -0
  116. package/lib/esm/utils.js +6 -1
  117. package/lib/esm/utils.js.map +1 -1
  118. package/package.json +10 -12
  119. package/src/ConfigObject.tsx +11 -5
  120. package/src/UiConfigRendererBlueprint.tsx +1 -1
  121. package/src/bpComponents/BPButtonComponent.tsx +1 -1
  122. package/src/bpComponents/BPColorInputComponent.tsx +13 -4
  123. package/src/bpComponents/BPComponent.tsx +4 -3
  124. package/src/bpComponents/BPContainerComponent.tsx +20 -3
  125. package/src/bpComponents/BPDropdownInputComponent.tsx +6 -4
  126. package/src/bpComponents/BPFileComponent.tsx +29 -20
  127. package/src/bpComponents/BPFolderComponent.scss +11 -6
  128. package/src/bpComponents/BPFolderComponent.tsx +122 -24
  129. package/src/bpComponents/BPInputComponent.tsx +1 -0
  130. package/src/bpComponents/BPPanelComponent.tsx +4 -4
  131. package/src/bpComponents/BPTextInputComponent.tsx +38 -5
  132. package/src/bpComponents/BPValueComponent.tsx +4 -4
  133. package/src/bpComponents/BPVectorInputComponent.tsx +80 -10
  134. package/src/bpComponents/InputGroup2.tsx +175 -0
  135. package/src/bpComponents/index.scss +0 -1
  136. package/src/components/ConfigurationPanelComponent.tsx +2 -2
  137. package/src/components/DialogContext.tsx +20 -12
  138. package/src/components/DraggableIcon.tsx +71 -49
  139. package/src/components/ExtendedNumericInput.tsx +2 -2
  140. package/src/components/FileComponent.tsx +37 -18
  141. package/src/components/FormGroupComponent.tsx +8 -4
  142. package/src/components/InspectorStackComponent.tsx +20 -7
  143. package/src/components/NumericInput.tsx +4 -5
  144. package/src/components/common.scss +1 -1
  145. package/src/lib.ts +2 -3
  146. package/src/renderer.scss +30 -8
  147. package/src/utils/PointerLockManager.md +334 -0
  148. package/src/utils/pointerLock.ts +264 -0
  149. package/src/utils.ts +8 -4
  150. package/dist/bpComponents/BPTreeComponent.d.ts +0 -46
  151. package/dist/bpComponents/BPTreeFolderComponent.d.ts +0 -10
  152. package/dist/components/Tree2.d.ts +0 -52
  153. package/dist/components/TreeNode2.d.ts +0 -43
  154. package/dist/components/treeTypes.d.ts +0 -18
  155. package/dist/index-BFBvfUPU.js +0 -671
  156. package/dist/index-BFBvfUPU.js.map +0 -1
  157. package/dist/index-CHQ1fP9-.js +0 -671
  158. package/dist/index-CHQ1fP9-.js.map +0 -1
  159. package/dist/index-Dbe8gLld.js +0 -13583
  160. package/dist/index-Dbe8gLld.js.map +0 -1
  161. package/src/bpComponents/BPTreeComponent.scss +0 -3
  162. package/src/bpComponents/BPTreeComponent.tsx +0 -244
  163. package/src/bpComponents/BPTreeFolderComponent.tsx +0 -31
  164. package/src/components/Tree2.tsx +0 -344
  165. package/src/components/TreeNode2.tsx +0 -192
  166. package/src/components/tree2.scss +0 -69
  167. package/src/components/treeTypes.ts +0 -97
@@ -2,22 +2,24 @@ import React from "react";
2
2
  import {BPComponentProps, UiConfigRendererContextType} from "./BPComponent";
3
3
  import {BPInputComponent} from "./BPInputComponent";
4
4
  import {BPValueComponentState} from "./BPValueComponent";
5
- import type {Vector2, Vector3, Vector4} from "three";
5
+ import type {Vector2, Vector3,Euler, Vector4} from "three";
6
6
  import {ExtendedNumericInput} from "../components/ExtendedNumericInput";
7
7
  import {wIcon3, xIcon3, yIcon3, zIcon3} from "../components/variableIcons";
8
8
  import {getOrCall} from 'ts-browser-helpers'
9
9
  import {getNumberTransformFunctions} from "./GetNumberTransformFunctions";
10
+ import {HTMLSelect} from "@blueprintjs/core";
10
11
 
11
- export type BPVectorComponentState = BPValueComponentState<Vector2|Vector3|Vector4> & {
12
+ export type BPVectorComponentState = BPValueComponentState<Vector2|Vector3|Euler|Vector4> & {
12
13
  min: number,
13
14
  max: number,
14
15
  step: number,
15
16
  components: 1|2|3|4,
16
17
  unit?: string,
18
+ isEuler: boolean,
17
19
  }
18
20
 
19
- export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vector4, BPVectorComponentState> {
20
- constructor(props: BPComponentProps<Vector2|Vector3|Vector4>, context: UiConfigRendererContextType) {
21
+ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Euler|Vector4, BPVectorComponentState> {
22
+ constructor(props: BPComponentProps<Vector2|Vector3|Euler|Vector4>, context: UiConfigRendererContextType) {
21
23
  super(props, context, {
22
24
  value: new context.THREE!.Vector2(),
23
25
  label: 'Vector',
@@ -25,6 +27,7 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
25
27
  max: Infinity,
26
28
  step: 0.01,
27
29
  components: 2,
30
+ isEuler: false,
28
31
  });
29
32
  }
30
33
 
@@ -46,6 +49,10 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
46
49
  // console.warn(state.value)
47
50
  let com = this.props.config.type!.replace('vector', '').replace('vec', '')
48
51
  let components: any = 0;
52
+ // Check if this is an Euler object
53
+ const isEuler = typeof (state.value as any).order === 'string';
54
+ state.isEuler = isEuler;
55
+
49
56
  // console.log(com, components)
50
57
  if(!com.length){
51
58
  let v = state.value as any;
@@ -62,6 +69,8 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
62
69
  }
63
70
 
64
71
  private _inputs = [React.createRef<ExtendedNumericInput>(), React.createRef<ExtendedNumericInput>(), React.createRef<ExtendedNumericInput>(), React.createRef<ExtendedNumericInput>()]
72
+ private _parent = React.createRef<HTMLDivElement>()
73
+ private _lastWidth?: number
65
74
 
66
75
  async refreshConfigState(state?: BPVectorComponentState): Promise<void> {
67
76
  await super.refreshConfigState(state);
@@ -70,6 +79,28 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
70
79
  await this._inputs[2].current?.setValue((this.state.value as any).z)
71
80
  await this._inputs[3].current?.setValue((this.state.value as any).w)
72
81
  }
82
+ // todo can we do it with css instead of ResizeObserver
83
+ private _resizeObserver = new ResizeObserver((entries) => {
84
+ for (const entry of entries) {
85
+ const newWidth = entry.contentRect.width
86
+ if (Math.abs(newWidth - (this._lastWidth||0)) > 5) {
87
+ this._lastWidth = newWidth
88
+ this.forceUpdate()
89
+ }
90
+ }
91
+ })
92
+
93
+ componentDidMount() {
94
+ if (this._parent.current) {
95
+ this._resizeObserver.observe(this._parent.current)
96
+ }
97
+ super.componentDidMount()
98
+ }
99
+
100
+ componentWillUnmount() {
101
+ this._resizeObserver.disconnect()
102
+ super.componentWillUnmount()
103
+ }
73
104
 
74
105
  renderInput() {
75
106
  let ret = []
@@ -92,13 +123,25 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
92
123
  ...transformValue,
93
124
  } as const
94
125
 
95
- // console.warn(this.state.value)
126
+ const showIcon = this._parent.current?.offsetWidth ? this._parent.current.offsetWidth > (60 * this.state.components) : true
127
+
128
+ // Euler rotation order options
129
+ const eulerOrderOptions = [
130
+ { label: 'XYZ', value: 'XYZ' },
131
+ { label: 'YXZ', value: 'YXZ' },
132
+ { label: 'ZXY', value: 'ZXY' },
133
+ { label: 'ZYX', value: 'ZYX' },
134
+ { label: 'YZX', value: 'YZX' },
135
+ { label: 'XZY', value: 'XZY' }
136
+ ];
137
+
96
138
  if (this.state.components > 0) {
97
139
  const x = (
98
140
  <ExtendedNumericInput
99
141
  style={{maxWidth: "8rem", minWidth: "2rem"}}
100
142
  // defaultValue={state}
101
143
  leftIcon={xIcon3}
144
+ draggableIcon={showIcon}
102
145
  value={this.state.value.x}
103
146
  key={this.props.config.uuid + '_x'}
104
147
  ref={this._inputs[0]}
@@ -117,6 +160,7 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
117
160
  // defaultValue={state}
118
161
  value={this.state.value.y}
119
162
  leftIcon={yIcon3}
163
+ draggableIcon={showIcon}
120
164
  key={this.props.config.uuid + '_y'}
121
165
  ref={this._inputs[1]}
122
166
  {...props}
@@ -132,26 +176,48 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
132
176
  <ExtendedNumericInput
133
177
  style={{maxWidth: "8rem", minWidth: "2rem"}}
134
178
  // defaultValue={state}
135
- value={(this.state.value as Vector3|Vector4).z}
179
+ value={(this.state.value as Vector3|Euler|Vector4).z}
136
180
  key={this.props.config.uuid + '_z'}
137
181
  leftIcon={zIcon3}
182
+ draggableIcon={showIcon}
138
183
  ref={this._inputs[2]}
139
184
  {...props}
140
185
  onChange2={(v, last) => {
141
- (this.state.value as Vector3 | Vector4).z = v
186
+ (this.state.value as Vector3|Euler | Vector4).z = v
142
187
  this.setValue(this.state.value, last) // todo: does need refresh?
143
188
  }}
144
189
  />)
145
190
  ret.push(z)
191
+
192
+ // Add Euler rotation order dropdown after z component
193
+ if(this.state.isEuler && this.props.config.showOrderSelector) { // todo add showOrderSelector to uiconfig types and other renderers
194
+ const eulerOrderDropdown = (
195
+ <HTMLSelect
196
+ options={eulerOrderOptions}
197
+ minimal={true}
198
+ fill={false}
199
+ disabled={this.state.disabled || this.state.readOnly}
200
+ value={(this.state.value as Euler).order}
201
+ key={this.props.config.uuid + '_order'}
202
+ onChange={(event) => {
203
+ (this.state.value as Euler).order = event.currentTarget.value as any;
204
+ this.setValue(this.state.value, true);
205
+ }}
206
+ style={{maxWidth: "6rem", minWidth: "2rem"}}
207
+ />
208
+ );
209
+ ret.push(eulerOrderDropdown);
210
+ }
146
211
  }
147
212
  if(this.state.components>3) {
148
- const z = (
213
+ const w = (
149
214
  <ExtendedNumericInput
150
215
  style={{maxWidth: "8rem", minWidth: "2rem"}}
151
216
  // defaultValue={state}
152
217
  value={(this.state.value as Vector4).w}
153
218
  key={this.props.config.uuid + '_w'}
154
219
  leftIcon={wIcon3}
220
+ draggableIcon={showIcon}
155
221
  ref={this._inputs[3]}
156
222
  {...props}
157
223
  onChange2={(v, last) => {
@@ -159,8 +225,12 @@ export class BPVectorInputComponent extends BPInputComponent<Vector2|Vector3|Vec
159
225
  this.setValue(this.state.value, last) // todo: does need refresh?
160
226
  }}
161
227
  />)
162
- ret.push(z)
228
+ ret.push(w)
163
229
  }
164
- return ret
230
+ return <div ref={this._parent}
231
+ className={"formGroupContent"}
232
+ >
233
+ {ret}
234
+ </div>
165
235
  }
166
236
  }
@@ -0,0 +1,175 @@
1
+ import {
2
+ AbstractPureComponent,
3
+ Classes,
4
+ DISPLAYNAME_PREFIX,
5
+ Icon,
6
+ InputGroupProps,
7
+ removeNonHTMLProps
8
+ } from "@blueprintjs/core";
9
+ import {InputGroupState} from "@blueprintjs/core/lib/esnext/components/forms/inputGroup";
10
+ import classNames from "classnames";
11
+ import * as React from "react";
12
+
13
+ export interface InputGroup2Props extends InputGroupProps{
14
+ leftElementWidth?: number|string
15
+ rightElementWidth?: number|string
16
+ }
17
+ export const NON_HTML_PROPS: Array<keyof InputGroup2Props> = ["inputSize", "onValueChange", "leftElementWidth", "rightElementWidth"];
18
+
19
+ export class InputGroup2 extends AbstractPureComponent<InputGroup2Props, InputGroupState> {
20
+ public static displayName = `${DISPLAYNAME_PREFIX}.InputGroup`;
21
+
22
+ public state: InputGroupState = {};
23
+
24
+ private leftElement: HTMLElement | null = null;
25
+
26
+ private rightElement: HTMLElement | null = null;
27
+
28
+ private refHandlers = {
29
+ leftElement: (ref: HTMLSpanElement | null) => (this.leftElement = ref),
30
+ rightElement: (ref: HTMLSpanElement | null) => (this.rightElement = ref),
31
+ };
32
+
33
+ public render() {
34
+ const {
35
+ // asyncControl = false,
36
+ className,
37
+ disabled,
38
+ fill,
39
+ inputClassName,
40
+ inputRef,
41
+ inputSize,
42
+ intent,
43
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
44
+ large,
45
+ readOnly,
46
+ round,
47
+ size = "medium",
48
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
49
+ small,
50
+ tagName = "div",
51
+ } = this.props;
52
+ const inputGroupClasses = classNames(
53
+ Classes.INPUT_GROUP,
54
+ Classes.intentClass(intent),
55
+ {
56
+ [Classes.DISABLED]: disabled,
57
+ [Classes.READ_ONLY]: readOnly,
58
+ [Classes.FILL]: fill,
59
+ [Classes.ROUND]: round,
60
+ },
61
+ Classes.sizeClass(size, {large, small}),
62
+ className,
63
+ );
64
+
65
+ const paddingLeft = this.state.leftElementWidth || this.props.leftElementWidth || undefined
66
+ const paddingRight = this.state.rightElementWidth || this.props.rightElementWidth || undefined
67
+ const style: React.CSSProperties = {
68
+ ...this.props.style,
69
+ // paddingLeft: this.state.leftElementWidth || this.props.leftElementWidth || 0,
70
+ // paddingRight: this.state.rightElementWidth || this.props.rightElementWidth || 0,
71
+ };
72
+ if(paddingLeft !== undefined)
73
+ style.paddingLeft = paddingLeft
74
+ if(paddingRight !== undefined)
75
+ style.paddingRight = paddingRight
76
+
77
+ const inputProps = {
78
+ type: "text",
79
+ ...removeNonHTMLProps(this.props, NON_HTML_PROPS, true),
80
+ "aria-disabled": disabled,
81
+ className: classNames(Classes.INPUT, inputClassName),
82
+ onChange: this.handleInputChange,
83
+ size: inputSize ?? (typeof size === "number" ? size : undefined),
84
+ style,
85
+ } satisfies React.HTMLProps<HTMLInputElement>;
86
+ const inputElement = /*asyncControl ? (
87
+ <AsyncControllableInput {...inputProps} inputRef={inputRef} />
88
+ ) : */(
89
+ <input {...inputProps} ref={inputRef}/>
90
+ );
91
+
92
+ return React.createElement(
93
+ tagName,
94
+ {className: inputGroupClasses},
95
+ this.maybeRenderLeftElement(),
96
+ inputElement,
97
+ this.maybeRenderRightElement(),
98
+ );
99
+ }
100
+
101
+ public componentDidMount() {
102
+ this.updateInputWidth();
103
+ }
104
+
105
+ public componentDidUpdate(prevProps: InputGroupProps) {
106
+ const {leftElement, rightElement} = this.props;
107
+ if (prevProps.leftElement !== leftElement || prevProps.rightElement !== rightElement) {
108
+ this.updateInputWidth();
109
+ }
110
+ }
111
+
112
+ protected validateProps(_props: InputGroupProps) {
113
+ // if (props.leftElement != null && props.leftIcon != null) {
114
+ // console.warn(INPUT_WARN_LEFT_ELEMENT_LEFT_ICON_MUTEX);
115
+ // }
116
+ }
117
+
118
+ private handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
119
+ const value = event.target.value;
120
+ this.props.onChange?.(event);
121
+ this.props.onValueChange?.(value, event.target);
122
+ };
123
+
124
+ private maybeRenderLeftElement() {
125
+ const {leftElement, leftIcon} = this.props;
126
+
127
+ if (leftElement != null) {
128
+ return (
129
+ <span className={Classes.INPUT_LEFT_CONTAINER} ref={this.refHandlers.leftElement}>
130
+ {leftElement}
131
+ </span>
132
+ );
133
+ } else if (leftIcon != null) {
134
+ return <Icon icon={leftIcon} aria-hidden={true} tabIndex={-1}/>;
135
+ }
136
+
137
+ return undefined;
138
+ }
139
+
140
+ private maybeRenderRightElement() {
141
+ const {rightElement} = this.props;
142
+ if (rightElement == null) {
143
+ return undefined;
144
+ }
145
+ return (
146
+ <span className={Classes.INPUT_ACTION} ref={this.refHandlers.rightElement}>
147
+ {rightElement}
148
+ </span>
149
+ );
150
+ }
151
+
152
+ private updateInputWidth() {
153
+ const {leftElementWidth, rightElementWidth} = this.state;
154
+
155
+ if (this.leftElement != null) {
156
+ const {clientWidth} = this.leftElement;
157
+ // small threshold to prevent infinite loops
158
+ if (leftElementWidth === undefined || Math.abs(clientWidth - leftElementWidth) > 2) {
159
+ this.setState({leftElementWidth: clientWidth});
160
+ }
161
+ } else {
162
+ this.setState({leftElementWidth: undefined});
163
+ }
164
+
165
+ if (this.rightElement != null) {
166
+ const {clientWidth} = this.rightElement;
167
+ // small threshold to prevent infinite loops
168
+ if (rightElementWidth === undefined || Math.abs(clientWidth - rightElementWidth) > 2) {
169
+ this.setState({rightElementWidth: clientWidth});
170
+ }
171
+ } else {
172
+ this.setState({rightElementWidth: undefined});
173
+ }
174
+ }
175
+ }
@@ -1,3 +1,2 @@
1
1
  @import "BPButtonComponent";
2
2
  @import "BPFolderComponent";
3
- @import "BPTreeComponent";
@@ -21,10 +21,10 @@ export function ConfigurationPanelComponent({config}: { config: UiObjectConfig<a
21
21
  renderPanel(props: ConfigProps) {
22
22
  // console.log(props.config === config)
23
23
  return (
24
- <ul style={{listStyleType: "none", paddingLeft: "0", margin: "0"}}>
24
+ <div style={{listStyleType: "none", paddingLeft: "0", margin: "0"}}>
25
25
  {/*{v && (<ConfigObject {...props}/>)}*/}
26
26
  {config && (<ConfigObject {...props} isPanel={true}/>)}
27
- </ul>
27
+ </div>
28
28
  )
29
29
  },
30
30
  title: renderer.methods.getLabel(config)
@@ -20,12 +20,12 @@ export const defaultDialogContext = {
20
20
  export function setupDialog(){
21
21
  const [dialog, setDialog] = useState<DialogStateType>(defaultDialogContext)
22
22
  const open = useCallback((d: Partial<DialogStateType>)=>{
23
- setDialog({...dialog, isOpen: true, ...d})
24
- }, [dialog, setDialog])
25
- const close = useCallback(()=>setDialog({...dialog, isOpen: false}), [dialog, setDialog])
23
+ setDialog((d1)=>({...d1, ...d, isOpen: true}))
24
+ }, [])
25
+ const close = useCallback(()=>setDialog((d1)=>({...d1, isOpen: false})), [])
26
26
  const setDialogState = useCallback((state: any)=>{
27
- setDialog({...dialog, state})
28
- }, [dialog, setDialog])
27
+ setDialog((d1)=>({...d1, state}))
28
+ }, [])
29
29
  return {dialog, open, close, setDialog, state: dialog.state, setState: setDialogState}
30
30
  }
31
31
  export const DialogContext = createContext<{
@@ -50,7 +50,11 @@ export function DialogProvider({children}: {children: ReactNode}){
50
50
  export function DialogComponent(){
51
51
  const {dialog, close} = useDialog()
52
52
  return (
53
- <Dialog title={dialog.title} isOpen={dialog.isOpen} isCloseButtonShown={dialog.canClose} onClose={() => {dialog.canClose && close()}}>
53
+ <Dialog title={dialog.title}
54
+ isOpen={dialog.isOpen}
55
+ usePortal={false}
56
+ isCloseButtonShown={dialog.canClose}
57
+ onClose={() => {dialog.canClose && close()}}>
54
58
  <DialogBody>
55
59
  {dialog.content}
56
60
  </DialogBody>
@@ -62,13 +66,13 @@ interface DialogPromptState {
62
66
  value: string,
63
67
  intent: Intent,
64
68
  helperText: string,
69
+ key: string,
65
70
  }
66
- interface DialogPromptProps extends Partial<DialogStateType>{
71
+ interface DialogPromptProps extends Partial<DialogStateType>, Partial<DialogPromptState>{
67
72
  closeButtonText?: string,
68
73
  submitButtonText?: string,
69
74
  message?: string,
70
75
  placeholder?: string,
71
- value?: string,
72
76
  showInput?: boolean,
73
77
  onClose?: (value: string)=>boolean|undefined|Promise<boolean|undefined>, // does not close if false
74
78
  onSubmit?: (value: string)=>boolean|undefined|any|Promise<boolean|undefined|any>, // does not close if false
@@ -99,15 +103,17 @@ export function useDialogPrompt(){
99
103
  value = '',
100
104
  showInput = true,
101
105
  onClose, onSubmit,
106
+ helperText = '',
107
+ intent = Intent.NONE,
102
108
  ...props}: DialogPromptProps) => {
103
109
  return new Promise<string|null>((resolve)=>{
104
110
  open({
105
111
  canClose: false,
106
- ...props,
107
112
  state: {
108
113
  value,
109
- intent: Intent.NONE,
110
- helperText: '',
114
+ intent,
115
+ helperText,
116
+ key: Math.random().toString(36).slice(2, 10),
111
117
  } as DialogPromptState,
112
118
  content: (
113
119
  <DialogPromptContent message={message} showInput={showInput} placeholder={placeholder}/>
@@ -115,10 +121,11 @@ export function useDialogPrompt(){
115
121
  actions: (
116
122
  <DialogPromptButtons closeButtonText={closeButtonText} submitButtonText={submitButtonText} onClose={onClose} onSubmit={onSubmit} resolve={resolve}/>
117
123
  ),
124
+ ...props,
118
125
  })
119
126
  })
120
127
  }, [open, close])
121
- return {prompt, close}
128
+ return {prompt, close, open}
122
129
  }
123
130
 
124
131
  function DialogPromptButtons({
@@ -192,6 +199,7 @@ function DialogPromptContent({
192
199
  labelFor="dialog-prompt-text-input"
193
200
  >
194
201
  <InputGroup
202
+ key={state.key}
195
203
  intent={state.intent}
196
204
  id="dialog-prompt-text-input"
197
205
  placeholder={placeholder}
@@ -1,74 +1,96 @@
1
1
  import * as React from "react";
2
2
  import {Icon, IconName, MaybeElement} from "@blueprintjs/core";
3
+ import {PointerLockManager} from "../utils/pointerLock";
3
4
 
4
5
  // todo: bounds and stepsize
6
+ // todo use the old version in safari etc that change the page height on pointer lock
5
7
  export class DraggableIcon extends React.Component<{ icon: IconName | MaybeElement, size?: number, value: number, stepSize?: number, small?: boolean, disabled?: boolean, onChange: (v: number, last?: boolean) => void }> {
6
8
  private cursor = 'auto'
7
- private dragStartOffset = -Infinity
8
9
  private dragStartValue = -Infinity
9
10
  private lastValue = -Infinity
11
+ private pointerLockManager: PointerLockManager | null = null
12
+ private divRef = React.createRef<HTMLDivElement>()
10
13
  private removeEvents = () => {
11
14
  if (isFinite(this.lastValue) && !this.props.disabled) this.props.onChange(this.lastValue)
12
15
  this.lastValue = -Infinity
13
- this.dragStartOffset = -Infinity
14
16
  this.dragStartValue = -Infinity
15
- document.removeEventListener('mousemove', this.mouseMoveEvent)
16
- document.removeEventListener('mouseup', this.mouseUpEvent)
17
+
18
+ if (this.pointerLockManager) {
19
+ this.pointerLockManager.releaseLock()
20
+ this.pointerLockManager = null
21
+ }
22
+
17
23
  document.documentElement.style.cursor = this.cursor
18
24
  // setDragging(false)
19
25
  };
20
- private mouseUpEvent = (ev: MouseEvent) => {
21
- ev.stopPropagation()
22
- ev.preventDefault()
23
- this.removeEvents()
24
- };
25
- private mouseMoveEvent = (ev: MouseEvent) => {
26
- ev.stopPropagation()
27
- ev.preventDefault()
28
- if (ev.buttons > 0) {
29
- if (isFinite(this.dragStartValue) && isFinite(this.dragStartOffset)) {
30
- let stepSize = (this.props.stepSize ?? 1) / 10
31
- let curr = ev.clientX;
32
- let mm = 100;
33
- let off = this.dragStartOffset - curr;
34
- // off = Math.min(mm, Math.max(-mm, off));
35
- off = off / mm; //-1, 1
36
- // off = (off + 1)/2;
37
- // off *= (props.max - props.min) / 2
38
- off *= ((stepSize) * 100) / 2
39
- if (ev.shiftKey) off *= 10
40
- if (ev.altKey) off *= 0.1
41
-
42
- let val = this.dragStartValue - off;
43
- // val = Math.min(props.max, Math.max(props.min, val)); // todo
44
- val = Number(val.toFixed(Math.max(1, -Math.log10(stepSize / 10)))); // clip decimal places depending on step size
45
- if(!this.props.disabled) this.props.onChange(val, false)
46
- this.lastValue = val;
47
- }
48
- } else {
49
- this.removeEvents()
50
- // setDragging(false)
26
+
27
+ private handlePointerMove = (movementX: number, _movementY: number, _cursorX: number, _cursorY: number) => {
28
+ if (isFinite(this.dragStartValue)) {
29
+ let stepSize = (this.props.stepSize ?? 1) / 10
30
+
31
+ // Use movementX for horizontal dragging
32
+ let off = movementX;
33
+
34
+ // Scale the movement
35
+ off *= stepSize;
36
+
37
+ // Apply modifiers - these need to be checked differently in pointer lock
38
+ // We'll accumulate the offset instead
39
+ if (!this.accumulatedOffset) this.accumulatedOffset = 0;
40
+ this.accumulatedOffset += off;
41
+
42
+ let val = this.dragStartValue + this.accumulatedOffset;
43
+ // val = Math.min(props.max, Math.max(props.min, val)); // todo
44
+ val = Number(val.toFixed(Math.max(1, -Math.log10(stepSize / 10)))); // clip decimal places depending on step size
45
+
46
+ if(!this.props.disabled) this.props.onChange(val, false)
47
+ this.lastValue = val;
51
48
  }
52
49
  };
53
50
 
51
+ private accumulatedOffset = 0;
52
+
54
53
  render() {
55
54
  // const [dragging, setDragging] = React.useState(false)
56
55
 
57
56
  return (
58
- <div style={{cursor: !this.props.disabled ? 'ew-resize': 'auto', marginLeft: "6px", marginRight: "6px", marginTop: this.props.small ? "3px" : "6px", marginBottom: this.props.small ? "3px" : "6px"}}
59
- onMouseDown={(ev) => {
60
- // if(dragging) return
61
- if(this.props.disabled) return
62
- this.dragStartOffset = ev.clientX
63
- this.dragStartValue = this.props.value
64
- ev.stopPropagation()
65
- ev.preventDefault()
66
- this.cursor = document.documentElement.style.cursor
67
- document.documentElement.style.cursor = "ew-resize"
68
- document.addEventListener('mousemove', this.mouseMoveEvent)
69
- document.addEventListener('mouseup', this.mouseUpEvent)
70
- // setDragging(true)
71
- }}
57
+ <div
58
+ ref={this.divRef}
59
+ style={{cursor: !this.props.disabled ? 'ew-resize': 'auto', marginLeft: "6px", marginRight: "6px", marginTop: this.props.small ? "3px" : "6px", marginBottom: this.props.small ? "3px" : "6px"}}
60
+ onMouseDown={(ev) => {
61
+ // if(dragging) return
62
+ if(this.props.disabled) return
63
+ if (!this.divRef.current) return;
64
+
65
+ this.dragStartValue = this.props.value
66
+ this.accumulatedOffset = 0
67
+
68
+ this.cursor = document.documentElement.style.cursor
69
+ document.documentElement.style.cursor = "none"
70
+
71
+ // Create pointer lock manager
72
+ this.pointerLockManager = new PointerLockManager(this.divRef.current, {
73
+ onMove: this.handlePointerMove,
74
+ onLockChange: (locked) => {
75
+ if (!locked) {
76
+ this.removeEvents();
77
+ }
78
+ }
79
+ });
80
+
81
+ this.pointerLockManager.requestLock(ev.clientX, ev.clientY);
82
+ ev.stopPropagation()
83
+ ev.preventDefault()
84
+
85
+ // Add mouseup listener to release lock
86
+ const handleMouseUp = () => {
87
+ this.removeEvents();
88
+ document.removeEventListener('mouseup', handleMouseUp);
89
+ };
90
+ document.addEventListener('mouseup', handleMouseUp);
91
+
92
+ // setDragging(true)
93
+ }}
72
94
  >
73
95
  <Icon icon={this.props.icon} size={this.props.size} aria-disabled={this.props.disabled} />
74
96
  </div>
@@ -105,14 +105,14 @@ export class ExtendedNumericInput extends React.PureComponent<Props, IExtendedNu
105
105
  draggableIcon !== false ? <DraggableIcon icon={leftIcon ?? "variable"}
106
106
  size={16}
107
107
  disabled={props2.readOnly}
108
- small={props2.small}
108
+ small={props2.small || props2.size as any === 'small'}
109
109
  value={parseFloat(value ?? '0')}
110
110
  stepSize={props2.stepSize}
111
111
  onChange={(v, last) => {
112
112
  this.handleValueChange(v, v.toString(), null, last, true)
113
113
  }}/> : undefined
114
114
  )}
115
- // leftIcon={"variable"}
115
+ // leftIcon={draggableIcon ? undefined : leftIcon}
116
116
  buttonPosition={props2.buttonPosition ?? (props2.disabled ? "none" : "right")}
117
117
  allowNumericCharactersOnly={false}
118
118
  clampValueOnBlur={true}