├── .gitignore
├── .npmignore
├── .babelrc.js
├── scripts
└── post_install.js
├── rollup.config.js
├── LICENSE
├── package.json
├── src
└── index.js
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | /node_modules
3 | yarn-error.log
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .babelrc
2 | .DS_Store
3 | .gitignore
4 | .yarn.lock
5 | /.git
6 | /node_modules
7 | rollup.config.js
8 | .babelrc.js
9 | .prettierrc.json
10 | /.vscode
--------------------------------------------------------------------------------
/.babelrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | test: {
4 | plugins: [
5 | [
6 | 'istanbul',
7 | {
8 | exclude: ['spec/**/*.js']
9 | }
10 | ]
11 | ]
12 | }
13 | },
14 | presets: [
15 | [
16 | '@babel/preset-env',
17 | {
18 | targets: {
19 | node: 'current'
20 | }
21 | }
22 | ]
23 | ],
24 | plugins: [
25 | '@babel/plugin-proposal-class-properties',
26 | '@babel/plugin-transform-classes',
27 | '@babel/plugin-proposal-object-rest-spread'
28 | ]
29 | }
--------------------------------------------------------------------------------
/scripts/post_install.js:
--------------------------------------------------------------------------------
1 | console.log(
2 | 'Registering a Stimulus controller for use is easy!\n\n' +
3 | '1. Open index.js in your controllers folder.\n' +
4 | '2. Add the following import:\n' +
5 | " import Radiolabel from 'radiolabel'\n" +
6 | '3. Register the radiolabel controller at the bottom:\n' +
7 | " application.register('radiolabel', Radiolabel)\n\n" +
8 | 'You can also set up Radiolabel for conditional import:\n\n' +
9 | "if (process.env.RAILS_ENV === 'development') {\n" +
10 | " import('radiolabel').then(Radiolabel =>\n" +
11 | " application.register('radiolabel', Radiolabel.default)\n" +
12 | ' )\n' +
13 | '}\n\n'
14 | )
15 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import filesize from 'rollup-plugin-filesize'
2 | import resolve from 'rollup-plugin-node-resolve'
3 | import babel from 'rollup-plugin-babel'
4 |
5 | const pkg = require('./package.json')
6 |
7 | const name = pkg.name
8 |
9 | export default {
10 | input: 'src/index.js',
11 | external: ['stimulus'],
12 | output: [
13 | {
14 | file: 'dist/index.js',
15 | format: 'cjs',
16 | sourcemap: true
17 | },
18 | {
19 | file: 'dist/index.m.js',
20 | format: 'es',
21 | sourcemap: true
22 | },
23 | {
24 | file: 'dist/index.umd.js',
25 | format: 'umd',
26 | name,
27 | sourcemap: true,
28 | globals: {
29 | stimulus: 'Stimulus'
30 | }
31 | }
32 | ],
33 | plugins: [resolve(), babel(), filesize()]
34 | }
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 leastbad
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": "radiolabel",
3 | "version": "1.1.1",
4 | "description": "Mutation indicator overlays for CableReady operations",
5 | "keywords": ["stimulusjs", "cableready", "rails", "development", "overlay"],
6 | "main": "dist/index.js",
7 | "umd:main": "dist/index.umd.js",
8 | "module": "dist/index.m.js",
9 | "source": "src/index.js",
10 | "author": "@leastbad",
11 | "license": "MIT",
12 | "external": "stimulus",
13 | "scripts": {
14 | "postinstall": "node scripts/post_install.js",
15 | "prettier-standard:check": "yarn run prettier-standard --check *.js **/*.js",
16 | "prettier-standard:format": "yarn run prettier-standard *.js **/*.js",
17 | "build": "rollup -c",
18 | "dev": "rollup -wc",
19 | "release": "np"
20 | },
21 | "homepage": "https://leastbad.com/",
22 | "bugs": {
23 | "url": "https://github.com/leastbad/radiolabel/issues"
24 | },
25 | "dependencies": {
26 | "cable_ready": ">=4.5.0",
27 | "gsap": "^3.8.0",
28 | "stimulus": ">=2.0.0"
29 | },
30 | "devDependencies": {
31 | "@babel/core": "^7.6.2",
32 | "@babel/plugin-proposal-class-properties": "^7.3.4",
33 | "@babel/plugin-proposal-object-rest-spread": "^7.5.5",
34 | "@babel/plugin-transform-classes": "^7.3.4",
35 | "@babel/plugin-transform-spread": "^7.2.2",
36 | "@babel/preset-env": "^7.6.2",
37 | "np": "^5.1.3",
38 | "prettier-standard": "^16.1.0",
39 | "rollup": "^1.20.3",
40 | "rollup-plugin-babel": "^4.3.2",
41 | "rollup-plugin-filesize": "^6.0.1",
42 | "rollup-plugin-node-resolve": "^5.2.0"
43 | },
44 | "repository": {
45 | "type": "git",
46 | "url": "https://github.com/leastbad/radiolabel.git"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import { Controller } from 'stimulus'
2 | import CableReady from 'cable_ready'
3 | import { gsap } from 'gsap'
4 |
5 | const dasherize = string => {
6 | return string.replace(/[A-Z]/g, function (char, index) {
7 | return (index !== 0 ? '-' : '') + char.toLowerCase()
8 | })
9 | }
10 |
11 | export default class extends Controller {
12 | static values = { duration: Number }
13 |
14 | initialize () {
15 | this.operations = Object.keys(CableReady.DOMOperations).map(key =>
16 | dasherize(key)
17 | )
18 | this.duration = 7
19 | }
20 |
21 | connect () {
22 | this.operations.forEach(operation =>
23 | document.addEventListener(
24 | `cable-ready:after-${operation}`,
25 | this.intercept
26 | )
27 | )
28 | }
29 |
30 | disconnect () {
31 | this.operations.forEach(operation =>
32 | document.removeEventListener(
33 | `cable-ready:after-${operation}`,
34 | this.intercept
35 | )
36 | )
37 | }
38 |
39 | durationValueChanged () {
40 | this.duration = this.durationValue
41 | }
42 |
43 | intercept = ({ detail, target, type }) => {
44 | if (target !== document) {
45 | const body = target === document.body
46 | const style = getComputedStyle(target)
47 | const border = style.getPropertyValue('border')
48 | const title = document.createElement('div')
49 | const overlay = document.createElement('div')
50 | const eventType = type.split('after-')[1]
51 | const color = eventType === 'morph' ? '#FF9800' : '#0F0'
52 | const d = detail.stimulusReflex
53 | const titleTarget = (d && d.target) || ''
54 | const reflexId = (d && d.reflexId) || ''
55 |
56 | setTimeout(() => {
57 | const t_rect = target.getBoundingClientRect()
58 | const rect = body ? { top: 56, left: 0 } : t_rect
59 | const titleTop = rect.top - 56 + Math.round(scrollY)
60 | const oTop = body ? 0 : t_rect.top + Math.round(scrollY)
61 |
62 | title.style.cssText = `position:absolute;z-index:5001;top:${titleTop}px;left:${rect.left}px;background-color:#fff;padding: 3px 8px 3px 8px;border: 1px solid #000;pointer-events: none;`
63 | title.innerHTML = `${eventType} ${titleTarget} \u2192 ${detail.selector}
${reflexId}`
64 |
65 | overlay.style.cssText = `position:absolute;z-index:5000;top:${oTop}px;left:${t_rect.left}px;width:${t_rect.width}px;height:${t_rect.height}px;background-color: ${color};pointer-events: none;`
66 | overlay.style.border = border
67 |
68 | document.body.appendChild(title)
69 | document.body.appendChild(overlay)
70 |
71 | gsap.fromTo(
72 | overlay,
73 | {
74 | opacity: 1.0
75 | },
76 | {
77 | opacity: 0,
78 | duration: this.duration,
79 | ease: 'expo',
80 | onComplete: () => {
81 | title.remove()
82 | overlay.remove()
83 | }
84 | }
85 | )
86 | })
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
9 | Mutation indicator overlays for CableReady operations 10 | Tiny at <100 LOC 11 |
12 | 13 |