lunchboxjs 0.1.4018 → 0.2.1001-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/lunchboxjs.js +1739 -1670
  2. package/dist/lunchboxjs.min.js +1 -1
  3. package/dist/lunchboxjs.module.js +1694 -1667
  4. package/extras/OrbitControlsWrapper.vue +5 -7
  5. package/package.json +15 -4
  6. package/src/components/LunchboxEventHandlers.tsx +237 -0
  7. package/src/components/LunchboxWrapper/LunchboxScene.tsx +8 -0
  8. package/src/components/LunchboxWrapper/LunchboxWrapper.tsx +341 -0
  9. package/src/components/LunchboxWrapper/prepCanvas.ts +27 -21
  10. package/src/components/LunchboxWrapper/resizeCanvas.ts +13 -12
  11. package/src/components/autoGeneratedComponents.ts +1 -1
  12. package/src/components/index.ts +2 -4
  13. package/src/core/createNode.ts +2 -18
  14. package/src/core/extend.ts +1 -1
  15. package/src/core/index.ts +0 -3
  16. package/src/core/instantiateThreeObject/index.ts +7 -2
  17. package/src/core/instantiateThreeObject/processProps.ts +1 -1
  18. package/src/core/interaction.ts +55 -0
  19. package/src/core/minidom.ts +5 -9
  20. package/src/core/update.ts +92 -53
  21. package/src/core/updateObjectProp.ts +5 -14
  22. package/src/index.ts +270 -76
  23. package/src/keys.ts +25 -0
  24. package/src/nodeOps/createElement.ts +2 -5
  25. package/src/nodeOps/index.ts +70 -57
  26. package/src/nodeOps/insert.ts +11 -32
  27. package/src/nodeOps/remove.ts +1 -17
  28. package/src/types.ts +34 -10
  29. package/src/utils/index.ts +11 -4
  30. package/dist/.DS_Store +0 -0
  31. package/src/.DS_Store +0 -0
  32. package/src/components/LunchboxWrapper/LunchboxWrapper.ts +0 -312
  33. package/src/components/catalogue.ts +0 -3
  34. package/src/core/.DS_Store +0 -0
  35. package/src/core/allNodes.ts +0 -4
  36. package/src/core/ensure.ts +0 -203
  37. package/src/core/interaction/index.ts +0 -102
  38. package/src/core/interaction/input.ts +0 -4
  39. package/src/core/interaction/interactables.ts +0 -14
  40. package/src/core/interaction/setupAutoRaycaster.ts +0 -224
  41. package/src/core/start.ts +0 -11
@@ -3,7 +3,6 @@ import {
3
3
  isLunchboxRootNode,
4
4
  isLunchboxStandardNode,
5
5
  } from '../utils'
6
- import { ensureRootNode, ensuredScene } from '../core'
7
6
  import { MiniDom } from '../core/minidom'
8
7
  import { Lunch } from '..'
9
8
 
@@ -12,9 +11,12 @@ export const insert = (
12
11
  parent: MiniDom.RendererBaseNode | null,
13
12
  anchor?: MiniDom.RendererBaseNode | null
14
13
  ) => {
14
+ if (!parent) {
15
+ throw new Error('missing parent')
16
+ }
15
17
  // add to parent tree node if we have one
16
- let effectiveParent = parent ?? ensureRootNode()
17
- effectiveParent.insertBefore(child, anchor)
18
+ // let effectiveParent = parent ?? ensureRootNode()
19
+ parent.insertBefore(child, anchor)
18
20
 
19
21
  // handle comment & text nodes
20
22
  if (child.metaType === 'commentMeta' || child.metaType === 'textMeta') {
@@ -33,54 +35,31 @@ export const insert = (
33
35
  // handle standard nodes
34
36
  if (isLunchboxStandardNode(child)) {
35
37
  // let effectiveParent = parent
36
- let effectiveParentNodeType = effectiveParent.metaType
38
+ let effectiveParentNodeType = parent.metaType
37
39
 
38
40
  if (
39
41
  effectiveParentNodeType === 'textMeta' ||
40
42
  effectiveParentNodeType === 'commentMeta'
41
43
  ) {
42
- const path = effectiveParent.getPath() as MiniDom.RendererBaseNode[]
44
+ const path = parent.getPath() as MiniDom.RendererBaseNode[]
43
45
  for (let i = path.length - 1; i >= 0; i--) {
44
46
  if (
45
47
  path[i].metaType !== 'textMeta' &&
46
48
  path[i].metaType !== 'commentMeta'
47
49
  ) {
48
- effectiveParent = path[i]
50
+ parent = path[i]
49
51
  break
50
52
  }
51
53
  }
52
54
  }
53
55
 
54
- // add to scene if parent is the wrapper node
55
56
  if (
56
- child.metaType === 'standardMeta' &&
57
- child.type !== 'scene' &&
58
- isLunchboxRootNode(effectiveParent)
59
- ) {
60
- // ensure scene exists
61
- const sceneNode = ensuredScene.value
62
-
63
- if (sceneNode.instance && child) {
64
- sceneNode.addChild(child)
65
- }
66
- if (
67
- child.instance &&
68
- child.instance.isObject3D &&
69
- sceneNode.instance
70
- ) {
71
- if (sceneNode !== child) {
72
- sceneNode.instance.add(child.instance)
73
- }
74
- }
75
- }
76
- // add to hierarchy otherwise
77
- else if (
78
57
  isLunchboxStandardNode(child) &&
79
58
  child.instance?.isObject3D &&
80
- isLunchboxStandardNode(effectiveParent) &&
81
- effectiveParent.instance?.isObject3D
59
+ isLunchboxStandardNode(parent) &&
60
+ parent.instance?.isObject3D
82
61
  ) {
83
- effectiveParent.instance?.add?.(child.instance)
62
+ parent.instance?.add?.(child.instance)
84
63
  }
85
64
 
86
65
  // add attached props
@@ -1,10 +1,8 @@
1
- import { allNodes, MiniDom } from '../core'
1
+ import { MiniDom } from '../core'
2
2
  import { isLunchboxStandardNode } from '../utils'
3
- import { overrides } from '../core'
4
3
 
5
4
  export const remove = (node: MiniDom.RendererBaseNode) => {
6
5
  if (!node) return
7
- const overrideKeys = Object.keys(overrides)
8
6
  // prep subtree
9
7
  const subtree: MiniDom.BaseNode[] = []
10
8
  node.walk((descendant) => {
@@ -14,14 +12,6 @@ export const remove = (node: MiniDom.RendererBaseNode) => {
14
12
 
15
13
  // clean up subtree
16
14
  subtree.forEach((n) => {
17
- const overrideKey = overrideKeys.find(
18
- (key) => overrides[key]?.uuid === n.uuid
19
- )
20
- // if this node is an override, remove it from the overrides list
21
- if (overrideKey) {
22
- overrides[overrideKey] = null
23
- }
24
-
25
15
  if (isLunchboxStandardNode(n)) {
26
16
  // try to remove three object
27
17
  n.instance?.removeFromParent?.()
@@ -38,11 +28,5 @@ export const remove = (node: MiniDom.RendererBaseNode) => {
38
28
 
39
29
  // drop tree node
40
30
  n.drop()
41
-
42
- // remove Lunchbox node from main list
43
- const idx = allNodes.findIndex((v) => v.uuid === n.uuid)
44
- if (idx !== -1) {
45
- allNodes.splice(idx, 1)
46
- }
47
31
  })
48
32
  }
package/src/types.ts CHANGED
@@ -1,14 +1,32 @@
1
+ type RendererStandardNode<T = THREE.Object3D> =
2
+ import('./core').MiniDom.RendererStandardNode<T>
1
3
  type RootNode = import('./core/minidom').MiniDom.RendererRootNode
2
4
  type VNodeProps = import('vue').VNodeProps
3
5
  type VueApp<T> = import('vue').App<T>
4
6
  type WatchSource = import('vue').WatchSource
5
- type RendererStandardNode<T = THREE.Object3D> =
6
- import('./core').MiniDom.RendererStandardNode<T>
7
+ type WatchStopHandle = import('vue').WatchStopHandle
8
+ type ThreeCamera = import('three').Camera
9
+ type ThreeRenderer = import('three').Renderer
10
+ type ThreeScene = import('three').Scene
7
11
 
8
12
  export declare namespace Lunch {
9
13
  /** Lunchbox app. */
10
- type App = VueApp<any> & {
14
+ type App = Omit<VueApp<any>, 'config'> & {
11
15
  clearCustomRender: () => void
16
+ config: Omit<VueApp<any>['config'], 'globalProperties'> & {
17
+ globalProperties: {
18
+ lunchbox: {
19
+ afterRender: Lunch.UpdateCallback[]
20
+ beforeRender: Lunch.UpdateCallback[]
21
+ camera: ThreeCamera | null
22
+ dpr: number
23
+ frameId: number
24
+ renderer: ThreeRenderer | null
25
+ scene: ThreeScene | null
26
+ watchStopHandle: WatchStopHandle | null
27
+ }
28
+ } & Record<string, any>
29
+ }
12
30
  customRender: ((opts: UpdateCallbackProperties) => void) | null
13
31
  extend: (v: Record<string, any>) => App
14
32
  rootNode: RootNode
@@ -18,6 +36,10 @@ export declare namespace Lunch {
18
36
  update: UpdateCallback
19
37
  }
20
38
 
39
+ type AppGlobals = App['config']['globalProperties']['lunchbox']
40
+
41
+ type AppGlobalsUpdate = (newValue: Partial<AppGlobals>) => void
42
+
21
43
  interface CanvasProps {
22
44
  dpr?: number
23
45
  wrapperProps?: WrapperProps
@@ -34,6 +56,10 @@ export declare namespace Lunch {
34
56
  text: string
35
57
  }
36
58
 
59
+ type CustomRenderFunctionSetter = (
60
+ render: (opts: Lunch.UpdateCallbackProperties) => void
61
+ ) => void
62
+
37
63
  interface DomMeta extends MetaBase {
38
64
  domElement: HTMLElement
39
65
  }
@@ -129,10 +155,6 @@ export declare namespace Lunch {
129
155
  renderer?: THREE.Renderer | null
130
156
  camera?: THREE.Camera | null
131
157
  updateSource?: WatchSource | null
132
-
133
- // sceneNode: Node<THREE.Scene> | null
134
- // rendererNode: Node<THREE.Renderer> | null
135
- // cameraNode: Node<THREE.Camera> | null
136
158
  }
137
159
 
138
160
  /** Universally unique identifier. */
@@ -140,12 +162,14 @@ export declare namespace Lunch {
140
162
 
141
163
  type SizePolicy = 'full' | 'container'
142
164
 
165
+ type Vector3AsArray = [number, number, number]
166
+
143
167
  interface WrapperProps {
144
168
  background?: string
145
169
  cameraArgs?: any[]
146
- cameraLook?: [number, number, number]
147
- cameraLookAt?: [number, number, number]
148
- cameraPosition?: [number, number, number]
170
+ cameraLook?: Vector3AsArray
171
+ cameraLookAt?: Vector3AsArray
172
+ cameraPosition?: Vector3AsArray
149
173
  dpr?: number
150
174
  ortho?: boolean
151
175
  orthographic?: boolean
@@ -1,4 +1,3 @@
1
- import { lunchboxDomComponentNames } from '../components'
2
1
  import { Lunch } from '..'
3
2
 
4
3
  export * from './find'
@@ -32,9 +31,7 @@ export const isLunchboxComponent = (
32
31
  export const isLunchboxDomComponent = (node: any): node is Lunch.DomMeta => {
33
32
  if ((node as Lunch.MetaBase)?.metaType === 'domMeta') return true
34
33
 
35
- const typeToCheck = typeof node === 'string' ? node : node?.type
36
-
37
- return lunchboxDomComponentNames.includes(typeToCheck ?? '')
34
+ return node?.props?.['data-lunchbox']
38
35
  }
39
36
 
40
37
  export const isLunchboxStandardNode = (
@@ -46,3 +43,13 @@ export const isLunchboxStandardNode = (
46
43
  export const isLunchboxRootNode = (node: any): node is Lunch.RootMeta => {
47
44
  return node.isLunchboxRootNode
48
45
  }
46
+
47
+ export const waitFor = async (get: () => any) => {
48
+ let output = get()
49
+ while (!output) {
50
+ await new Promise((resolve) => requestAnimationFrame(resolve))
51
+ output = get()
52
+ console.log(output)
53
+ }
54
+ return output
55
+ }
package/dist/.DS_Store DELETED
Binary file
package/src/.DS_Store DELETED
Binary file
@@ -1,312 +0,0 @@
1
- import {
2
- h,
3
- ComponentOptions,
4
- getCurrentInstance,
5
- onBeforeUnmount,
6
- onMounted,
7
- ref,
8
- WatchSource,
9
- WritableComputedRef,
10
- } from 'vue'
11
- import {
12
- cameraReady,
13
- cancelUpdate,
14
- cancelUpdateSource,
15
- createNode,
16
- ensuredCamera,
17
- ensureRenderer,
18
- ensuredScene,
19
- fallbackCameraUuid,
20
- fallbackRendererUuid,
21
- MiniDom,
22
- rendererReady,
23
- startCallbacks,
24
- tryGetNodeWithInstanceType,
25
- update,
26
- } from '../../core'
27
- import { set } from 'lodash'
28
- import { globals, Lunch } from '../..'
29
- // import { Color, Vector2, sRGBEncoding, ACESFilmicToneMapping } from 'three'
30
- import * as THREE from 'three'
31
- import { prepCanvas } from './prepCanvas'
32
-
33
- // TODO:
34
- // Continue r3f prop - what else (besides camera fov) makes r3f look good?
35
-
36
- /** fixed & fill styling for container */
37
- const fillStyle = (position: string) => {
38
- return {
39
- position,
40
- top: 0,
41
- right: 0,
42
- bottom: 0,
43
- left: 0,
44
- width: '100%',
45
- height: '100%',
46
- display: 'block',
47
- }
48
- }
49
-
50
- export const LunchboxWrapper: ComponentOptions = {
51
- name: 'Lunchbox',
52
- props: {
53
- // These should match the Lunchbox.WrapperProps interface
54
- background: String,
55
- cameraArgs: Array,
56
- cameraLook: Array,
57
- cameraLookAt: Array,
58
- cameraPosition: Array,
59
- dpr: Number,
60
- ortho: Boolean,
61
- orthographic: Boolean,
62
- r3f: Boolean,
63
- rendererArguments: Object,
64
- rendererProperties: Object,
65
- sizePolicy: String,
66
- shadow: [Boolean, Object],
67
- transparent: Boolean,
68
- zoom: Number,
69
- updateSource: Object,
70
- },
71
- setup(props: Lunch.WrapperProps, context) {
72
- const canvas = ref<MiniDom.RendererDomNode>()
73
- const useFallbackRenderer = ref(true)
74
- const dpr = ref(props.dpr ?? -1)
75
- const container = ref<MiniDom.RendererDomNode>()
76
- let renderer: Lunch.Node<THREE.WebGLRenderer> | null
77
- let camera: Lunch.Node<THREE.Camera> | null
78
- let scene: MiniDom.RendererStandardNode<THREE.Scene>
79
-
80
- // https://threejs.org/docs/index.html#manual/en/introduction/Color-management
81
- if (props.r3f && (THREE as any)?.ColorManagement) {
82
- ;(THREE as any).ColorManagement.legacyMode = false
83
- }
84
-
85
- // MOUNT
86
- // ====================
87
- onMounted(() => {
88
- // canvas needs to exist
89
- if (!canvas.value) throw new Error('missing canvas')
90
-
91
- // RENDERER
92
- // ====================
93
- // is there already a renderer?
94
- // TODO: allow other renderer types
95
- renderer = tryGetNodeWithInstanceType([
96
- 'WebGLRenderer',
97
- ]) as unknown as Lunch.Node<THREE.WebGLRenderer> | null
98
-
99
- // if renderer is missing, initialize with options
100
- if (!renderer) {
101
- // build renderer args
102
- const rendererArgs: THREE.WebGLRendererParameters = {
103
- alpha: props.transparent,
104
- antialias: true,
105
- canvas: canvas.value.domElement,
106
- powerPreference: !!props.r3f
107
- ? 'high-performance'
108
- : 'default',
109
- ...(props.rendererArguments ?? {}),
110
- }
111
-
112
- // create new renderer
113
- ensureRenderer.value = createNode<THREE.WebGLRenderer>({
114
- type: 'WebGLRenderer',
115
- uuid: fallbackRendererUuid,
116
- props: {
117
- args: [rendererArgs],
118
- },
119
- })
120
-
121
- // we've initialized the renderer, so anything depending on it can execute now
122
- rendererReady.value = true
123
-
124
- const rendererAsWebGlRenderer =
125
- ensureRenderer as WritableComputedRef<
126
- Lunch.Node<THREE.WebGLRenderer>
127
- >
128
-
129
- // apply r3f settings if desired
130
- if (props.r3f) {
131
- if (rendererAsWebGlRenderer.value.instance) {
132
- rendererAsWebGlRenderer.value.instance.outputEncoding =
133
- THREE.sRGBEncoding
134
- rendererAsWebGlRenderer.value.instance.toneMapping =
135
- THREE.ACESFilmicToneMapping
136
- }
137
- }
138
-
139
- // update render sugar
140
- const sugar = {
141
- shadow: props.shadow,
142
- }
143
- if (rendererAsWebGlRenderer.value.instance && sugar?.shadow) {
144
- rendererAsWebGlRenderer.value.instance.shadowMap.enabled =
145
- true
146
- if (typeof sugar.shadow === 'object') {
147
- rendererAsWebGlRenderer.value.instance.shadowMap.type =
148
- sugar.shadow.type
149
- }
150
- }
151
-
152
- // set renderer props if needed
153
- if (props.rendererProperties) {
154
- Object.keys(props.rendererProperties).forEach((key) => {
155
- set(
156
- rendererAsWebGlRenderer.value,
157
- key,
158
- (props.rendererProperties as any)[key]
159
- )
160
- })
161
- }
162
-
163
- // update using created renderer
164
- renderer = rendererAsWebGlRenderer.value
165
- } else {
166
- useFallbackRenderer.value = false
167
- // the user has initialized the renderer, so anything depending
168
- // on the renderer can execute
169
- rendererReady.value = true
170
- }
171
-
172
- // CAMERA
173
- // ====================
174
- // is there already a camera?
175
- camera = tryGetNodeWithInstanceType([
176
- 'PerspectiveCamera',
177
- 'OrthographicCamera',
178
- ])
179
- // if not, let's create one
180
- if (!camera) {
181
- // create ortho camera
182
- if (props.ortho || props.orthographic) {
183
- ensuredCamera.value = createNode<THREE.OrthographicCamera>({
184
- props: { args: props.cameraArgs ?? [] },
185
- type: 'OrthographicCamera',
186
- uuid: fallbackCameraUuid,
187
- })
188
- } else {
189
- ensuredCamera.value = createNode<THREE.PerspectiveCamera>({
190
- props: {
191
- args: props.cameraArgs ?? [
192
- props.r3f ? 75 : 45,
193
- 0.5625,
194
- 1,
195
- 1000,
196
- ],
197
- },
198
- type: 'PerspectiveCamera',
199
- uuid: fallbackCameraUuid,
200
- })
201
- }
202
-
203
- cameraReady.value = true
204
-
205
- camera = ensuredCamera.value
206
- } else {
207
- cameraReady.value = true
208
- }
209
- if (!camera.instance) {
210
- throw new Error('Error creating camera.')
211
- }
212
- // move camera if needed
213
- if (camera && props.cameraPosition) {
214
- camera.instance.position.set(...props.cameraPosition)
215
- }
216
- // angle camera if needed
217
- if (camera && (props.cameraLookAt || props.cameraLook)) {
218
- const source = (props.cameraLookAt || props.cameraLook)!
219
- camera.instance.lookAt(...source)
220
- }
221
- // zoom camera if needed
222
- if (camera && props.zoom !== undefined) {
223
- ;(camera.instance as THREE.OrthographicCamera).zoom = props.zoom
224
- }
225
-
226
- // SCENE
227
- // ====================
228
- scene = ensuredScene.value
229
- // set background color
230
- if (scene && scene.instance && props.background) {
231
- scene.instance.background = new THREE.Color(props.background)
232
- }
233
-
234
- // MISC PROPERTIES
235
- // ====================
236
- if (dpr.value === -1) {
237
- dpr.value = window.devicePixelRatio
238
- }
239
-
240
- if (renderer?.instance) {
241
- renderer.instance.setPixelRatio(dpr.value)
242
- globals.dpr.value = dpr.value
243
- // prep canvas (sizing, observe, unmount, etc)
244
- prepCanvas(
245
- container,
246
- renderer.instance.domElement,
247
- onBeforeUnmount,
248
- props.sizePolicy,
249
- )
250
- } else {
251
- throw new Error('missing renderer')
252
- }
253
-
254
- // CALLBACK PREP
255
- // ====================
256
- const app = getCurrentInstance()!.appContext.app as Lunch.App
257
-
258
- // START
259
- // ====================
260
- for (let startCallback of startCallbacks) {
261
- startCallback({
262
- app,
263
- camera: camera.instance,
264
- renderer: renderer.instance,
265
- scene: scene.instance,
266
- })
267
- }
268
-
269
- // KICK UPDATE
270
- // ====================
271
- update({
272
- app,
273
- camera: camera.instance,
274
- renderer: renderer.instance,
275
- scene: scene.instance,
276
- updateSource: props.updateSource,
277
- })
278
- })
279
-
280
- // UNMOUNT
281
- // ====================
282
- onBeforeUnmount(() => {
283
- cancelUpdate()
284
- cancelUpdateSource()
285
- })
286
-
287
- // RENDER FUNCTION
288
- // ====================
289
- const containerFillStyle = props.sizePolicy === 'container' ? 'static' : 'absolute'
290
- const canvasFillStyle = props.sizePolicy === 'container' ? 'static' : 'fixed'
291
-
292
- return () => [
293
- context.slots.default?.() ?? null,
294
- h(
295
- 'div',
296
- {
297
- style: fillStyle(containerFillStyle),
298
- ref: container,
299
- },
300
- [
301
- useFallbackRenderer.value
302
- ? h('canvas', {
303
- style: fillStyle(canvasFillStyle),
304
- class: 'lunchbox-canvas',
305
- ref: canvas,
306
- })
307
- : null,
308
- ]
309
- ),
310
- ]
311
- },
312
- }
@@ -1,3 +0,0 @@
1
- import { Lunch } from '..'
2
-
3
- export const catalogue: Lunch.Catalogue = {}
Binary file
@@ -1,4 +0,0 @@
1
- import { MiniDom } from '.'
2
-
3
- // this needs to be in a separate file to ensure it's created immediately
4
- export const allNodes = [] as Array<MiniDom.BaseNode>