lunchboxjs 0.2.1020 → 2.0.0-beta.0

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 (38) hide show
  1. package/dist/lunchboxjs.es.d.ts +1 -1
  2. package/dist/lunchboxjs.js +6 -5
  3. package/dist/lunchboxjs.min.js +1 -1
  4. package/dist/lunchboxjs.module.js +6 -5
  5. package/dist/lunchboxjs.umd.d.ts +1 -1
  6. package/package.json +37 -82
  7. package/LICENSE.md +0 -7
  8. package/README.md +0 -17
  9. package/src/components/LunchboxEventHandlers.tsx +0 -237
  10. package/src/components/LunchboxWrapper/LunchboxScene.tsx +0 -8
  11. package/src/components/LunchboxWrapper/LunchboxWrapper.tsx +0 -341
  12. package/src/components/LunchboxWrapper/prepCanvas.ts +0 -55
  13. package/src/components/LunchboxWrapper/resizeCanvas.ts +0 -41
  14. package/src/components/autoGeneratedComponents.ts +0 -175
  15. package/src/components/index.ts +0 -31
  16. package/src/core/createNode.ts +0 -71
  17. package/src/core/extend.ts +0 -25
  18. package/src/core/index.ts +0 -7
  19. package/src/core/instantiateThreeObject/index.ts +0 -37
  20. package/src/core/instantiateThreeObject/processProps.ts +0 -40
  21. package/src/core/interaction.ts +0 -55
  22. package/src/core/minidom.ts +0 -256
  23. package/src/core/update.ts +0 -149
  24. package/src/core/updateObjectProp.ts +0 -153
  25. package/src/index.ts +0 -400
  26. package/src/keys.ts +0 -31
  27. package/src/nodeOps/createElement.ts +0 -34
  28. package/src/nodeOps/index.ts +0 -83
  29. package/src/nodeOps/insert.ts +0 -165
  30. package/src/nodeOps/remove.ts +0 -32
  31. package/src/plugins/bridge/BridgeComponent.tsx +0 -60
  32. package/src/plugins/bridge/bridge.ts +0 -9
  33. package/src/types.ts +0 -186
  34. package/src/utils/find.ts +0 -24
  35. package/src/utils/get.ts +0 -18
  36. package/src/utils/index.ts +0 -60
  37. package/src/utils/isNumber.ts +0 -87
  38. package/src/utils/set.ts +0 -14
@@ -1,71 +0,0 @@
1
- import { isLunchboxRootNode } from '../utils'
2
- import { instantiateThreeObject, MiniDom } from '.'
3
- import type { Lunch } from '..'
4
-
5
- /** Create a new Lunchbox comment node. */
6
- export function createCommentNode(options: Partial<Lunch.CommentMeta> = {}) {
7
- const defaults: Omit<Lunch.CommentMeta, keyof Lunch.MetaBase> = {
8
- text: options.text ?? '',
9
- }
10
- return new MiniDom.RendererCommentNode({
11
- ...defaults,
12
- ...options,
13
- metaType: 'commentMeta',
14
- })
15
- }
16
-
17
- /** Create a new DOM node. */
18
- export function createDomNode(options: Partial<Lunch.DomMeta> = {}) {
19
- const domElement = document.createElement(options.type ?? '')
20
- const defaults: Omit<Lunch.DomMeta, keyof Lunch.MetaBase> = {
21
- domElement,
22
- }
23
-
24
- const node = new MiniDom.RendererDomNode({
25
- ...defaults,
26
- ...options,
27
- metaType: 'domMeta',
28
- })
29
- return node
30
- }
31
-
32
- /** Create a new Lunchbox text node. */
33
- export function createTextNode(options: Partial<Lunch.TextMeta> = {}) {
34
- const defaults: Omit<Lunch.CommentMeta, keyof Lunch.MetaBase> = {
35
- text: options.text ?? '',
36
- }
37
- return new MiniDom.RendererTextNode({
38
- ...options,
39
- ...defaults,
40
- metaType: 'textMeta',
41
- })
42
- }
43
-
44
- /** Create a new Lunchbox standard node. */
45
- export function createNode<T extends object = THREE.Object3D>(
46
- options: Partial<Lunch.StandardMeta<T>> = {},
47
- props: Lunch.LunchboxMetaProps = {}
48
- ) {
49
- const defaults: Omit<Lunch.StandardMeta<T>, keyof Lunch.MetaBase> = {
50
- attached: options.attached ?? [],
51
- attachedArray: options.attachedArray ?? {},
52
- instance: options.instance ?? null,
53
- }
54
- const node = new MiniDom.RendererStandardNode<T>({
55
- ...options,
56
- ...defaults,
57
- metaType: 'standardMeta',
58
- })
59
-
60
- if (node.type && !isLunchboxRootNode(node) && !node.instance) {
61
- node.instance = instantiateThreeObject({
62
- ...node,
63
- props: {
64
- ...node.props,
65
- ...props,
66
- },
67
- })
68
- }
69
-
70
- return node
71
- }
@@ -1,25 +0,0 @@
1
- import { h, defineComponent } from 'vue'
2
- import { catalogue } from '../components'
3
- import type { Lunch } from '..'
4
-
5
- const createComponent = (tag: string) =>
6
- defineComponent({
7
- inheritAttrs: false,
8
- name: tag,
9
- render() {
10
- return h(tag, this.$attrs, this.$slots?.default?.() || [])
11
- },
12
- })
13
-
14
- export const extend = ({
15
- app,
16
- ...targets
17
- }: {
18
- app: Lunch.App
19
- [key: string]: any
20
- }) => {
21
- Object.keys(targets).forEach((key) => {
22
- app.component(key, createComponent(key))
23
- catalogue[key] = targets[key]
24
- })
25
- }
package/src/core/index.ts DELETED
@@ -1,7 +0,0 @@
1
- export * from './createNode'
2
- export * from './interaction'
3
- export * from './extend'
4
- export * from './instantiateThreeObject'
5
- export * from './minidom'
6
- export * from './update'
7
- export * from './updateObjectProp'
@@ -1,37 +0,0 @@
1
- import { catalogue } from '../../components'
2
- import * as THREE from 'three'
3
- import { processPropAsArray } from './processProps'
4
- import type { Lunch } from '../..'
5
-
6
- export function instantiateThreeObject<T>(node: Lunch.StandardMeta<T>) {
7
- if (!node.type) return null
8
-
9
- // what class will we be instantiating?
10
- const uppercaseType = node.type[0].toUpperCase() + node.type.slice(1)
11
- const translatedType = uppercaseType.replace(/Lunchbox$/, '')
12
- const targetClass =
13
- catalogue[node.type] ||
14
- (THREE as any)[uppercaseType] ||
15
- catalogue[translatedType] ||
16
- (THREE as any)[translatedType]
17
- if (!targetClass)
18
- throw `${uppercaseType} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`
19
-
20
- // what args have we been provided?
21
- const args: Array<any> = node.props.args ?? []
22
-
23
- // replace $attached values with their instances
24
- // we need to guarantee everything comes back as an array so we can spread $attachedArrays,
25
- // so we'll use processPropAsArray
26
- const argsWrappedInArrays = args.map((arg: any) => {
27
- return processPropAsArray({ node, prop: arg })
28
- })
29
- let processedArgs = [] as Array<any>
30
- argsWrappedInArrays.forEach((arr) => {
31
- processedArgs = processedArgs.concat(arr)
32
- })
33
-
34
- const instance = new targetClass(...processedArgs)
35
-
36
- return instance as T
37
- }
@@ -1,40 +0,0 @@
1
- import type { Lunch } from '../..'
2
-
3
- /** Process props into either themselves or the $attached value */
4
- export function processProp<T, U = THREE.Object3D>({
5
- node,
6
- prop,
7
- }: {
8
- node: Lunch.StandardMeta<U>
9
- prop: any
10
- }) {
11
- // return $attachedArray value if needed
12
- if (typeof prop === 'string' && prop.startsWith('$attachedArray')) {
13
- return node.attachedArray[
14
- prop.replace('$attachedArray.', '')
15
- ] as any as T
16
- }
17
-
18
- // return $attached value if needed
19
- if (typeof prop === 'string' && prop.startsWith('$attached')) {
20
- return node.attached[prop.replace('$attached.', '')] as T
21
- }
22
-
23
- // otherwise, return plain value
24
- return prop as T
25
- }
26
-
27
- export function processPropAsArray<T, U = THREE.Object3D>({
28
- node,
29
- prop,
30
- }: {
31
- node: Lunch.StandardMeta<U>
32
- prop: any
33
- }) {
34
- const isAttachedArray =
35
- typeof prop === 'string' && prop.startsWith('$attachedArray')
36
- const output = processProp<T, U>({ node, prop })
37
- return Array.isArray(output) && isAttachedArray
38
- ? (output as Array<T>)
39
- : [output]
40
- }
@@ -1,55 +0,0 @@
1
- import type { Ref } from 'vue'
2
- import type { Lunch } from '..'
3
-
4
- /** Add an event listener to the given node. Also creates the event teardown function and any necessary raycaster/interaction dictionary updates. */
5
- export function addEventListener({
6
- node,
7
- key,
8
- interactables,
9
- value,
10
- }: {
11
- node: Lunch.Node
12
- key: Lunch.EventKey
13
- interactables: Ref<Lunch.Node[]>
14
- value: Lunch.EventCallback
15
- }) {
16
- // create new records for this key if needed
17
- if (!node.eventListeners[key]) {
18
- node.eventListeners[key] = []
19
- }
20
- if (!node.eventListenerRemoveFunctions[key]) {
21
- node.eventListenerRemoveFunctions[key] = []
22
- }
23
-
24
- // add event listener
25
- node.eventListeners[key].push(value)
26
-
27
- // if we need it, let's get/create the main raycaster
28
- if (interactionsRequiringRaycaster.includes(key)) {
29
- if (node.instance && !interactables.value.includes(node)) {
30
- // add to interactables
31
- interactables.value.push(node)
32
- node.eventListenerRemoveFunctions[key].push(() => {
33
- // remove from interactables
34
- const idx = interactables.value.indexOf(node)
35
- if (idx !== -1) {
36
- interactables.value.splice(idx, 1)
37
- }
38
- })
39
- }
40
- }
41
-
42
- return node
43
- }
44
-
45
- const interactionsRequiringRaycaster = [
46
- 'onClick',
47
- 'onPointerUp',
48
- 'onPointerDown',
49
- 'onPointerOver',
50
- 'onPointerOut',
51
- 'onPointerEnter',
52
- 'onPointerLeave',
53
- 'onPointerMove',
54
- // 'onPointerMissed',
55
- ]
@@ -1,256 +0,0 @@
1
- import { v4 as createUuid } from 'uuid'
2
- import type { Lunch } from '..'
3
-
4
- // MiniDom recreates DOM node properties and methods.
5
- // Since Vue 3 is a DOM-first framework, many of its nodeOps depend on
6
- // properties and methods the DOM naturally contains. MiniDom recreates
7
- // those properties (as well as a few from the tree-model npm package)
8
- // to make a DOM-like but otherwise agnostic hierarchy structure.
9
- export namespace MiniDom {
10
- export class BaseNode {
11
- constructor(
12
- options: Partial<BaseNode> = {},
13
- parent?: MiniDom.BaseNode
14
- ) {
15
- this.parentNode = options?.parentNode ?? parent ?? null
16
- this.minidomType = 'MinidomBaseNode'
17
- this.uuid = options?.uuid ?? createUuid()
18
-
19
- // allNodes.push(this)
20
- }
21
- uuid: Lunch.Uuid
22
-
23
- // DOM FEATURES
24
- // ====================
25
- parentNode: MiniDom.BaseNode | null
26
-
27
- get nextSibling(): MiniDom.BaseNode | null {
28
- if (!this.parentNode) return null
29
-
30
- const idx = this.parentNode.children.findIndex(
31
- (n) => n.uuid === this.uuid
32
- )
33
- // return next sibling if we're present and not the last child of the parent
34
- if (idx !== -1 && idx < this.parentNode.children.length - 1) {
35
- return this.parentNode.children[idx + 1]
36
- }
37
-
38
- return null
39
- }
40
-
41
- insertBefore(
42
- child: MiniDom.BaseNode,
43
- anchor?: MiniDom.BaseNode | null
44
- ) {
45
- child.removeAsChildFromAnyParents()
46
- child.parentNode = this
47
- const anchorIdx = this.children.findIndex(
48
- (n) => n.uuid === anchor?.uuid
49
- )
50
- if (anchorIdx !== -1) {
51
- this.children.splice(anchorIdx, 0, child)
52
- } else {
53
- this.children.push(child)
54
- }
55
- }
56
- removeChild(child: MiniDom.BaseNode) {
57
- const idx = this.children.findIndex((n) => n?.uuid === child?.uuid)
58
- if (idx !== -1) {
59
- this.children.splice(idx, 1)
60
- }
61
- }
62
-
63
- // TREE FEATURES
64
- // ====================
65
- children = [] as MiniDom.BaseNode[]
66
- addChild(child: MiniDom.BaseNode) {
67
- if (child) {
68
- // remove child from any other parents
69
- child.removeAsChildFromAnyParents()
70
-
71
- // add to this node
72
- child.parentNode = this
73
- this.insertBefore(child, null)
74
- }
75
- return this
76
- }
77
- /** Get the array of Nodes representing the path from the root to this Node (inclusive). */
78
- getPath() {
79
- const output = [] as BaseNode[]
80
- let current = this as BaseNode | null
81
- while (current) {
82
- output.unshift(current)
83
- current = current.parentNode
84
- }
85
- return output
86
- }
87
-
88
- /** Drop this node. Removes parent's knowledge of this node
89
- * and resets this node's internal parent. */
90
- drop() {
91
- // remove as child
92
- this.removeAsChildFromAnyParents()
93
- // remove parent
94
- this.parentNode = null
95
- }
96
-
97
- /** Walk over the entire subtree. Return falsey value in callback to end early. */
98
- // TODO: depth-first vs breadth-first
99
- walk(callback: (item: MiniDom.BaseNode) => boolean) {
100
- const queue = [this, ...this.children] as MiniDom.BaseNode[]
101
- const traversed: MiniDom.BaseNode[] = []
102
- let canContinue = true
103
- while (queue.length && canContinue) {
104
- const current = queue.shift()
105
- if (current) {
106
- if (traversed.includes(current)) continue
107
-
108
- traversed.push(current)
109
- queue.push(
110
- ...current.children.filter(
111
- (child) => !traversed.includes(child)
112
- )
113
- )
114
- canContinue = callback(current)
115
- } else {
116
- canContinue = false
117
- }
118
- }
119
- }
120
-
121
- // INTERNAL FEATURES
122
- // ====================
123
- minidomType: MiniDom.NodeType
124
-
125
- removeAsChildFromAnyParents() {
126
- this.parentNode?.removeChild(this)
127
- }
128
- }
129
-
130
- export class RendererBaseNode
131
- extends MiniDom.BaseNode
132
- implements Lunch.MetaBase
133
- {
134
- constructor(
135
- options: Partial<Lunch.MetaBase> = {},
136
- parent?: MiniDom.BaseNode
137
- ) {
138
- super(options, parent)
139
- this.minidomType = 'RendererNode'
140
-
141
- this.eventListeners = {}
142
- this.eventListenerRemoveFunctions = {}
143
- this.name = options.name ?? ''
144
- this.metaType = options.metaType ?? 'standardMeta'
145
- this.props = options.props ?? []
146
- this.type = options.type ?? ''
147
- }
148
-
149
- eventListeners: Record<string, Lunch.EventCallback[]>
150
- eventListenerRemoveFunctions: Record<string, Function[]>
151
- name: string | null
152
- metaType: Lunch.MetaType
153
- props: Lunch.LunchboxMetaProps
154
- type: string | null
155
-
156
- drop() {
157
- super.drop()
158
- // handle remove functions
159
- Object.keys(this.eventListenerRemoveFunctions).forEach((key) => {
160
- this.eventListenerRemoveFunctions[key].forEach((func) => func())
161
- })
162
- }
163
- }
164
-
165
- // ====================
166
- // SPECIFIC RENDERER NODES BELOW
167
- // ====================
168
-
169
- export class RendererRootNode
170
- extends MiniDom.RendererBaseNode
171
- implements Lunch.RootMeta
172
- {
173
- constructor(
174
- options: Partial<Lunch.RootMeta> = {},
175
- parent?: MiniDom.BaseNode
176
- ) {
177
- super(options, parent)
178
- this.domElement =
179
- options.domElement ?? document.createElement('div')
180
- }
181
-
182
- domElement: HTMLElement
183
- isLunchboxRootNode = true
184
- }
185
-
186
- export class RendererCommentNode
187
- extends MiniDom.RendererBaseNode
188
- implements Lunch.CommentMeta
189
- {
190
- constructor(
191
- options: Partial<Lunch.CommentMeta> = {},
192
- parent?: MiniDom.BaseNode
193
- ) {
194
- super(options, parent)
195
- this.text = options.text ?? ''
196
- }
197
-
198
- text: string
199
- }
200
-
201
- export class RendererDomNode
202
- extends MiniDom.RendererBaseNode
203
- implements Lunch.DomMeta
204
- {
205
- constructor(
206
- options: Partial<Lunch.DomMeta> = {},
207
- parent?: MiniDom.BaseNode
208
- ) {
209
- super(options, parent)
210
- this.domElement =
211
- options.domElement ?? document.createElement('div')
212
- }
213
-
214
- domElement: HTMLElement
215
- }
216
-
217
- export class RendererTextNode
218
- extends MiniDom.RendererBaseNode
219
- implements Lunch.TextMeta
220
- {
221
- constructor(
222
- options: Partial<Lunch.TextMeta> = {},
223
- parent?: MiniDom.BaseNode
224
- ) {
225
- super(options, parent)
226
- this.text = options.text ?? ''
227
- }
228
-
229
- text: string
230
- }
231
-
232
- export class RendererStandardNode<T = THREE.Object3D>
233
- extends MiniDom.RendererBaseNode
234
- implements Lunch.StandardMeta<T>
235
- {
236
- constructor(
237
- options: Partial<Lunch.StandardMeta<T>> = {},
238
- parent?: MiniDom.BaseNode
239
- ) {
240
- super(options, parent)
241
- this.attached = options.attached ?? []
242
- this.attachedArray = options.attachedArray ?? {}
243
- this.instance = options.instance ?? null
244
- }
245
-
246
- attached: { [key: string]: any }
247
- attachedArray: { [key: string]: Array<any> }
248
- instance: T | null
249
- }
250
-
251
- export type NodeType = 'MinidomBaseNode' | 'RendererNode' | 'RootNode'
252
- }
253
-
254
- export function isMinidomNode(item: any): item is MiniDom.RendererBaseNode {
255
- return (item as MiniDom.BaseNode)?.minidomType === 'RendererNode'
256
- }
@@ -1,149 +0,0 @@
1
- import type { Lunch } from '..'
2
- import { inject, toRaw, watch } from 'vue'
3
- import * as Keys from '../keys'
4
-
5
- const requestUpdate = (opts: Lunch.UpdateCallbackProperties) => {
6
- if (typeof opts.app.config.globalProperties.lunchbox.frameId === 'number') {
7
- cancelAnimationFrame(opts.app.config.globalProperties.lunchbox.frameId)
8
- }
9
- opts.app.config.globalProperties.lunchbox.frameId = requestAnimationFrame(
10
- () =>
11
- update({
12
- app: opts.app,
13
- renderer: opts.renderer,
14
- scene: opts.scene,
15
- camera: opts.camera,
16
- updateSource: opts.updateSource,
17
- })
18
- )
19
- }
20
-
21
- export const update: Lunch.UpdateCallback = (opts) => {
22
- if (opts.updateSource) {
23
- if (!opts.app.config.globalProperties.lunchbox.watchStopHandle) {
24
- // request next frame only when state changes
25
- opts.app.config.globalProperties.lunchbox.watchStopHandle = watch(
26
- opts.updateSource,
27
- () => {
28
- requestUpdate(opts)
29
- },
30
- {
31
- deep: true,
32
- }
33
- )
34
- }
35
- } else {
36
- // request next frame on a continuous loop
37
- requestUpdate(opts)
38
- }
39
-
40
- // prep options
41
- const { app, renderer, scene } = opts
42
-
43
- // BEFORE RENDER
44
- app.config.globalProperties.lunchbox.beforeRender.forEach((cb) => {
45
- cb?.(opts)
46
- })
47
-
48
- // RENDER
49
- if (renderer && scene && opts.app.config.globalProperties.lunchbox.camera) {
50
- if (app.customRender) {
51
- app.customRender(opts)
52
- } else {
53
- renderer.render(
54
- toRaw(scene),
55
- opts.app.config.globalProperties.lunchbox.camera
56
- // toRaw(camera)
57
- )
58
- }
59
- }
60
-
61
- // AFTER RENDER
62
- app.config.globalProperties.lunchbox.afterRender.forEach((cb) => {
63
- cb?.(opts)
64
- })
65
- }
66
-
67
- // before render
68
- // ====================
69
- /** Obtain callback methods for `onBeforeRender` and `offBeforeRender`. Usually used internally by Lunchbox. */
70
- export const useBeforeRender = () => {
71
- return {
72
- onBeforeRender: inject<typeof onBeforeRender>(Keys.onBeforeRenderKey),
73
- offBeforeRender: inject<typeof offBeforeRender>(
74
- Keys.offBeforeRenderKey
75
- ),
76
- }
77
- }
78
-
79
- /** Run a function before every render.
80
- *
81
- * Note that if `updateSource` is set in the Lunchbox wrapper component, this will **only** run
82
- * before a render triggered by that `updateSource`. Normally, the function should run every frame.
83
- */
84
- export const onBeforeRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
85
- useBeforeRender().onBeforeRender?.(cb, index)
86
- }
87
-
88
- /** Remove a function from the `beforeRender` callback list. Useful for tearing down functions added
89
- * by `onBeforeRender`.
90
- */
91
- export const offBeforeRender = (cb: Lunch.UpdateCallback | number) => {
92
- useBeforeRender().offBeforeRender?.(cb)
93
- }
94
-
95
- // after render
96
- // ====================
97
- /** Obtain callback methods for `onAfterRender` and `offAfterRender`. Usually used internally by Lunchbox. */
98
- export const useAfterRender = () => {
99
- return {
100
- onAfterRender: inject<typeof onAfterRender>(Keys.onBeforeRenderKey),
101
- offAfterRender: inject<typeof offAfterRender>(Keys.offBeforeRenderKey),
102
- }
103
- }
104
-
105
- /** Run a function after every render.
106
- *
107
- * Note that if `updateSource` is set in the Lunchbox wrapper component, this will **only** run
108
- * after a render triggered by that `updateSource`. Normally, the function should run every frame.
109
- */
110
- export const onAfterRender = (cb: Lunch.UpdateCallback, index = Infinity) => {
111
- useBeforeRender().onBeforeRender?.(cb, index)
112
- }
113
-
114
- /** Remove a function from the `afterRender` callback list. Useful for tearing down functions added
115
- * by `onAfterRender`.
116
- */
117
- export const offAfterRender = (cb: Lunch.UpdateCallback | number) => {
118
- useBeforeRender().offBeforeRender?.(cb)
119
- }
120
-
121
- /** Obtain a function used to cancel the current update frame. Use `cancelUpdate` if you wish
122
- * to immediately invoke the cancellation function. Usually used internally by Lunchbox.
123
- */
124
- export const useCancelUpdate = () => {
125
- const frameId = inject<number>(Keys.frameIdKey)
126
- return () => {
127
- if (frameId !== undefined) cancelAnimationFrame(frameId)
128
- }
129
- }
130
-
131
- /** Cancel the current update frame. Usually used internally by Lunchbox. */
132
- export const cancelUpdate = () => {
133
- useCancelUpdate()?.()
134
- }
135
-
136
- /** Obtain a function used to cancel an update source. Use `cancelUpdateSource` if you wish to
137
- * immediately invoke the cancellation function. Usually used internally by Lunchbox.
138
- */
139
- export const useCancelUpdateSource = () => {
140
- const cancel = inject<
141
- Lunch.App['config']['globalProperties']['watchStopHandle']
142
- >(Keys.watchStopHandleKey)
143
- return () => cancel?.()
144
- }
145
-
146
- /** Cancel an update source. Usually used internally by Lunchbox. */
147
- export const cancelUpdateSource = () => {
148
- useCancelUpdateSource()?.()
149
- }