diff --git a/.changeset/green-knives-return.md b/.changeset/green-knives-return.md new file mode 100644 index 0000000..699c358 --- /dev/null +++ b/.changeset/green-knives-return.md @@ -0,0 +1,5 @@ +--- +'@orca-fe/pdf-viewer': major +--- + +feat: 将 PDFViewer 的 Page 调整为 absolute 定位 diff --git a/.github/workflows/changesets-auto-pre-publish.yml b/.github/workflows/changesets-auto-pre-publish.yml index 02999d3..93a91fd 100644 --- a/.github/workflows/changesets-auto-pre-publish.yml +++ b/.github/workflows/changesets-auto-pre-publish.yml @@ -60,7 +60,7 @@ jobs: "msgtype": "markdown", "markdown": { "title":"orca-fe 发布提醒", - "text": "## Orca-Pocket 临时版本已发布\n ${{steps.changesets.outputs.changedPackages}}\n\nTriggered by [PR#${{ github.event.pull_request.number }}](https://github.com/orca-team/pocket/pull/${{ github.event.pull_request.number }})" + "text": "## Orca-Pocket 临时版本已发布\n ${{steps.changesets.outputs.changedPackages}}\n\nTriggered by [PR#${{ github.event.pull_request.number }} {{github.event.pull_request.title}}](https://github.com/orca-team/pocket/pull/${{ github.event.pull_request.number }})" }, "at": { "isAtAll": false diff --git a/packages/pdf-viewer/demo/DemoDev.tsx b/packages/pdf-viewer/demo/DemoDev.tsx index c40d3c9..77ff341 100644 --- a/packages/pdf-viewer/demo/DemoDev.tsx +++ b/packages/pdf-viewer/demo/DemoDev.tsx @@ -4,10 +4,20 @@ * debug: true */ -import React from 'react'; -import PdfViewer, { PDFContextPrintPlugin, PDFOpenFileButtonPlugin, PDFPainterPlugin, PDFTooltipPlugin, usePdfViewerRef } from '@orca-fe/pdf-viewer'; +import React, { useState } from 'react'; +import PdfViewer, { + PDFContextPrintPlugin, + PDFOpenFileButtonPlugin, + PDFPageDebugPlugin, + PDFPainterPlugin, + PDFTooltipPlugin, + usePdfViewerRef, +} from '@orca-fe/pdf-viewer'; +import { JsonViewer } from '@orca-fe/pocket'; const Demo1 = () => { + const [data, setData] = useState([]); + const pdfViewerRef = usePdfViewerRef(); return (
@@ -26,10 +36,13 @@ const Demo1 = () => { /> - + + +
绘图数据:
+
); }; diff --git a/packages/pdf-viewer/src/PDFViewer.style.ts b/packages/pdf-viewer/src/PDFViewer.style.ts index a1db647..44f1ed6 100644 --- a/packages/pdf-viewer/src/PDFViewer.style.ts +++ b/packages/pdf-viewer/src/PDFViewer.style.ts @@ -49,16 +49,18 @@ export default createUseStyles( position: 'relative', height: '100%', overflow: 'auto', - padding: '24px 0', + // padding: '24px 0', backgroundColor: '#f0f2f5', - paddingBottom: 48, + // paddingBottom: 48, }, pageContainer: { - position: 'relative', + position: 'absolute', backgroundColor: '#fff', - marginLeft: 'auto', - marginRight: 'auto', + // marginLeft: 'auto', + // marginRight: 'auto', boxShadow: [0, 0, 12, 'rgba(0, 0, 0, 0.3)'], + left: '0%', + // transform: 'translateX(-50%)', }, page: { width: '100%', @@ -95,6 +97,11 @@ export default createUseStyles( backgroundColor: 'rgba(0,129,255,0.3)', }, }, + pageBottomPlaceholder: { + position: 'absolute', + pointerEvents: 'none', + visibility: 'hidden', + }, }, { classNamePrefix: prefix, diff --git a/packages/pdf-viewer/src/PDFViewer.tsx b/packages/pdf-viewer/src/PDFViewer.tsx index b00997c..9ce3955 100644 --- a/packages/pdf-viewer/src/PDFViewer.tsx +++ b/packages/pdf-viewer/src/PDFViewer.tsx @@ -30,6 +30,10 @@ const ef = () => undefined; const round001 = roundBy(0.001); +const PAGE_PADDING_TOP = 24; +const PAGE_PADDING_HORIZONTAL = 24; +const PAGE_PADDING_BOTTOM = 60; + const DefaultLoadingTips = () => { const [l] = useLocale(zhCN); return
{l.loadingTips}
; @@ -218,39 +222,39 @@ const PDFViewer = React.forwardRef((props, pRef // 根据 viewport 信息生成每一页的实际位置信息 const { - topArr: pageTopArr, - maxWidth, + topArr: topArrOrigin, pageMaxWidth, pageMaxHeight, + bottom: pageBottomOrigin, } = useMemo(() => { let top = 0; - let maxWidth = 0; let pageMaxWidth = 0; let pageMaxHeight = 0; const topArr = viewports.map(({ height: _height, width: _width }) => { - const width = _width * PixelsPerInch.PDF_TO_CSS_UNITS; - const height = _height * PixelsPerInch.PDF_TO_CSS_UNITS; + const width = _width; + const height = _height; const _top = top; - top += Math.floor(height + pageGap) * scale; - maxWidth = Math.max(width * scale, maxWidth); + top += height + pageGap; pageMaxWidth = Math.max(width, pageMaxWidth); pageMaxHeight = Math.max(height, pageMaxHeight); return _top; }); - return { topArr, maxWidth, pageMaxWidth, pageMaxHeight }; - }, [viewports, pageGap, scale]); + return { topArr, pageMaxWidth, pageMaxHeight, bottom: top }; + }, [viewports, pageGap]); + + const pageTopArr = useMemo(() => topArrOrigin.map(top => top * scale * PixelsPerInch.PDF_TO_CSS_UNITS), [scale, topArrOrigin]); const [zoomMode, setZoomMode] = useState(typeof defaultZoom === 'number' ? false : defaultZoom); const autoZoomDebounce = useDebounceFn( () => { let newZoom = zoom; - if (zoomMode && _this.size && maxWidth && pageMaxHeight) { + if (zoomMode && _this.size && pageMaxWidth && pageMaxHeight) { if (zoomMode === 'autoWidth') { // 调整缩放级别,使其与容器宽度匹配 - newZoom = Math.log2((_this.size.width - 32) / pageMaxWidth); + newZoom = Math.log2((_this.size.width - 20 - 2 * PAGE_PADDING_HORIZONTAL) / (pageMaxWidth * PixelsPerInch.PDF_TO_CSS_UNITS)); } else if (zoomMode === 'autoHeight') { - newZoom = Math.log2((_this.size.height - 32) / pageMaxHeight); + newZoom = Math.log2((_this.size.height - 32) / (pageMaxHeight * PixelsPerInch.PDF_TO_CSS_UNITS)); } } @@ -275,8 +279,13 @@ const PDFViewer = React.forwardRef((props, pRef _this.size = size; + const body = bodyRef; + if (body) { + body.style.setProperty('--pdf-viewer-page-width', `${size.width}px`); + } + autoZoomDebounce.run(); - }, rootRef); + }, bodyRef); // 翻頁 const changePage = useMemoizedFn((page: number, anim = false) => { @@ -487,9 +496,11 @@ const PDFViewer = React.forwardRef((props, pRef const x = clientX - left; const y = clientY - top; + const pageMaxWidthScale = pageMaxWidth * scale * PixelsPerInch.PDF_TO_CSS_UNITS; + if (!_this.mousePositionBeforeWheel) { _this.mousePositionBeforeWheel = { - x: x + dom.scrollLeft - 0.5 * (maxWidth < width ? width - maxWidth : 0), + x: x + dom.scrollLeft - 0.5 * (pageMaxWidthScale < width ? width - pageMaxWidthScale : 0), y: y + dom.scrollTop, zoom, }; @@ -690,7 +701,17 @@ const PDFViewer = React.forwardRef((props, pRef setToolbarRightDom(dom); }} /> -
+
((props, pRef }, } as ContextMenuItemType, ].concat(menuCollector.collect().sort((a, b) => (a.order || 0) - (b.order || 0)))} - style={ - { - '--scale-factor': scale * PixelsPerInch.PDF_TO_CSS_UNITS, - '--scale-factor-origin': scale, - '--pdf-viewer-page-scale': scale * PixelsPerInch.PDF_TO_CSS_UNITS, - } as CSSProperties - } > {viewports.length === 0 && !loading && !pluginLoading && emptyTips} {viewports.map((viewport, pageIndex) => { const shouldRender = pageIndex >= renderRange[0] && pageIndex <= renderRange[1]; + const top = `calc(var(--scale-factor) * ${PAGE_PADDING_TOP + Math.floor(topArrOrigin[pageIndex])}px)`; + const marginLeft = `max(${PAGE_PADDING_HORIZONTAL}px, (var(--pdf-viewer-page-width) - var(--scale-factor) * ${pageMaxWidth}px) * 0.5)`; + const left = `calc(${marginLeft} + var(--scale-factor) * ${Math.floor((pageMaxWidth - viewport.width) * 0.5)}px)`; const width = `calc(var(--scale-factor) * ${Math.floor(viewport.width)}px)`; const height = `calc(var(--scale-factor) * ${Math.floor(viewport.height)}px)`; - const gap = `calc(var(--scale-factor) * ${pageGap}px)`; + // const gap = `calc(var(--scale-factor) * ${pageGap}px)`; return ( -
+
{shouldRender && ( <> @@ -734,6 +751,16 @@ const PDFViewer = React.forwardRef((props, pRef
); })} +
+   +
{(loading || !!pluginLoading) && loadingTips} diff --git a/packages/pdf-viewer/src/index.ts b/packages/pdf-viewer/src/index.ts index b75e69c..76c4b77 100644 --- a/packages/pdf-viewer/src/index.ts +++ b/packages/pdf-viewer/src/index.ts @@ -12,6 +12,7 @@ import PDFOpenFileButtonPlugin from './plugins/PDFOpenFileButtonPlugin'; import type { ToolbarButtonProps } from './ToolbarButton'; import ToolbarButton from './ToolbarButton'; import ToolbarPortal from './ToolbarPortal'; +import PDFPageDebugPlugin from './plugins/PDFPageDebugPlugin'; export default PDFViewer; @@ -47,3 +48,5 @@ export type * from './plugins/PDFOpenFileButtonPlugin'; export { PDFContextPrintPlugin, PDFContextMenuPlugin }; export type * from './plugins/PDFContextMenuPlugin'; + +export { PDFPageDebugPlugin }; diff --git a/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/PDFPageDebugPlugin.style.ts b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/PDFPageDebugPlugin.style.ts new file mode 100644 index 0000000..98cab9f --- /dev/null +++ b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/PDFPageDebugPlugin.style.ts @@ -0,0 +1,16 @@ +import { createUseStyles } from '@orca-fe/simple-jss'; +import jssAutoPrefix from '@orca-fe/jss-plugin-auto-prefix'; + +const prefix = 'pdf-page-debug-plugin'; + +export default createUseStyles( + { + root: { + position: 'relative', + }, + }, + { + classNamePrefix: prefix, + plugins: [jssAutoPrefix({ prefix })], + }, +); diff --git a/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/PDFPageDebugPlugin.tsx b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/PDFPageDebugPlugin.tsx new file mode 100644 index 0000000..ed09520 --- /dev/null +++ b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/PDFPageDebugPlugin.tsx @@ -0,0 +1,17 @@ +/* eslint-disable react/no-unused-prop-types */ +import React from 'react'; +import { usePageCoverRenderer } from '../../context'; + +const PDFPageDebugPlugin = () => { + const renderPageCover = usePageCoverRenderer(); + + return ( + <> + {renderPageCover((pageIndex, { viewport, zoom }) => ( +
{pageIndex}
+ ))} + + ); +}; + +export default PDFPageDebugPlugin; diff --git a/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/index.ts b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/index.ts new file mode 100644 index 0000000..b4b0df1 --- /dev/null +++ b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/index.ts @@ -0,0 +1,3 @@ +import PDFPageDebugPlugin from './PDFPageDebugPlugin'; + +export default PDFPageDebugPlugin; diff --git a/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/utils.ts b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/utils.ts new file mode 100644 index 0000000..55b5762 --- /dev/null +++ b/packages/pdf-viewer/src/plugins/PDFPageDebugPlugin/utils.ts @@ -0,0 +1,65 @@ +import type { Point, ShapeDataType } from '@orca-fe/painter'; +import { isGraphShapeType } from '@orca-fe/painter'; +import { PixelsPerInch } from '../../utils'; + +/** + * 将 GraphShape 的 PDF 坐标转换为 CSS 坐标 + * @param shape + */ +export function shapePdfToCss(shape: ShapeDataType): ShapeDataType { + if (isGraphShapeType(shape)) { + const newShape = { ...shape }; + if ('x' in newShape && typeof newShape.x === 'number') { + newShape.x *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('y' in newShape && typeof newShape.y === 'number') { + newShape.y *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('width' in newShape && typeof newShape.width === 'number') { + newShape.width *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('height' in newShape && typeof newShape.height === 'number') { + newShape.height *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('point1' in newShape && Array.isArray(newShape.point1)) { + newShape.point1 = newShape.point1.map(v => v * PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + if ('point2' in newShape && Array.isArray(newShape.point2)) { + newShape.point2 = newShape.point2.map(v => v * PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + + return newShape; + } + return shape; +} + +/** + * 将 GraphShape 的 CSS 坐标转换为 PDF 坐标 + * @param shape + */ +export function shapeCssToPdf(shape: ShapeDataType): ShapeDataType { + if (isGraphShapeType(shape)) { + const newShape = { ...shape }; + if ('x' in newShape && typeof newShape.x === 'number') { + newShape.x /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('y' in newShape && typeof newShape.y === 'number') { + newShape.y /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('width' in newShape && typeof newShape.width === 'number') { + newShape.width /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('height' in newShape && typeof newShape.height === 'number') { + newShape.height /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('point1' in newShape && Array.isArray(newShape.point1)) { + newShape.point1 = newShape.point1.map(v => v / PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + if ('point2' in newShape && Array.isArray(newShape.point2)) { + newShape.point2 = newShape.point2.map(v => v / PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + + return newShape; + } + return shape; +} diff --git a/packages/pdf-viewer/src/plugins/PDFPainterPlugin/PDFPainterPlugin.tsx b/packages/pdf-viewer/src/plugins/PDFPainterPlugin/PDFPainterPlugin.tsx index 276c1c8..6b77e04 100644 --- a/packages/pdf-viewer/src/plugins/PDFPainterPlugin/PDFPainterPlugin.tsx +++ b/packages/pdf-viewer/src/plugins/PDFPainterPlugin/PDFPainterPlugin.tsx @@ -1,6 +1,6 @@ /* eslint-disable react/no-unused-prop-types */ import type { CSSProperties } from 'react'; -import React, { useContext, useImperativeHandle, useState } from 'react'; +import React, { useMemo, useContext, useImperativeHandle, useState } from 'react'; import { IconButton, Trigger } from '@orca-fe/pocket'; import type { PainterRef, ShapeDataType, ShapeType } from '@orca-fe/painter'; import Painter from '@orca-fe/painter'; @@ -20,6 +20,7 @@ import type { PropsType } from '../SimplePropsEditor/def'; import useStyle from './PDFPainterPlugin.style'; import { useLocale } from '../../locale/context'; import zhCN from '../../locale/zh_CN'; +import { shapeCssToPdf, shapePdfToCss } from './utils'; const deepClone = rfdc(); @@ -36,7 +37,7 @@ export type PDFPainterPluginHandle = { const eArr = []; -const ef = () => { }; +const ef = () => {}; /** * PDFPainterPlugin 绘图插件属性 @@ -93,7 +94,15 @@ const drawingNamePDFPainterPlugin = 'PDFPainterPlugin'; */ const PDFPainterPlugin = React.forwardRef((props, pRef) => { const [l] = useLocale(zhCN); - const { disabledButton, autoCheck = true, onChangeStart = ef, buttonName = l.paint, popupVisible = true, drawingVisible = true, drawingPluginId = drawingNamePDFPainterPlugin } = props; + const { + disabledButton, + autoCheck = true, + onChangeStart = ef, + buttonName = l.paint, + popupVisible = true, + drawingVisible = true, + drawingPluginId = drawingNamePDFPainterPlugin, + } = props; const styles = useStyle(); const { internalState, setInternalState } = useContext(PDFViewerContext); @@ -120,17 +129,31 @@ const PDFPainterPlugin = React.forwardRef(props, { + const [_dataList = eArr, _setDataList] = useControllableValue(props, { defaultValuePropName: 'defaultData', trigger: 'onDataChange', valuePropName: 'data', }); + const dataList = useMemo(() => _dataList.map(shapes => shapes.map(shapePdfToCss)), [_dataList]); + + const setDataList = useMemoizedFn((data, ...args) => { + if (typeof data === 'function') { + _setDataList(oData => data(oData).map(shapes => shapes.map(shapeCssToPdf)), ...args); + } else { + _setDataList( + data.map(shapes => shapes.map(shapeCssToPdf)), + ...args, + ); + } + }); + /* 绘图功能 */ const drawing = internalState.drawingPluginName === drawingPluginId; const setDrawing = useMemoizedFn((b: boolean) => { - setInternalState({ // 这里设置的时候,已经是全局的了 + setInternalState({ + // 这里设置的时候,已经是全局的了 drawingPluginName: b ? drawingPluginId : '', }); }); diff --git a/packages/pdf-viewer/src/plugins/PDFPainterPlugin/utils.ts b/packages/pdf-viewer/src/plugins/PDFPainterPlugin/utils.ts new file mode 100644 index 0000000..55b5762 --- /dev/null +++ b/packages/pdf-viewer/src/plugins/PDFPainterPlugin/utils.ts @@ -0,0 +1,65 @@ +import type { Point, ShapeDataType } from '@orca-fe/painter'; +import { isGraphShapeType } from '@orca-fe/painter'; +import { PixelsPerInch } from '../../utils'; + +/** + * 将 GraphShape 的 PDF 坐标转换为 CSS 坐标 + * @param shape + */ +export function shapePdfToCss(shape: ShapeDataType): ShapeDataType { + if (isGraphShapeType(shape)) { + const newShape = { ...shape }; + if ('x' in newShape && typeof newShape.x === 'number') { + newShape.x *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('y' in newShape && typeof newShape.y === 'number') { + newShape.y *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('width' in newShape && typeof newShape.width === 'number') { + newShape.width *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('height' in newShape && typeof newShape.height === 'number') { + newShape.height *= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('point1' in newShape && Array.isArray(newShape.point1)) { + newShape.point1 = newShape.point1.map(v => v * PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + if ('point2' in newShape && Array.isArray(newShape.point2)) { + newShape.point2 = newShape.point2.map(v => v * PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + + return newShape; + } + return shape; +} + +/** + * 将 GraphShape 的 CSS 坐标转换为 PDF 坐标 + * @param shape + */ +export function shapeCssToPdf(shape: ShapeDataType): ShapeDataType { + if (isGraphShapeType(shape)) { + const newShape = { ...shape }; + if ('x' in newShape && typeof newShape.x === 'number') { + newShape.x /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('y' in newShape && typeof newShape.y === 'number') { + newShape.y /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('width' in newShape && typeof newShape.width === 'number') { + newShape.width /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('height' in newShape && typeof newShape.height === 'number') { + newShape.height /= PixelsPerInch.PDF_TO_CSS_UNITS; + } + if ('point1' in newShape && Array.isArray(newShape.point1)) { + newShape.point1 = newShape.point1.map(v => v / PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + if ('point2' in newShape && Array.isArray(newShape.point2)) { + newShape.point2 = newShape.point2.map(v => v / PixelsPerInch.PDF_TO_CSS_UNITS) as Point; + } + + return newShape; + } + return shape; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8ff2ee6..4e50db5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -151,13 +151,13 @@ importers: specifier: '>=4.8.0' version: 5.1.3(react-dom@18.2.0)(react@18.2.0) '@orca-fe/hooks': - specifier: ^1.11.1 + specifier: ^1.12.0 version: link:../hooks '@orca-fe/jss-plugin-auto-prefix': specifier: ^0.0.1 version: 0.0.1(jss@10.10.0)(react@18.2.0) '@orca-fe/pocket': - specifier: ^3.4.3 + specifier: ^3.4.4 version: link:../pocket '@orca-fe/simple-jss': specifier: ^0.0.3 @@ -291,13 +291,13 @@ importers: specifier: ^4.7.0 version: 4.7.0(react-dom@18.2.0)(react@18.2.0) '@orca-fe/hooks': - specifier: ^1.11.1 + specifier: ^1.12.0 version: link:../hooks '@orca-fe/jss-plugin-auto-prefix': specifier: ^0.0.1 version: 0.0.1(jss@10.10.0)(react@18.2.0) '@orca-fe/pocket': - specifier: ^3.4.3 + specifier: ^3.4.4 version: link:../pocket '@orca-fe/simple-jss': specifier: ^0.0.3 @@ -306,7 +306,7 @@ importers: specifier: ^0.10.1 version: link:../tools '@orca-fe/transformer': - specifier: ^0.3.30 + specifier: ^0.3.31 version: link:../transformer ahooks: specifier: ^3.7.8 @@ -346,7 +346,7 @@ importers: specifier: ^4.7.0 version: 4.7.0(react-dom@18.2.0)(react@18.2.0) '@orca-fe/hooks': - specifier: ^1.11.1 + specifier: ^1.11.0 version: link:../hooks '@orca-fe/jss-plugin-auto-prefix': specifier: ^0.0.1 @@ -358,7 +358,7 @@ importers: specifier: ^3.8.24 version: 3.8.24 '@orca-fe/pocket': - specifier: ^3.4.3 + specifier: ^3.2.4 version: link:../pocket '@orca-fe/simple-jss': specifier: ^0.0.3 @@ -416,7 +416,7 @@ importers: specifier: '>=4.7.0' version: 5.1.3(react-dom@18.2.0)(react@17.0.2) '@orca-fe/hooks': - specifier: ^1.11.1 + specifier: ^1.12.0 version: link:../hooks '@orca-fe/jss-plugin-auto-prefix': specifier: ^0.0.1 @@ -534,7 +534,7 @@ importers: packages/transformer: dependencies: '@orca-fe/hooks': - specifier: ^1.11.1 + specifier: ^1.12.0 version: link:../hooks '@orca-fe/jss-plugin-auto-prefix': specifier: ^0.0.1