Skip to content

Commit

Permalink
Better typescript support. Fixed multiple issues when handling both c…
Browse files Browse the repository at this point in the history
…lick and hover events.

This package was not set up very well when consumed by other svelte apps, especially the typescript svelte apps.
Notably, there were no typings exported, and the "svelte" key was not present in the package.json.

I followed [this](https://github.com/mattjennings/svelte-typescript-component-template) wonderful template to get running. The only downside is we don't get real `.d.ts` files for the popover. But without autogenerated typings I don't plan to pursue it. See: sveltejs/component-template#29 (comment).

I may look to use [sveld](https://github.com/IBM/sveld) to do this in the future.

Additionally, I found a lot of edge cases if you want both "click" and "hover". Primarily you might want this for keyboard and touch devices if you like hover but want to remain accessible. I made it work a lot better, and added some nice features like escape to close or click away to close.
  • Loading branch information
jguze committed Jun 24, 2021
1 parent 1975ac6 commit 4127038
Show file tree
Hide file tree
Showing 13 changed files with 366 additions and 53 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.DS_Store
node_modules
/dist/
.vscode/
.vscode/
storybook-static/
18 changes: 9 additions & 9 deletions .storybook/main.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
module.exports = {
"stories": [
"../src/**/*.stories.mdx",
"../src/**/*.stories.@(js|jsx|ts|tsx|svelte)"
stories: [
"../stories/**/*.stories.mdx",
"../stories/**/*.stories.@(js|jsx|ts|tsx|svelte)",
],
"addons": [
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-svelte-csf"
"@storybook/addon-svelte-csf",
],
"svelteOptions": {
"preprocess": require("svelte-preprocess")()
}
}
svelteOptions: {
preprocess: require("svelte-preprocess")(),
},
};
85 changes: 78 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
{
"name": "svelte-easy-popover",
"version": "0.1.0",
"svelte": "dist/index.js",
"module": "dist/index.mjs",
"main": "dist/index.js",
"main": "dist/index.umd.js",
"types": "dist/ts/index.d.ts",
"author": "Justin Guze",
"repository": {
"type": "git",
"url": "git+https://github.com/jguze/svelte-easy-popover.git"
},
"scripts": {
"prebuild": "rm -rf ./dist",
"dev": "rollup -c -w",
"validate": "svelte-check",
"build": "rollup -c",
"prepublishOnly": "npm run build",
"storybook": "start-storybook -p 6006",
Expand All @@ -23,12 +28,15 @@
"@storybook/addon-actions": "^6.2.9",
"@storybook/addon-essentials": "^6.2.9",
"@storybook/addon-links": "^6.2.9",
"@storybook/addon-svelte-csf": "^1.0.0",
"@storybook/addon-svelte-csf": "^1.1.0",
"@storybook/storybook-deployer": "^2.8.8",
"@storybook/svelte": "^6.2.9",
"@tsconfig/svelte": "^2.0.1",
"babel-loader": "^8.2.2",
"fs-extra": "^10.0.0",
"glob": "^7.1.7",
"rollup": "^2.0.0",
"rollup-plugin-execute": "^1.1.1",
"rollup-plugin-svelte": "^6.0.0",
"rollup-plugin-terser": "^7.0.2",
"svelte": "^3.38.2",
Expand Down
60 changes: 34 additions & 26 deletions rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,34 +1,42 @@
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import pkg from './package.json';
import autoPreprocess from 'svelte-preprocess';
import typescript from '@rollup/plugin-typescript';
import replace from '@rollup/plugin-replace';
import svelte from "rollup-plugin-svelte";
import resolve from "@rollup/plugin-node-resolve";
import pkg from "./package.json";
import autoPreprocess from "svelte-preprocess";
import execute from "rollup-plugin-execute";
import typescript from "@rollup/plugin-typescript";
import { terser } from "rollup-plugin-terser";

const production = !process.env.ROLLUP_WATCH;

const name = pkg.name
.replace(/^(@\S+\/)?(svelte-)?(\S+)/, '$3')
.replace(/^\w/, m => m.toUpperCase())
.replace(/-\w/g, m => m[1].toUpperCase());
.replace(/^(@\S+\/)?(svelte-)?(\S+)/, "$3")
.replace(/^\w/, (m) => m.toUpperCase())
.replace(/-\w/g, (m) => m[1].toUpperCase());

export default {
input: 'src/index.ts',
output: [
{ file: pkg.module, 'format': 'es' },
{ file: pkg.main, 'format': 'umd', name }
],
plugins: [
svelte({
preprocess: autoPreprocess(),
}),
typescript({ sourceMap: !production }),
resolve(),
replace({
'process.env.NODE_ENV': production ? '"production"' : '"development"',
preventAssignment: true,
}),
production && terser()
]
input: "src/index.ts",
output: [
{ file: pkg.module, format: "es" },
{
file: pkg.main,
format: "umd",
name,
sourcemap: !production,
plugins: [
// we only want to run this once, so we'll just make it part of this output's plugins
execute([
"tsc --outDir ./dist --declaration",
"node scripts/preprocess.js",
]),
],
},
],
plugins: [
svelte({
preprocess: autoPreprocess(),
}),
typescript({ sourceMap: !production }),
resolve(),
production && terser(),
],
};
85 changes: 85 additions & 0 deletions scripts/preprocess.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
const fs = require("fs-extra");
const glob = require("glob");
const path = require("path");
const svelte = require("svelte/compiler");
const sveltePreprocess = require("svelte-preprocess");

const basePath = path.resolve(__dirname, "../");
const srcPath = path.resolve(basePath, "src");
const distPath = path.resolve(basePath, "dist");

/**
* This will process .svelte files into plain javascript so consumers do not have to setup Typescript to use this library
*
* Additionally, it will move the .d.ts files into /dist/ts
*/
async function main() {
// get all .svelte files
glob(path.join(srcPath, "**/*.svelte"), null, async function (err, files) {
if (err) throw err;
// process them
await Promise.all(
files.map((filePath) => preprocessSvelte(path.resolve(filePath)))
);
});

// move .d.ts files into /dist/ts
glob(path.join(distPath, "**/*.d.ts"), null, async function (err, files) {
if (err) throw err;
const tsPath = path.join(distPath, "ts");

await Promise.all(
files.map(async (filePath) => {
filePath = path.resolve(filePath);
// ignore anything in /dist/ts (could probably make a better glob pattern)
if (!filePath.includes(tsPath)) {
await fs.move(filePath, filePath.replace(distPath, tsPath), {
overwrite: true,
});
}
})
);
});
}

/**
* Processes .svelte file and write it to /dist, also copies the original .svelte file to /dist/ts
*/
async function preprocessSvelte(filePath) {
const srcCode = await fs.readFile(filePath, { encoding: "utf-8" });
let { code } = await svelte.preprocess(
srcCode,
sveltePreprocess({
// unfortunately, sourcemap on .svelte files sometimes comments out the </script> tag
// so we need to disable sourcemapping for them
sourceMap: false,
typescript: {
compilerOptions: {
sourceMap: false,
},
},
}),
{
filename: filePath,
}
);

// remove lang=ts from processed .svelte files
code = code.replace(/script lang="ts"/g, "script");

const relativePath = filePath.split(srcPath)[1];
const destination = path.join(distPath, filePath.split(srcPath)[1]);

// write preprocessed svelte file to /dist
await fs.ensureFile(destination);
await fs.writeFile(destination, code, { encoding: "utf-8" });

// write the unprocessed svelte component to /dist/ts/ so we can have correct types for ts users
const tsDest = path.join(distPath, "ts", relativePath);
await fs.ensureFile(tsDest);
await fs.writeFile(tsDest, srcCode, {
encoding: "utf-8",
});
}

main();
Loading

0 comments on commit 4127038

Please sign in to comment.