ultimate_turbo_modal 1.7.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,108 @@
1
+ import { Controller } from '@hotwired/stimulus';
2
+ import { enter, leave } from 'el-transition';
3
+
4
+ export default class extends Controller {
5
+ static targets = ["container", "content"]
6
+ static values = {
7
+ advanceUrl: String,
8
+ allowedClickOutsideSelector: String
9
+ }
10
+
11
+ connect() {
12
+ let _this = this;
13
+ this.showModal();
14
+
15
+ this.turboFrame = this.element.closest('turbo-frame');
16
+
17
+ // hide modal when back button is pressed
18
+ window.addEventListener('popstate', function (event) {
19
+ if (_this.#hasHistoryAdvanced()) _this.#resetModalElement();
20
+ });
21
+
22
+ window.modal = this;
23
+ }
24
+
25
+ disconnect() {
26
+ window.modal = undefined;
27
+ }
28
+
29
+ showModal() {
30
+ enter(this.containerTarget);
31
+
32
+ if (this.advanceUrlValue && !this.#hasHistoryAdvanced()) {
33
+ this.#setHistoryAdvanced();
34
+ history.pushState({}, "", this.advanceUrlValue);
35
+ }
36
+ }
37
+
38
+ // if we advanced history, go back, which will trigger
39
+ // hiding the model. Otherwise, hide the modal directly.
40
+ hideModal() {
41
+ // Prevent multiple calls to hideModal.
42
+ // Sometimes some events are double-triggered.
43
+ if (this.hidingModal) return
44
+ this.hidingModal = true;
45
+
46
+ let event = new Event('modal:closing', { cancelable: true });
47
+ this.turboFrame.dispatchEvent(event);
48
+ if (event.defaultPrevented) return
49
+
50
+ this.#resetModalElement();
51
+
52
+ event = new Event('modal:closed', { cancelable: false });
53
+ this.turboFrame.dispatchEvent(event);
54
+
55
+ if (this.#hasHistoryAdvanced())
56
+ history.back();
57
+ }
58
+
59
+ hide() {
60
+ this.hideModal();
61
+ }
62
+
63
+ refreshPage() {
64
+ window.Turbo.visit(window.location.href, { action: "replace" });
65
+ }
66
+
67
+ // hide modal on successful form submission
68
+ // action: "turbo:submit-end->modal#submitEnd"
69
+ submitEnd(e) {
70
+ if (e.detail.success) this.hideModal();
71
+ }
72
+
73
+ // hide modal when clicking ESC
74
+ // action: "keyup@window->modal#closeWithKeyboard"
75
+ closeWithKeyboard(e) {
76
+ if (e.code == "Escape") this.hideModal();
77
+ }
78
+
79
+ // hide modal when clicking outside of modal
80
+ // action: "click@window->modal#outsideModalClicked"
81
+ outsideModalClicked(e) {
82
+ let clickedInsideModal = this.contentTarget.contains(e.target) || this.contentTarget == e.target;
83
+ let clickedAllowedSelector = this.allowedClickOutsideSelectorValue && this.allowedClickOutsideSelectorValue !== '' && e.target.closest(this.allowedClickOutsideSelectorValue) != null;
84
+
85
+ if (!clickedInsideModal && !clickedAllowedSelector)
86
+ this.hideModal();
87
+ }
88
+
89
+ #resetModalElement() {
90
+ leave(this.containerTarget).then(() => {
91
+ this.turboFrame.removeAttribute("src");
92
+ this.containerTarget.remove();
93
+ this.#resetHistoryAdvanced();
94
+ });
95
+ }
96
+
97
+ #hasHistoryAdvanced() {
98
+ return document.body.getAttribute("data-turbo-modal-history-advanced") == "true"
99
+ }
100
+
101
+ #setHistoryAdvanced() {
102
+ return document.body.setAttribute("data-turbo-modal-history-advanced", "true")
103
+ }
104
+
105
+ #resetHistoryAdvanced() {
106
+ document.body.removeAttribute("data-turbo-modal-history-advanced");
107
+ }
108
+ }
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "ultimate_turbo_modal",
3
+ "version": "0.0.0",
4
+ "description": "The ultimate Turbo / Stimulus / Hotwire modal window for Rails",
5
+ "main": "dist/ultimate_turbo_modal.min.js",
6
+ "module": "dist/ultimate_turbo_modal.min.js",
7
+ "files": [
8
+ "dist"
9
+ ],
10
+ "scripts": {
11
+ "update-version": "node scripts/update-version.js",
12
+ "build": "yarn install && rollup -c",
13
+ "release": "bash scripts/release-npm.sh"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/cmer/ultimate_turbo_modal.git"
18
+ },
19
+ "keywords": [
20
+ "hotwire",
21
+ "turbo",
22
+ "stimulus",
23
+ "tailwind",
24
+ "modal",
25
+ "rubyonrails",
26
+ "rails"
27
+ ],
28
+ "author": "Carl Mercier",
29
+ "license": "MIT",
30
+ "bugs": {
31
+ "url": "https://github.com/cmer/ultimate_turbo_modal/issues"
32
+ },
33
+ "homepage": "https://github.com/cmer/ultimate_turbo_modal#readme",
34
+ "dependencies": {
35
+ "@hotwired/stimulus": "^3.2.2",
36
+ "@hotwired/turbo-rails": "^8.0.0",
37
+ "el-transition": "^0.0.7",
38
+ "idiomorph": "^0.7.3"
39
+ },
40
+ "devDependencies": {
41
+ "@rollup/plugin-node-resolve": "^15.2.3",
42
+ "rollup": "^2.79.1",
43
+ "rollup-plugin-copy": "^3.5.0",
44
+ "rollup-plugin-css-only": "^4.3.0",
45
+ "rollup-plugin-terser": "^7.0.2"
46
+ }
47
+ }
@@ -0,0 +1,24 @@
1
+ import resolve from '@rollup/plugin-node-resolve';
2
+ import css from 'rollup-plugin-css-only';
3
+ import { terser } from 'rollup-plugin-terser';
4
+
5
+ export default {
6
+ input: './index.js',
7
+ output: [
8
+ {
9
+ file: 'dist/ultimate_turbo_modal.js',
10
+ format: 'esm'
11
+ },
12
+ {
13
+ file: 'dist/ultimate_turbo_modal.min.js',
14
+ format: 'esm',
15
+ plugins: [terser()]
16
+ }
17
+ ],
18
+ external: ['@hotwired/stimulus'],
19
+ inlineDynamicImports: true,
20
+ plugins: [
21
+ resolve(),
22
+ css({ output: 'vanilla.css' })
23
+ ]
24
+ };
@@ -0,0 +1,37 @@
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ # Check for uncommitted changes
5
+ echo "Checking for uncommitted changes..."
6
+ if ! git diff --quiet; then
7
+ echo "There are uncommitted changes. Aborting."
8
+ exit 1
9
+ fi
10
+ echo "No uncommitted changes found."
11
+
12
+ # Update version
13
+ echo "Updating version..."
14
+ npm run update-version
15
+
16
+ # Install dependencies
17
+ echo "Installing dependencies..."
18
+ npm install
19
+
20
+ # Build project
21
+ echo "Building project..."
22
+ npm run build
23
+
24
+ # Add, commit, and push changes
25
+ VERSION=$(cat VERSION)
26
+ echo "Adding changes to git..."
27
+ git add .
28
+ echo "Committing changes (Release NPM v$VERSION)..."
29
+ git commit -m "Release NPM v$VERSION"
30
+ echo "Pushing changes..."
31
+ git push
32
+
33
+ # Publish to npm
34
+ echo "Publishing to npm..."
35
+ npm publish
36
+
37
+ echo "Release complete!"
@@ -0,0 +1,21 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const versionFilePath = path.resolve(__dirname, '..', 'VERSION');
5
+ const packageJsonPath = path.resolve(__dirname, '..', 'package.json');
6
+
7
+ // Read version from VERSION file
8
+ const version = fs.readFileSync(versionFilePath, 'utf8').trim();
9
+
10
+ // Read package.json
11
+ const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
12
+
13
+ // Update version if it's different
14
+ if (packageJson.version !== version) {
15
+ packageJson.version = version;
16
+ // Write updated package.json, preserving indentation (2 spaces)
17
+ fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
18
+ console.log(`Updated package.json version to ${version}`);
19
+ } else {
20
+ console.log(`package.json version (${packageJson.version}) is already up to date.`);
21
+ }
@@ -0,0 +1,179 @@
1
+ .dark {
2
+ .modal-overlay {
3
+ background-color: rgba(17, 24, 39, 0.8)
4
+ }
5
+
6
+ .modal-header,
7
+ .modal-footer {
8
+ border-color: #4B5563;
9
+ }
10
+
11
+ .modal-content {
12
+ background-color: #1F2937;
13
+ color: #ffffff;
14
+ }
15
+
16
+ .modal-close-button:hover,
17
+ .modal-close-icon:hover {
18
+ background-color: #6B7280;
19
+ color: #ffffff;
20
+ }
21
+ }
22
+
23
+ :not(.dark) {
24
+
25
+ .modal-close-button,
26
+ .modal-close-icon {
27
+ color: #9CA3AF;
28
+
29
+ &:hover {
30
+ color: #111827;
31
+ background-color: #E5E7EB;
32
+ }
33
+ }
34
+ }
35
+
36
+ .modal-container {
37
+ position: relative;
38
+
39
+ &[data-header="false"] .modal-header {
40
+ position: absolute;
41
+ }
42
+
43
+ &[data-header-divider="true"] .modal-header {
44
+ border-bottom-width: 1px;
45
+ }
46
+
47
+ &[data-footer-divider="true"] .modal-footer {
48
+ border-top-width: 1px;
49
+ }
50
+
51
+ &[data-padding="true"] .modal-main {
52
+ padding: 1rem;
53
+ padding-top: 0.5rem;
54
+ }
55
+
56
+ &[data-title="false"] .modal-title-h {
57
+ display: none;
58
+ }
59
+
60
+ &[data-close-button="false"] .modal-close {
61
+ display: none;
62
+ }
63
+
64
+ .sr-only {
65
+ position: absolute;
66
+ width: 1px;
67
+ height: 1px;
68
+ padding: 0;
69
+ margin: -1px;
70
+ overflow: hidden;
71
+ clip: rect(0, 0, 0, 0);
72
+ white-space: nowrap;
73
+ border-width: 0;
74
+ }
75
+ }
76
+
77
+ .modal-overlay {
78
+ position: fixed;
79
+ top: 0;
80
+ right: 0;
81
+ bottom: 0;
82
+ left: 0;
83
+ z-index: 40;
84
+ background-color: rgba(17, 24, 39, 0.7);
85
+ transition-property: opacity;
86
+ }
87
+
88
+ .modal-outer {
89
+ overflow-y: auto;
90
+ position: fixed;
91
+ top: 0;
92
+ right: 0;
93
+ bottom: 0;
94
+ left: 0;
95
+ z-index: 50;
96
+ margin: 1rem;
97
+
98
+ @media (min-width: 640px) {
99
+ margin-left: auto;
100
+ margin-right: auto;
101
+ }
102
+
103
+ @media (min-width: 768px) {
104
+ max-width: 48rem;
105
+ }
106
+ }
107
+
108
+ .modal-inner {
109
+ display: flex;
110
+ padding: 0.25rem;
111
+ justify-content: center;
112
+ align-items: center;
113
+ min-height: 100%;
114
+
115
+ @media (min-width: 640px) {
116
+ padding: 1rem;
117
+ }
118
+ }
119
+
120
+ .modal-content {
121
+ overflow: hidden;
122
+ position: relative;
123
+ background-color: #ffffff;
124
+ transition-property: all;
125
+ text-align: left;
126
+ border-radius: 0.5rem;
127
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
128
+
129
+ @media (min-width: 640px) {
130
+ margin-top: 2rem;
131
+ margin-bottom: 2rem;
132
+ max-width: 48rem;
133
+ }
134
+ }
135
+
136
+ .modal-header {
137
+ display: flex;
138
+ padding-top: 1rem;
139
+ padding-bottom: 1rem;
140
+ justify-content: space-between;
141
+ align-items: center;
142
+ width: 100%;
143
+ border-top-left-radius: 0.25rem;
144
+ border-top-right-radius: 0.25rem;
145
+ }
146
+
147
+ .modal-title {
148
+ line-height: 1.75rem;
149
+ font-weight: 600;
150
+ padding-left: 1rem;
151
+ }
152
+
153
+ .modal-footer {
154
+ display: flex;
155
+ padding: 1rem;
156
+ border-bottom-right-radius: 0.25rem;
157
+ border-bottom-left-radius: 0.25rem;
158
+ border-top-width: 1px;
159
+ }
160
+
161
+ .modal-close {
162
+ margin-right: 1rem;
163
+ }
164
+
165
+ .modal-close-button {
166
+ display: inline-flex;
167
+ padding: 0.375rem;
168
+ margin-left: auto;
169
+ background-color: transparent;
170
+ font-size: 0.875rem;
171
+ line-height: 1.25rem;
172
+ align-items: center;
173
+ border-radius: 0.5rem;
174
+ }
175
+
176
+ .modal-close-icon {
177
+ width: 1.25rem;
178
+ height: 1.25rem;
179
+ }