sun-sword 0.0.8 → 0.0.10
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +9 -4
- data/README.md +2 -13
- data/lib/generators/sun_sword/USAGE +1 -0
- data/lib/generators/sun_sword/frontend_generator.rb +8 -7
- data/lib/generators/sun_sword/templates_frontend/controllers/application_controller.rb.tt +5 -1
- data/lib/generators/sun_sword/templates_frontend/frontend/entrypoints/application.js +1 -1
- data/lib/generators/sun_sword/templates_frontend/frontend/pages/web.js +103 -101
- data/lib/generators/sun_sword/templates_frontend/frontend/stylesheets/application.css +221 -0
- data/lib/generators/sun_sword/templates_frontend/views/components/_action_destroy.html.erb.tt +1 -1
- data/lib/generators/sun_sword/templates_frontend/views/layouts/application.html.erb.tt +1 -2
- data/lib/generators/sun_sword/templates_frontend/views/layouts/dashboard/application.html.erb.tt +10 -3
- data/lib/generators/sun_sword/templates_frontend/vite.config.ts.tt +3 -7
- data/lib/generators/sun_sword/templates_scaffold/controllers/controller.rb.tt +2 -2
- data/lib/generators/sun_sword/templates_scaffold/views/index.html.erb.tt +5 -3
- data/lib/sun_sword/version.rb +1 -1
- metadata +4 -9
- data/lib/generators/sun_sword/templates_frontend/frontend/stylesheets/application.scss +0 -198
- data/lib/generators/sun_sword/templates_frontend/postcss.config.js +0 -6
- data/lib/generators/sun_sword/templates_frontend/tailwind.config.js +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b3549043ef82d7091d8e6d984f86eefaf03ea039f2844f34f2b4f73e308006e1
|
4
|
+
data.tar.gz: 7d311b8b6e938425160c8d83d9a4122c7ced6271cec8e361caf91156b407c99b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d1e7a1946d73a1172608407db3d9edfb29d7832445cbd6eeb75bc648f05934250be28f1bc614b00e757a5984b08cd4ab82b8a22f60c994ad715bf0b21faa523
|
7
|
+
data.tar.gz: 9617f1d30d53033195b5387d677c79526db7744550529f51828a3b6470f2aca849b755e666c64190de81121d0e2880fbd0157be400f1789e2ec1a4f0e00f2fbb
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,14 @@
|
|
1
1
|
# Omakase Ruby styling for Rails
|
2
2
|
inherit_gem: { rubocop-rails-omakase: rubocop.yml }
|
3
3
|
|
4
|
+
# Load extensions via Plugin API (bukan `require:`)
|
5
|
+
plugins:
|
6
|
+
- rubocop-rails
|
7
|
+
- rubocop-performance
|
8
|
+
# tambahkan jika dipakai:
|
9
|
+
# - rubocop-rspec
|
10
|
+
# - rubocop-minitest
|
11
|
+
|
4
12
|
# Overwrite or add rules to create your own house style
|
5
13
|
#
|
6
14
|
# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
|
@@ -9,7 +17,7 @@ inherit_gem: { rubocop-rails-omakase: rubocop.yml }
|
|
9
17
|
|
10
18
|
AllCops:
|
11
19
|
SuggestExtensions: false
|
12
|
-
TargetRubyVersion: 3.3
|
20
|
+
TargetRubyVersion: 3.3
|
13
21
|
DisabledByDefault: true
|
14
22
|
Exclude:
|
15
23
|
- '**/templates/**/*'
|
@@ -526,9 +534,6 @@ Lint/ShadowedException:
|
|
526
534
|
Lint/RedundantStringCoercion:
|
527
535
|
Enabled: true
|
528
536
|
|
529
|
-
Lint/Syntax:
|
530
|
-
Enabled: true
|
531
|
-
|
532
537
|
Lint/UnderscorePrefixedVariableName:
|
533
538
|
Enabled: true
|
534
539
|
|
data/README.md
CHANGED
@@ -15,28 +15,17 @@ gem 'sun-sword'
|
|
15
15
|
|
16
16
|
And then execute:
|
17
17
|
```bash
|
18
|
-
$ rails new kotaro_minami -d=postgresql -T --skip-javascript --skip-asset-pipeline
|
19
|
-
$ bundle install
|
20
|
-
$ rails generate rider_kick:init
|
21
|
-
$ rails generate rider_kick:clean_arch --setup
|
22
|
-
$ rails db:drop db:create db:migrate db:seed
|
23
18
|
$ rails generate sun_sword:frontend
|
24
|
-
$ rubocop -
|
19
|
+
$ rubocop -A
|
25
20
|
```
|
26
21
|
## Usage
|
27
22
|
```bash
|
28
23
|
Description:
|
29
24
|
Clean Architecture CRUD generator
|
30
|
-
rails new kotaro_minami -d=postgresql -T --skip-javascript --skip-asset-pipeline
|
31
25
|
|
32
26
|
Example:
|
33
|
-
To Generate Init:
|
34
|
-
bin/rails generate rider_kick:init
|
35
|
-
|
36
|
-
To Generate Pattern:
|
37
|
-
bin/rails generate rider_kick:clean_arch --setup
|
38
|
-
|
39
27
|
To Generate Frontend:
|
28
|
+
bin/rails generate sun_sword:init
|
40
29
|
bin/rails generate sun_sword:frontend --setup
|
41
30
|
|
42
31
|
To Generate scaffold:
|
@@ -49,6 +49,10 @@ module SunSword
|
|
49
49
|
gem "turbo-rails"
|
50
50
|
gem "stimulus-rails"
|
51
51
|
gem "vite_rails"
|
52
|
+
|
53
|
+
group :development do
|
54
|
+
gem "listen"
|
55
|
+
end
|
52
56
|
RUBY
|
53
57
|
append_to_file('Gemfile', gem_dependencies)
|
54
58
|
say 'Vite Rails gem added and bundle installed', :green
|
@@ -57,10 +61,9 @@ module SunSword
|
|
57
61
|
def install_vite
|
58
62
|
template 'package.json', 'package.json'
|
59
63
|
run 'bundle exec vite install'
|
60
|
-
run 'yarn add -D
|
61
|
-
run 'yarn add -
|
62
|
-
run 'yarn add -D eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-tailwindcss
|
63
|
-
run 'yarn add @hotwired/stimulus @hotwired/turbo-rails stimulus-vite-helpers vite animejs stimulus-use'
|
64
|
+
run 'yarn add -D vite vite-plugin-full-reload vite-plugin-ruby vite-plugin-stimulus-hmr'
|
65
|
+
run 'yarn add path stimulus-vite-helpers @hotwired/stimulus @hotwired/turbo-rails @tailwindcss/aspect-ratio @tailwindcss/forms @tailwindcss/line-clamp @tailwindcss/typography @tailwindcss/vite tailwindcss vite-plugin-rails autoprefixer'
|
66
|
+
run 'yarn add -D eslint prettier eslint-plugin-prettier eslint-config-prettier eslint-plugin-tailwindcss'
|
64
67
|
say 'Vite installed successfully', :green
|
65
68
|
end
|
66
69
|
|
@@ -68,8 +71,6 @@ module SunSword
|
|
68
71
|
say 'Configuring Vite...'
|
69
72
|
|
70
73
|
# Add a basic Vite configuration file to your Rails app
|
71
|
-
template 'tailwind.config.js', 'tailwind.config.js'
|
72
|
-
template 'postcss.config.js', 'postcss.config.js'
|
73
74
|
template 'vite.config.ts.tt', 'vite.config.ts'
|
74
75
|
template 'Procfile.dev', 'Procfile.dev'
|
75
76
|
template 'bin/watch', 'bin/watch'
|
@@ -102,7 +103,7 @@ module SunSword
|
|
102
103
|
template 'controllers/application_controller.rb.tt', File.join('app/controllers/application_controller.rb')
|
103
104
|
site_route = <<-RUBY
|
104
105
|
|
105
|
-
default_url_options :host => "
|
106
|
+
default_url_options :host => "ENV['BASE_URL']"
|
106
107
|
root "site#stimulus"
|
107
108
|
get "site/jadi_a"
|
108
109
|
get "site/jadi_b"
|
@@ -34,6 +34,10 @@ class ApplicationController < ActionController::Base
|
|
34
34
|
|
35
35
|
def set_layouts
|
36
36
|
# "#{current_auth.user.role}/application"
|
37
|
-
'
|
37
|
+
'application'
|
38
38
|
end
|
39
|
+
|
40
|
+
def ensure_turbo_frame!
|
41
|
+
turbo_frame_request? || turbo_native_app?
|
42
|
+
end
|
39
43
|
end
|
@@ -5,7 +5,7 @@ import {stimulus} from "./stimulus"
|
|
5
5
|
import WebController from "../pages/web"
|
6
6
|
import SiteStimulusController from "../pages/stimulus.js"
|
7
7
|
|
8
|
-
import "../stylesheets/application.
|
8
|
+
import "../stylesheets/application.css"
|
9
9
|
console.log("Kotaro is here")
|
10
10
|
console.log(window.location.hash.slice(1))
|
11
11
|
|
@@ -1,116 +1,118 @@
|
|
1
|
-
import {Controller} from "@hotwired/stimulus"
|
2
|
-
import anime from "animejs";
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
3
2
|
|
4
3
|
export default class extends Controller {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
4
|
+
connect() {
|
5
|
+
this.sidebarEl = document.querySelector(".sidebar")
|
6
|
+
this.backdropEl = document.querySelector(".backdrop-active")
|
7
|
+
this.toggleBtns = document.querySelectorAll("[data-action~='web#sidebarToggle']")
|
8
|
+
if (!this.sidebarEl || !this.backdropEl) return
|
9
|
+
|
10
|
+
this.isOpen = false
|
11
|
+
this.prefersReduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches
|
12
|
+
this._onEsc = (e) => { if (e.key === "Escape") this.sidebarClose() }
|
13
|
+
|
14
|
+
this.backdropEl.addEventListener("click", () => this.sidebarClose(), { passive: true })
|
15
|
+
|
16
|
+
// Inisialisasi: pastikan posisi tertutup
|
17
|
+
this.sidebarEl.classList.add("-translate-x-full")
|
18
|
+
this.sidebarEl.classList.remove("translate-x-0")
|
19
|
+
this._setBackdrop(false)
|
10
20
|
}
|
11
21
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
})
|
22
|
+
// === Sidebar ===
|
23
|
+
sidebarToggle(e) {
|
24
|
+
e?.preventDefault()
|
25
|
+
this.isOpen ? this.sidebarClose() : this.sidebarOpen(e?.currentTarget)
|
17
26
|
}
|
18
27
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
}
|
28
|
+
sidebarOpen(triggerEl) {
|
29
|
+
if (this.isOpen) return
|
30
|
+
this.isOpen = true
|
31
|
+
|
32
|
+
// Kurangi jank: pastikan element “on GPU”
|
33
|
+
this.sidebarEl.style.transform = "translate3d(-100%,0,0)"
|
34
|
+
// Force reflow → lalu transisi ke posisi buka pada frame berikut
|
35
|
+
requestAnimationFrame(() => {
|
36
|
+
this.sidebarEl.classList.remove("-translate-x-full")
|
37
|
+
this.sidebarEl.classList.add("translate-x-0")
|
38
|
+
this.sidebarEl.style.transform = "" // kembalikan, biar Tailwind kelas yang mengatur
|
39
|
+
})
|
40
|
+
|
41
|
+
this._setBackdrop(true)
|
42
|
+
document.documentElement.classList.add("overflow-hidden")
|
43
|
+
triggerEl?.setAttribute("aria-expanded", "true")
|
44
|
+
this.sidebarEl.setAttribute("aria-hidden", "false")
|
45
|
+
document.addEventListener("keydown", this._onEsc, { passive: true })
|
46
|
+
|
47
|
+
// Fokus pertama
|
48
|
+
this.sidebarEl.querySelector("a, button, input, [tabindex]")
|
49
|
+
?.focus({ preventScroll: true })
|
37
50
|
}
|
38
51
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
})
|
54
|
-
anime({
|
55
|
-
targets: '.sidebar',
|
56
|
-
translateX: 300,
|
57
|
-
duration: 1000,
|
58
|
-
easing: 'easeInOutExpo',
|
59
|
-
complete: function (anim) {
|
60
|
-
console.log('Sidebar show!');
|
61
|
-
}
|
62
|
-
});
|
63
|
-
} else {
|
64
|
-
sidebar.classList.add('side_hide');
|
65
|
-
anime({
|
66
|
-
targets: '.sidebar',
|
67
|
-
easing: 'easeInOutExpo',
|
68
|
-
translateX: -300,
|
69
|
-
duration: 1000,
|
70
|
-
complete: function (anim) {
|
71
|
-
console.log('Sidebar Close!');
|
72
|
-
}
|
73
|
-
});
|
74
|
-
anime({
|
75
|
-
targets: ".backdrop-active",
|
76
|
-
translateX: 0,
|
77
|
-
opacity: [0.8, 0],
|
78
|
-
easing: 'easeInOutSine',
|
79
|
-
complete: function (anim) {
|
80
|
-
backdropActive.classList.add('hidden');
|
81
|
-
}
|
82
|
-
})
|
83
|
-
}
|
52
|
+
sidebarClose() {
|
53
|
+
if (!this.isOpen) return
|
54
|
+
this.isOpen = false
|
55
|
+
|
56
|
+
// Transisi balik (geser keluar)
|
57
|
+
this.sidebarEl.classList.add("-translate-x-full")
|
58
|
+
this.sidebarEl.classList.remove("translate-x-0")
|
59
|
+
|
60
|
+
this._setBackdrop(false)
|
61
|
+
document.documentElement.classList.remove("overflow-hidden")
|
62
|
+
this.sidebarEl.setAttribute("aria-hidden", "true")
|
63
|
+
this.toggleBtns.forEach((btn) => btn.setAttribute("aria-expanded", "false"))
|
64
|
+
document.removeEventListener("keydown", this._onEsc)
|
65
|
+
this.toggleBtns[0]?.focus({ preventScroll: true })
|
84
66
|
}
|
85
67
|
|
86
68
|
onSidebarClick(event) {
|
87
|
-
event.
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
69
|
+
const a = event.target.closest("a, button[type='submit']")
|
70
|
+
if (!a) return
|
71
|
+
setTimeout(() => this.sidebarClose(), 0)
|
72
|
+
}
|
73
|
+
|
74
|
+
// === Util ===
|
75
|
+
_setBackdrop(show) {
|
76
|
+
// Jika user minta “reduce motion”, skip animasi
|
77
|
+
if (this.prefersReduced) {
|
78
|
+
this.backdropEl.classList.toggle("hidden", !show)
|
79
|
+
this.backdropEl.classList.toggle("pointer-events-none", !show)
|
80
|
+
this.backdropEl.style.opacity = show ? "1" : "0"
|
81
|
+
return
|
82
|
+
}
|
83
|
+
|
84
|
+
// Pastikan elemen ada di flow saat mulai animasi
|
85
|
+
this.backdropEl.classList.remove("hidden")
|
86
|
+
requestAnimationFrame(() => {
|
87
|
+
if (show) {
|
88
|
+
this.backdropEl.classList.remove("opacity-0", "pointer-events-none")
|
89
|
+
this.backdropEl.classList.add("opacity-100")
|
90
|
+
} else {
|
91
|
+
// Fade out, lalu sembunyikan setelah selesai
|
92
|
+
this.backdropEl.classList.remove("opacity-100")
|
93
|
+
this.backdropEl.classList.add("opacity-0", "pointer-events-none")
|
94
|
+
const onEnd = () => {
|
95
|
+
this.backdropEl.classList.add("hidden")
|
96
|
+
this.backdropEl.removeEventListener("transitionend", onEnd)
|
111
97
|
}
|
112
|
-
|
98
|
+
this.backdropEl.addEventListener("transitionend", onEnd)
|
99
|
+
}
|
100
|
+
})
|
101
|
+
}
|
102
|
+
|
103
|
+
// Opsional: submenu & profil tetap bisa dipakai dari versi sebelumnya
|
104
|
+
profileSetting(event) {
|
105
|
+
const container = event.currentTarget.closest("li")
|
106
|
+
const dropdown = container?.querySelector("[class^='profile-']")
|
107
|
+
if (!dropdown) return
|
108
|
+
|
109
|
+
dropdown.classList.toggle("hidden")
|
110
|
+
const closeOnOutside = (e) => {
|
111
|
+
if (!dropdown.contains(e.target) && !event.currentTarget.contains(e.target)) {
|
112
|
+
dropdown.classList.add("hidden")
|
113
|
+
window.removeEventListener("click", closeOnOutside, true)
|
114
|
+
}
|
113
115
|
}
|
116
|
+
window.addEventListener("click", closeOnOutside, true)
|
114
117
|
}
|
115
118
|
}
|
116
|
-
|
@@ -0,0 +1,221 @@
|
|
1
|
+
@import "tailwindcss";
|
2
|
+
|
3
|
+
@plugin "@tailwindcss/forms";
|
4
|
+
@plugin "@tailwindcss/typography";
|
5
|
+
@plugin "@tailwindcss/aspect-ratio";
|
6
|
+
|
7
|
+
@source "../../../app/views/**/*.html.erb";
|
8
|
+
@source "../../../app/views/**/*.rb";
|
9
|
+
@source "../../../app/helpers/**/*.rb";
|
10
|
+
@source "./app/frontend/**/*.{js,ts,jsx,tsx,css,scss,ejs}";
|
11
|
+
|
12
|
+
|
13
|
+
/* Theme tokens: memetakan screens & font family */
|
14
|
+
@theme {
|
15
|
+
/* Breakpoints (sesuai config kamu) */
|
16
|
+
--breakpoint-sm: 640px;
|
17
|
+
--breakpoint-md: 768px;
|
18
|
+
--breakpoint-lg: 1024px;
|
19
|
+
--breakpoint-xl: 1280px;
|
20
|
+
--breakpoint-2xl: 1536px;
|
21
|
+
|
22
|
+
/* Font stack: Open Sans + fallback default Tailwind */
|
23
|
+
--font-sans: "Open Sans", ui-sans-serif, system-ui, sans-serif,
|
24
|
+
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
25
|
+
}
|
26
|
+
|
27
|
+
|
28
|
+
@layer base {
|
29
|
+
* {
|
30
|
+
box-sizing: border-box;
|
31
|
+
}
|
32
|
+
|
33
|
+
*:before,
|
34
|
+
*:after {
|
35
|
+
box-sizing: border-box;
|
36
|
+
}
|
37
|
+
|
38
|
+
html {
|
39
|
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
40
|
+
}
|
41
|
+
|
42
|
+
body {
|
43
|
+
font-family: "Open Sans", sans-serif;
|
44
|
+
font-size: 1.6rem;
|
45
|
+
line-height: 1.75;
|
46
|
+
font-weight: 300;
|
47
|
+
color: #303030;
|
48
|
+
letter-spacing: 0.045em;
|
49
|
+
background-color: #fbfbfb;
|
50
|
+
}
|
51
|
+
|
52
|
+
.tooltip {
|
53
|
+
position: relative;
|
54
|
+
}
|
55
|
+
|
56
|
+
strong {
|
57
|
+
font-weight: 500;
|
58
|
+
}
|
59
|
+
|
60
|
+
.tooltip::before {
|
61
|
+
content: "";
|
62
|
+
position: absolute;
|
63
|
+
top: -6px;
|
64
|
+
left: 50%;
|
65
|
+
transform: translateX(-50%);
|
66
|
+
border-width: 4px 6px 0 6px;
|
67
|
+
border-style: solid;
|
68
|
+
border-color: rgba(0, 0, 0, 0.7) transparent transparent transparent;
|
69
|
+
z-index: 99;
|
70
|
+
opacity: 0;
|
71
|
+
transition: .3s opacity;
|
72
|
+
}
|
73
|
+
|
74
|
+
[tooltip-position='left']::before {
|
75
|
+
left: 0%;
|
76
|
+
top: 50%;
|
77
|
+
margin-left: -12px;
|
78
|
+
transform: translatey(-50%) rotate(-90deg)
|
79
|
+
}
|
80
|
+
|
81
|
+
[tooltip-position='top']::before {
|
82
|
+
left: 50%;
|
83
|
+
}
|
84
|
+
|
85
|
+
[tooltip-position='buttom']::before {
|
86
|
+
top: 100%;
|
87
|
+
margin-top: 8px;
|
88
|
+
transform: translateX(-50%) translatey(-100%) rotate(-180deg)
|
89
|
+
}
|
90
|
+
|
91
|
+
[tooltip-position='right']::before {
|
92
|
+
left: 100%;
|
93
|
+
top: 50%;
|
94
|
+
margin-left: 1px;
|
95
|
+
transform: translatey(-50%) rotate(90deg)
|
96
|
+
}
|
97
|
+
|
98
|
+
.tooltip::after {
|
99
|
+
content: attr(data-text);
|
100
|
+
position: absolute;
|
101
|
+
min-width: 10rem;
|
102
|
+
left: 50%;
|
103
|
+
top: -6px;
|
104
|
+
transform: translateX(-50%) translateY(-100%);
|
105
|
+
background: rgba(0, 0, 0, 0.7);
|
106
|
+
text-align: center;
|
107
|
+
color: #fff;
|
108
|
+
font-size: 12px;
|
109
|
+
border-radius: 5px;
|
110
|
+
pointer-events: none;
|
111
|
+
padding: 4px 4px;
|
112
|
+
z-index: 99;
|
113
|
+
opacity: 0;
|
114
|
+
transition: .3s opacity;
|
115
|
+
}
|
116
|
+
|
117
|
+
[tooltip-position='left']::after {
|
118
|
+
left: 0;
|
119
|
+
top: 50%;
|
120
|
+
margin-left: -8px;
|
121
|
+
transform: translateX(-100%) translateY(-50%);
|
122
|
+
}
|
123
|
+
|
124
|
+
[tooltip-position='top']::after {
|
125
|
+
left: 50%;
|
126
|
+
}
|
127
|
+
|
128
|
+
[tooltip-position='buttom']::after {
|
129
|
+
top: 100%;
|
130
|
+
margin-top: 8px;
|
131
|
+
transform: translateX(-50%) translateY(0%);
|
132
|
+
}
|
133
|
+
|
134
|
+
[tooltip-position='right']::after {
|
135
|
+
left: 100%;
|
136
|
+
top: 50%;
|
137
|
+
margin-left: 8px;
|
138
|
+
transform: translateX(0%) translateY(-50%);
|
139
|
+
}
|
140
|
+
|
141
|
+
.tooltip:hover::after, .tooltip:hover::before {
|
142
|
+
opacity: 1
|
143
|
+
}
|
144
|
+
|
145
|
+
|
146
|
+
pre {
|
147
|
+
white-space: pre-wrap;
|
148
|
+
word-wrap: break-word;
|
149
|
+
}
|
150
|
+
|
151
|
+
//#------------
|
152
|
+
h1 {
|
153
|
+
@apply text-2xl;
|
154
|
+
}
|
155
|
+
|
156
|
+
h2 {
|
157
|
+
@apply text-xl;
|
158
|
+
}
|
159
|
+
|
160
|
+
h3 {
|
161
|
+
@apply text-lg;
|
162
|
+
}
|
163
|
+
|
164
|
+
.class-button {
|
165
|
+
@apply rounded-md px-3 py-2 text-center text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2;
|
166
|
+
@apply focus-visible:outline-gray-500 bg-gray-500 hover:bg-white hover:text-gray-500 hover:border-gray-50 hover:outline;
|
167
|
+
}
|
168
|
+
|
169
|
+
.class-button-outline {
|
170
|
+
@apply rounded-md px-3 py-2 text-center text-sm font-semibold text-gray-500 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2;
|
171
|
+
@apply outline outline-1 border-gray-500 focus-visible:outline-gray-500 bg-white hover:bg-gray-500 hover:text-white hover:border-gray-500 hover:outline;
|
172
|
+
}
|
173
|
+
|
174
|
+
.class-label {
|
175
|
+
@apply text-sm font-semibold leading-6 text-gray-900;
|
176
|
+
}
|
177
|
+
|
178
|
+
.class-text-field {
|
179
|
+
@apply block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6;
|
180
|
+
}
|
181
|
+
|
182
|
+
.class-card-container {
|
183
|
+
@apply overflow-hidden bg-white shadow sm:rounded-lg p-5
|
184
|
+
}
|
185
|
+
|
186
|
+
.class-input {
|
187
|
+
@apply sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6 pl-2
|
188
|
+
}
|
189
|
+
|
190
|
+
.class-tr {
|
191
|
+
@apply top-0 z-10 border-b border-gray-300 bg-white/75 px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell
|
192
|
+
}
|
193
|
+
|
194
|
+
.class-td {
|
195
|
+
@apply whitespace-nowrap px-3 py-5 text-sm text-gray-500
|
196
|
+
}
|
197
|
+
|
198
|
+
.class-menu-link {
|
199
|
+
@apply hover:font-semibold hover:text-gray-500 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700
|
200
|
+
}
|
201
|
+
|
202
|
+
.class-text-link {
|
203
|
+
@apply hover:font-semibold hover:text-gray-500 block rounded-md text-sm leading-6 text-gray-700
|
204
|
+
}
|
205
|
+
|
206
|
+
.class-menu-active-link {
|
207
|
+
@apply font-semibold block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
@layer utilities {
|
212
|
+
/* Chrome, Safari and Opera */
|
213
|
+
.no-scrollbar::-webkit-scrollbar {
|
214
|
+
display: none;
|
215
|
+
}
|
216
|
+
|
217
|
+
.no-scrollbar {
|
218
|
+
-ms-overflow-style: none; /* IE and Edge */
|
219
|
+
scrollbar-width: none; /* Firefox */
|
220
|
+
}
|
221
|
+
}
|
data/lib/generators/sun_sword/templates_frontend/views/components/_action_destroy.html.erb.tt
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
</svg>
|
6
6
|
</button>
|
7
7
|
<div class="confirmation-destroy-<%%= value.id %> hidden relative z-10" aria-labelledby="modal-title" role="dialog" aria-modal="false">
|
8
|
-
<div class="fixed inset-0 bg-gray-500
|
8
|
+
<div class="fixed inset-0 bg-gray-500/75 transition-opacity min-h-screen z-100"></div>
|
9
9
|
<div class="fixed inset-0 z-100 w-screen overflow-y-auto">
|
10
10
|
<div class="flex min-h-full justify-center p-4 text-center items-center sm:p-0">
|
11
11
|
<div class="relative transform overflow-hidden rounded-lg bg-white px-4 pb-4 pt-5 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-lg sm:p-6">
|
@@ -16,8 +16,7 @@
|
|
16
16
|
<%%= csp_meta_tag %>
|
17
17
|
|
18
18
|
<%%= vite_client_tag %>
|
19
|
-
<%%=
|
20
|
-
<%%= vite_javascript_tag 'application' %>
|
19
|
+
<%%= vite_javascript_tag "application", "data-turbo-track": "reload", defer: true %>
|
21
20
|
</head>
|
22
21
|
|
23
22
|
<body class="h-full" data-turbo="true">
|
data/lib/generators/sun_sword/templates_frontend/views/layouts/dashboard/application.html.erb.tt
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
<%%= csp_meta_tag %>
|
17
17
|
|
18
18
|
<%%= vite_client_tag %>
|
19
|
-
<%%= vite_javascript_tag
|
19
|
+
<%%= vite_javascript_tag "application", "data-turbo-track": "reload", defer: true %>
|
20
20
|
</head>
|
21
21
|
|
22
22
|
<body class="h-full" data-turbo="true">
|
@@ -27,7 +27,11 @@
|
|
27
27
|
<div class="relative isolate flex min-h-svh w-full bg-white max-lg:flex-col lg:bg-zinc-100 dark:bg-zinc-900 dark:lg:bg-zinc-950">
|
28
28
|
|
29
29
|
<%%# mobile %>
|
30
|
-
<div
|
30
|
+
<div
|
31
|
+
class="fixed inset-y-0 left-0 z-50 w-64 max-w-[85vw] bg-white rounded-2xl m-2
|
32
|
+
-translate-x-full will-change-transform transition-transform duration-300 ease-out
|
33
|
+
lg:hidden sidebar"
|
34
|
+
data-action="click->web#onSidebarClick">
|
31
35
|
<nav class="flex h-full min-h-0 flex-col">
|
32
36
|
<%%= render "components/layouts/sidebar", from: :mobile %>
|
33
37
|
</nav>
|
@@ -53,7 +57,10 @@
|
|
53
57
|
</div>
|
54
58
|
|
55
59
|
<main class="flex flex-1 flex-col pb-2 lg:min-w-0 lg:pl-64 lg:pr-2 lg:pt-2">
|
56
|
-
<div
|
60
|
+
<div
|
61
|
+
class="fixed inset-0 z-40 bg-black/50 opacity-0 pointer-events-none
|
62
|
+
transition-opacity duration-300 ease-out backdrop-active lg:hidden hidden"
|
63
|
+
aria-hidden="true"></div>
|
57
64
|
<div class="grow p-6 lg:rounded-lg lg:bg-white lg:p-10 lg:shadow-sm lg:ring-1 lg:ring-zinc-950/5 dark:lg:bg-zinc-900 dark:lg:ring-white/10">
|
58
65
|
<div class="mx-auto max-w-6xl">
|
59
66
|
<%%= yield %>
|
@@ -2,9 +2,12 @@ import {defineConfig} from 'vite'
|
|
2
2
|
import RubyPlugin from 'vite-plugin-ruby'
|
3
3
|
import FullReload from 'vite-plugin-full-reload'
|
4
4
|
import StimulusHMR from 'vite-plugin-stimulus-hmr';
|
5
|
+
// @ts-ignore
|
6
|
+
import tailwindcss from "@tailwindcss/vite";
|
5
7
|
export default defineConfig({
|
6
8
|
plugins: [
|
7
9
|
RubyPlugin(),
|
10
|
+
tailwindcss(),
|
8
11
|
FullReload(['config/routes.rb', 'app/views/**/*', 'app/frontend/pages/**/*']),
|
9
12
|
StimulusHMR()
|
10
13
|
],
|
@@ -16,12 +19,5 @@ export default defineConfig({
|
|
16
19
|
application: 'app/frontend/entrypoints/application.js'
|
17
20
|
}
|
18
21
|
}
|
19
|
-
},
|
20
|
-
css: {
|
21
|
-
preprocessorOptions: {
|
22
|
-
scss: {
|
23
|
-
api: 'modern-compiler' // or "modern"
|
24
|
-
}
|
25
|
-
}
|
26
22
|
}
|
27
23
|
})
|
@@ -104,9 +104,9 @@ class <%= [@route_scope_class, @scope_class].reject { |c| c.empty? }.join("::")
|
|
104
104
|
def set_<%= @variable_subject %>
|
105
105
|
<% if @resource_owner_id.present? -%>
|
106
106
|
@<%= @variable_subject %> = <%= @model_class %>.find_by(id: params[:id], <%=@resource_owner_id%>: <%=@resource_owner_id%>)
|
107
|
-
<%else
|
107
|
+
<%else -%>
|
108
108
|
@<%= @variable_subject %> = <%= @model_class %>.find_by(id: params[:id])
|
109
|
-
<%end
|
109
|
+
<%end -%>
|
110
110
|
redirect_to <%= [@route_scope_path, @scope_path].reject { |c| c.empty? }.join("_") %>_url, error: '<%= @subject_class %> not found.' if @<%= @variable_subject %>.nil?
|
111
111
|
end
|
112
112
|
|
@@ -9,8 +9,10 @@
|
|
9
9
|
<p class="mt-2 text-sm text-gray-700">A list of all the <%= @subject_class %>.</p>
|
10
10
|
</div>
|
11
11
|
<div class="mt-4 sm:ml-16 sm:mt-0 sm:flex-none">
|
12
|
-
|
13
|
-
|
12
|
+
<%% if Rails.application.routes.url_helpers.respond_to?(:new_<%= [@route_scope_path, @scope_path.singularize].reject { |c| c.empty? }.join("_") %>_path) %>
|
13
|
+
<%%= link_to new_<%= [@route_scope_path, @scope_path.singularize].reject { |c| c.empty? }.join("_") %>_path do %>
|
14
|
+
<button type="button" class="block class-button">Add <%= @subject_class %></button>
|
15
|
+
<%% end %>
|
14
16
|
<%% end %>
|
15
17
|
</div>
|
16
18
|
</div>
|
@@ -19,7 +21,7 @@
|
|
19
21
|
<table class="min-w-full divide-y divide-gray-300">
|
20
22
|
<thead>
|
21
23
|
<tr>
|
22
|
-
<%% <%= @controllers.list_fields.map { |tc| [tc.titleize.to_s, ''] + [["Action", "text-center"]]
|
24
|
+
<%% <%= @controllers.list_fields.map { |tc| [tc.titleize.to_s, '']} + [["Action", "text-center"]]%>.each do |title, attr_class| %>
|
23
25
|
<th scope="col" class="class-tr attr-class"><%%= title %></th>
|
24
26
|
<%% end %>
|
25
27
|
</th>
|
data/lib/sun_sword/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sun-sword
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kotarominami
|
8
|
-
autorequire:
|
9
8
|
bindir: exe
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
12
11
|
dependencies:
|
13
12
|
- !ruby/object:Gem::Dependency
|
14
13
|
name: bundler
|
@@ -88,12 +87,10 @@ files:
|
|
88
87
|
- lib/generators/sun_sword/templates_frontend/frontend/entrypoints/stimulus.js
|
89
88
|
- lib/generators/sun_sword/templates_frontend/frontend/pages/stimulus.js
|
90
89
|
- lib/generators/sun_sword/templates_frontend/frontend/pages/web.js
|
91
|
-
- lib/generators/sun_sword/templates_frontend/frontend/stylesheets/application.
|
90
|
+
- lib/generators/sun_sword/templates_frontend/frontend/stylesheets/application.css
|
92
91
|
- lib/generators/sun_sword/templates_frontend/helpers/application_helper.rb
|
93
92
|
- lib/generators/sun_sword/templates_frontend/package.json
|
94
|
-
- lib/generators/sun_sword/templates_frontend/postcss.config.js
|
95
93
|
- lib/generators/sun_sword/templates_frontend/rubocop.yml.tt
|
96
|
-
- lib/generators/sun_sword/templates_frontend/tailwind.config.js
|
97
94
|
- lib/generators/sun_sword/templates_frontend/views/components/_action_destroy.html.erb.tt
|
98
95
|
- lib/generators/sun_sword/templates_frontend/views/components/_action_edit.html.erb.tt
|
99
96
|
- lib/generators/sun_sword/templates_frontend/views/components/_action_show.html.erb.tt
|
@@ -124,7 +121,6 @@ licenses:
|
|
124
121
|
- MIT
|
125
122
|
metadata:
|
126
123
|
source_code_uri: https://github.com/kotaroisme/sun-sword
|
127
|
-
post_install_message:
|
128
124
|
rdoc_options: []
|
129
125
|
require_paths:
|
130
126
|
- lib
|
@@ -139,8 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
139
135
|
- !ruby/object:Gem::Version
|
140
136
|
version: '0'
|
141
137
|
requirements: []
|
142
|
-
rubygems_version: 3.
|
143
|
-
signing_key:
|
138
|
+
rubygems_version: 3.7.2
|
144
139
|
specification_version: 4
|
145
140
|
summary: Sun Sword is a Generator for Clean Architecture
|
146
141
|
test_files: []
|
@@ -1,198 +0,0 @@
|
|
1
|
-
@use "tailwindcss/base";
|
2
|
-
@use "tailwindcss/components";
|
3
|
-
@use "tailwindcss/utilities";
|
4
|
-
|
5
|
-
@layer base {
|
6
|
-
* {
|
7
|
-
box-sizing: border-box;
|
8
|
-
}
|
9
|
-
|
10
|
-
*:before,
|
11
|
-
*:after {
|
12
|
-
box-sizing: border-box;
|
13
|
-
}
|
14
|
-
|
15
|
-
html {
|
16
|
-
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
17
|
-
}
|
18
|
-
|
19
|
-
body {
|
20
|
-
font-family: "Open Sans", sans-serif;
|
21
|
-
font-size: 1.6rem;
|
22
|
-
line-height: 1.75;
|
23
|
-
font-weight: 300;
|
24
|
-
color: #303030;
|
25
|
-
letter-spacing: 0.045em;
|
26
|
-
background-color: #fbfbfb;
|
27
|
-
}
|
28
|
-
|
29
|
-
.tooltip {
|
30
|
-
position: relative;
|
31
|
-
}
|
32
|
-
|
33
|
-
strong {
|
34
|
-
font-weight: 500;
|
35
|
-
}
|
36
|
-
|
37
|
-
.tooltip::before {
|
38
|
-
content: "";
|
39
|
-
position: absolute;
|
40
|
-
top: -6px;
|
41
|
-
left: 50%;
|
42
|
-
transform: translateX(-50%);
|
43
|
-
border-width: 4px 6px 0 6px;
|
44
|
-
border-style: solid;
|
45
|
-
border-color: rgba(0, 0, 0, 0.7) transparent transparent transparent;
|
46
|
-
z-index: 99;
|
47
|
-
opacity: 0;
|
48
|
-
transition: .3s opacity;
|
49
|
-
}
|
50
|
-
|
51
|
-
[tooltip-position='left']::before {
|
52
|
-
left: 0%;
|
53
|
-
top: 50%;
|
54
|
-
margin-left: -12px;
|
55
|
-
transform: translatey(-50%) rotate(-90deg)
|
56
|
-
}
|
57
|
-
|
58
|
-
[tooltip-position='top']::before {
|
59
|
-
left: 50%;
|
60
|
-
}
|
61
|
-
|
62
|
-
[tooltip-position='buttom']::before {
|
63
|
-
top: 100%;
|
64
|
-
margin-top: 8px;
|
65
|
-
transform: translateX(-50%) translatey(-100%) rotate(-180deg)
|
66
|
-
}
|
67
|
-
|
68
|
-
[tooltip-position='right']::before {
|
69
|
-
left: 100%;
|
70
|
-
top: 50%;
|
71
|
-
margin-left: 1px;
|
72
|
-
transform: translatey(-50%) rotate(90deg)
|
73
|
-
}
|
74
|
-
|
75
|
-
.tooltip::after {
|
76
|
-
content: attr(data-text);
|
77
|
-
position: absolute;
|
78
|
-
min-width: 10rem;
|
79
|
-
left: 50%;
|
80
|
-
top: -6px;
|
81
|
-
transform: translateX(-50%) translateY(-100%);
|
82
|
-
background: rgba(0, 0, 0, 0.7);
|
83
|
-
text-align: center;
|
84
|
-
color: #fff;
|
85
|
-
font-size: 12px;
|
86
|
-
border-radius: 5px;
|
87
|
-
pointer-events: none;
|
88
|
-
padding: 4px 4px;
|
89
|
-
z-index: 99;
|
90
|
-
opacity: 0;
|
91
|
-
transition: .3s opacity;
|
92
|
-
}
|
93
|
-
|
94
|
-
[tooltip-position='left']::after {
|
95
|
-
left: 0;
|
96
|
-
top: 50%;
|
97
|
-
margin-left: -8px;
|
98
|
-
transform: translateX(-100%) translateY(-50%);
|
99
|
-
}
|
100
|
-
|
101
|
-
[tooltip-position='top']::after {
|
102
|
-
left: 50%;
|
103
|
-
}
|
104
|
-
|
105
|
-
[tooltip-position='buttom']::after {
|
106
|
-
top: 100%;
|
107
|
-
margin-top: 8px;
|
108
|
-
transform: translateX(-50%) translateY(0%);
|
109
|
-
}
|
110
|
-
|
111
|
-
[tooltip-position='right']::after {
|
112
|
-
left: 100%;
|
113
|
-
top: 50%;
|
114
|
-
margin-left: 8px;
|
115
|
-
transform: translateX(0%) translateY(-50%);
|
116
|
-
}
|
117
|
-
|
118
|
-
.tooltip:hover::after, .tooltip:hover::before {
|
119
|
-
opacity: 1
|
120
|
-
}
|
121
|
-
|
122
|
-
|
123
|
-
pre {
|
124
|
-
white-space: pre-wrap;
|
125
|
-
word-wrap: break-word;
|
126
|
-
}
|
127
|
-
|
128
|
-
//#------------
|
129
|
-
h1 {
|
130
|
-
@apply text-2xl;
|
131
|
-
}
|
132
|
-
|
133
|
-
h2 {
|
134
|
-
@apply text-xl;
|
135
|
-
}
|
136
|
-
|
137
|
-
h3 {
|
138
|
-
@apply text-lg;
|
139
|
-
}
|
140
|
-
|
141
|
-
.class-button {
|
142
|
-
@apply rounded-md px-3 py-2 text-center text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2;
|
143
|
-
@apply focus-visible:outline-gray-500 bg-gray-500 hover:bg-white hover:text-gray-500 hover:border-gray-50 hover:outline;
|
144
|
-
}
|
145
|
-
|
146
|
-
.class-button-outline {
|
147
|
-
@apply rounded-md px-3 py-2 text-center text-sm font-semibold text-gray-500 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2;
|
148
|
-
@apply outline outline-1 border-gray-500 focus-visible:outline-gray-500 bg-white hover:bg-gray-500 hover:text-white hover:border-gray-500 hover:outline;
|
149
|
-
}
|
150
|
-
|
151
|
-
.class-label {
|
152
|
-
@apply text-sm font-semibold leading-6 text-gray-900;
|
153
|
-
}
|
154
|
-
|
155
|
-
.class-text-field {
|
156
|
-
@apply block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6;
|
157
|
-
}
|
158
|
-
|
159
|
-
.class-card-container {
|
160
|
-
@apply overflow-hidden bg-white shadow sm:rounded-lg p-5
|
161
|
-
}
|
162
|
-
|
163
|
-
.class-input {
|
164
|
-
@apply sm:grid sm:grid-cols-3 sm:items-start sm:gap-4 sm:py-6 pl-2
|
165
|
-
}
|
166
|
-
|
167
|
-
.class-tr {
|
168
|
-
@apply top-0 z-10 border-b border-gray-300 bg-white bg-opacity-75 px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell
|
169
|
-
}
|
170
|
-
|
171
|
-
.class-td {
|
172
|
-
@apply whitespace-nowrap px-3 py-5 text-sm text-gray-500
|
173
|
-
}
|
174
|
-
|
175
|
-
.class-menu-link {
|
176
|
-
@apply hover:font-semibold hover:text-gray-500 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700
|
177
|
-
}
|
178
|
-
|
179
|
-
.class-text-link {
|
180
|
-
@apply hover:font-semibold hover:text-gray-500 block rounded-md text-sm leading-6 text-gray-700
|
181
|
-
}
|
182
|
-
|
183
|
-
.class-menu-active-link {
|
184
|
-
@apply font-semibold block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700
|
185
|
-
}
|
186
|
-
}
|
187
|
-
|
188
|
-
@layer utilities {
|
189
|
-
/* Chrome, Safari and Opera */
|
190
|
-
.no-scrollbar::-webkit-scrollbar {
|
191
|
-
display: none;
|
192
|
-
}
|
193
|
-
|
194
|
-
.no-scrollbar {
|
195
|
-
-ms-overflow-style: none; /* IE and Edge */
|
196
|
-
scrollbar-width: none; /* Firefox */
|
197
|
-
}
|
198
|
-
}
|
@@ -1,39 +0,0 @@
|
|
1
|
-
/** @type {import('tailwindcss').Config} */
|
2
|
-
const defaultTheme = require('tailwindcss/defaultTheme')
|
3
|
-
|
4
|
-
module.exports = {
|
5
|
-
content: [
|
6
|
-
'./app/helpers/**/*.rb',
|
7
|
-
'./app/views/**/*.{.erb,erb}',
|
8
|
-
'./app/frontend/**/*.{js, css, scss, ejs}',
|
9
|
-
],
|
10
|
-
theme: {
|
11
|
-
screens: {
|
12
|
-
'sm': '640px',
|
13
|
-
// => @media (min-width: 640px) { ... }
|
14
|
-
|
15
|
-
'md': '768px',
|
16
|
-
// => @media (min-width: 768px) { ... }
|
17
|
-
|
18
|
-
'lg': '1024px',
|
19
|
-
// => @media (min-width: 1024px) { ... }
|
20
|
-
|
21
|
-
'xl': '1280px',
|
22
|
-
// => @media (min-width: 1280px) { ... }
|
23
|
-
|
24
|
-
'2xl': '1536px',
|
25
|
-
// => @media (min-width: 1536px) { ... }
|
26
|
-
},
|
27
|
-
extend: {
|
28
|
-
fontFamily: {
|
29
|
-
sans: ['Open Sans', ...defaultTheme.fontFamily.sans],
|
30
|
-
},
|
31
|
-
},
|
32
|
-
},
|
33
|
-
plugins: [
|
34
|
-
require('@tailwindcss/aspect-ratio'),
|
35
|
-
require('@tailwindcss/forms'),
|
36
|
-
require('@tailwindcss/typography'),
|
37
|
-
],
|
38
|
-
}
|
39
|
-
|