uiconfig-blueprint 0.1.0-dev.12 → 0.1.0-dev.14

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 (165) hide show
  1. package/dist/ConfigObject.d.ts +3 -1
  2. package/dist/{allPaths-DtaFoocb.js → allPaths-DANRR6MZ.js} +5 -5
  3. package/dist/{allPaths-DtaFoocb.js.map → allPaths-DANRR6MZ.js.map} +1 -1
  4. package/dist/{allPathsLoader-B5mUU0us.js → allPathsLoader-BdHGVD6B.js} +4 -4
  5. package/dist/{allPathsLoader-B5mUU0us.js.map → allPathsLoader-BdHGVD6B.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/BPFileComponent.d.ts +12 -10
  10. package/dist/bpComponents/BPFolderComponent.d.ts +13 -4
  11. package/dist/bpComponents/BPPanelComponent.d.ts +3 -3
  12. package/dist/bpComponents/BPTextInputComponent.d.ts +4 -0
  13. package/dist/bpComponents/BPValueComponent.d.ts +2 -2
  14. package/dist/bpComponents/BPVectorInputComponent.d.ts +11 -5
  15. package/dist/bpComponents/InputGroup2.d.ts +25 -0
  16. package/dist/components/DialogContext.d.ts +10 -3
  17. package/dist/components/DraggableIcon.d.ts +4 -3
  18. package/dist/components/FileComponent.d.ts +13 -6
  19. package/dist/components/FormGroupComponent.d.ts +3 -2
  20. package/dist/components/InspectorStackComponent.d.ts +11 -2
  21. package/dist/index-6kveHKKU.js +695 -0
  22. package/dist/index-6kveHKKU.js.map +1 -0
  23. package/dist/index-D9WNL8Mc.js +695 -0
  24. package/dist/index-D9WNL8Mc.js.map +1 -0
  25. package/dist/index-t3WzvX5M.js +13501 -0
  26. package/dist/index-t3WzvX5M.js.map +1 -0
  27. package/dist/index.js +28 -41
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +2 -2
  30. package/dist/lib.d.ts +2 -3
  31. package/dist/{splitPathsBySizeLoader-BGjtD8Dg.js → splitPathsBySizeLoader-Bhwx_O-M.js} +5 -5
  32. package/dist/{splitPathsBySizeLoader-BGjtD8Dg.js.map → splitPathsBySizeLoader-Bhwx_O-M.js.map} +1 -1
  33. package/dist/utils/pointerLock.d.ts +44 -0
  34. package/docs/classes/UI.html +3 -3
  35. package/docs/classes/UiConfigRendererBlueprint.html +3 -3
  36. package/lib/css/renderer.css +35 -103
  37. package/lib/css/renderer.css.map +1 -1
  38. package/lib/esm/ConfigObject.d.ts +3 -1
  39. package/lib/esm/ConfigObject.js +5 -4
  40. package/lib/esm/ConfigObject.js.map +1 -1
  41. package/lib/esm/UiConfigRendererBlueprint.js +2 -1
  42. package/lib/esm/UiConfigRendererBlueprint.js.map +1 -1
  43. package/lib/esm/bpComponents/BPButtonComponent.js +1 -1
  44. package/lib/esm/bpComponents/BPButtonComponent.js.map +1 -1
  45. package/lib/esm/bpComponents/BPColorInputComponent.d.ts +1 -0
  46. package/lib/esm/bpComponents/BPColorInputComponent.js +17 -4
  47. package/lib/esm/bpComponents/BPColorInputComponent.js.map +1 -1
  48. package/lib/esm/bpComponents/BPComponent.d.ts +2 -0
  49. package/lib/esm/bpComponents/BPComponent.js +4 -4
  50. package/lib/esm/bpComponents/BPComponent.js.map +1 -1
  51. package/lib/esm/bpComponents/BPContainerComponent.d.ts +10 -2
  52. package/lib/esm/bpComponents/BPContainerComponent.js +4 -1
  53. package/lib/esm/bpComponents/BPContainerComponent.js.map +1 -1
  54. package/lib/esm/bpComponents/BPDropdownInputComponent.js +4 -3
  55. package/lib/esm/bpComponents/BPDropdownInputComponent.js.map +1 -1
  56. package/lib/esm/bpComponents/BPFileComponent.d.ts +12 -10
  57. package/lib/esm/bpComponents/BPFileComponent.js +10 -8
  58. package/lib/esm/bpComponents/BPFileComponent.js.map +1 -1
  59. package/lib/esm/bpComponents/BPFolderComponent.d.ts +13 -4
  60. package/lib/esm/bpComponents/BPFolderComponent.js +58 -13
  61. package/lib/esm/bpComponents/BPFolderComponent.js.map +1 -1
  62. package/lib/esm/bpComponents/BPInputComponent.js +1 -1
  63. package/lib/esm/bpComponents/BPInputComponent.js.map +1 -1
  64. package/lib/esm/bpComponents/BPPanelComponent.d.ts +3 -3
  65. package/lib/esm/bpComponents/BPPanelComponent.js +1 -1
  66. package/lib/esm/bpComponents/BPPanelComponent.js.map +1 -1
  67. package/lib/esm/bpComponents/BPTextInputComponent.d.ts +4 -0
  68. package/lib/esm/bpComponents/BPTextInputComponent.js +34 -3
  69. package/lib/esm/bpComponents/BPTextInputComponent.js.map +1 -1
  70. package/lib/esm/bpComponents/BPTreeComponent.d.ts +4 -4
  71. package/lib/esm/bpComponents/BPTreeComponent.js +2 -2
  72. package/lib/esm/bpComponents/BPTreeComponent.js.map +1 -1
  73. package/lib/esm/bpComponents/BPValueComponent.d.ts +2 -2
  74. package/lib/esm/bpComponents/BPValueComponent.js +5 -4
  75. package/lib/esm/bpComponents/BPValueComponent.js.map +1 -1
  76. package/lib/esm/bpComponents/BPVectorInputComponent.d.ts +11 -5
  77. package/lib/esm/bpComponents/BPVectorInputComponent.js +47 -6
  78. package/lib/esm/bpComponents/BPVectorInputComponent.js.map +1 -1
  79. package/lib/esm/bpComponents/InputGroup2.d.ts +25 -0
  80. package/lib/esm/bpComponents/InputGroup2.js +93 -0
  81. package/lib/esm/bpComponents/InputGroup2.js.map +1 -0
  82. package/lib/esm/components/ConfigurationPanelComponent.js +1 -1
  83. package/lib/esm/components/ConfigurationPanelComponent.js.map +1 -1
  84. package/lib/esm/components/DialogContext.d.ts +10 -3
  85. package/lib/esm/components/DialogContext.js +14 -13
  86. package/lib/esm/components/DialogContext.js.map +1 -1
  87. package/lib/esm/components/DraggableIcon.d.ts +4 -3
  88. package/lib/esm/components/DraggableIcon.js +41 -39
  89. package/lib/esm/components/DraggableIcon.js.map +1 -1
  90. package/lib/esm/components/ExtendedNumericInput.js +1 -1
  91. package/lib/esm/components/ExtendedNumericInput.js.map +1 -1
  92. package/lib/esm/components/FileComponent.d.ts +13 -6
  93. package/lib/esm/components/FileComponent.js +15 -6
  94. package/lib/esm/components/FileComponent.js.map +1 -1
  95. package/lib/esm/components/FormGroupComponent.d.ts +3 -2
  96. package/lib/esm/components/FormGroupComponent.js +1 -6
  97. package/lib/esm/components/FormGroupComponent.js.map +1 -1
  98. package/lib/esm/components/InspectorStackComponent.d.ts +11 -2
  99. package/lib/esm/components/InspectorStackComponent.js +14 -4
  100. package/lib/esm/components/InspectorStackComponent.js.map +1 -1
  101. package/lib/esm/components/NumericInput.js +3 -2
  102. package/lib/esm/components/NumericInput.js.map +1 -1
  103. package/lib/esm/components/TreeNode2.d.ts +1 -1
  104. package/lib/esm/components/TreeNode2.js +4 -2
  105. package/lib/esm/components/TreeNode2.js.map +1 -1
  106. package/lib/esm/components/treeTypes.d.ts +2 -1
  107. package/lib/esm/lib.d.ts +2 -3
  108. package/lib/esm/lib.js +2 -3
  109. package/lib/esm/lib.js.map +1 -1
  110. package/lib/esm/renderer.css.js +1 -1
  111. package/lib/esm/utils/pointerLock.d.ts +44 -0
  112. package/lib/esm/utils/pointerLock.js +215 -0
  113. package/lib/esm/utils/pointerLock.js.map +1 -0
  114. package/lib/esm/utils.js +6 -1
  115. package/lib/esm/utils.js.map +1 -1
  116. package/package.json +10 -12
  117. package/src/ConfigObject.tsx +11 -5
  118. package/src/UiConfigRendererBlueprint.tsx +1 -1
  119. package/src/bpComponents/BPButtonComponent.tsx +1 -1
  120. package/src/bpComponents/BPColorInputComponent.tsx +13 -4
  121. package/src/bpComponents/BPComponent.tsx +4 -3
  122. package/src/bpComponents/BPContainerComponent.tsx +20 -3
  123. package/src/bpComponents/BPDropdownInputComponent.tsx +4 -3
  124. package/src/bpComponents/BPFileComponent.tsx +29 -20
  125. package/src/bpComponents/BPFolderComponent.scss +11 -6
  126. package/src/bpComponents/BPFolderComponent.tsx +122 -24
  127. package/src/bpComponents/BPInputComponent.tsx +1 -0
  128. package/src/bpComponents/BPPanelComponent.tsx +4 -4
  129. package/src/bpComponents/BPTextInputComponent.tsx +38 -5
  130. package/src/bpComponents/BPValueComponent.tsx +4 -4
  131. package/src/bpComponents/BPVectorInputComponent.tsx +80 -10
  132. package/src/bpComponents/InputGroup2.tsx +175 -0
  133. package/src/bpComponents/index.scss +0 -1
  134. package/src/components/ConfigurationPanelComponent.tsx +2 -2
  135. package/src/components/DialogContext.tsx +20 -12
  136. package/src/components/DraggableIcon.tsx +71 -49
  137. package/src/components/ExtendedNumericInput.tsx +2 -2
  138. package/src/components/FileComponent.tsx +37 -18
  139. package/src/components/FormGroupComponent.tsx +8 -4
  140. package/src/components/InspectorStackComponent.tsx +20 -7
  141. package/src/components/NumericInput.tsx +4 -5
  142. package/src/components/common.scss +1 -1
  143. package/src/lib.ts +2 -3
  144. package/src/renderer.scss +30 -8
  145. package/src/utils/PointerLockManager.md +334 -0
  146. package/src/utils/pointerLock.ts +264 -0
  147. package/src/utils.ts +8 -4
  148. package/dist/bpComponents/BPTreeComponent.d.ts +0 -46
  149. package/dist/bpComponents/BPTreeFolderComponent.d.ts +0 -10
  150. package/dist/components/Tree2.d.ts +0 -52
  151. package/dist/components/TreeNode2.d.ts +0 -43
  152. package/dist/components/treeTypes.d.ts +0 -18
  153. package/dist/index-BPcAfGYu.js +0 -13583
  154. package/dist/index-BPcAfGYu.js.map +0 -1
  155. package/dist/index-BsXaCp6n.js +0 -671
  156. package/dist/index-BsXaCp6n.js.map +0 -1
  157. package/dist/index-CIFbDQFr.js +0 -671
  158. package/dist/index-CIFbDQFr.js.map +0 -1
  159. package/src/bpComponents/BPTreeComponent.scss +0 -3
  160. package/src/bpComponents/BPTreeComponent.tsx +0 -244
  161. package/src/bpComponents/BPTreeFolderComponent.tsx +0 -31
  162. package/src/components/Tree2.tsx +0 -344
  163. package/src/components/TreeNode2.tsx +0 -192
  164. package/src/components/tree2.scss +0 -69
  165. package/src/components/treeTypes.ts +0 -97
@@ -1,15 +1,22 @@
1
- import React, {useEffect, useRef} from "react";
1
+ import React, {JSX, ReactNode, useEffect, useRef} from "react";
2
2
  import {Button, ControlGroup, FileInput, HTMLSelect, InputGroup} from "@blueprintjs/core";
3
3
  import {BPFileComponentState} from "../bpComponents/BPFileComponent";
4
4
  import {useLoadingStateKey} from './loadingState'
5
5
 
6
- export interface FileComponentProps {
7
- state: BPFileComponentState
8
- onChange: (state: Partial<BPFileComponentState>)=>Promise<void>
9
- previewSlot?: React.ReactNode,
6
+ export interface FileComponentProps<TSV = never> {
7
+ state: BPFileComponentState<TSV>
8
+ onChange: (state: Partial<BPFileComponentState<TSV>>)=>Promise<void>
9
+ previewSlot?: ReactNode,
10
10
  uuid?: string
11
+ AssetPicker?: (props: {
12
+ state: BPFileComponentState<TSV>
13
+ onChange: (state: Partial<BPFileComponentState<TSV>>)=>Promise<void>
14
+ className?: string
15
+ style?: React.CSSProperties
16
+ })=>JSX.Element
17
+ disableFileInput?: boolean // todo
11
18
  }
12
- export const FileComponent: React.FC<FileComponentProps> = ({state, onChange, previewSlot})=>{
19
+ export const FileComponent = <TSV,>({state, onChange, previewSlot, AssetPicker}: FileComponentProps<TSV>)=>{
13
20
  const fileInputRef = useRef<HTMLInputElement>()
14
21
  const textInputRef = useRef<HTMLInputElement>()
15
22
  // console.log('render file component', state)
@@ -28,8 +35,15 @@ export const FileComponent: React.FC<FileComponentProps> = ({state, onChange, pr
28
35
  }
29
36
  if(!fileElement) return;
30
37
  // console.log(val)
38
+
39
+ // it can be Blob also because of GLTF loaded...
40
+ const file = val instanceof File ? val :
41
+ typeof val === 'string' || typeof (val as any as Blob).arrayBuffer === 'function' ?
42
+ new File([val as string | Blob], (val as any).name||('file'+((val as any).ext?'.'+(val as any).ext:'')))
43
+ : null
44
+ if(!file) return
31
45
  const dataTransfer = new DataTransfer();
32
- dataTransfer.items.add(val instanceof File ? val : new File([val], (val as any).name||('file'+((val as any).ext?'.'+(val as any).ext:'')))); // it can be Blob also because of GLTF loaded...
46
+ dataTransfer.items.add(file);
33
47
  fileElement!.files = dataTransfer.files
34
48
  }, [state.value]);
35
49
  // useEffect(() => {
@@ -38,6 +52,9 @@ export const FileComponent: React.FC<FileComponentProps> = ({state, onChange, pr
38
52
 
39
53
  // const hasValue = !!state.value || !!state.preview
40
54
 
55
+ const dropdownOptions = ['url', 'file']
56
+ if(AssetPicker) dropdownOptions.push('asset')
57
+
41
58
  const {loadingState, updateLoading} = useLoadingStateKey()
42
59
 
43
60
  return (
@@ -46,8 +63,8 @@ export const FileComponent: React.FC<FileComponentProps> = ({state, onChange, pr
46
63
  <>
47
64
  {previewSlot}
48
65
  <Button icon="small-cross"
49
- minimal={false}
50
- small={true}
66
+ size={"small"}
67
+ variant={"solid"}
51
68
  disabled={state.disabled}
52
69
  intent={"danger"}
53
70
  style={{position: "absolute", top: 0, right: 0, opacity: 0.7}}
@@ -55,25 +72,25 @@ export const FileComponent: React.FC<FileComponentProps> = ({state, onChange, pr
55
72
  onClick={() => updateLoading(onChange({value: null}))}></Button>
56
73
  </>
57
74
  )}
58
- {(!state.preview || !previewSlot) && <ControlGroup fill={false} vertical={false} style={{width: "100%"}}>
59
- {!state.readOnly && !state.value ? (<HTMLSelect options={['url', 'file']} minimal={true} fill={false}
75
+ <ControlGroup fill={false} vertical={false} style={{width: "100%"}}>
76
+ {!state.readOnly && !state.value ? (<HTMLSelect options={dropdownOptions} minimal={true} fill={false}
60
77
  disabled={state.disabled}
61
78
  className={"file-component-select"}
62
79
  value={state.mode} onChange={(e) => {
63
- onChange({mode: e.target.value as 'url' | 'file'})
80
+ onChange({mode: e.target.value as BPFileComponentState['mode']})
64
81
  }}/>) : null}
65
82
  {state.mode === 'url' ? (
66
83
  <InputGroup style={{flexGrow: "1", flexShrink: "1"}} inputRef={textInputRef as any} type="url"
67
84
  defaultValue={typeof state.value === 'string' ? state.value : ''}
68
85
  rightElement={(
69
- <Button disabled={state.readOnly} minimal={true} icon="arrow-right" onClick={() => {
86
+ <Button disabled={state.readOnly} variant={"minimal"} icon="arrow-right" onClick={() => {
70
87
  onChange({mode: 'url', value: textInputRef.current?.value ?? ''})
71
88
  }}></Button>
72
89
  )}
73
90
  disabled={state.disabled} readOnly={state.readOnly}
74
91
  onChange={(_) => {
75
92
  }} placeholder="https://example.com/file.png"/>
76
- ) : (
93
+ ) : state.mode === 'file' ? (
77
94
  <FileInput inputProps={{ref: fileInputRef as any}}
78
95
  style={{flexGrow: "1", flexShrink: "1", minWidth: "50px"}}
79
96
  text={(state.value as File)?.name || 'No file'}
@@ -88,15 +105,17 @@ export const FileComponent: React.FC<FileComponentProps> = ({state, onChange, pr
88
105
  onChange={() => {
89
106
  onChange({mode: 'file', value: fileInputRef.current?.files?.[0] ?? null})
90
107
  }} className="inputGroupFile"/>
91
- )}
92
- {!state.readOnly && state.value && (
93
- <Button minimal={true} icon="small-cross"
108
+ ) : state.mode === 'asset' && AssetPicker ? (
109
+ <AssetPicker state={state} onChange={onChange} className="inputGroupFile"/>
110
+ ) : null}
111
+ {!state.readOnly && state.value && !state.preview && (
112
+ <Button variant={"minimal"} icon="small-cross"
94
113
  disabled={state.disabled}
95
114
  loading={loadingState}
96
115
  onClick={() => updateLoading(onChange({value: null}))
97
116
  }></Button>
98
117
  )}
99
- </ControlGroup>}
118
+ </ControlGroup>
100
119
  </div>
101
120
  )
102
121
  }
@@ -1,17 +1,21 @@
1
1
  import {FormGroup} from "@blueprintjs/core";
2
- import {PropsWithChildren} from "react";
2
+ import {CSSProperties, PropsWithChildren, ReactNode} from "react";
3
3
 
4
- export function FormGroupComponent(props: PropsWithChildren<{ label: string, flexBasis?: string, disabled?: boolean }>) {
4
+ export function FormGroupComponent(props: PropsWithChildren<{
5
+ label: string|ReactNode, flexBasis?: string, disabled?: boolean,
6
+ style?: CSSProperties
7
+ }>) {
5
8
  return (
6
9
  <FormGroup className="xPaddedContent folderContent" contentClassName="formGroupContent"
7
10
  style={{
8
11
  justifyContent: "space-between",
9
12
  marginTop: "2px",
10
13
  marginBottom: "2px",
11
- flexBasis: props.flexBasis ?? "50%"
14
+ flexBasis: props.flexBasis ?? "50%",
15
+ ...props.style,
12
16
  }}
13
17
  // helperText="Helper text with details..."
14
- label={(<span title={props.label}>{props.label}</span>)}
18
+ label={typeof props.label !== 'string' ? props.label : (<span title={props.label}>{props.label}</span>)}
15
19
  inline={true}
16
20
  disabled={props.disabled}
17
21
  // labelInfo="(required)"
@@ -2,12 +2,14 @@ import React from "react";
2
2
  import {Card, Panel, PanelStack2} from "@blueprintjs/core";
3
3
  import {ConfigObject, ConfigProps} from "../ConfigObject";
4
4
  import {UiObjectConfig} from 'uiconfig.js'
5
- import {UiConfigRendererContext} from '../bpComponents/BPComponent'
5
+ import {UiConfigRendererBaseBp, UiConfigRendererContext} from '../bpComponents/BPComponent'
6
+ import {getOrCall, ValOrFunc} from "ts-browser-helpers";
6
7
 
7
8
  // import {ViewerAppContext} from "./ViewerAppComponent";
8
9
 
9
- export function InspectorStackComponent({config, className}: { config: UiObjectConfig<any, 'panel'>, className?: string }) {
10
- const renderer = React.useContext(UiConfigRendererContext)
10
+ export function useConfigToStackItem(config: UiObjectConfig<any, 'panel'>, renderer?: UiConfigRendererBaseBp){
11
+ renderer = renderer ?? React.useContext(UiConfigRendererContext)
12
+ if(!renderer) throw new Error('No renderer provided or found in context')
11
13
  const stackItem = React.useCallback(() => {
12
14
  return {
13
15
  props: {config: config},
@@ -20,13 +22,24 @@ export function InspectorStackComponent({config, className}: { config: UiObjectC
20
22
  </ul>
21
23
  )
22
24
  },
23
- title: renderer.methods.getLabel(config)
25
+ title: renderer!.methods.getLabel(config)
24
26
  } as Panel<{ config: UiObjectConfig }>
25
27
  }, [config])
26
- const [currentPanelStack, setCurrentPanelStack] = React.useState<Array<Panel<{ config: UiObjectConfig }>>>([stackItem()]);
28
+ return stackItem
29
+ }
30
+ export type InspectorStackItem = ValOrFunc<Panel<{ config: UiObjectConfig }>>
31
+ function getStackItem(i: InspectorStackItem){
32
+ const r = getOrCall(i)
33
+ return r?[r] : []
34
+ }
35
+ export function InspectorStackComponent({stackItem, className}: {
36
+ stackItem: InspectorStackItem,
37
+ className?: string
38
+ }) {
39
+ const [currentPanelStack, setCurrentPanelStack] = React.useState<Array<Panel<{ config: UiObjectConfig }>>>(getStackItem(stackItem));
27
40
  React.useEffect(() => {
28
- // console.warn('change', config)
29
- setCurrentPanelStack([stackItem()])
41
+ // console.warn('change', stackItem)
42
+ setCurrentPanelStack(getStackItem(stackItem))
30
43
  }, [setCurrentPanelStack, stackItem])
31
44
 
32
45
  return (
@@ -27,7 +27,6 @@ import {
27
27
  ControlGroup,
28
28
  DISPLAYNAME_PREFIX,
29
29
  type HTMLInputProps,
30
- InputGroup,
31
30
  Intent,
32
31
  Position,
33
32
  refHandler,
@@ -46,6 +45,7 @@ import {
46
45
  sanitizeNumericInput,
47
46
  toLocaleString,
48
47
  } from "@blueprintjs/core/src/components/forms/numericInputUtils";
48
+ import {InputGroup2} from "../bpComponents/InputGroup2";
49
49
 
50
50
  export interface NumericInputProps extends InputSharedProps {
51
51
  /**
@@ -439,8 +439,8 @@ export class NumericInput extends AbstractPureComponent<HTMLInputProps & Numeric
439
439
  const valueAsNumber = this.getCurrentValueAsNumber();
440
440
 
441
441
  return (
442
- <InputGroup
443
- asyncControl={this.props.asyncControl}
442
+ <InputGroup2
443
+ // asyncControl={this.props.asyncControl}
444
444
  autoComplete="off"
445
445
  id={this.numericInputId}
446
446
  role={this.props.allowNumericCharactersOnly ? "spinbutton" : undefined}
@@ -451,7 +451,6 @@ export class NumericInput extends AbstractPureComponent<HTMLInputProps & Numeric
451
451
  intent={this.state.currentImeInputInvalid ? Intent.DANGER : this.props.intent}
452
452
  inputClassName={this.props.inputClassName}
453
453
  inputRef={this.inputRef}
454
- large={this.props.large}
455
454
  leftElement={this.props.leftElement}
456
455
  leftIcon={this.props.leftIcon}
457
456
  onFocus={this.handleInputFocus}
@@ -463,7 +462,7 @@ export class NumericInput extends AbstractPureComponent<HTMLInputProps & Numeric
463
462
  onPaste={this.handleInputPaste}
464
463
  onValueChange={this.handleInputChange}
465
464
  rightElement={this.props.rightElement}
466
- small={this.props.small}
465
+ size={this.props.small ? "small" : this.props.large ? "large" : "medium"}
467
466
  value={this.state.value}
468
467
  />
469
468
  );
@@ -1,4 +1,3 @@
1
- @import './tree2.scss';
2
1
 
3
2
  .bpButton {
4
3
  display: flex;
@@ -42,3 +41,4 @@
42
41
  }
43
42
  }
44
43
  }
44
+
package/src/lib.ts CHANGED
@@ -13,7 +13,7 @@ export * from './components/VisualStyleContext'
13
13
  export * from './components/DialogContext'
14
14
  export * from './components/loadingState'
15
15
  export * from './components/AppToaster'
16
- export * from "./components/treeTypes";
16
+ export * from './bpComponents/InputGroup2'
17
17
  export * from './bpComponents/BPButtonComponent'
18
18
  export * from './bpComponents/BPColorInputComponent'
19
19
  export * from './bpComponents/BPComponent'
@@ -28,9 +28,8 @@ export * from './bpComponents/BPPanelComponent'
28
28
  export * from './bpComponents/BPSliderInputComponent'
29
29
  export * from './bpComponents/BPTextInputComponent'
30
30
  export * from './bpComponents/BPToggleInputComponent'
31
- export * from './bpComponents/BPTreeComponent'
32
- export * from './bpComponents/BPTreeFolderComponent'
33
31
  export * from './bpComponents/BPValueComponent'
34
32
  export * from './bpComponents/BPVectorInputComponent'
35
33
  export * from "./bpComponents/NumberUnits";
36
34
  export * from "./bpComponents/GetNumberTransformFunctions";
35
+ export {InputGroup2} from "./bpComponents/InputGroup2";
package/src/renderer.scss CHANGED
@@ -14,6 +14,15 @@
14
14
  @import "blueprint-styler/base/blueprint";
15
15
  @import "blueprint-styler/base/tokens.scss";
16
16
 
17
+ .bp5-vars, :root {
18
+ //--pt-icon-color: var(--pt-text-color);
19
+ }
20
+
21
+ .bp5-dark {
22
+ --pt-icon-color: var(--pt-text-color);
23
+ --menu-background-color: var(--tooltip-background-color);
24
+ }
25
+
17
26
  :root.bpx-bpv3{
18
27
  @import "blueprint-styler/overrides/bpv3/custom-tokens.scss";
19
28
  @import "blueprint-styler/overrides/bpv3/override";
@@ -117,14 +126,14 @@
117
126
  --background-color-transition-time: 0.2s;
118
127
  --background-color-transition: background-color var(--background-color-transition-time) ease-in-out;
119
128
  }
120
- .bp5-panel-stack-view {
129
+ .bp5-panel-stack2-view {
121
130
  background-color: $light-gray4 !important;
122
131
  transition: var(--background-color-transition);
123
132
  }
124
133
 
125
134
  .bp5-dark{
126
- .bp5-panel-stack-view {
127
- background-color: $dark-gray2 !important;
135
+ .bp5-panel-stack2-view {
136
+ background-color: $dark-gray1 !important;
128
137
  }
129
138
  }
130
139
 
@@ -232,10 +241,6 @@
232
241
  }
233
242
  }
234
243
 
235
- .bp5-panel-stack2-view{
236
- background: transparent;
237
- }
238
-
239
244
  .bp5-slider-handle{
240
245
  border-radius: 100%;
241
246
  }
@@ -253,7 +258,7 @@
253
258
  }
254
259
 
255
260
  .bp5-dark {
256
- --slider-progress-color: hsla(var(--gray4-hsl),0.15);
261
+ --slider-progress-color: hsla(var(--gray4-hsl), 0.15);
257
262
  }
258
263
 
259
264
  .bp5-slider-progress, .bp5-slider-track{
@@ -265,3 +270,20 @@
265
270
  background-color: hsla(var(--pt-intent-primary-hsl), 1) !important;
266
271
  //backdrop-filter: blur(4px);
267
272
  }
273
+
274
+ .bp5-button.bp5-small {
275
+ .bp5-button-text{
276
+ font-size: $pt-font-size-small;
277
+ padding: calc($pt-grid-size * 0.5) 0 calc($pt-grid-size * 0.5) 0;
278
+ }
279
+ .bp5-icon > svg{
280
+ width: $pt-font-size;
281
+ height: $pt-font-size;
282
+ }
283
+ }
284
+
285
+ // todo not sure why its required again, its also in blueprint...
286
+ .bp5-dark .bp5-divider{
287
+ border-color:rgba(255, 255, 255, 0.2);
288
+ }
289
+
@@ -0,0 +1,334 @@
1
+ # PointerLockManager
2
+
3
+ A utility class for implementing Unity-style cursor wrap-around behavior using the Pointer Lock API. This allows for infinite dragging without cursor constraints.
4
+
5
+ ## Overview
6
+
7
+ The `PointerLockManager` provides a seamless way to capture the mouse pointer, hide the real cursor, display a fake cursor, and implement cursor wrap-around at screen edges. This is particularly useful for draggable UI elements that need unlimited range of motion.
8
+
9
+ ## Features
10
+
11
+ - 🔒 **Pointer Lock API integration** - Captures mouse for unlimited movement
12
+ - 🎯 **Fake cursor rendering** - Shows a custom cursor while the real one is hidden
13
+ - 🔄 **Screen edge wrap-around** - Cursor automatically wraps to opposite edge
14
+ - 📍 **Movement tracking** - Provides both movement deltas and absolute cursor position
15
+ - 🧹 **Automatic cleanup** - Properly releases pointer lock and cleans up resources
16
+
17
+ ## Installation
18
+
19
+ The PointerLockManager is part of the internal utils package:
20
+
21
+ ```typescript
22
+ import { PointerLockManager } from '../utils/pointerLock';
23
+ ```
24
+
25
+ ## Basic Usage
26
+
27
+ ### 1. Setup
28
+
29
+ Create a reference to the element that will request pointer lock:
30
+
31
+ ```typescript
32
+ import * as React from 'react';
33
+ import { PointerLockManager } from '../utils/pointerLock';
34
+
35
+ function MyComponent() {
36
+ const pointerLockManagerRef = React.useRef<PointerLockManager | null>(null);
37
+ const elementRef = React.useRef<HTMLDivElement>(null);
38
+
39
+ // ... rest of component
40
+ }
41
+ ```
42
+
43
+ ### 2. Initialize on Mouse Down
44
+
45
+ Request pointer lock when the user starts interacting:
46
+
47
+ ```typescript
48
+ const handleMouseDown = (ev: React.MouseEvent) => {
49
+ if (!elementRef.current) return;
50
+
51
+ // Create the pointer lock manager
52
+ pointerLockManagerRef.current = new PointerLockManager(
53
+ elementRef.current,
54
+ {
55
+ onMove: handlePointerMove,
56
+ onLockChange: (locked) => {
57
+ if (!locked) {
58
+ cleanup();
59
+ }
60
+ }
61
+ }
62
+ );
63
+
64
+ // Request lock at current cursor position
65
+ pointerLockManagerRef.current.requestLock(ev.clientX, ev.clientY);
66
+ };
67
+ ```
68
+
69
+ ### 3. Handle Movement
70
+
71
+ Implement the movement handler to track cursor changes:
72
+
73
+ ```typescript
74
+ const handlePointerMove = (
75
+ movementX: number,
76
+ movementY: number,
77
+ cursorX: number,
78
+ cursorY: number
79
+ ) => {
80
+ // movementX, movementY: delta movement since last event
81
+ // cursorX, cursorY: absolute fake cursor position on screen
82
+
83
+ console.log(`Movement: ${movementX}, ${movementY}`);
84
+ console.log(`Cursor at: ${cursorX}, ${cursorY}`);
85
+
86
+ // Apply movement to your logic
87
+ updateValue(movementX);
88
+ };
89
+ ```
90
+
91
+ ### 4. Release Lock
92
+
93
+ Clean up when interaction ends:
94
+
95
+ ```typescript
96
+ const cleanup = () => {
97
+ if (pointerLockManagerRef.current) {
98
+ pointerLockManagerRef.current.releaseLock();
99
+ pointerLockManagerRef.current = null;
100
+ }
101
+ };
102
+
103
+ // Call cleanup on mouse up
104
+ onMouseUp={() => {
105
+ cleanup();
106
+ }}
107
+ ```
108
+
109
+ ## Complete Example
110
+
111
+ Here's a complete example of a draggable number input:
112
+
113
+ ```typescript
114
+ import * as React from 'react';
115
+ import { PointerLockManager } from '../utils/pointerLock';
116
+
117
+ interface DraggableNumberInputProps {
118
+ value: number;
119
+ onChange: (value: number) => void;
120
+ }
121
+
122
+ export function DraggableNumberInput({ value, onChange }: DraggableNumberInputProps) {
123
+ const pointerLockManagerRef = React.useRef<PointerLockManager | null>(null);
124
+ const divRef = React.useRef<HTMLDivElement>(null);
125
+ const dragStartValueRef = React.useRef(0);
126
+ const accumulatedOffsetRef = React.useRef(0);
127
+
128
+ const handlePointerMove = React.useCallback(
129
+ (movementX: number, _movementY: number, _cursorX: number, _cursorY: number) => {
130
+ // Accumulate horizontal movement
131
+ accumulatedOffsetRef.current += movementX;
132
+
133
+ // Calculate new value
134
+ const newValue = dragStartValueRef.current + accumulatedOffsetRef.current * 0.1;
135
+
136
+ // Update parent
137
+ onChange(newValue);
138
+ },
139
+ [onChange]
140
+ );
141
+
142
+ const endDrag = React.useCallback(() => {
143
+ if (pointerLockManagerRef.current) {
144
+ pointerLockManagerRef.current.releaseLock();
145
+ pointerLockManagerRef.current = null;
146
+ }
147
+
148
+ document.documentElement.style.cursor = 'auto';
149
+ document.removeEventListener('mouseup', endDrag);
150
+ }, []);
151
+
152
+ const startDrag = React.useCallback(
153
+ (ev: React.MouseEvent) => {
154
+ if (!divRef.current) return;
155
+
156
+ dragStartValueRef.current = value;
157
+ accumulatedOffsetRef.current = 0;
158
+
159
+ // Hide real cursor
160
+ document.documentElement.style.cursor = 'none';
161
+
162
+ // Create pointer lock manager
163
+ pointerLockManagerRef.current = new PointerLockManager(divRef.current, {
164
+ onMove: handlePointerMove,
165
+ onLockChange: (locked) => {
166
+ if (!locked) {
167
+ endDrag();
168
+ }
169
+ }
170
+ });
171
+
172
+ pointerLockManagerRef.current.requestLock(ev.clientX, ev.clientY);
173
+
174
+ this.pointerLockManager = null;
175
+ }
176
+
177
+ document.documentElement.style.cursor = 'auto';
178
+ document.removeEventListener('mouseup', this.endDrag);
179
+ };
180
+
181
+ render() {
182
+ return (
183
+ <div
184
+ ref={this.divRef}
185
+ onMouseDown={this.startDrag}
186
+ style={{ cursor: 'ew-resize' }}
187
+ >
188
+ Value: {this.props.value.toFixed(2)}
189
+ </div>
190
+ );
191
+ }
192
+ }
193
+ ```
194
+
195
+ ## API Reference
196
+
197
+ ### Constructor
198
+
199
+ ```typescript
200
+ constructor(element: HTMLElement, options: PointerLockOptions)
201
+ ```
202
+
203
+ **Parameters:**
204
+ - `element`: The HTML element that will request pointer lock
205
+ - `options`: Configuration object
206
+
207
+ ### PointerLockOptions
208
+
209
+ ```typescript
210
+ interface PointerLockOptions {
211
+ onMove: (movementX: number, movementY: number, cursorX: number, cursorY: number) => void;
212
+ onLockChange?: (locked: boolean) => void;
213
+ }
214
+ ```
215
+
216
+ **Properties:**
217
+ - `onMove`: Callback fired on mouse movement
218
+ - `movementX`: Horizontal movement delta (pixels)
219
+ - `movementY`: Vertical movement delta (pixels)
220
+ - `cursorX`: Absolute X position of fake cursor (pixels)
221
+ - `cursorY`: Absolute Y position of fake cursor (pixels)
222
+ - `onLockChange`: Optional callback when lock state changes
223
+ - `locked`: Whether pointer is currently locked
224
+
225
+ ### Methods
226
+
227
+ #### `requestLock(initialX: number, initialY: number): void`
228
+
229
+ Requests pointer lock and shows the fake cursor.
230
+
231
+ **Parameters:**
232
+ - `initialX`: Initial X position for fake cursor
233
+ - `initialY`: Initial Y position for fake cursor
234
+
235
+ **Example:**
236
+ ```typescript
237
+ manager.requestLock(event.clientX, event.clientY);
238
+ ```
239
+
240
+ #### `releaseLock(): void`
241
+
242
+ Releases pointer lock and hides the fake cursor. Automatically called when the user presses ESC.
243
+
244
+ **Example:**
245
+ ```typescript
246
+ manager.releaseLock();
247
+ ```
248
+
249
+ #### `isPointerLocked(): boolean`
250
+
251
+ Returns whether the pointer is currently locked.
252
+
253
+ **Returns:** `true` if locked, `false` otherwise
254
+
255
+ **Example:**
256
+ ```typescript
257
+ if (manager.isPointerLocked()) {
258
+ console.log('Pointer is locked');
259
+ }
260
+ ```
261
+
262
+ ## Cursor Wrap-Around Behavior
263
+
264
+ When the fake cursor reaches the edge of the screen, it automatically wraps to the opposite side:
265
+
266
+ - **Left edge** → wraps to right edge
267
+ - **Right edge** → wraps to left edge
268
+ - **Top edge** → wraps to bottom edge
269
+ - **Bottom edge** → wraps to top edge
270
+
271
+ This provides infinite dragging space, similar to Unity's inspector fields.
272
+
273
+ ## Fake Cursor
274
+
275
+ The fake cursor is a singleton instance shared across all `PointerLockManager` instances. It:
276
+
277
+ - Appears as a white arrow with black stroke
278
+ - Has `pointer-events: none` to not interfere with interactions
279
+ - Has maximum z-index (999999) to stay on top
280
+ - Is automatically managed (shown/hidden) by the manager
281
+
282
+ ## Best Practices
283
+
284
+ 1. **Always clean up**: Make sure to call `releaseLock()` when done
285
+ 2. **Listen for ESC**: The browser will release pointer lock when ESC is pressed, handle this in `onLockChange`
286
+ 3. **Store reference**: Keep the manager instance as a class property
287
+ 4. **Reset state**: Reset your drag state when pointer lock is released
288
+ 5. **Hide real cursor**: Set `cursor: 'none'` on a parent element when locking
289
+
290
+ ## Browser Compatibility
291
+
292
+ The Pointer Lock API is supported in all modern browsers:
293
+ - Chrome/Edge 37+
294
+ - Firefox 50+
295
+ - Safari 10.1+
296
+
297
+ ## Limitations
298
+
299
+ - User can exit pointer lock by pressing ESC
300
+ - Some browsers may show a notification when pointer lock is activated
301
+ - Pointer lock can only be requested in response to user interaction (e.g., click)
302
+ - Only one element can have pointer lock at a time
303
+
304
+ ## Troubleshooting
305
+
306
+ ### Pointer lock not activating
307
+
308
+ **Problem:** `requestLock()` is called but nothing happens.
309
+
310
+ **Solution:** Ensure the call is made in response to a user gesture (like a mouse click).
311
+
312
+ ### Fake cursor not showing
313
+
314
+ **Problem:** Pointer locks but no cursor appears.
315
+
316
+ **Solution:** Check that the element is properly mounted in the DOM before requesting lock.
317
+
318
+ ### Lock releases immediately
319
+
320
+ **Problem:** Pointer lock is released right after requesting.
321
+
322
+ **Solution:** Check browser console for security errors. Ensure the element is visible and focusable.
323
+
324
+ ### Movement feels wrong
325
+
326
+ **Problem:** Movement direction or sensitivity is incorrect.
327
+
328
+ **Solution:** Adjust the movement multiplier in your `onMove` handler. You may need to negate or scale the values.
329
+
330
+ ## See Also
331
+
332
+ - [Pointer Lock API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API)
333
+ - [DraggableIcon Component](../components/DraggableIcon.tsx) - Reference implementation
334
+