├── .editorconfig
├── .eslintrc.cjs
├── .gitignore
├── changelog.md
├── license.txt
├── package-lock.json
├── package.json
├── readme.md
├── sample.webp
├── src
└── index.ts
└── tsconfig.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = tab
6 | indent_size = 2
7 | trim_trailing_whitespace = true
8 | insert_final_newline = true
9 | end_of_line = lf
10 |
11 | [*.md]
12 | indent_style = space
13 |
--------------------------------------------------------------------------------
/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: "sweet"
3 | };
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # folders
2 | node_modules
3 | dist
4 |
5 | # macos
6 | .DS_Store
7 |
--------------------------------------------------------------------------------
/changelog.md:
--------------------------------------------------------------------------------
1 | # v3.0.2
2 | _2023-12-10_
3 |
4 | * re-publish as compiled directly by `tsc`
5 |
6 | # v3.0.1
7 | _2023-03-25_
8 |
9 | * re-publish without `livereload` in source code
10 |
11 | # v3.0.0
12 | _2023-03-25_
13 |
14 | * drop `unpkg`/`iife` bundle, only emit `esm`
15 | * have everything in the `options` object (incl. `className`)
16 |
17 | # v2.0.3
18 | _2022-10-17_
19 |
20 | * use the `browser` and `unpkg` fields
21 | * minimize `unpkg` bundle, but don't shit source maps
22 |
23 | # v2.0.2
24 | _2022-10-17_
25 |
26 | * fix paths in package.json
27 | * don't minify browser bundle
28 | * always ship source maps
29 |
30 | # v2.0.1
31 | _2022-10-17_
32 |
33 | * move to ts
34 | * refer to generated typing
35 |
36 | # v2.0.0
37 | _2022-01-15_
38 |
39 | * drop ie
40 | * clean up injected css
41 | * simplify api
42 |
43 | # v1.1.1
44 | _2021-05-10_
45 |
46 | * run `esm` and `cjs` bundles through `buble`, too (fix breaking on ie)
47 | * check for `-ms-filter` instead of `NodeList.prototype.forEach` to target ie
48 |
49 | # v1.1.0
50 | _2020-11-12_
51 |
52 | * add source maps to `cjs` and `esm` bundles
53 |
54 | # v1.0.0
55 | _2020-10-22_
56 |
57 | * no breaking changes since v0.3.12, just felt like it's ready
58 | * introduce types
59 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Robin Löffel
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cosha",
3 | "version": "3.0.2",
4 | "description": "Colorful shadows for your images. 🎨",
5 | "type": "module",
6 | "main": "dist/index.js",
7 | "types": "dist/index.d.ts",
8 | "homepage": "https://github.com/robinloeffel/cosha",
9 | "author": "Robin Löffel",
10 | "license": "MIT",
11 | "keywords": [
12 | "browser",
13 | "image",
14 | "shadow",
15 | "colors",
16 | "html",
17 | "css filters",
18 | "dom"
19 | ],
20 | "files": [
21 | "dist"
22 | ],
23 | "devDependencies": {
24 | "browser-sync": "^2.29.3",
25 | "concurrently": "^8.2.2",
26 | "eslint": "^8.55.0",
27 | "eslint-config-sweet": "^18.0.0",
28 | "gh-pages": "^6.1.0",
29 | "typescript": "^5.3.3"
30 | },
31 | "scripts": {
32 | "start": "concurrently 'tsc -w' 'browser-sync dist -w' -n 'typescript,browser-sync'",
33 | "prepublishOnly": "rm -rf dist && tsc",
34 | "postpublish": "gh-pages -d dist -s '*.{html,js}'"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # cosha
6 |
7 | [](https://www.npmjs.com/package/cosha)
8 | [](https://www.npmjs.com/package/cosha)
9 | [](https://www.npmjs.com/package/cosha)
10 | [](https://bundlephobia.com/package/cosha)
11 | [](https://github.com/robinloeffel/cosha/blob/main/license.txt)
12 |
13 | > Colorful shadows for your images. 🎨
14 |
15 | [`cosha`](https://npm.robinloeffel.ch/cosha) lets you add **co**lorful **sha**dows to your images. Try it out and look for yourself—it really couldn't be easier to set up!
16 |
17 | ## How
18 |
19 | ```bash
20 | npm i cosha
21 | ```
22 |
23 | ```html
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | ```
34 |
35 | ```js
36 | import cosha from "cosha";
37 |
38 | cosha({
39 | className: "colorful-shadow",
40 | blur: "10px",
41 | brightness: "125%",
42 | saturation: "110%",
43 | x: "2px",
44 | y: "6px"
45 | });
46 | ```
47 |
48 | Alternatively, if that module bundler stuff isn't for you, you can get it directly from [`https://unpkg.com/cosha`](https://unpkg.com/cosha).
49 |
50 | ```html
51 |
56 | ```
57 |
58 | ## Config
59 |
60 | Everything in the config is optional. You can also use it by just calling `cosha()`.
61 |
62 | ```js
63 | cosha(options);
64 | ```
65 |
66 | ### `options.className`
67 |
68 | Type: `string`
69 | Default: `"cosha"`
70 |
71 | The class the plugin looks for. This should be on the original `img` or `picture` node(s).
72 |
73 | ### `options.blur`
74 |
75 | Type: `number | string`
76 | Default: `"5px"`
77 |
78 | The amount of blur to apply to the image. See the [CSS `blur` function docs](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/blur) on MDN for more details.
79 |
80 | ### `options.brightness`
81 |
82 | Type: `number | string`
83 | Default: `1`
84 |
85 | The amount of brightness to apply to the image. See the [CSS `brightness` function docs](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/brightness) on MDN for more details.
86 |
87 | ### `options.saturation`
88 |
89 | Type: `number | string`
90 | Default: `1`
91 |
92 | The amount of saturation to apply to the image. See the [CSS `saturation` function docs](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/saturation) on MDN for more details.
93 |
94 | ### `options.x`
95 |
96 | Type: `number | string`
97 | Default: `0`
98 |
99 | The amount of horizontal translation to apply to the image. See the [CSS `translate` function docs](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate) on MDN for more details.
100 |
101 | ### `options.y`
102 |
103 | Type: `number | string`
104 | Default: `0`
105 |
106 | The amount of vertical translation to apply to the image. See the [CSS `translate` function docs](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate) on MDN for more details.
107 |
108 | ## Gotcha
109 |
110 | It runs in every browser except Internet Explorer. This is because of missing support for standard [CSS `filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/filter#Browser_compatibility) functions.
111 |
112 | ## License
113 |
114 | MIT
115 |
--------------------------------------------------------------------------------
/sample.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/robinloeffel/cosha/110465c3cd340222b97baa1cb34e5b8b2d059139/sample.webp
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | type Image = HTMLImageElement | HTMLPictureElement;
2 |
3 | interface Options {
4 | className?: string;
5 | blur?: string | number;
6 | brightness?: string | number;
7 | saturation?: string | number;
8 | x?: string | number;
9 | y?: string | number;
10 | }
11 |
12 | export default ({
13 | className = "cosha",
14 | blur = "5px",
15 | brightness = 1,
16 | saturation = 1,
17 | x = 0,
18 | y = 0
19 | }: Options = {}) => {
20 | const images = document.querySelectorAll(`.${className}`);
21 | const styles = document.createElement("style");
22 |
23 | styles.textContent = `
24 | .${className}-wrapper {
25 | position: relative;
26 | display: grid;
27 | place-content: center;
28 | }
29 |
30 | .${className}-clone {
31 | position: absolute;
32 | z-index: -1;
33 | translate: ${x} ${y} 0;
34 | filter: blur(${blur}) brightness(${brightness}) saturate(${saturation});
35 | }
36 | `;
37 | document.body.append(styles);
38 |
39 | for (const original of images) {
40 | const cloned = original.cloneNode(true) as typeof original;
41 | const wrapper = document.createElement("div");
42 |
43 | cloned.classList.remove(className);
44 | cloned.classList.add(`${className}-clone`);
45 |
46 | wrapper.classList.add(`${className}-wrapper`);
47 | wrapper.append(original.cloneNode(true), cloned);
48 | wrapper.querySelectorAll("img").item(1).alt = "";
49 |
50 | original.replaceWith(wrapper);
51 | }
52 | };
53 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "moduleResolution": "bundler",
6 | "lib": ["esnext", "dom", "dom.iterable"],
7 | "strict": true,
8 | "noUncheckedIndexedAccess": true,
9 | "skipLibCheck": true,
10 | "verbatimModuleSyntax": true,
11 | "moduleDetection": "force",
12 | "declaration": true,
13 | "outDir": "dist"
14 | },
15 | "include": ["src"]
16 | }
17 |
--------------------------------------------------------------------------------