@embedpdf/plugin-viewport 1.0.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/index.ts","../../src/react/components/viewport.tsx","../../src/react/hooks/use-viewport.ts","../../src/react/hooks/use-viewport-ref.ts"],"sourcesContent":["export * from './components';\nexport * from './hooks';\n","import React, { ReactNode, useEffect, useState } from 'react';\n\nimport { useViewportCapability } from '../hooks';\nimport { useViewportRef } from '../hooks/use-viewport-ref';\n\ntype ViewportProps = React.HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n};\n\nexport function Viewport({ children, ...props }: ViewportProps) {\n const [viewportGap, setViewportGap] = useState(0);\n const viewportRef = useViewportRef();\n const { provides: viewportProvides } = useViewportCapability();\n\n useEffect(() => {\n if (viewportProvides) {\n setViewportGap(viewportProvides.getViewportGap());\n }\n }, [viewportProvides]);\n\n const { style, ...restProps } = props;\n return (\n <div\n {...restProps}\n ref={viewportRef}\n style={{\n ...(typeof style === 'object' ? style : {}),\n padding: `${viewportGap}px`,\n }}\n >\n {children}\n </div>\n );\n}\n","import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nexport const useViewport = () => usePlugin<ViewportPlugin>(ViewportPlugin.id);\nexport const useViewportCapability = () => useCapability<ViewportPlugin>(ViewportPlugin.id);\n","import { useLayoutEffect, useRef } from 'react';\n\nimport { useViewportCapability } from './use-viewport';\nimport { Rect } from '@embedpdf/models';\n\nexport function useViewportRef() {\n const { provides: viewportProvides } = useViewportCapability();\n const containerRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (!viewportProvides) return;\n\n const container = containerRef.current;\n if (!container) return;\n\n /* ---------- live rect provider --------------------------------- */\n const provideRect = (): Rect => {\n const r = container.getBoundingClientRect();\n return {\n origin: { x: r.left, y: r.top },\n size: { width: r.width, height: r.height },\n };\n };\n viewportProvides.registerBoundingRectProvider(provideRect);\n\n // Example: On scroll, call setMetrics\n const onScroll = () => {\n viewportProvides.setViewportScrollMetrics({\n scrollTop: container.scrollTop,\n scrollLeft: container.scrollLeft,\n });\n };\n container.addEventListener('scroll', onScroll);\n\n // Example: On resize, call setMetrics\n const resizeObserver = new ResizeObserver(() => {\n const rect = container.getBoundingClientRect();\n\n viewportProvides.setViewportMetrics({\n width: container.offsetWidth,\n height: container.offsetHeight,\n clientWidth: container.clientWidth,\n clientHeight: container.clientHeight,\n scrollTop: container.scrollTop,\n scrollLeft: container.scrollLeft,\n scrollWidth: container.scrollWidth,\n scrollHeight: container.scrollHeight,\n });\n });\n resizeObserver.observe(container);\n\n const unsubscribeScrollRequest = viewportProvides.onScrollRequest(\n ({ x, y, behavior = 'auto' }) => {\n requestAnimationFrame(() => {\n container.scrollTo({ left: x, top: y, behavior });\n });\n },\n );\n\n // Cleanup\n return () => {\n viewportProvides.registerBoundingRectProvider(null);\n container.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n unsubscribeScrollRequest();\n };\n }, [viewportProvides]);\n\n // Return the ref so your React code can attach it to a div\n return containerRef;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,gBAAsD;;;ACAtD,mBAAyC;AACzC,6BAA+B;AAExB,IAAM,cAAc,UAAM,wBAA0B,sCAAe,EAAE;AACrE,IAAM,wBAAwB,UAAM,4BAA8B,sCAAe,EAAE;;;ACJ1F,IAAAC,gBAAwC;AAKjC,SAAS,iBAAiB;AAC/B,QAAM,EAAE,UAAU,iBAAiB,IAAI,sBAAsB;AAC7D,QAAM,mBAAe,sBAAuB,IAAI;AAEhD,qCAAgB,MAAM;AACpB,QAAI,CAAC,iBAAkB;AAEvB,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,UAAW;AAGhB,UAAM,cAAc,MAAY;AAC9B,YAAM,IAAI,UAAU,sBAAsB;AAC1C,aAAO;AAAA,QACL,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,IAAI;AAAA,QAC9B,MAAM,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO;AAAA,MAC3C;AAAA,IACF;AACA,qBAAiB,6BAA6B,WAAW;AAGzD,UAAM,WAAW,MAAM;AACrB,uBAAiB,yBAAyB;AAAA,QACxC,WAAW,UAAU;AAAA,QACrB,YAAY,UAAU;AAAA,MACxB,CAAC;AAAA,IACH;AACA,cAAU,iBAAiB,UAAU,QAAQ;AAG7C,UAAM,iBAAiB,IAAI,eAAe,MAAM;AAC9C,YAAM,OAAO,UAAU,sBAAsB;AAE7C,uBAAiB,mBAAmB;AAAA,QAClC,OAAO,UAAU;AAAA,QACjB,QAAQ,UAAU;AAAA,QAClB,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,QACxB,WAAW,UAAU;AAAA,QACrB,YAAY,UAAU;AAAA,QACtB,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,MAC1B,CAAC;AAAA,IACH,CAAC;AACD,mBAAe,QAAQ,SAAS;AAEhC,UAAM,2BAA2B,iBAAiB;AAAA,MAChD,CAAC,EAAE,GAAG,GAAG,WAAW,OAAO,MAAM;AAC/B,8BAAsB,MAAM;AAC1B,oBAAU,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAAA,QAClD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,WAAO,MAAM;AACX,uBAAiB,6BAA6B,IAAI;AAClD,gBAAU,oBAAoB,UAAU,QAAQ;AAChD,qBAAe,WAAW;AAC1B,+BAAyB;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAGrB,SAAO;AACT;;;AFhDI;AAbG,SAAS,SAAS,EAAE,UAAU,GAAG,MAAM,GAAkB;AAC9D,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,CAAC;AAChD,QAAM,cAAc,eAAe;AACnC,QAAM,EAAE,UAAU,iBAAiB,IAAI,sBAAsB;AAE7D,+BAAU,MAAM;AACd,QAAI,kBAAkB;AACpB,qBAAe,iBAAiB,eAAe,CAAC;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAErB,QAAM,EAAE,OAAO,GAAG,UAAU,IAAI;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,KAAK;AAAA,MACL,OAAO;AAAA,QACL,GAAI,OAAO,UAAU,WAAW,QAAQ,CAAC;AAAA,QACzC,SAAS,GAAG,WAAW;AAAA,MACzB;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":["import_react","import_react"]}
@@ -0,0 +1,25 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import React__default, { ReactNode } from 'react';
4
+ import * as _embedpdf_plugin_viewport from '@embedpdf/plugin-viewport';
5
+ import { ViewportPlugin } from '@embedpdf/plugin-viewport';
6
+
7
+ type ViewportProps = React__default.HTMLAttributes<HTMLDivElement> & {
8
+ children: ReactNode;
9
+ };
10
+ declare function Viewport({ children, ...props }: ViewportProps): react_jsx_runtime.JSX.Element;
11
+
12
+ declare const useViewport: () => {
13
+ plugin: ViewportPlugin | null;
14
+ isLoading: boolean;
15
+ ready: Promise<void>;
16
+ };
17
+ declare const useViewportCapability: () => {
18
+ provides: Readonly<_embedpdf_plugin_viewport.ViewportCapability> | null;
19
+ isLoading: boolean;
20
+ ready: Promise<void>;
21
+ };
22
+
23
+ declare function useViewportRef(): React.RefObject<HTMLDivElement>;
24
+
25
+ export { Viewport, useViewport, useViewportCapability, useViewportRef };
@@ -0,0 +1,25 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import React__default, { ReactNode } from 'react';
4
+ import * as _embedpdf_plugin_viewport from '@embedpdf/plugin-viewport';
5
+ import { ViewportPlugin } from '@embedpdf/plugin-viewport';
6
+
7
+ type ViewportProps = React__default.HTMLAttributes<HTMLDivElement> & {
8
+ children: ReactNode;
9
+ };
10
+ declare function Viewport({ children, ...props }: ViewportProps): react_jsx_runtime.JSX.Element;
11
+
12
+ declare const useViewport: () => {
13
+ plugin: ViewportPlugin | null;
14
+ isLoading: boolean;
15
+ ready: Promise<void>;
16
+ };
17
+ declare const useViewportCapability: () => {
18
+ provides: Readonly<_embedpdf_plugin_viewport.ViewportCapability> | null;
19
+ isLoading: boolean;
20
+ ready: Promise<void>;
21
+ };
22
+
23
+ declare function useViewportRef(): React.RefObject<HTMLDivElement>;
24
+
25
+ export { Viewport, useViewport, useViewportCapability, useViewportRef };
@@ -0,0 +1,96 @@
1
+ // src/react/components/viewport.tsx
2
+ import { useEffect, useState } from "react";
3
+
4
+ // src/react/hooks/use-viewport.ts
5
+ import { useCapability, usePlugin } from "@embedpdf/core/react";
6
+ import { ViewportPlugin } from "@embedpdf/plugin-viewport";
7
+ var useViewport = () => usePlugin(ViewportPlugin.id);
8
+ var useViewportCapability = () => useCapability(ViewportPlugin.id);
9
+
10
+ // src/react/hooks/use-viewport-ref.ts
11
+ import { useLayoutEffect, useRef } from "react";
12
+ function useViewportRef() {
13
+ const { provides: viewportProvides } = useViewportCapability();
14
+ const containerRef = useRef(null);
15
+ useLayoutEffect(() => {
16
+ if (!viewportProvides) return;
17
+ const container = containerRef.current;
18
+ if (!container) return;
19
+ const provideRect = () => {
20
+ const r = container.getBoundingClientRect();
21
+ return {
22
+ origin: { x: r.left, y: r.top },
23
+ size: { width: r.width, height: r.height }
24
+ };
25
+ };
26
+ viewportProvides.registerBoundingRectProvider(provideRect);
27
+ const onScroll = () => {
28
+ viewportProvides.setViewportScrollMetrics({
29
+ scrollTop: container.scrollTop,
30
+ scrollLeft: container.scrollLeft
31
+ });
32
+ };
33
+ container.addEventListener("scroll", onScroll);
34
+ const resizeObserver = new ResizeObserver(() => {
35
+ const rect = container.getBoundingClientRect();
36
+ viewportProvides.setViewportMetrics({
37
+ width: container.offsetWidth,
38
+ height: container.offsetHeight,
39
+ clientWidth: container.clientWidth,
40
+ clientHeight: container.clientHeight,
41
+ scrollTop: container.scrollTop,
42
+ scrollLeft: container.scrollLeft,
43
+ scrollWidth: container.scrollWidth,
44
+ scrollHeight: container.scrollHeight
45
+ });
46
+ });
47
+ resizeObserver.observe(container);
48
+ const unsubscribeScrollRequest = viewportProvides.onScrollRequest(
49
+ ({ x, y, behavior = "auto" }) => {
50
+ requestAnimationFrame(() => {
51
+ container.scrollTo({ left: x, top: y, behavior });
52
+ });
53
+ }
54
+ );
55
+ return () => {
56
+ viewportProvides.registerBoundingRectProvider(null);
57
+ container.removeEventListener("scroll", onScroll);
58
+ resizeObserver.disconnect();
59
+ unsubscribeScrollRequest();
60
+ };
61
+ }, [viewportProvides]);
62
+ return containerRef;
63
+ }
64
+
65
+ // src/react/components/viewport.tsx
66
+ import { jsx } from "react/jsx-runtime";
67
+ function Viewport({ children, ...props }) {
68
+ const [viewportGap, setViewportGap] = useState(0);
69
+ const viewportRef = useViewportRef();
70
+ const { provides: viewportProvides } = useViewportCapability();
71
+ useEffect(() => {
72
+ if (viewportProvides) {
73
+ setViewportGap(viewportProvides.getViewportGap());
74
+ }
75
+ }, [viewportProvides]);
76
+ const { style, ...restProps } = props;
77
+ return /* @__PURE__ */ jsx(
78
+ "div",
79
+ {
80
+ ...restProps,
81
+ ref: viewportRef,
82
+ style: {
83
+ ...typeof style === "object" ? style : {},
84
+ padding: `${viewportGap}px`
85
+ },
86
+ children
87
+ }
88
+ );
89
+ }
90
+ export {
91
+ Viewport,
92
+ useViewport,
93
+ useViewportCapability,
94
+ useViewportRef
95
+ };
96
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/components/viewport.tsx","../../src/react/hooks/use-viewport.ts","../../src/react/hooks/use-viewport-ref.ts"],"sourcesContent":["import React, { ReactNode, useEffect, useState } from 'react';\n\nimport { useViewportCapability } from '../hooks';\nimport { useViewportRef } from '../hooks/use-viewport-ref';\n\ntype ViewportProps = React.HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n};\n\nexport function Viewport({ children, ...props }: ViewportProps) {\n const [viewportGap, setViewportGap] = useState(0);\n const viewportRef = useViewportRef();\n const { provides: viewportProvides } = useViewportCapability();\n\n useEffect(() => {\n if (viewportProvides) {\n setViewportGap(viewportProvides.getViewportGap());\n }\n }, [viewportProvides]);\n\n const { style, ...restProps } = props;\n return (\n <div\n {...restProps}\n ref={viewportRef}\n style={{\n ...(typeof style === 'object' ? style : {}),\n padding: `${viewportGap}px`,\n }}\n >\n {children}\n </div>\n );\n}\n","import { useCapability, usePlugin } from '@embedpdf/core/react';\nimport { ViewportPlugin } from '@embedpdf/plugin-viewport';\n\nexport const useViewport = () => usePlugin<ViewportPlugin>(ViewportPlugin.id);\nexport const useViewportCapability = () => useCapability<ViewportPlugin>(ViewportPlugin.id);\n","import { useLayoutEffect, useRef } from 'react';\n\nimport { useViewportCapability } from './use-viewport';\nimport { Rect } from '@embedpdf/models';\n\nexport function useViewportRef() {\n const { provides: viewportProvides } = useViewportCapability();\n const containerRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (!viewportProvides) return;\n\n const container = containerRef.current;\n if (!container) return;\n\n /* ---------- live rect provider --------------------------------- */\n const provideRect = (): Rect => {\n const r = container.getBoundingClientRect();\n return {\n origin: { x: r.left, y: r.top },\n size: { width: r.width, height: r.height },\n };\n };\n viewportProvides.registerBoundingRectProvider(provideRect);\n\n // Example: On scroll, call setMetrics\n const onScroll = () => {\n viewportProvides.setViewportScrollMetrics({\n scrollTop: container.scrollTop,\n scrollLeft: container.scrollLeft,\n });\n };\n container.addEventListener('scroll', onScroll);\n\n // Example: On resize, call setMetrics\n const resizeObserver = new ResizeObserver(() => {\n const rect = container.getBoundingClientRect();\n\n viewportProvides.setViewportMetrics({\n width: container.offsetWidth,\n height: container.offsetHeight,\n clientWidth: container.clientWidth,\n clientHeight: container.clientHeight,\n scrollTop: container.scrollTop,\n scrollLeft: container.scrollLeft,\n scrollWidth: container.scrollWidth,\n scrollHeight: container.scrollHeight,\n });\n });\n resizeObserver.observe(container);\n\n const unsubscribeScrollRequest = viewportProvides.onScrollRequest(\n ({ x, y, behavior = 'auto' }) => {\n requestAnimationFrame(() => {\n container.scrollTo({ left: x, top: y, behavior });\n });\n },\n );\n\n // Cleanup\n return () => {\n viewportProvides.registerBoundingRectProvider(null);\n container.removeEventListener('scroll', onScroll);\n resizeObserver.disconnect();\n unsubscribeScrollRequest();\n };\n }, [viewportProvides]);\n\n // Return the ref so your React code can attach it to a div\n return containerRef;\n}\n"],"mappings":";AAAA,SAA2B,WAAW,gBAAgB;;;ACAtD,SAAS,eAAe,iBAAiB;AACzC,SAAS,sBAAsB;AAExB,IAAM,cAAc,MAAM,UAA0B,eAAe,EAAE;AACrE,IAAM,wBAAwB,MAAM,cAA8B,eAAe,EAAE;;;ACJ1F,SAAS,iBAAiB,cAAc;AAKjC,SAAS,iBAAiB;AAC/B,QAAM,EAAE,UAAU,iBAAiB,IAAI,sBAAsB;AAC7D,QAAM,eAAe,OAAuB,IAAI;AAEhD,kBAAgB,MAAM;AACpB,QAAI,CAAC,iBAAkB;AAEvB,UAAM,YAAY,aAAa;AAC/B,QAAI,CAAC,UAAW;AAGhB,UAAM,cAAc,MAAY;AAC9B,YAAM,IAAI,UAAU,sBAAsB;AAC1C,aAAO;AAAA,QACL,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,EAAE,IAAI;AAAA,QAC9B,MAAM,EAAE,OAAO,EAAE,OAAO,QAAQ,EAAE,OAAO;AAAA,MAC3C;AAAA,IACF;AACA,qBAAiB,6BAA6B,WAAW;AAGzD,UAAM,WAAW,MAAM;AACrB,uBAAiB,yBAAyB;AAAA,QACxC,WAAW,UAAU;AAAA,QACrB,YAAY,UAAU;AAAA,MACxB,CAAC;AAAA,IACH;AACA,cAAU,iBAAiB,UAAU,QAAQ;AAG7C,UAAM,iBAAiB,IAAI,eAAe,MAAM;AAC9C,YAAM,OAAO,UAAU,sBAAsB;AAE7C,uBAAiB,mBAAmB;AAAA,QAClC,OAAO,UAAU;AAAA,QACjB,QAAQ,UAAU;AAAA,QAClB,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,QACxB,WAAW,UAAU;AAAA,QACrB,YAAY,UAAU;AAAA,QACtB,aAAa,UAAU;AAAA,QACvB,cAAc,UAAU;AAAA,MAC1B,CAAC;AAAA,IACH,CAAC;AACD,mBAAe,QAAQ,SAAS;AAEhC,UAAM,2BAA2B,iBAAiB;AAAA,MAChD,CAAC,EAAE,GAAG,GAAG,WAAW,OAAO,MAAM;AAC/B,8BAAsB,MAAM;AAC1B,oBAAU,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAAA,QAClD,CAAC;AAAA,MACH;AAAA,IACF;AAGA,WAAO,MAAM;AACX,uBAAiB,6BAA6B,IAAI;AAClD,gBAAU,oBAAoB,UAAU,QAAQ;AAChD,qBAAe,WAAW;AAC1B,+BAAyB;AAAA,IAC3B;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAGrB,SAAO;AACT;;;AFhDI;AAbG,SAAS,SAAS,EAAE,UAAU,GAAG,MAAM,GAAkB;AAC9D,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAChD,QAAM,cAAc,eAAe;AACnC,QAAM,EAAE,UAAU,iBAAiB,IAAI,sBAAsB;AAE7D,YAAU,MAAM;AACd,QAAI,kBAAkB;AACpB,qBAAe,iBAAiB,eAAe,CAAC;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,gBAAgB,CAAC;AAErB,QAAM,EAAE,OAAO,GAAG,UAAU,IAAI;AAChC,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,KAAK;AAAA,MACL,OAAO;AAAA,QACL,GAAI,OAAO,UAAU,WAAW,QAAQ,CAAC;AAAA,QACzC,SAAS,GAAG,WAAW;AAAA,MACzB;AAAA,MAEC;AAAA;AAAA,EACH;AAEJ;","names":[]}
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@embedpdf/plugin-viewport",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "main": "./dist/index.cjs",
6
+ "module": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs"
13
+ },
14
+ "./preact": {
15
+ "types": "./dist/preact/index.d.ts",
16
+ "import": "./dist/preact/index.js",
17
+ "require": "./dist/preact/index.cjs"
18
+ },
19
+ "./react": {
20
+ "types": "./dist/react/index.d.ts",
21
+ "import": "./dist/react/index.js",
22
+ "require": "./dist/react/index.cjs"
23
+ }
24
+ },
25
+ "dependencies": {},
26
+ "devDependencies": {
27
+ "@types/react": "^18.2.0",
28
+ "tsup": "^8.0.0",
29
+ "typescript": "^5.0.0",
30
+ "@embedpdf/models": "1.0.0",
31
+ "@embedpdf/core": "1.0.0"
32
+ },
33
+ "peerDependencies": {
34
+ "react": ">=16.8.0",
35
+ "react-dom": ">=16.8.0",
36
+ "preact": "^10.26.4",
37
+ "@embedpdf/core": "1.0.0"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "README.md"
42
+ ],
43
+ "repository": {
44
+ "type": "git",
45
+ "url": "https://github.com/embedpdf/embed-pdf-viewer",
46
+ "directory": "packages/plugin-viewport"
47
+ },
48
+ "homepage": "https://www.embedpdf.com/docs",
49
+ "bugs": {
50
+ "url": "https://github.com/embedpdf/embed-pdf-viewer/issues"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "scripts": {
56
+ "build": "PROJECT_CWD=$(pwd) pnpm -w p:build",
57
+ "build:watch": "PROJECT_CWD=$(pwd) pnpm -w p:build:watch",
58
+ "clean": "PROJECT_CWD=$(pwd) pnpm -w p:clean",
59
+ "lint": "PROJECT_CWD=$(pwd) pnpm -w p:lint",
60
+ "lint:fix": "PROJECT_CWD=$(pwd) pnpm -w p:lint:fix",
61
+ "typecheck": "PROJECT_CWD=$(pwd) pnpm -w p:typecheck"
62
+ }
63
+ }