nativescript-vue 3.0.3 → 3.1.1

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 (68) hide show
  1. package/README.md +37 -2
  2. package/devtools.js +100 -24
  3. package/dist/components/ActionBar.js +1 -1
  4. package/dist/components/ActionBar.js.map +1 -1
  5. package/dist/components/ListView.d.ts +9 -3
  6. package/dist/components/ListView.js +46 -14
  7. package/dist/components/ListView.js.map +1 -1
  8. package/dist/components/Platform.d.ts +8 -0
  9. package/dist/components/Platform.js +15 -0
  10. package/dist/components/Platform.js.map +1 -0
  11. package/dist/components/index.d.ts +16 -5
  12. package/dist/components/index.js +4 -1
  13. package/dist/components/index.js.map +1 -1
  14. package/dist/directives/vShow.js.map +1 -1
  15. package/dist/dom/index.d.ts +14 -1
  16. package/dist/dom/index.js +58 -19
  17. package/dist/dom/index.js.map +1 -1
  18. package/dist/index.d.ts +6 -2
  19. package/dist/index.js +52 -6
  20. package/dist/index.js.map +1 -1
  21. package/dist/nativescript/elements.js +61 -43
  22. package/dist/nativescript/elements.js.map +1 -1
  23. package/dist/nativescript/index.js.map +1 -1
  24. package/dist/plugins/modals.d.ts +4 -1
  25. package/dist/plugins/modals.js +85 -15
  26. package/dist/plugins/modals.js.map +1 -1
  27. package/dist/plugins/navigation.d.ts +7 -2
  28. package/dist/plugins/navigation.js +45 -7
  29. package/dist/plugins/navigation.js.map +1 -1
  30. package/dist/registry/index.js.map +1 -1
  31. package/dist/renderer/index.js.map +1 -1
  32. package/dist/renderer/modules/attrs.js +27 -8
  33. package/dist/renderer/modules/attrs.js.map +1 -1
  34. package/dist/renderer/modules/class.js.map +1 -1
  35. package/dist/renderer/modules/events.js +0 -1
  36. package/dist/renderer/modules/events.js.map +1 -1
  37. package/dist/renderer/modules/style.js +13 -16
  38. package/dist/renderer/modules/style.js.map +1 -1
  39. package/dist/renderer/nodeOps.js.map +1 -1
  40. package/dist/renderer/patchProp.js +38 -16
  41. package/dist/renderer/patchProp.js.map +1 -1
  42. package/dist/renderer/runtimeDomOverrides.d.ts +11 -0
  43. package/dist/renderer/runtimeDomOverrides.js +23 -0
  44. package/dist/renderer/runtimeDomOverrides.js.map +1 -1
  45. package/dist/runtimeHelpers.d.ts +12 -1
  46. package/dist/runtimeHelpers.js +27 -3
  47. package/dist/runtimeHelpers.js.map +1 -1
  48. package/dist/util/logger.js.map +1 -1
  49. package/nativescript.webpack.js +199 -54
  50. package/package.json +49 -19
  51. package/dist/compiler-sfc/index.d.ts +0 -1
  52. package/dist/compiler-sfc/index.js +0 -2
  53. package/dist/compiler-sfc/index.js.map +0 -1
  54. package/dist/compiler.d.ts +0 -4
  55. package/dist/compiler.js +0 -32
  56. package/dist/compiler.js.map +0 -1
  57. package/dist/directives/vModel.d.ts +0 -8
  58. package/dist/directives/vModel.js +0 -38
  59. package/dist/directives/vModel.js.map +0 -1
  60. package/dist/plugins/templates.d.ts +0 -10
  61. package/dist/plugins/templates.js +0 -12
  62. package/dist/plugins/templates.js.map +0 -1
  63. package/dist/types.d.ts +0 -15
  64. package/dist/types.js +0 -2
  65. package/dist/types.js.map +0 -1
  66. package/dist/withCompiler.d.ts +0 -3
  67. package/dist/withCompiler.js +0 -6
  68. package/dist/withCompiler.js.map +0 -1
@@ -4,6 +4,7 @@ import { patchEvent } from './modules/events';
4
4
  import { patchStyle } from './modules/style';
5
5
  import { getViewMeta } from '../registry';
6
6
  import { isOn } from '../runtimeHelpers';
7
+ import { logger } from '../util/logger';
7
8
  export const patchProp = (el, key, prevValue, nextValue, namespace, parentComponent) => {
8
9
  switch (key) {
9
10
  // special
@@ -16,23 +17,29 @@ export const patchProp = (el, key, prevValue, nextValue, namespace, parentCompon
16
17
  patchStyle(el, prevValue, nextValue);
17
18
  break;
18
19
  case 'modelValue':
19
- case 'onUpdate:modelValue':
20
- try {
21
- // v-model - maps modelValue/onUpdate:modelValue to the correct prop/events from the registry meta
22
- const { prop, event } = getViewMeta(el.tagName)
23
- .model;
24
- if (key === 'modelValue') {
25
- patchAttr(el, prop, prevValue, nextValue);
26
- }
27
- else {
28
- const cb = nextValue
29
- ? ($event) => nextValue($event.object[prop])
30
- : nextValue;
31
- patchEvent(el, `on:${event}`, prevValue, cb);
32
- }
20
+ case 'onUpdate:modelValue': {
21
+ // v-model maps modelValue/onUpdate:modelValue to the prop/event pair
22
+ // declared in the element's registry meta
23
+ const model = resolveModel(el);
24
+ if (!model) {
25
+ break;
33
26
  }
34
- catch (err) {
35
- // ignore if the view meta can't be found.
27
+ if (key === 'modelValue') {
28
+ patchAttr(el, model.prop, prevValue, nextValue);
29
+ }
30
+ else {
31
+ const cb = nextValue
32
+ ? ($event) => nextValue($event.object[model.prop])
33
+ : nextValue;
34
+ patchEvent(el, `on:${model.event}`, prevValue, cb);
35
+ }
36
+ break;
37
+ }
38
+ case 'modelModifiers':
39
+ if (__DEV__ && nextValue && Object.keys(nextValue).length) {
40
+ logger.warn(`v-model modifiers (.${Object.keys(nextValue).join(', .')}) are ` +
41
+ `not supported on <${el.tagName}>; apply the transformation in ` +
42
+ `a computed setter instead.`);
36
43
  }
37
44
  break;
38
45
  default:
@@ -44,4 +51,19 @@ export const patchProp = (el, key, prevValue, nextValue, namespace, parentCompon
44
51
  }
45
52
  }
46
53
  };
54
+ function resolveModel(el) {
55
+ let model;
56
+ try {
57
+ model = getViewMeta(el.tagName).model;
58
+ }
59
+ catch {
60
+ // unregistered element, fall through to the warning
61
+ }
62
+ if (!model && __DEV__) {
63
+ logger.warn(`v-model is not supported on <${el.tagName}>: no model prop/event ` +
64
+ `pair is registered for it. Pass { model: { prop, event } } to ` +
65
+ `registerElement() to enable it.`);
66
+ }
67
+ return model;
68
+ }
47
69
  //# sourceMappingURL=patchProp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"patchProp.js","sourceRoot":"","sources":["../../src/renderer/patchProp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,OAAO,EAAE,WAAW,EAAsB,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAQzC,MAAM,CAAC,MAAM,SAAS,GAAiC,CACrD,EAAc,EACd,GAAW,EACX,SAAc,EACd,SAAc,EACd,SAA4B,EAC5B,eAAkD,EAClD,EAAE;IACF,QAAQ,GAAG,EAAE,CAAC;QACZ,UAAU;QACV,KAAK,OAAO;YACV,mCAAmC;YACnC,UAAU,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;YAC1B,MAAM;QACR,KAAK,OAAO;YACV,mCAAmC;YACnC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YACrC,MAAM;QACR,KAAK,YAAY,CAAC;QAClB,KAAK,qBAAqB;YACxB,IAAI,CAAC;gBACH,kGAAkG;gBAClG,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,OAAO,CAAC;qBAC5C,KAA2B,CAAC;gBAC/B,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;oBACzB,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBAC5C,CAAC;qBAAM,CAAC;oBACN,MAAM,EAAE,GAAG,SAAS;wBAClB,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBAC5C,CAAC,CAAC,SAAS,CAAC;oBACd,UAAU,CAAC,EAAE,EAAE,MAAM,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,0CAA0C;YAC5C,CAAC;YACD,MAAM;QACR;YACE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBACd,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;YAC7D,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YAC3C,CAAC;IACL,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"patchProp.js","sourceRoot":"","sources":["../../src/renderer/patchProp.ts"],"names":[],"mappings":"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","sourcesContent":["import { NSVElement } from '../dom';\nimport { patchAttr } from './modules/attrs';\nimport { patchClass } from './modules/class';\nimport { patchEvent } from './modules/events';\nimport { patchStyle } from './modules/style';\n\nimport { getViewMeta, NSVModelDescriptor } from '../registry';\nimport { isOn } from '../runtimeHelpers';\nimport { logger } from '../util/logger';\n\nimport type {\n ComponentInternalInstance,\n ElementNamespace,\n RendererOptions,\n} from '@vue/runtime-core';\n\nexport const patchProp: RendererOptions['patchProp'] = (\n el: NSVElement,\n key: string,\n prevValue: any,\n nextValue: any,\n namespace?: ElementNamespace,\n parentComponent?: ComponentInternalInstance | null,\n) => {\n switch (key) {\n // special\n case 'class':\n // console.log('->patchProp+Class')\n patchClass(el, nextValue);\n break;\n case 'style':\n // console.log('->patchProp+Style')\n patchStyle(el, prevValue, nextValue);\n break;\n case 'modelValue':\n case 'onUpdate:modelValue': {\n // v-model maps modelValue/onUpdate:modelValue to the prop/event pair\n // declared in the element's registry meta\n const model = resolveModel(el);\n if (!model) {\n break;\n }\n if (key === 'modelValue') {\n patchAttr(el, model.prop, prevValue, nextValue);\n } else {\n const cb = nextValue\n ? ($event) => nextValue($event.object[model.prop])\n : nextValue;\n patchEvent(el, `on:${model.event}`, prevValue, cb);\n }\n break;\n }\n case 'modelModifiers':\n if (__DEV__ && nextValue && Object.keys(nextValue).length) {\n logger.warn(\n `v-model modifiers (.${Object.keys(nextValue).join(', .')}) are ` +\n `not supported on <${el.tagName}>; apply the transformation in ` +\n `a computed setter instead.`,\n );\n }\n break;\n default:\n if (isOn(key)) {\n patchEvent(el, key, prevValue, nextValue, parentComponent);\n } else {\n patchAttr(el, key, prevValue, nextValue);\n }\n }\n};\n\nfunction resolveModel(el: NSVElement): NSVModelDescriptor | undefined {\n let model: NSVModelDescriptor | undefined;\n try {\n model = getViewMeta(el.tagName).model;\n } catch {\n // unregistered element, fall through to the warning\n }\n if (!model && __DEV__) {\n logger.warn(\n `v-model is not supported on <${el.tagName}>: no model prop/event ` +\n `pair is registered for it. Pass { model: { prop, event } } to ` +\n `registerElement() to enable it.`,\n );\n }\n return model;\n}\n"]}
@@ -1,5 +1,16 @@
1
+ import { KeepAlive as KeepAliveCore } from '@vue/runtime-core';
1
2
  export declare const TransitionGroup: {
2
3
  "new"(): {
3
4
  $props: {};
4
5
  };
5
6
  };
7
+ /**
8
+ * runtime-core's KeepAlive parks deactivated subtrees in a container it
9
+ * obtains from createElement('div'), which is not a registered view here.
10
+ * It reads the renderer from the instance context during setup, so hand it
11
+ * one whose createElement yields a detached container instead. Deactivated
12
+ * views are removed from their native parent and re-added on activation;
13
+ * NativeScript recreates their native views then, so the component state
14
+ * survives but native-only state such as scroll offsets does not.
15
+ */
16
+ export declare const KeepAlive: typeof KeepAliveCore;
@@ -1,3 +1,5 @@
1
+ import { getCurrentInstance, KeepAlive as KeepAliveCore, } from '@vue/runtime-core';
2
+ import { NSVDetachedContainer } from '../dom';
1
3
  import { logger } from '../util/logger';
2
4
  export const TransitionGroup = {
3
5
  new() {
@@ -5,4 +7,25 @@ export const TransitionGroup = {
5
7
  return { $props: {} };
6
8
  },
7
9
  };
10
+ /**
11
+ * runtime-core's KeepAlive parks deactivated subtrees in a container it
12
+ * obtains from createElement('div'), which is not a registered view here.
13
+ * It reads the renderer from the instance context during setup, so hand it
14
+ * one whose createElement yields a detached container instead. Deactivated
15
+ * views are removed from their native parent and re-added on activation;
16
+ * NativeScript recreates their native views then, so the component state
17
+ * survives but native-only state such as scroll offsets does not.
18
+ */
19
+ export const KeepAlive = {
20
+ ...KeepAliveCore,
21
+ setup(props, ctx) {
22
+ const { ctx: sharedContext } = getCurrentInstance();
23
+ const renderer = sharedContext.renderer;
24
+ sharedContext.renderer = {
25
+ ...renderer,
26
+ o: { ...renderer.o, createElement: () => new NSVDetachedContainer() },
27
+ };
28
+ return KeepAliveCore.setup(props, ctx);
29
+ },
30
+ };
8
31
  //# sourceMappingURL=runtimeDomOverrides.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeDomOverrides.js","sourceRoot":"","sources":["../../src/renderer/runtimeDomOverrides.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,GAAG;QACD,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"runtimeDomOverrides.js","sourceRoot":"","sources":["../../src/renderer/runtimeDomOverrides.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,SAAS,IAAI,aAAa,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAExC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,GAAG;QACD,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,GAAI,aAAqB;IACzB,KAAK,CAAC,KAAU,EAAE,GAAQ;QACxB,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,kBAAkB,EAAS,CAAC;QAC3D,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;QAExC,aAAa,CAAC,QAAQ,GAAG;YACvB,GAAG,QAAQ;YACX,CAAC,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAC,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,oBAAoB,EAAE,EAAE;SACtE,CAAC;QAEF,OAAQ,aAAqB,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;CACiC,CAAC","sourcesContent":["import {\n getCurrentInstance,\n KeepAlive as KeepAliveCore,\n} from '@vue/runtime-core';\nimport { NSVDetachedContainer } from '../dom';\nimport { logger } from '../util/logger';\n\nexport const TransitionGroup = {\n new() {\n logger.warn('TransitionGroup is not supported');\n return { $props: {} };\n },\n};\n\n/**\n * runtime-core's KeepAlive parks deactivated subtrees in a container it\n * obtains from createElement('div'), which is not a registered view here.\n * It reads the renderer from the instance context during setup, so hand it\n * one whose createElement yields a detached container instead. Deactivated\n * views are removed from their native parent and re-added on activation;\n * NativeScript recreates their native views then, so the component state\n * survives but native-only state such as scroll offsets does not.\n */\nexport const KeepAlive = {\n ...(KeepAliveCore as any),\n setup(props: any, ctx: any) {\n const { ctx: sharedContext } = getCurrentInstance() as any;\n const renderer = sharedContext.renderer;\n\n sharedContext.renderer = {\n ...renderer,\n o: { ...renderer.o, createElement: () => new NSVDetachedContainer() },\n };\n\n return (KeepAliveCore as any).setup(props, ctx);\n },\n} as unknown as typeof KeepAliveCore;\n"]}
@@ -5,15 +5,21 @@ export declare const setRootApp: (app: App) => void;
5
5
  export type ContextOverrides = {
6
6
  reload?(): void;
7
7
  };
8
+ /**
9
+ * Devtools label each app after its root component's `name`. Script-setup
10
+ * SFCs only carry `__name`, which Vue already treats as the fallback
11
+ * everywhere else, so every page and modal would otherwise show as "App N".
12
+ */
13
+ export declare function nameForDevtools(component: Component): void;
8
14
  export type CreateNativeViewProps<P> = Partial<P & VNodeProps & Record<string, any>>;
9
15
  export declare function createNativeView<T = View, P = any>(component: Component<P>, props?: CreateNativeViewProps<P>, contextOverrides?: ContextOverrides): {
10
16
  context: {
11
- reload?(): void;
12
17
  config: import("@vue/runtime-core").AppConfig;
13
18
  mixins: import("@vue/runtime-core").ComponentOptions[];
14
19
  components: Record<string, Component>;
15
20
  directives: Record<string, import("@vue/runtime-core").Directive>;
16
21
  provides: Record<string | symbol, any>;
22
+ reload?: () => void;
17
23
  };
18
24
  readonly vnode: VNode<RendererNode, RendererElement, {
19
25
  [key: string]: any;
@@ -28,4 +34,9 @@ export declare const ELEMENT_REF: unique symbol;
28
34
  export declare const isOn: (key: string) => boolean;
29
35
  export declare const isAndroidKey: (key: string) => boolean;
30
36
  export declare const isIOSKey: (key: string) => boolean;
37
+ /**
38
+ * `android:foo` targets the view's own `foo`; `android.foo` keeps its path
39
+ * into the view's platform-specific settings object.
40
+ */
41
+ export declare const stripPlatformPrefix: (key: string, platform: string) => string;
31
42
  export declare const isBoolean: (value: unknown) => boolean;
@@ -4,9 +4,24 @@ let rootApp = null;
4
4
  export const setRootApp = (app) => {
5
5
  rootApp = app;
6
6
  };
7
+ /**
8
+ * Devtools label each app after its root component's `name`. Script-setup
9
+ * SFCs only carry `__name`, which Vue already treats as the fallback
10
+ * everywhere else, so every page and modal would otherwise show as "App N".
11
+ */
12
+ export function nameForDevtools(component) {
13
+ if (__DEV__ &&
14
+ component &&
15
+ typeof component === 'object' &&
16
+ !component.name &&
17
+ component.__name) {
18
+ component.name = component.__name;
19
+ }
20
+ }
7
21
  export function createNativeView(component, props, contextOverrides) {
8
22
  let isMounted = false;
9
23
  let vm;
24
+ nameForDevtools(component);
10
25
  let currentApp = renderer.createApp(component, props);
11
26
  // Destructure so as not to copy over the root app instance
12
27
  const { app, ...rootContext } = rootApp._context;
@@ -48,10 +63,19 @@ export function createNativeView(component, props, contextOverrides) {
48
63
  };
49
64
  }
50
65
  export const ELEMENT_REF = Symbol(__DEV__ ? `elementRef` : ``);
51
- const onRE = /^on.+/;
66
+ // matches Vue's own isOn: "on" followed by anything but a lowercase letter,
67
+ // so onTap and on:textChange are events while onboardingTitle is a prop
68
+ const onRE = /^on[^a-z]/;
52
69
  export const isOn = (key) => onRE.test(key);
53
- export const isAndroidKey = (key) => key.startsWith('android:');
54
- export const isIOSKey = (key) => key.startsWith('ios:');
70
+ export const isAndroidKey = (key) => key.startsWith('android:') || key.startsWith('android.');
71
+ export const isIOSKey = (key) => key.startsWith('ios:') || key.startsWith('ios.');
72
+ /**
73
+ * `android:foo` targets the view's own `foo`; `android.foo` keeps its path
74
+ * into the view's platform-specific settings object.
75
+ */
76
+ export const stripPlatformPrefix = (key, platform) => key.charAt(platform.length) === ':'
77
+ ? key.substring(platform.length + 1)
78
+ : key;
55
79
  export const isBoolean = (value) => {
56
80
  return typeof value === 'boolean' || value instanceof Boolean;
57
81
  };
@@ -1 +1 @@
1
- {"version":3,"file":"runtimeHelpers.js","sourceRoot":"","sources":["../src/runtimeHelpers.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtimeHelpers.js","sourceRoot":"","sources":["../src/runtimeHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["import { View } from '@nativescript/core';\nimport {\n App,\n Component,\n ComponentPublicInstance,\n RendererElement,\n RendererNode,\n VNode,\n VNodeProps,\n} from '@vue/runtime-core';\nimport { NSVNode, NSVRoot } from './dom';\nimport { renderer } from './renderer';\n\nlet rootApp: App = null;\nexport const setRootApp = (app: App) => {\n rootApp = app;\n};\n\nexport type ContextOverrides = { reload?(): void };\n\n/**\n * Devtools label each app after its root component's `name`. Script-setup\n * SFCs only carry `__name`, which Vue already treats as the fallback\n * everywhere else, so every page and modal would otherwise show as \"App N\".\n */\nexport function nameForDevtools(component: Component) {\n if (\n __DEV__ &&\n component &&\n typeof component === 'object' &&\n !(component as any).name &&\n (component as any).__name\n ) {\n (component as any).name = (component as any).__name;\n }\n}\nexport type CreateNativeViewProps<P> = Partial<\n P & VNodeProps & Record<string, any>\n>;\n\nexport function createNativeView<T = View, P = any>(\n component: Component<P>,\n props?: CreateNativeViewProps<P>,\n contextOverrides?: ContextOverrides,\n) {\n let isMounted = false;\n let vm: ComponentPublicInstance | null;\n nameForDevtools(component);\n let currentApp = renderer.createApp(component, props);\n // Destructure so as not to copy over the root app instance\n const { app, ...rootContext } = rootApp._context;\n const context = { ...rootContext, ...contextOverrides };\n\n type M = VNode<RendererNode, RendererElement, { nativeView: T }>;\n return {\n context,\n get vnode() {\n return vm?.$.vnode;\n },\n get nativeView(): T {\n return this.vnode?.el.nativeView;\n },\n mount(root: NSVNode = new NSVRoot()) {\n if (isMounted) {\n return this.vnode as M;\n }\n\n // Create a NEW app instance for remount (after HMR unmount) as Vue doesn't allow mounting the same app instance twice\n if (!currentApp._instance) {\n currentApp = renderer.createApp(component, props);\n }\n\n Object.keys(context).forEach((key) => {\n currentApp._context[key] = context[key];\n });\n\n vm = currentApp.mount(root);\n\n // Set reload callback on the component instance's appContext, for HMR to work on navigated pages\n if (context.reload && vm && (vm as any).$?.appContext) {\n (vm as any).$.appContext.reload = context.reload;\n }\n\n isMounted = true;\n\n return this.vnode as M;\n },\n unmount() {\n if (!isMounted) return;\n\n vm = null;\n currentApp.unmount();\n\n isMounted = false;\n },\n };\n}\n\nexport const ELEMENT_REF = Symbol(__DEV__ ? `elementRef` : ``);\n\n// matches Vue's own isOn: \"on\" followed by anything but a lowercase letter,\n// so onTap and on:textChange are events while onboardingTitle is a prop\nconst onRE = /^on[^a-z]/;\nexport const isOn = (key: string) => onRE.test(key);\n\nexport const isAndroidKey = (key: string) =>\n key.startsWith('android:') || key.startsWith('android.');\n\nexport const isIOSKey = (key: string) =>\n key.startsWith('ios:') || key.startsWith('ios.');\n\n/**\n * `android:foo` targets the view's own `foo`; `android.foo` keeps its path\n * into the view's platform-specific settings object.\n */\nexport const stripPlatformPrefix = (key: string, platform: string) =>\n key.charAt(platform.length) === ':'\n ? key.substring(platform.length + 1)\n : key;\n\nexport const isBoolean = (value: unknown): boolean => {\n return typeof value === 'boolean' || value instanceof Boolean;\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,CAAC,GAAW;QACd,IAAI,CAAC,GAAG,UAAU,IAAI,GAAG,EAAE,CAAC,CAAC;IAC/B,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,MAAM,UAAU,GAAG,oBAAoB,CAAC;AAExC,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,CAAC,GAAW;QACd,IAAI,CAAC,GAAG,UAAU,IAAI,GAAG,EAAE,CAAC,CAAC;IAC/B,CAAC;CACF,CAAC","sourcesContent":["import { warn } from '@vue/runtime-core';\n\nconst baseLogger = '[NativeScript-Vue]';\n\nexport const logger = {\n warn(msg: string) {\n warn(`${baseLogger} ${msg}`);\n },\n};\n"]}
@@ -1,5 +1,7 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { spawn } = require('child_process');
1
4
  const { VueLoaderPlugin } = require('vue-loader');
2
- const spawn = require('cross-spawn');
3
5
 
4
6
  function findFreePort(startingPort = 8098) {
5
7
  let found = false;
@@ -30,31 +32,141 @@ function findFreePort(startingPort = 8098) {
30
32
 
31
33
  findFreePort();
32
34
 
35
+ // webpack config hooks are synchronous; listen() reports through nextTick
36
+ // and the promise through microtasks, both of which _tickCallback drains
37
+ if (typeof process._tickCallback !== 'function') {
38
+ return port;
39
+ }
40
+
33
41
  while (!found) {
34
42
  process._tickCallback();
35
43
  const start = Date.now();
36
44
  while (Date.now() - start < 100) {
37
- // busy wait... not ideal, but we need to find a port synchronously...
45
+ // busy wait
38
46
  }
39
47
  }
40
48
 
41
49
  return port;
42
50
  }
43
51
 
44
- function startVueDevtools(port, isAndroid = false) {
45
- console.log(`[VueDevtools] Starting standalone Vue Devtools on port ${port}`);
52
+ /**
53
+ * Finds the directory of an installed package the way Node would, without
54
+ * going through its exports map (most of the devtools packages do not
55
+ * expose package.json there). Handles hoisted, nested and pnpm layouts.
56
+ */
57
+ function findPackageDir(name, from) {
58
+ let dir = from;
59
+ for (;;) {
60
+ const candidates = [path.join(dir, 'node_modules', name)];
61
+ if (path.basename(dir) === 'node_modules') {
62
+ candidates.push(path.join(dir, name));
63
+ }
64
+ for (const candidate of candidates) {
65
+ if (fs.existsSync(path.join(candidate, 'package.json'))) {
66
+ return fs.realpathSync(candidate);
67
+ }
68
+ }
69
+ const parent = path.dirname(dir);
70
+ if (parent === dir) {
71
+ return null;
72
+ }
73
+ dir = parent;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Locates @vue/devtools and the client packages it brings along, resolving
79
+ * from the app so a hoisted or nested layout both work.
80
+ */
81
+ function resolveDevtools(projectRoot) {
82
+ const devtoolsDir = findPackageDir('@vue/devtools', projectRoot);
83
+ if (!devtoolsDir) {
84
+ return null;
85
+ }
86
+
87
+ const version = require(path.join(devtoolsDir, 'package.json')).version;
88
+ const major = parseInt(version.split('.')[0], 10);
89
+ if (major < 8) {
90
+ throw new Error(
91
+ `@vue/devtools ${version} is installed but nativescript-vue needs ^8. Run: npm i -D @vue/devtools@^8`,
92
+ );
93
+ }
94
+
95
+ const requireDir = (name, from) => {
96
+ const dir = findPackageDir(name, from);
97
+ if (!dir) {
98
+ throw new Error(
99
+ `[VueDevtools] ${name} is missing next to @vue/devtools. Reinstall it: npm i -D @vue/devtools@^8`,
100
+ );
101
+ }
102
+ return dir;
103
+ };
104
+
105
+ const electronDir = requireDir('@vue/devtools-electron', devtoolsDir);
106
+
107
+ return {
108
+ version,
109
+ cli: path.join(electronDir, 'dist/cli.mjs'),
110
+ aliases: {
111
+ // the package entry resolves to the Node build under NativeScript's
112
+ // node target; the app needs the browser build (global XMLHttpRequest)
113
+ 'socket.io-client': path.join(
114
+ requireDir('socket.io-client', electronDir),
115
+ 'build/esm/index.js',
116
+ ),
117
+ '@vue/devtools-kit': requireDir('@vue/devtools-kit', devtoolsDir),
118
+ '@vue/devtools-core': requireDir('@vue/devtools-core', electronDir),
119
+ },
120
+ };
121
+ }
122
+
123
+ // packages whose imports must resolve with browser conditions and fields,
124
+ // otherwise the socket.io stack pulls in ws, xmlhttprequest-ssl and Node
125
+ // core modules that do not exist in the app
126
+ const BROWSER_RESOLVED_PACKAGES =
127
+ /[\\/]node_modules[\\/](socket\.io-client|engine\.io-client|socket\.io-parser|engine\.io-parser)[\\/]/;
128
+
129
+ function startVueDevtools(cli, port, isAndroid, debug) {
130
+ console.log(`[VueDevtools] Starting Vue Devtools on port ${port}`);
46
131
  if (isAndroid) {
47
132
  console.log(
48
- `[VueDevtools] If the app doesn't automatically connect, check if http traffic is allowed. (e.g. on Android, you may need to set android:usesCleartextTraffic="true" in AndroidManifest.xml)`,
133
+ `[VueDevtools] If the app doesn't connect, make sure cleartext HTTP is allowed: set android:usesCleartextTraffic="true" on <application> in AndroidManifest.xml`,
49
134
  );
50
135
  }
51
- spawn(require.resolve('@vue/devtools/bin.js'), [], {
52
- stdio: 'ignore',
136
+ const child = spawn(process.execPath, [cli], {
137
+ stdio: debug ? 'inherit' : 'ignore',
53
138
  env: {
54
139
  ...process.env,
55
- PORT: port,
140
+ PORT: String(port),
56
141
  },
57
142
  });
143
+ child.on('error', (err) => {
144
+ console.warn(`[VueDevtools] Failed to start the devtools app: ${err}`);
145
+ });
146
+ }
147
+
148
+ /**
149
+ * Warns when the app resolves a `vue` package whose version differs from the
150
+ * runtime nativescript-vue ships. vue-loader compiles templates with that
151
+ * package's compiler when present, and a mismatch can emit helpers the
152
+ * runtime does not have.
153
+ */
154
+ function checkVueVersionSkew(projectRoot) {
155
+ let vuePkg;
156
+ try {
157
+ vuePkg = require(
158
+ require.resolve('vue/package.json', { paths: [projectRoot] }),
159
+ );
160
+ } catch {
161
+ return;
162
+ }
163
+ const runtimeVersion = require('@vue/runtime-core/package.json').version;
164
+ if (vuePkg.version !== runtimeVersion) {
165
+ console.warn(
166
+ `[nativescript-vue] vue@${vuePkg.version} is installed in this project but nativescript-vue uses @vue/runtime-core@${runtimeVersion}. ` +
167
+ `Templates are compiled with the installed vue's compiler, so keep both on the same version.`,
168
+ );
169
+ }
58
170
  }
59
171
 
60
172
  /**
@@ -62,44 +174,76 @@ function startVueDevtools(port, isAndroid = false) {
62
174
  */
63
175
  module.exports = (webpack) => {
64
176
  webpack.chainWebpack((config, env) => {
177
+ const projectRoot = webpack.Utils.project.getProjectRootPath();
65
178
  const additionalDefines = {
66
179
  __VUE_PROD_DEVTOOLS__: false,
67
- __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false
180
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
68
181
  };
69
182
 
70
- // todo: support configuring the devtools host/port from the nativescript.config.ts...
71
- if (!!env.vueDevtools) {
72
- // find a free port for the devtools
73
- const vueDevtoolsPort = findFreePort(8098);
74
- const isAndroid = webpack.Utils.platform.getPlatformName() === 'android';
75
-
76
- // on android simulators, localhost is not the host machine...
77
- const vueDevtoolsHost = isAndroid
78
- ? 'http://10.0.2.2'
79
- : 'http://localhost';
80
-
81
- additionalDefines['__VUE_PROD_DEVTOOLS__'] = true;
82
- additionalDefines['__NS_VUE_DEVTOOLS_HOST__'] =
83
- JSON.stringify(vueDevtoolsHost);
84
- additionalDefines['__NS_VUE_DEVTOOLS_PORT__'] = vueDevtoolsPort;
85
-
86
- const devtoolsEntryPath = require.resolve('./devtools.js');
87
- const entryPath = webpack.Utils.platform.getEntryPath();
88
- const paths = config.entry('bundle').values();
89
- const entryIndex = paths.indexOf(entryPath);
90
-
91
- if (entryIndex === -1) {
92
- // if the app entry is not found, add the devtools entry at the beginning - generally should not happen, but just in case.
93
- paths.unshift(entryPath);
183
+ checkVueVersionSkew(projectRoot);
184
+
185
+ if (env.vueDevtools) {
186
+ const devtools = resolveDevtools(projectRoot);
187
+
188
+ if (!devtools) {
189
+ console.warn(
190
+ `[VueDevtools] --env.vueDevtools was passed but @vue/devtools is not installed. Run: npm i -D @vue/devtools@^8`,
191
+ );
94
192
  } else {
95
- // insert devtools entry before the app entry, but after globals etc.
96
- paths.splice(entryIndex, 0, devtoolsEntryPath);
97
- }
193
+ const isAndroid =
194
+ webpack.Utils.platform.getPlatformName() === 'android';
195
+ const port = env.vueDevtoolsPort
196
+ ? parseInt(env.vueDevtoolsPort, 10)
197
+ : findFreePort(8098);
198
+ // on Android emulators, localhost is not the host machine
199
+ const host =
200
+ env.vueDevtoolsHost ??
201
+ (isAndroid ? 'http://10.0.2.2' : 'http://localhost');
98
202
 
99
- config.entry('bundle').clear().merge(paths);
203
+ additionalDefines['__VUE_PROD_DEVTOOLS__'] = true;
204
+ additionalDefines['__NS_VUE_DEVTOOLS_HOST__'] = JSON.stringify(host);
205
+ additionalDefines['__NS_VUE_DEVTOOLS_PORT__'] = port;
206
+ additionalDefines['__NS_VUE_DEVTOOLS_DEBUG__'] = !!env.vueDevtoolsDebug;
100
207
 
101
- // start the devtools...
102
- startVueDevtools(vueDevtoolsPort, isAndroid);
208
+ for (const [name, dir] of Object.entries(devtools.aliases)) {
209
+ config.resolve.alias.set(name, dir);
210
+ }
211
+
212
+ const clientRule = config.module
213
+ .rule('vue-devtools-client')
214
+ .test(BROWSER_RESOLVED_PACKAGES);
215
+ clientRule.resolve.set('conditionNames', [
216
+ 'browser',
217
+ 'import',
218
+ 'module',
219
+ 'default',
220
+ ]);
221
+ clientRule.resolve.aliasFields.add('browser');
222
+ clientRule.resolve.mainFields.merge(['browser', 'module', 'main']);
223
+
224
+ const devtoolsEntryPath = require.resolve('./devtools.js');
225
+ const entryPath = webpack.Utils.platform.getEntryPath();
226
+ const paths = config.entry('bundle').values();
227
+ const entryIndex = paths.indexOf(entryPath);
228
+
229
+ if (entryIndex === -1) {
230
+ paths.unshift(devtoolsEntryPath);
231
+ } else {
232
+ // before the app entry, after globals etc.
233
+ paths.splice(entryIndex, 0, devtoolsEntryPath);
234
+ }
235
+
236
+ config.entry('bundle').clear().merge(paths);
237
+
238
+ if (String(env.vueDevtoolsSpawn) !== 'false') {
239
+ startVueDevtools(
240
+ devtools.cli,
241
+ port,
242
+ isAndroid,
243
+ !!env.vueDevtoolsDebug,
244
+ );
245
+ }
246
+ }
103
247
  }
104
248
 
105
249
  // resolve any imports from "vue" to "nativescript-vue"
@@ -116,10 +260,7 @@ module.exports = (webpack) => {
116
260
  return {
117
261
  ...options,
118
262
  isServerBuild: false,
119
- compilerOptions: {
120
- // isCustomElement: (el) => el.toLowerCase() === 'label',
121
- // transformHoist: null
122
- },
263
+ compilerOptions: {},
123
264
  };
124
265
  });
125
266
 
@@ -142,19 +283,23 @@ module.exports = (webpack) => {
142
283
  return args;
143
284
  });
144
285
 
145
- // disable vue fork ts checker, as it doesn't work with vue3 yet?
146
- config.plugin('ForkTsCheckerWebpackPlugin').tap((args) => {
147
- args[0] = webpack.merge(args[0], {
148
- typescript: {
149
- extensions: {
150
- vue: {
151
- enabled: false,
286
+ // @nativescript/webpack only registers the checker when the project
287
+ // depends on typescript; tapping an unregistered plugin throws
288
+ if (config.plugins.has('ForkTsCheckerWebpackPlugin')) {
289
+ // disable vue fork ts checker, as it doesn't work with vue3 yet?
290
+ config.plugin('ForkTsCheckerWebpackPlugin').tap((args) => {
291
+ args[0] = webpack.merge(args[0], {
292
+ typescript: {
293
+ extensions: {
294
+ vue: {
295
+ enabled: false,
296
+ },
152
297
  },
153
298
  },
154
- },
155
- });
299
+ });
156
300
 
157
- return args;
158
- });
301
+ return args;
302
+ });
303
+ }
159
304
  });
160
305
  };