@pinegrow/vite-plugin 3.0.0-beta.103 → 3.0.0-beta.105

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pinegrow/vite-plugin",
3
- "version": "3.0.0-beta.103",
3
+ "version": "3.0.0-beta.105",
4
4
  "description": "Pinegrow Vite Plugin",
5
5
  "type": "module",
6
6
  "files": [
package/types.d.ts CHANGED
@@ -1,13 +1,87 @@
1
- declare module '@pinegrow/vite-plugin'
2
-
3
- // export interface liveDesigner {
4
- // repoRoot?: string;
5
- // configPath?: string;
6
- // plugins?: string[];
7
- // devtoolsKey?: string;
8
- // vscodeTunnelUrl?: string
9
- // customTypes?: {
10
- // default?: {};
11
- // };
12
- // };
1
+ import type { Options as PinegrowTailwindCSSPluginOptions } from '@pinegrow/tailwindcss-plugin'
2
+ import type { Options as AutoImportComponentsOptions } from 'unplugin-vue-components/types'
3
+ import type { Options as AutoImportAPIsOptions } from 'unplugin-auto-import/types'
4
+
5
+ interface Options {
6
+ repoRoot?: string // relative path from the project root to the root of the monorepo
7
+
8
+ configPath?: string // relative path from project root to the custom config file when it's not auto-detected, for eg, './my-config.dev.js' or './docs/my-config.dev.js', defaults to viteServer.config.configFile
9
+
10
+ // pinegrow plugins
11
+ plugins?: string[]
12
+
13
+ // User can override the themePath in the plugin's options
14
+ // {
15
+ // key: 'vuetify',
16
+ // pluginPath: '...',
17
+ // options: {
18
+ // themePath: './src/themes' // directory or file, for eg, './src/themes/my-pg-theme.cjs'
19
+ // }
20
+ // }
21
+
22
+ devtoolsKey?: string
23
+ // vscodeTunnelUrl?: string
24
+
25
+ // routerHistoryMode?: string // 'hash', 'html5' (default)
26
+
27
+ // Adds to package.json, used when a package was installed (available in lock file) probably as a peer dependency, so not available in package.json
28
+ // mergeWithPackageJson?: {
29
+ // dependencies?: {}
30
+ // devDependencies?: {
31
+ // // vite: string;
32
+ // }
33
+ // }
34
+
35
+ customTypes?: {
36
+ // To apply type overrides to a specific component (overrides above default fn),
37
+ // ComponentName: { prop: { customType: 'icon' } },
38
+ // VRating: {
39
+ // ripple: {
40
+ // customType: "boolean";
41
+ // };
42
+ // };
43
+ // VSelect: {
44
+ // variant: {
45
+ // customType: 'select',
46
+ // options: ['plain', 'outlined', 'underlined', 'solo'],
47
+ // default: ''
48
+ // },
49
+ // density: {
50
+ // customType: 'select',
51
+ // options: ['default', 'compact', 'comfortable']
52
+ // },
53
+ // disabled: {
54
+ // customType: 'boolean'
55
+ // },
56
+ // appendIcon: {
57
+ // customType: 'icon'
58
+ // },
59
+ // }
60
+ // To apply type overrides to all components,
61
+ // all: { prop: { customType: 'icon' } },
62
+ defaultTypes?: {
63
+ // density: {
64
+ // customType: "select";
65
+ // // add options when customType is 'select'
66
+ // options: ["default", "compact", "comfortable"];
67
+ // };
68
+ }
69
+ }
70
+
71
+ tailwindcss?: PinegrowTailwindCSSPluginOptions
72
+
73
+ autoImportComponents?: AutoImportComponentsOptions
74
+
75
+ autoImportAPIs?: AutoImportAPIsOptions
76
+ }
77
+
78
+ interface PinegrowVitePlugin {
79
+ liveDesigner?: {
80
+ [key in string]?: any
81
+ } & Options
82
+ }
83
+
84
+ declare function export_default(liveDesigner: Options): PinegrowVitePlugin
85
+
86
+ export { PinegrowVitePlugin, Options, export_default as default, export_default as liveDesigner }
13
87
 
@@ -1,401 +0,0 @@
1
- import { onBeforeMount, onMounted, onBeforeUnmount, getCurrentInstance, ref, reactive, computed, onUpdated } from 'vue'
2
-
3
- export function usePinegrow() {
4
- const initCache = () => {
5
- // conditional
6
- const winObj = window
7
-
8
- if (!(winObj?.process?.client && winObj.process.client !== true)) {
9
- if (!winObj.pinegrow) {
10
- // conditional
11
- // console.log('Cache initialized by Pinegrow Vue Plugin!')
12
- const elCache = reactive(new Map())
13
-
14
- const enrichWithComponentName = (elCacheObj, localFile) => {
15
- return {
16
- name: elCacheObj.instance.type.__name || '',
17
- localFile,
18
- ...elCacheObj,
19
- }
20
- }
21
-
22
- const pgIdToElComputed = computed(() => {
23
- const pgIds = {}
24
- for (let [el, elCacheNodes] of elCache.entries()) {
25
- if (el.isConnected) {
26
- elCacheNodes.forEach(elCacheObj => {
27
- if (
28
- // elCacheObj.vnode.el.isConnected &&
29
- elCacheObj.instance.isMounted &&
30
- !elCacheObj.instance.isUnmounted &&
31
- elCacheObj.pgId &&
32
- (!elCacheObj.rootEl || elCacheObj.isRootFragment)
33
- ) {
34
- if (!pgIds[elCacheObj.pgId]) {
35
- pgIds[elCacheObj.pgId] = []
36
- }
37
- if (elCacheObj.key === undefined || elCacheObj.key === null) {
38
- pgIds[elCacheObj.pgId].push(elCacheObj)
39
- } else {
40
- pgIds[elCacheObj.pgId].push([elCacheObj.key, elCacheObj])
41
- }
42
- }
43
- })
44
- }
45
- }
46
- return pgIds
47
- })
48
-
49
- const localComponentToElComputed = computed(() => {
50
- const localComponents = {}
51
- for (let [el, elCacheNodes] of elCache.entries()) {
52
- if (el.isConnected) {
53
- elCacheNodes.forEach(elCacheObj => {
54
- if (
55
- // elCacheObj.vnode.el.isConnected &&
56
- elCacheObj.instance.isMounted &&
57
- !elCacheObj.instance.isUnmounted &&
58
- elCacheObj.localFile
59
- // && !elCacheObj.isIsland
60
- // && (!elCacheObj.rootEl || elCacheObj.isRootFragment)
61
- ) {
62
- if (!localComponents[elCacheObj.localFile]) {
63
- localComponents[elCacheObj.localFile] = []
64
- }
65
- // There might be a elCache that was hydrated, and has the ile-root as a parent. If it was already there, then update the iles-root instead of adding a new node
66
- const possibleIslandRootIndex = localComponents[elCacheObj.localFile].findIndex(
67
- prevElCacheObj =>
68
- prevElCacheObj.isIsland &&
69
- prevElCacheObj.firstEl?.firstElementChild === elCacheObj.el
70
- )
71
-
72
- if (possibleIslandRootIndex > -1) {
73
- const pgId = localComponents[elCacheObj.localFile][possibleIslandRootIndex].pgId
74
- localComponents[elCacheObj.localFile][possibleIslandRootIndex] =
75
- enrichWithComponentName({ ...elCacheObj, pgId }, elCacheObj.localFile)
76
- } else {
77
- localComponents[elCacheObj.localFile].push(
78
- enrichWithComponentName(elCacheObj, elCacheObj.localFile)
79
- )
80
- }
81
- }
82
- })
83
- }
84
- }
85
- return localComponents
86
- })
87
-
88
- const appTree = computed(() => {
89
- const appTreeNodes = Object.values(localComponentToElComputed.value).reduce(
90
- (acc, localComponent) => [...acc, ...localComponent],
91
- []
92
- )
93
- const appTreeNodesSorted = appTreeNodes.sort((a, b) =>
94
- a.el.compareDocumentPosition(b.el) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
95
- )
96
- return appTreeNodesSorted
97
- })
98
-
99
- winObj.pinegrow = {
100
- elCache,
101
- // // Uncomment these two to test locally
102
- // elCacheErrHandlerFn,
103
- // elUpdateHanderFn,
104
- // rootFragmentToPgIdComputed,
105
- pgIdToElComputed,
106
- localComponentToElComputed,
107
- appTree,
108
- }
109
- }
110
- }
111
- }
112
-
113
- // pgId & key can be optional
114
- const pgUpdateElCache = (hook, pgId, rootEl, key, localFile) => async vnode => {
115
- if (!vnode) return
116
- if (window?.process?.client && process?.client !== true) return
117
- if (!window.pinegrow) initCache()
118
-
119
- let el = vnode.el
120
- if (!el) return
121
-
122
- const instance = vnode.component || vnode.ctx || el.__vueParentComponent
123
-
124
- try {
125
- if ((key !== null && key !== undefined) || (vnode.key !== null && vnode.key !== undefined)) {
126
- key = vnode.key || key
127
- }
128
-
129
- localFile = localFile || vnode.type.__file
130
-
131
- let isRootFragment = false
132
- let isFragment = el.nodeType !== 1
133
- let firstEl,
134
- lastEl,
135
- isIsland = false,
136
- isLayout = false,
137
- isPage = false,
138
- childVNodes = []
139
-
140
- const getChildLocalFile = el => {
141
- const childEl = el?.nextElementSibling
142
- const childInstance = childEl?.$ || childEl?.__vueParentComponent
143
- const childVNode = childInstance?.vnode // or subTree?
144
- if (childVNode) {
145
- return childVNode.type.__file || childInstance.type.__file
146
- }
147
- }
148
-
149
- if ((instance.type.name || instance.type.__name) === 'NuxtLayout') {
150
- isLayout = true
151
- localFile = localFile || getChildLocalFile(el)
152
- }
153
-
154
- if ((instance.type.name || instance.type.__name) === 'NuxtPage') {
155
- isPage = true
156
- localFile = localFile || getChildLocalFile(el)
157
- }
158
-
159
- // May be an iles Island that wraps components with client directives
160
- if (localFile) {
161
- if (localFile.includes('node_modules/iles') && localFile.includes('Island.vue')) {
162
- // Retain localFiles of iles island to apply to child elements
163
- isIsland = true
164
- }
165
-
166
- if (localFile.includes('node_modules')) {
167
- // Ignore SFCs from node_modules
168
- localFile = null
169
- }
170
- }
171
-
172
- const localFileFromInstance = instance.type.__file
173
- if (
174
- localFileFromInstance &&
175
- localFileFromInstance.includes('node_modules/iles') &&
176
- localFileFromInstance.includes('Island.vue')
177
- ) {
178
- // Retain localFiles of iles island to apply to child elements
179
- isIsland = true
180
-
181
- localFile = instance.props.component?.__file || instance.props.importFrom
182
- }
183
-
184
- // // Computed props anyway filters out unmounted ones, and we use the local components unmounted hooks to cleanup unmounted nodes. Using the unmounted hook seems to be out of sync when el is reused but instance is remounted.
185
- // if (hook === 'unmounted') {
186
- // if (pinegrow.elCache.has(el)) {
187
- // pinegrow.elCache.delete(el)
188
- // }
189
- // for (let [key, value] of pinegrow.elCache.entries()) {
190
- // if (value.rootEl === rootEl) {
191
- // pinegrow.elCache.delete(key)
192
- // }
193
- // }
194
- // return
195
- // }
196
-
197
- // Text/comment node
198
- if (isFragment) {
199
- if (!rootEl) {
200
- // root Fragment
201
- isRootFragment = true
202
- }
203
-
204
- function isFragmentEl(instance) {
205
- // return appRecord.options.types.Fragment === instance.subTree?.type
206
- return instance.subTree.el.nodeType !== 1
207
- }
208
-
209
- function getRootVNodesFromComponentInstance(instance) {
210
- if (isFragmentEl(instance)) {
211
- return getFragmentRootVNodes(instance.subTree)
212
- }
213
- if (!instance.subTree) return []
214
- return [instance.subTree]
215
- }
216
-
217
- function getFragmentRootVNodes(vnode) {
218
- if (!vnode.children) return []
219
- // children is v-if when the vnode has a condition
220
- if (!Array.isArray(vnode.children)) return []
221
-
222
- const list = []
223
-
224
- for (let i = 0, l = vnode.children.length; i < l; i++) {
225
- const childVnode = vnode.children[i]
226
- if (childVnode.component) {
227
- list.push(...getRootVNodesFromComponentInstance(childVnode.component))
228
- } else if (childVnode) {
229
- list.push(childVnode)
230
- }
231
- }
232
-
233
- return list
234
- }
235
-
236
- childVNodes = getRootVNodesFromComponentInstance(instance)
237
-
238
- if (!childVNodes.length) {
239
- // For NuxtLayout, no childVNodes are returned, the subTree.children is in fact an object {ctx: {}, default: f}
240
- if (el.nextElementSibling) {
241
- const childEl = el.nextElementSibling
242
- firstEl = lastEl = childEl
243
- const childInstance = childEl.$ || childEl.__vueParentComponent
244
- const childVNode = childInstance?.vnode // or subTree?
245
- if (childVNode) {
246
- childVNodes.push(childVNode)
247
- }
248
- }
249
- }
250
-
251
- if (childVNodes.length) {
252
- // Filter out recursive vnodes text1 -> div, text1 (happens when text1 is the closest to a fragment with div & slot)
253
- childVNodes = childVNodes.filter(childVNode => childVNode.el !== el)
254
-
255
- if (childVNodes.length) {
256
- if (childVNodes.length === 1) {
257
- firstEl = lastEl = childVNodes[0].el
258
- } else {
259
- firstEl = childVNodes[0].el
260
- lastEl = childVNodes[childVNodes.length - 1].el
261
- }
262
-
263
- if (firstEl && firstEl.nodeType !== 1) {
264
- firstEl = firstEl.nextElementSibling
265
- }
266
- if (lastEl && lastEl.nodeType !== 1) {
267
- lastEl = lastEl.nextElementSibling
268
- }
269
- }
270
- }
271
- }
272
-
273
- if (isIsland && !isRootFragment) {
274
- return
275
- }
276
-
277
- if (isFragment && !firstEl) {
278
- return
279
- }
280
-
281
- let elCacheObj = {
282
- el,
283
- isRootFragment,
284
- rootEl,
285
- vnode,
286
- instance,
287
- isFragment,
288
- firstEl,
289
- lastEl,
290
- pgId,
291
- key,
292
- localFile,
293
- isIsland,
294
- isLayout,
295
- isPage,
296
- }
297
-
298
- let prevElCacheNodes = pinegrow.elCache.get(el)
299
-
300
- if (prevElCacheNodes) {
301
- let index = prevElCacheNodes.findIndex(elCacheObj => elCacheObj.instance.uid === instance.uid)
302
-
303
- if (index > -1) {
304
- const prevElCacheObj = prevElCacheNodes[index]
305
- elCacheObj.localFile = elCacheObj.localFile || prevElCacheObj.localFile
306
- elCacheObj.pgId = elCacheObj.pgId || prevElCacheObj.pgId
307
- prevElCacheNodes[index] = elCacheObj
308
- } else {
309
- prevElCacheNodes.push(elCacheObj)
310
- }
311
- pinegrow.elCache.set(el, prevElCacheNodes)
312
- } else {
313
- pinegrow.elCache.set(el, [elCacheObj])
314
- childVNodes.forEach(childVNode => {
315
- pgUpdateElCache(hook, pgId, isRootFragment ? el : rootEl, key)(childVNode)
316
- })
317
- }
318
-
319
- if (pinegrow.elUpdateHanderFn) {
320
- pinegrow.elUpdateHanderFn(el)
321
- }
322
- } catch (err) {
323
- console.log(err)
324
- if (pinegrow.elCacheErrHandlerFn) {
325
- pinegrow.elCacheErrHandlerFn(vnode, hook, rootEl, pgId, key, el, instance, err.message)
326
- }
327
- }
328
- }
329
-
330
- const elUpdateHanderFn = el => {
331
- // if (pinegrow.elCache.has(el)) {
332
- // const { pgId } = pinegrow.elCache.get(el)
333
- // if (pgId) {
334
- // // console.log(`Reselect ${pgId}`)
335
- // }
336
- // }
337
- }
338
-
339
- const elCacheErrHandlerFn = () => {
340
- if (message) {
341
- // console.log(message)
342
- }
343
- }
344
-
345
- const cleanupCache = () => {
346
- // for (let [key, value] of pinegrow.elCache.entries()) {
347
- // if (value.isFragment && !value.firstEl) {
348
- // console.log(value)
349
- // }
350
- // }
351
- for (let [el, elCacheNodes] of pinegrow.elCache.entries()) {
352
- // if (!el.isConnected) {
353
- // pinegrow.elCache.delete(el)
354
- // continue
355
- // }
356
- const cleanedUpElCacheNodes = elCacheNodes.filter(
357
- elCacheObj => !elCacheObj.instance.isUnmounted // || elCacheObj.localFile
358
- )
359
- if (cleanedUpElCacheNodes.length) {
360
- if (cleanedUpElCacheNodes.length !== elCacheNodes.length) {
361
- pinegrow.elCache.set(el, cleanedUpElCacheNodes)
362
- }
363
- } else {
364
- pinegrow.elCache.delete(el)
365
- }
366
- }
367
- }
368
-
369
- // Local Component
370
- const rootVNode = ref(null)
371
-
372
- const mountLocalComponent = () => {
373
- const instance = getCurrentInstance()
374
- const vnode = instance?.vnode
375
- const el = vnode?.el
376
- const localFile = instance.type.__file && !instance.type.__file.includes('node_modules') && instance.type.__file
377
- if (instance && vnode && el) {
378
- rootVNode.value = vnode
379
- pgUpdateElCache('mounted', null, null, null, localFile)(vnode)
380
- }
381
- }
382
-
383
- const unmountLocalComponent = () => {
384
- if (rootVNode.value) {
385
- pgUpdateElCache('unmounted')(rootVNode.value)
386
- }
387
- cleanupCache()
388
- }
389
-
390
- onBeforeMount(() => initCache())
391
- onMounted(() => {
392
- mountLocalComponent()
393
- })
394
- onBeforeUnmount(() => unmountLocalComponent())
395
- onUpdated(() => {
396
- mountLocalComponent()
397
- })
398
-
399
- return { pgUpdateElCache }
400
- }
401
-