From 84afaeb8ddbb52aa1e1db15f0ce508b90e87cf9c Mon Sep 17 00:00:00 2001 From: "oe.sonnh" Date: Mon, 1 Apr 2024 11:24:06 +0700 Subject: [PATCH] Update: optimize es build as splitted file chunks --- build/configs/append-component-css.ts | 89 +++++++++++ build/configs/common.ts | 142 ++++++++++++++++++ build/configs/create-dist-transform.ts | 43 ++++++ build/configs/fix-generic-file-names.ts | 56 +++++++ build/configs/remove-side-effect-chunks.ts | 15 ++ build/configs/vite.cjs.ts | 8 + build/configs/vite.es.ts | 6 + docs/.vitepress/config.mts | 2 - package.json | 11 +- src/components/AppProvider/AppProvider.vue | 2 +- .../CheckableButton/CheckableButton.vue | 9 +- src/components/CheckableButton/index.ts | 3 +- src/components/CheckableButton/types.ts | 7 + src/components/Popover/Popover.vue | 56 +------ .../components/PopoverOverlay/types.ts | 2 +- src/components/Popover/index.ts | 3 +- src/components/Popover/types.ts | 53 +++++++ .../PositionedOverlay/PositionedOverlay.vue | 15 +- src/components/PositionedOverlay/types.ts | 14 ++ .../components/TooltipOverlay/utils.ts | 2 +- tsconfig.json | 2 +- vite.config.ts | 24 +-- yarn.lock | 19 +++ 23 files changed, 475 insertions(+), 108 deletions(-) create mode 100644 build/configs/append-component-css.ts create mode 100644 build/configs/common.ts create mode 100644 build/configs/create-dist-transform.ts create mode 100644 build/configs/fix-generic-file-names.ts create mode 100644 build/configs/remove-side-effect-chunks.ts create mode 100644 build/configs/vite.cjs.ts create mode 100644 build/configs/vite.es.ts create mode 100644 src/components/CheckableButton/types.ts create mode 100644 src/components/Popover/types.ts create mode 100644 src/components/PositionedOverlay/types.ts diff --git a/build/configs/append-component-css.ts b/build/configs/append-component-css.ts new file mode 100644 index 000000000..8161605f6 --- /dev/null +++ b/build/configs/append-component-css.ts @@ -0,0 +1,89 @@ +import { existsSync } from 'fs' +import { extname, dirname, basename, relative, resolve } from 'path' +import { createDistTransformPlugin } from './create-dist-transform' + +const parsePath = (path: string) => { + const ext = extname(path).replace('.', '') + + return { + ext, + dir: dirname(path), + name: basename(path, `.${ext}`), + } +} + +/** + * Checks if file is Vuestic component template source + * If file is script source, but there is not template then add css to script. + * Component usually have script which is stored in file with name like Va[ComponentName].vue_vue_type_script_lang + * + * @notice Component can have render function without template block. It also can have only template without script block. + */ +const isComponent = (filename: string) => { + // [ComponentName].vue_vue_type_script_lang.mjs + // [ComponentName].vue_vue_type_script_setup_true_lang.mjs + const isScriptFile = /\w*.vue_vue_type_script\w*_lang.m?js$/.test(filename) + if (isScriptFile) { + return true + } + + // Va[ComponentName].mjs + const isTemplateFile = /\w*\.m?js$/.test(filename) + + // Va[ComponentName].vue_vue_type_script_lang.mjs + const scriptFilePath = filename.replace(/\.(mjs|js)/, '.vue_vue_type_script_lang.mjs') + const scriptSetupFilePath = filename.replace(/\.(mjs|js)/, '.vue_vue_type_script_setup_true_lang.mjs') + + const haveScript = existsSync(scriptFilePath) || existsSync(scriptSetupFilePath) + + if (isTemplateFile && !haveScript) { + return true + } + + return false +} + +const extractVuesticComponentName = (filename: string) => { + return filename.match(/(\w*)/)?.[1] +} + +const SOURCE_MAP_COMMENT_FRAGMENT = '//# sourceMappingURL=' + +const appendBeforeSourceMapComment = (content: string, append: string): string => { + return content.replace(SOURCE_MAP_COMMENT_FRAGMENT, `${append}\n${SOURCE_MAP_COMMENT_FRAGMENT}`) +} + +export const appendComponentCss = createDistTransformPlugin({ + name: 'vuestic:append-component-css', + + dir: (outDir) => `${outDir}/src/components`, + + transform (componentContent, path) { + if (!isComponent(path)) { return } + + const { name, dir } = parsePath(path) + + const componentName = extractVuesticComponentName(name) + + if (!componentName) { + throw new Error(`Can't extract component name from ${name}`) + } + + const distPath = resolve(this.outDir, '..', '..') + const relativeDistPath = relative(dir, distPath) + const relativeFilePath = relativeDistPath + '/' + componentName.replace(/-.*$/, '') + '.css' + + // There are few cases how vite can store css files (depends on vite version, but we handle both for now): + // CSS stored in dist folder (root) + if (existsSync(resolve(dir, relativeFilePath))) { + return appendBeforeSourceMapComment(componentContent, `\nimport '${relativeFilePath}';`) + } + + // CSS stored in component folder + const cssFilePath = `${dir}/${componentName}.css` + + if (existsSync(cssFilePath)) { + return appendBeforeSourceMapComment(componentContent, `\nimport './${componentName}.css';`) + } + }, +}) diff --git a/build/configs/common.ts b/build/configs/common.ts new file mode 100644 index 000000000..530011975 --- /dev/null +++ b/build/configs/common.ts @@ -0,0 +1,142 @@ +/** + * Inspired by VuesticUI build config + * https://github.com/epicmaxco/vuestic-ui/blob/develop/packages/ui/build/common-config.ts + */ +import { readFileSync, lstatSync, readdirSync } from 'fs' +import vue from '@vitejs/plugin-vue' +import { UserConfig } from 'vite' +import { resolve as resolver } from 'path' +import { chunkSplitPlugin } from 'vite-plugin-chunk-split' +import { removeSideEffectedChunks } from './remove-side-effect-chunks' +import { fixVueGenericComponentFileNames } from './fix-generic-file-names' +import { appendComponentCss } from './append-component-css' +import { generateScopedName } from '../namespaced-classname.js'; +import svgLoader from 'vite-svg-loader'; +import { replaceCodePlugin } from 'vite-plugin-replace'; +import dts from 'vite-plugin-dts'; + +export const defineViteConfig = (p: T): UserConfig & T => p + +import type { RollupOptions } from 'vite/node_modules/rollup'; + +const packageJSON = JSON.parse(readFileSync(resolver(process.cwd(), './package.json')).toString()) +const dependencies = [...Object.keys(packageJSON.dependencies), ...Object.keys(packageJSON.peerDependencies)] + +export type BuildFormat = 'iife' | 'es' | 'cjs' | 'esm-node' + +export const readDirRecursive = (path: string): string[] => { + return readdirSync(path) + .reduce((acc, entry) => { + const p = `${path}/${entry}` + + if (lstatSync(p).isDirectory()) { + return [...acc, ...readDirRecursive(p)] + } + + return [...acc, p] + }, []) +} + +export const resolve = { + alias: { + '@icons': resolver(process.cwd(), 'node_modules/@shopify/polaris-icons/dist/svg'), + '@polaris': resolver(process.cwd(), './polaris/polaris-react/src'), + '@': resolver(process.cwd(), './src'), + '~': resolver(process.cwd(), './node_modules'), + }, + dedupe: ['vue'], +} + +const rollupOutputOptions = (ext: string): RollupOptions['output'] => ({ + entryFileNames: `[name].${ext}`, + chunkFileNames: `[name].${ext}`, + assetFileNames: '[name].[ext]', +}) + +const rollupMjsBuildOptions: RollupOptions = { + input: resolver(process.cwd(), 'src/polaris-vue.ts'), + + output: { + sourcemap: true, + dir: 'dist/esm-node', + format: 'esm', + ...rollupOutputOptions('mjs'), + }, +} + +const libBuildOptions = (format: 'iife' | 'es' | 'cjs') => ({ + entry: resolver(process.cwd(), 'src/polaris-vue.ts'), + fileName: () => 'polaris-vue.js', + formats: [format], + + // only for iife/umd + name: 'PolarisVue', +}) + +export default function createViteConfig (format: BuildFormat) { + const isEsm = ['es', 'esm-node'].includes(format) + const isNode = format === 'esm-node' + + const config = defineViteConfig({ + resolve, + + css: { + preprocessorOptions: { + scss: { + quietDeps: true, // Silent the deprecation warning + }, + }, + modules: { + generateScopedName, + }, + }, + + build: { + outDir: `dist/${isEsm ? format : ''}`, + cssCodeSplit: false, + sourcemap: true, + minify: isEsm ? false : 'esbuild', + lib: libBuildOptions(isNode ? 'es' : format), + }, + + plugins: [ + vue({ + isProduction: true, + exclude: [/\.md$/, /\.spec\.ts$/, /\.spec\.disabled$/], + }), + svgLoader(), + replaceCodePlugin({ + replacements: [ + { + from: '%POLARIS_VERSION%', + to: packageJSON.polaris_version, + }, + ], + }), + dts({ + rollupTypes: true, + outDir: 'dist/types', + }), + ], + }) + + // https://github.com/sanyuan0704/vite-plugin-chunk-split + isEsm && config.plugins.push(chunkSplitPlugin({ strategy: 'unbundle' })) + // isEsm && !isNode && config.plugins.push(appendComponentCss()) + isEsm && config.plugins.push(removeSideEffectedChunks()) + isEsm && config.plugins.push(fixVueGenericComponentFileNames) + + if (isNode) { + config.build.rollupOptions = { + external: [...dependencies, 'vue'], + ...rollupMjsBuildOptions, + }; + } else { + config.build.rollupOptions = { + external: [...dependencies, 'vue'], + output: rollupOutputOptions('js'), + } + } + + return config +} diff --git a/build/configs/create-dist-transform.ts b/build/configs/create-dist-transform.ts new file mode 100644 index 000000000..289e38cd4 --- /dev/null +++ b/build/configs/create-dist-transform.ts @@ -0,0 +1,43 @@ +import type { Plugin } from 'vite' +import { readdir, readFile, writeFile, lstat } from 'fs/promises' + +type Nothing = null | undefined | void +type TransformFnResult = string | Nothing +type TransformFn = (this: { outDir: string }, content: string, path: string) => TransformFnResult | Promise + +export const createDistTransformPlugin = (options: { + name: string, + dir?: (outDir: string) => string, + transform: TransformFn, +}) => { + let outDir = '' + + const processFiles = async (dir: string) => { + return (await readdir(dir)) + .map(async (entryName) => { + const currentPath = `${dir}/${entryName}` + + if ((await lstat(currentPath)).isDirectory()) { + return processFiles(currentPath) + } + + const content = await readFile(currentPath, 'utf8') + + const result = await options.transform.call({ outDir }, content, currentPath) + + if (!result) { return } + + await writeFile(currentPath, result) + }) + } + + return (): Plugin => ({ + name: 'vuestic:append-component-css', + configResolved: (config) => { + outDir = options.dir?.(config.build.outDir) || config.build.outDir + }, + closeBundle: async () => { + processFiles(outDir) + }, + }) +} diff --git a/build/configs/fix-generic-file-names.ts b/build/configs/fix-generic-file-names.ts new file mode 100644 index 000000000..745f692dd --- /dev/null +++ b/build/configs/fix-generic-file-names.ts @@ -0,0 +1,56 @@ +import { Plugin } from 'vite'; + +const defineVitePlugin = (p: T): Plugin & T => p; + +/** + * When vue compiles file, it encode generic into file name + * + * @example + * AppProvider.vue_vue_type_script_generic_Item%20extends%20Record%3Cstring%2C%20any%3E_setup_true_lang + * + * This might be helpful for compiler, but it makes file names unreadable and some bundlers may not allow encoded characters in file names. + * This plugin replaces encoded characters in file names and source maps with underscores. + */ +const GENERIC_NAME_REGEX = /.vue_vue_type_script_generic_.*_setup_true_lang/gm +const URL_ENCODED_REGEX = /%([0-9]|[A-F]){2}/gm + +const replaceEncodedCharacters = (match: string) => match + .replace(URL_ENCODED_REGEX, '_') // Replace any encoded character with underscore + .replace(/_{2,}/g, '_') // Replace multiple underscores with single underscore + +export const fixVueGenericComponentFileNames = defineVitePlugin({ + name: 'polaris-vue:fix-vue-generic-component-file-names', + + generateBundle (options, bundle) { + Object.keys(bundle).forEach(fileName => { + console.log(fileName); + const file = bundle[fileName] + + // Replace encoded characters in generic names in source maps + if (file.type === 'asset' && file.fileName.endsWith('.map')) { + if (typeof file.source === 'string') { + file.source = file.source + .replace(GENERIC_NAME_REGEX, replaceEncodedCharacters) + } + } + + // Replace encoded characters in generic names in code + if (file.type === 'chunk') { + file.code = file.code + .replace(GENERIC_NAME_REGEX, replaceEncodedCharacters) + } + + // Update file name if it has encoded characters + if (GENERIC_NAME_REGEX.test(fileName)) { + const newFileName = replaceEncodedCharacters(fileName) + + bundle[newFileName] = { + ...bundle[fileName], + fileName: newFileName, + } + + delete bundle[fileName] + } + }) + }, +}) diff --git a/build/configs/remove-side-effect-chunks.ts b/build/configs/remove-side-effect-chunks.ts new file mode 100644 index 000000000..5083ba5eb --- /dev/null +++ b/build/configs/remove-side-effect-chunks.ts @@ -0,0 +1,15 @@ +import { createDistTransformPlugin } from './create-dist-transform'; + +/** + * Vite think that some chunks contain side effects, + * so it keep them in bundle and imports with `import "..."`. + * It simply removes all imports from chunks that import side effected chunks + * after build is done. + */ +export const removeSideEffectedChunks = createDistTransformPlugin({ + name: 'polaris-vue:remove-side-effected-chunks', + + transform: (content) => { + return content.replace(/import ".*";(\n)*/gm, '') + }, +}) diff --git a/build/configs/vite.cjs.ts b/build/configs/vite.cjs.ts new file mode 100644 index 000000000..995b3f9da --- /dev/null +++ b/build/configs/vite.cjs.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite' +import createViteConfig from './common' + +export default () => { + return defineConfig({ + ...createViteConfig('cjs'), + }) +} diff --git a/build/configs/vite.es.ts b/build/configs/vite.es.ts new file mode 100644 index 000000000..9843d2ee6 --- /dev/null +++ b/build/configs/vite.es.ts @@ -0,0 +1,6 @@ +import { defineConfig } from 'vite' +import createViteConfig from './common' + +export default () => defineConfig({ + ...createViteConfig('es'), +}) diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 08234ec46..c83336319 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -121,8 +121,6 @@ export default defineConfig({ // @ts-ignore '@polaris': fileURLToPath(new URL('../../polaris/polaris-react/src', import.meta.url)), // @ts-ignore - '@tokens': fileURLToPath(new URL('../../polaris/polaris-tokens/src', import.meta.url)), - // @ts-ignore '@': fileURLToPath(new URL('../../src', import.meta.url)), // @ts-ignore '~': fileURLToPath(new URL('../../node_modules', import.meta.url)), diff --git a/package.json b/package.json index 2742f1a7b..f91d2accb 100644 --- a/package.json +++ b/package.json @@ -21,17 +21,19 @@ "README.md" ], "types": "./dist/types/polaris-vue.d.ts", - "main": "./dist/polaris-vue.umd.js", - "module": "./dist/polaris-vue.es.js", + "main": "./dist/polaris-vue.js", + "module": "./dist/es/polaris-vue.js", "scripts": { "dev": "vite", - "build": "rimraf dist && vue-tsc --noEmit && vite build && npm run gen-dts && npm run copy-locales && npm run remove-trashes", + "build": "rimraf dist && yarn build:cjs && yarn build:es && npm run gen-dts && npm run copy-locales && npm run remove-trashes", + "build:cjs": "vite build --config ./build/configs/vite.cjs.ts", + "build:es": "vite build --config ./build/configs/vite.es.ts", "preview": "vite preview --port 5050", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", "gen-dts": "esbuild build/gen-component-declaration.js --bundle --platform=node | node && npm run move-dts", "move-dts": "mv volar.d.ts dist/volar.d.ts", "copy-locales": "cp -R polaris/polaris-react/locales dist/", - "remove-trashes": "rimraf dist/index.html dist/favicon.ico dist/images", + "remove-trashes": "rimraf dist/favicon.ico dist/images dist/es/favicon.ico dist/es/images", "gen:meta": "build/gen-meta.ts", "gen:docs-content": "build/gen-docs-content.ts", "gen:docs-types": "build/gen-docs-types.ts", @@ -73,6 +75,7 @@ "typescript": "^5.3.3", "url": "^0.11.3", "vite": "^5.0.10", + "vite-plugin-chunk-split": "^0.5.0", "vite-plugin-dts": "^3.7.3", "vite-plugin-eslint": "^1.8.1", "vite-plugin-replace": "^0.1.1", diff --git a/src/components/AppProvider/AppProvider.vue b/src/components/AppProvider/AppProvider.vue index 443fe2579..85a07ee55 100644 --- a/src/components/AppProvider/AppProvider.vue +++ b/src/components/AppProvider/AppProvider.vue @@ -132,7 +132,7 @@ function measureScrollbars() { document.body.removeChild(parentEl); } -provide('themeName', themeName); // TODO: This should be reactive +provide('themeName', themeName); provide('theme', getTheme(themeName.value)); // TODO: This should be reactive provide('features', props.features ?? {}); provide('i18n', new I18n(props.i18n)); diff --git a/src/components/CheckableButton/CheckableButton.vue b/src/components/CheckableButton/CheckableButton.vue index 7ae8d390e..8c69b36f9 100644 --- a/src/components/CheckableButton/CheckableButton.vue +++ b/src/components/CheckableButton/CheckableButton.vue @@ -21,20 +21,13 @@ div(:class="className", @click="emits('toggle-all')") import { computed, ref } from 'vue'; import { classNames } from '@/utilities/css'; import { Checkbox } from '@/components'; +import type { CheckableButtonProps } from './types'; import styles from '@polaris/components/CheckableButton/CheckableButton.module.css'; export interface CheckboxHandles { focus(): void; } -export type CheckableButtonProps = { - accessibilityLabel?: string; - label?: string; - selected?: boolean | 'indeterminate'; - disabled?: boolean; - ariaLive?: 'off' | 'polite'; -} - const props = withDefaults(defineProps(), { label: '', }); diff --git a/src/components/CheckableButton/index.ts b/src/components/CheckableButton/index.ts index f906045a9..0705c3aeb 100644 --- a/src/components/CheckableButton/index.ts +++ b/src/components/CheckableButton/index.ts @@ -1 +1,2 @@ -export { default as CheckableButton, type CheckableButtonProps } from './CheckableButton.vue'; +export { default as CheckableButton } from './CheckableButton.vue'; +export type { CheckableButtonProps } from './types'; diff --git a/src/components/CheckableButton/types.ts b/src/components/CheckableButton/types.ts new file mode 100644 index 000000000..cbda4717f --- /dev/null +++ b/src/components/CheckableButton/types.ts @@ -0,0 +1,7 @@ +export type CheckableButtonProps = { + accessibilityLabel?: string; + label?: string; + selected?: boolean | 'indeterminate'; + disabled?: boolean; + ariaLive?: 'off' | 'polite'; +} diff --git a/src/components/Popover/Popover.vue b/src/components/Popover/Popover.vue index 401e72ce1..6c327f0c7 100644 --- a/src/components/Popover/Popover.vue +++ b/src/components/Popover/Popover.vue @@ -32,62 +32,10 @@ import { findFirstFocusableNodeIncludingDisabled, focusNextFocusableNode } from import { Portal, PopoverOverlay } from '@/components'; import { portal } from '@polaris/components/shared'; import { setActivatorAttributes } from './set-activator-attributes'; -import { - type PopoverOverlayProps, - type PopoverAutofocusTarget, - PopoverCloseSource, -} from './components/PopoverOverlay/types'; +import { PopoverCloseSource } from './components/PopoverOverlay/types'; import useId from '@/use/useId'; import type { VueNode } from '@/utilities/types'; - -export type PopoverProps = { - /** The preferred direction to open the popover */ - preferredPosition?: PopoverOverlayProps['preferredPosition']; - /** The preferred alignment of the popover relative to its activator */ - preferredAlignment?: PopoverOverlayProps['preferredAlignment']; - /** Show or hide the Popover */ - active: boolean; - /** - * Use the activator's input element to calculate the Popover position - * @default true - */ - preferInputActivator?: PopoverOverlayProps['preferInputActivator']; - /** - * The element type to wrap the activator with - * @default 'div' - */ - activatorWrapper?: string; - /** Override on the default z-index of 400 */ - zIndexOverride?: number; - /** Prevents focusing the activator or the next focusable element when the popover is deactivated */ - preventFocusOnClose?: boolean; - /** Automatically add wrap content in a section */ - sectioned?: boolean; - /** Allow popover to stretch to the full width of its activator */ - fullWidth?: boolean; - /** Allow popover to stretch to fit content vertically */ - fullHeight?: boolean; - /** Allow popover content to determine the overlay width and height */ - fluidContent?: boolean; - /** Remains in a fixed position */ - fixed?: boolean; - /** Used to illustrate the type of popover element */ - ariaHaspopup?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | undefined; - /** Allow the popover overlay to be hidden when printing */ - hideOnPrint?: boolean; - /** - * The preferred auto focus target defaulting to the popover container - * @default 'container' - */ - autofocusTarget?: PopoverAutofocusTarget; - /** Prevents closing the popover when other overlays are clicked */ - preventCloseOnChildOverlayClick?: boolean; - /** - * Prevents page scrolling when the end of the scrollable Popover overlay content is reached - applied to Pane subcomponent - * @default false - */ - captureOverscroll?: boolean; -} +import type { PopoverProps } from './types'; const props = withDefaults(defineProps(), { activatorWrapper: 'div', diff --git a/src/components/Popover/components/PopoverOverlay/types.ts b/src/components/Popover/components/PopoverOverlay/types.ts index 7093cb10d..4eb6c83ea 100644 --- a/src/components/Popover/components/PopoverOverlay/types.ts +++ b/src/components/Popover/components/PopoverOverlay/types.ts @@ -1,4 +1,4 @@ -import type { PositionedOverlayProps } from '@/components/PositionedOverlay/PositionedOverlay.vue'; +import type { PositionedOverlayProps } from '@/components/PositionedOverlay/types'; export enum PopoverCloseSource { Click, diff --git a/src/components/Popover/index.ts b/src/components/Popover/index.ts index 6655e1893..ca7756744 100644 --- a/src/components/Popover/index.ts +++ b/src/components/Popover/index.ts @@ -1,2 +1,3 @@ -export { default as Popover, type PopoverProps } from './Popover.vue'; +export { default as Popover } from './Popover.vue'; export * from './components'; +export type { PopoverProps } from './types'; diff --git a/src/components/Popover/types.ts b/src/components/Popover/types.ts new file mode 100644 index 000000000..8019442e5 --- /dev/null +++ b/src/components/Popover/types.ts @@ -0,0 +1,53 @@ +import type { + PopoverOverlayProps, + PopoverAutofocusTarget, +} from './components/PopoverOverlay/types'; + +export type PopoverProps = { + /** The preferred direction to open the popover */ + preferredPosition?: PopoverOverlayProps['preferredPosition']; + /** The preferred alignment of the popover relative to its activator */ + preferredAlignment?: PopoverOverlayProps['preferredAlignment']; + /** Show or hide the Popover */ + active: boolean; + /** + * Use the activator's input element to calculate the Popover position + * @default true + */ + preferInputActivator?: PopoverOverlayProps['preferInputActivator']; + /** + * The element type to wrap the activator with + * @default 'div' + */ + activatorWrapper?: string; + /** Override on the default z-index of 400 */ + zIndexOverride?: number; + /** Prevents focusing the activator or the next focusable element when the popover is deactivated */ + preventFocusOnClose?: boolean; + /** Automatically add wrap content in a section */ + sectioned?: boolean; + /** Allow popover to stretch to the full width of its activator */ + fullWidth?: boolean; + /** Allow popover to stretch to fit content vertically */ + fullHeight?: boolean; + /** Allow popover content to determine the overlay width and height */ + fluidContent?: boolean; + /** Remains in a fixed position */ + fixed?: boolean; + /** Used to illustrate the type of popover element */ + ariaHaspopup?: boolean | 'false' | 'true' | 'menu' | 'listbox' | 'tree' | 'grid' | 'dialog' | undefined; + /** Allow the popover overlay to be hidden when printing */ + hideOnPrint?: boolean; + /** + * The preferred auto focus target defaulting to the popover container + * @default 'container' + */ + autofocusTarget?: PopoverAutofocusTarget; + /** Prevents closing the popover when other overlays are clicked */ + preventCloseOnChildOverlayClick?: boolean; + /** + * Prevents page scrolling when the end of the scrollable Popover overlay content is reached - applied to Pane subcomponent + * @default false + */ + captureOverscroll?: boolean; +} diff --git a/src/components/PositionedOverlay/PositionedOverlay.vue b/src/components/PositionedOverlay/PositionedOverlay.vue index 98c0d6266..203b69e57 100644 --- a/src/components/PositionedOverlay/PositionedOverlay.vue +++ b/src/components/PositionedOverlay/PositionedOverlay.vue @@ -41,7 +41,7 @@ import { intersectionWithViewport, windowRect, } from './utilities/math'; -import type { PreferredPosition, PreferredAlignment } from './utilities/math'; +import type { PositionedOverlayProps } from './types'; import type { VueNode } from '@/utilities/types'; type Positioning = 'above' | 'below' | 'cover'; @@ -56,19 +56,6 @@ export interface OverlayDetails { chevronOffset: number; } -export type PositionedOverlayProps = { - active: boolean; - activator: HTMLElement; - preferInputActivator?: boolean; - preferredPosition?: PreferredPosition; - preferredAlignment?: PreferredAlignment; - fullWidth?: boolean; - fixed?: boolean; - preventInteraction?: boolean; - classNames?: string; - zIndexOverride?: number; -} - interface State { measuring: boolean; activatorRect: Rect; diff --git a/src/components/PositionedOverlay/types.ts b/src/components/PositionedOverlay/types.ts new file mode 100644 index 000000000..a1d53b105 --- /dev/null +++ b/src/components/PositionedOverlay/types.ts @@ -0,0 +1,14 @@ +import type { PreferredPosition, PreferredAlignment } from './utilities/math'; + +export type PositionedOverlayProps = { + active: boolean; + activator: HTMLElement; + preferInputActivator?: boolean; + preferredPosition?: PreferredPosition; + preferredAlignment?: PreferredAlignment; + fullWidth?: boolean; + fixed?: boolean; + preventInteraction?: boolean; + classNames?: string; + zIndexOverride?: number; +} diff --git a/src/components/Tooltip/components/TooltipOverlay/utils.ts b/src/components/Tooltip/components/TooltipOverlay/utils.ts index 911c7e45f..e63d388c0 100644 --- a/src/components/Tooltip/components/TooltipOverlay/utils.ts +++ b/src/components/Tooltip/components/TooltipOverlay/utils.ts @@ -1,5 +1,5 @@ import type { Width, Padding, BorderRadius } from '../../types'; -import type { PositionedOverlayProps } from '@/components/PositionedOverlay/PositionedOverlay.vue'; +import type { PositionedOverlayProps } from '@/components/PositionedOverlay/types'; export type TooltipOverlayBaseProps = { id: string; diff --git a/tsconfig.json b/tsconfig.json index 300ddceb7..a1082be34 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -28,7 +28,7 @@ "allowSyntheticDefaultImports": true }, "include": [ - "docs/components/**/*.vue", + // "docs/components/**/*.vue", "src/**/*.ts", "src/**/*.vue", "dts/*.ts" diff --git a/vite.config.ts b/vite.config.ts index 59293d1fa..b67555a41 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,12 +1,14 @@ +import {readFileSync} from 'fs'; import { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; import svgLoader from 'vite-svg-loader'; import { fileURLToPath } from 'url'; import { replaceCodePlugin } from 'vite-plugin-replace'; -import packageJson from './package.json'; import { generateScopedName } from './build/namespaced-classname.js'; import dts from 'vite-plugin-dts'; +const pkg = JSON.parse(readFileSync(new URL('./package.json', import.meta.url).pathname).toString()); + // https://vitejs.dev/config/ export default () => { return defineConfig({ @@ -17,7 +19,7 @@ export default () => { replacements: [ { from: '%POLARIS_VERSION%', - to: packageJson.polaris_version, + to: pkg.polaris_version, }, ], }), @@ -30,7 +32,6 @@ export default () => { alias: { '@icons': fileURLToPath(new URL('node_modules/@shopify/polaris-icons/dist/svg', import.meta.url)), '@polaris': fileURLToPath(new URL('./polaris/polaris-react/src', import.meta.url)), - '@tokens': fileURLToPath(new URL('./polaris/polaris-tokens/src', import.meta.url)), '@': fileURLToPath(new URL('./src', import.meta.url)), '~': fileURLToPath(new URL('./node_modules', import.meta.url)), }, @@ -46,22 +47,5 @@ export default () => { generateScopedName, }, }, - build: { - lib: { - entry: fileURLToPath(new URL('./src/polaris-vue.ts', import.meta.url)), - name: 'Polaris Vue', - fileName: (format) => `polaris-vue.${format}.js`, - }, - cssCodeSplit: false, - rollupOptions: { - external: ['vue'], - output: { - globals: { - vue: 'Vue', - }, - exports: 'named', - }, - }, - }, }); }; diff --git a/yarn.lock b/yarn.lock index 7544e39f2..9beb0ffdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1338,6 +1338,11 @@ entities@^4.2.0, entities@^4.4.0, entities@^4.5.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== +es-module-lexer@^1.4.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.0.tgz#4878fee3789ad99e065f975fdd3c645529ff0236" + integrity sha512-pqrTKmwEIgafsYZAGw9kszYzmagcE/n4dbgwGWLEXg7J4QFJVQRBld8j3Q3GNez79jzxZshq0bcT962QHOghjw== + esbuild@^0.19.3: version "0.19.8" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.8.tgz#ad05b72281d84483fa6b5345bd246c27a207b8f1" @@ -1746,6 +1751,11 @@ import-lazy@~4.0.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" integrity sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw== +import-meta-resolve@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz#0b1195915689f60ab00f830af0f15cc841e8919e" + integrity sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA== + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -2764,6 +2774,15 @@ validator@^13.7.0: resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b" integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ== +vite-plugin-chunk-split@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/vite-plugin-chunk-split/-/vite-plugin-chunk-split-0.5.0.tgz#b5da3382f88b50354887560760c8b6bf15295bf8" + integrity sha512-pasNKLhH+ICjoCF6HoKKvgmZ1LEPSCIKAa8Lz0ZpMyQC9bLmCLT7UxgKMULewsc9SUw89OX0udsGiIQCtr8wLA== + dependencies: + es-module-lexer "^1.4.1" + import-meta-resolve "^4.0.0" + magic-string "^0.30.5" + vite-plugin-dts@^3.7.3: version "3.7.3" resolved "https://registry.yarnpkg.com/vite-plugin-dts/-/vite-plugin-dts-3.7.3.tgz#072ec78face3b76a7a492ffeb83469ef5318ce0b"