├── .gitignore ├── .storybook └── main.js ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── jest.config.js ├── package-lock.json ├── package.json ├── rollup.config.js ├── src ├── Component.svelte └── index.js ├── stories └── component.stories.js ├── svelte.config.js └── test └── component.spec.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist/ 4 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | stories: ['../stories/**/*.stories.js'], 3 | addons: ['@storybook/addon-actions', '@storybook/addon-links'], 4 | }; 5 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 1.0.0 / 2021-10-15 2 | ================== 3 | 4 | * Run jest only in test folder and added test:watch 5 | * Fix svelte.config.js syntax error (#11) 6 | * Fix failed tests when running yarn test 7 | * Update dependencies 8 | 9 | 0.1.0 / 2020-04-04 10 | ================== 11 | 12 | # Provide svelte component library template 13 | 14 | * Basic Component.svelte 15 | * Testing using svelte-testing-library + Jest 16 | * Storybook 17 | * Rollup 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | NOTICE: 4 | ======= 5 | svelte-component-library-template is based on sveltejs/component-template: 6 | https://github.com/sveltejs/component-template 7 | That was originally created by Rich Harris. 8 | 9 | svelte-component-library-template is Copyright (c) 2020 Nir Maoz 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | *Psst — looking for an app template? Go here --> [sveltejs/template](https://github.com/sveltejs/template)* 2 | 3 | --- 4 | 5 | # svelt-component-library-template 6 | 7 | A base for building shareable Svelte component library. Clone it with [degit](https://github.com/Rich-Harris/degit): 8 | 9 | ```bash 10 | npx degit nirmaoz/svelte-component-library-template my-new-component 11 | cd my-new-component 12 | npm install # or yarn 13 | ``` 14 | 15 | Your component's source code lives in `src/Component.svelte`. 16 | 17 | You can create a package that exports multiple components by adding them to the `src` directory and editing `src/index.js` to reexport them as named exports. 18 | 19 | ## This template includes: 20 | 21 | * Svelte Component 22 | * Testing using svelte-testing-library + Jest 23 | * Storybook 24 | * Rollup, configured to build .js (umd), .min.js (iife), .mjs (es) 25 | 26 | ## Setting up 27 | 28 | * Run `npm init` (or `yarn init`) 29 | * Replace this README with your own 30 | 31 | ## Consuming components 32 | 33 | Your package.json has a `"svelte"` field pointing to `src/index.js`, which allows Svelte apps to import the source code directly, if they are using a bundler plugin like [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) or [svelte-loader](https://github.com/sveltejs/svelte-loader) (where [`resolve.mainFields`](https://webpack.js.org/configuration/resolve/#resolve-mainfields) in your webpack config includes `"svelte"`). **This is recommended.** 34 | 35 | For everyone else, `npm run build` will bundle your component's source code into a plain JavaScript module (`dist/index.mjs`) and a UMD script (`dist/index.js`). This will happen automatically when you publish your component to npm, courtesy of the `prepublishOnly` hook in package.json. 36 | 37 | ### Based on sveltejs/component-template 38 | I couldn't find an opinionated components library template to my liking, so I used [sveltejs/component-template](https://github.com/sveltejs/component-template) as base. And then I added minified build configuration using terser plugin + tests + storybook. 39 | 40 | ### Testing 41 | Comes with tests out of the box using [svelte-testing-library](https://github.com/testing-library/svelte-testing-library) + [Jest](https://github.com/facebook/jest). 42 | 43 | To Run tests: 44 | ```bash 45 | npm test # or yarn 46 | ``` 47 | 48 | ### Storybook 49 | To serve development build: 50 | ```bash 51 | npm run storybook 52 | ``` 53 | 54 | To build static storybook site (default output folder is /docs for easly sharing on github pages): 55 | ```bash 56 | npm run build-storybook 57 | ``` -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | } -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | transform: { 3 | '^.+\\.svelte$': 'svelte-jester', 4 | '^.+\\.js$': 'babel-jest', 5 | }, 6 | moduleFileExtensions: ['js', 'svelte'], 7 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "svelte-component-library", 3 | "version": "0.2.0", 4 | "svelte": "src/index.js", 5 | "module": "dist/index.mjs", 6 | "main": "dist/index.js", 7 | "scripts": { 8 | "build": "rollup -c", 9 | "prepublishOnly": "npm run build", 10 | "test": "jest test", 11 | "test:watch": "yarn test -- --watch", 12 | "storybook": "start-storybook -p 6006", 13 | "build-storybook": "del-cli docs && build-storybook -c .storybook -o docs" 14 | }, 15 | "devDependencies": { 16 | "@babel/core": "^7.9.0", 17 | "@babel/preset-env": "^7.9.0", 18 | "@rollup/plugin-node-resolve": "^6.0.0", 19 | "@storybook/addon-actions": "^5.3.18", 20 | "@storybook/addon-links": "^5.3.18", 21 | "@storybook/addons": "^5.3.18", 22 | "@storybook/svelte": "^8.0.5", 23 | "@testing-library/jest-dom": "^5.3.0", 24 | "@testing-library/svelte": "^3.0.0", 25 | "babel-jest": "^25.2.6", 26 | "babel-loader": "^8.1.0", 27 | "del-cli": "^3.0.0", 28 | "jest": "^25.2.7", 29 | "rollup": "^1.20.0", 30 | "rollup-plugin-svelte": "^5.0.0", 31 | "rollup-plugin-terser": "^5.3.0", 32 | "svelte": "^3.49.0", 33 | "svelte-jester": "^1.0.5", 34 | "svelte-loader": "^2.13.6" 35 | }, 36 | "keywords": [ 37 | "svelte" 38 | ], 39 | "files": [ 40 | "src", 41 | "dist" 42 | ], 43 | "dependencies": {} 44 | } 45 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import svelte from 'rollup-plugin-svelte'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import {terser} from 'rollup-plugin-terser'; 4 | import pkg from './package.json'; 5 | 6 | const name = pkg.name 7 | .replace(/^(@\S+\/)?(svelte-)?(\S+)/, '$3') 8 | .replace(/^\w/, m => m.toUpperCase()) 9 | .replace(/-\w/g, m => m[1].toUpperCase()); 10 | 11 | export default { 12 | input: 'src/index.js', 13 | output: [ 14 | { file: pkg.module, 'format': 'es' }, 15 | { file: pkg.main, 'format': 'umd', name }, 16 | { file: pkg.main.replace('.js','.min.js'), format: 'iife', name, plugins: [terser()]} 17 | ], 18 | plugins: [ 19 | svelte(), 20 | resolve() 21 | ] 22 | }; 23 | -------------------------------------------------------------------------------- /src/Component.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 |

Hello {name}!

12 | 13 | 14 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | export { default as default } from './Component.svelte'; 2 | -------------------------------------------------------------------------------- /stories/component.stories.js: -------------------------------------------------------------------------------- 1 | import { action } from '@storybook/addon-actions'; 2 | import Component from '../src/index'; 3 | 4 | export default { 5 | title: 'Component', 6 | component: Component, 7 | }; 8 | 9 | export const Text = () => ({ 10 | Component: Component, 11 | props: { name: 'World', buttonText: 'Hello Button' }, 12 | on: { click: action('clicked') }, 13 | }); 14 | 15 | export const Emoji = () => ({ 16 | Component: Component, 17 | props: { name: '😀 😎', buttonText: '👍 💯' }, 18 | on: { click: action('clicked') }, 19 | }); 20 | -------------------------------------------------------------------------------- /svelte.config.js: -------------------------------------------------------------------------------- 1 | module.exports = {}; -------------------------------------------------------------------------------- /test/component.spec.js: -------------------------------------------------------------------------------- 1 | // NOTE: original code from https://testing-library.com/docs/svelte-testing-library/example 2 | // NOTE: jest-dom adds handy assertions to Jest and it is recommended, but not required. 3 | import '@testing-library/jest-dom/extend-expect' 4 | 5 | import { render, fireEvent } from '@testing-library/svelte' 6 | 7 | import Component from '../src/Component.svelte' 8 | 9 | describe('Component', () => { 10 | it('shows proper heading when rendered', () => { 11 | const { getByText } = render(Component, { name: 'World' }) 12 | 13 | expect(getByText('Hello World!')).toBeInTheDocument() 14 | }); 15 | 16 | // Note: This is as an async test as we are using `fireEvent` 17 | it('changes button text on click', async () => { 18 | const { getByText } = render(Component, { name: 'World' }) 19 | const button = getByText('Button') 20 | 21 | // Using await when firing events is unique to the svelte testing library because 22 | // we have to wait for the next `tick` so that Svelte flushes all pending state changes. 23 | await fireEvent.click(button) 24 | 25 | expect(button).toHaveTextContent('Button Clicked') 26 | }); 27 | }); --------------------------------------------------------------------------------