kern 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/Gemfile.lock +13 -4
- data/README.md +1 -0
- data/Rakefile +1 -1
- data/app/assets/builds/tailwind.kern.css +31 -39
- data/app/controllers/concerns/authentication.rb +4 -0
- data/app/controllers/concerns/authentication.rb.tt +4 -0
- data/app/controllers/concerns/layouts.rb +22 -0
- data/app/controllers/kern/application_controller.rb +7 -0
- data/app/controllers/kern/passwords_controller.rb +1 -1
- data/app/controllers/kern/sessions_controller.rb +1 -1
- data/app/controllers/kern/signups_controller.rb +6 -2
- data/app/controllers/kern/signups_controller.rb.tt +1 -1
- data/app/models/billing_profile/subscription.rb +1 -1
- data/app/models/workspace/members.rb +6 -0
- data/app/views/components/_heading.html.erb +1 -1
- data/app/views/components/_section.html.erb +12 -0
- data/app/views/components/flash/_message.html.erb +2 -2
- data/app/views/kern/pages/welcome.html.erb +2 -15
- data/app/views/kern/passwords/new.html.erb +2 -0
- data/app/views/kern/sessions/new.html.erb +2 -4
- data/app/views/kern/signups/new.html.erb +1 -3
- data/app/views/layouts/kern/application.html.erb +1 -1
- data/app/views/layouts/kern/application.html.erb.tt +5 -3
- data/app/views/layouts/kern/auth.html.erb +3 -0
- data/app/views/layouts/kern/auth.html.erb.tt +46 -0
- data/app/webhooks/stripe/base.rb +1 -1
- data/lib/generators/kern/layouts/layouts_generator.rb +1 -1
- data/lib/kern/engine.rb +4 -0
- data/lib/kern/form_builder/input.rb +9 -11
- data/lib/kern/form_builder/styles.rb +35 -0
- data/lib/kern/form_builder.rb +17 -4
- data/lib/kern/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e5939e78f0c9a8ed8f74d2108f04e1a7d1a6b57464d85770a513e3bc8186582
|
|
4
|
+
data.tar.gz: 2b6ffa3d55e045514e9d19fff2a378c354bc1efd8af39caca8cc79e9bac813d2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 53f4f292112352c6c980b7d9f7a6ce0bb7f69d02247bb0f2d504778d72aed6141cd18c3a51d5b1082dbe2c387ec0580e3a5205a3e0cb33763498fab9ba06de87
|
|
7
|
+
data.tar.gz: bb31cce5665edc407bfafcd4fefddfc9dff1a888f22152f0c03aed30450457f2e209362a7729a0f77bcee94a491b28d8c576c2ca85d51b1479dd54f26b2e5094
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
kern (0.
|
|
4
|
+
kern (0.8.0)
|
|
5
5
|
rails (>= 8.0.0)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
@@ -120,6 +120,7 @@ GEM
|
|
|
120
120
|
net-smtp
|
|
121
121
|
marcel (1.1.0)
|
|
122
122
|
mini_mime (1.1.5)
|
|
123
|
+
mini_portile2 (2.8.9)
|
|
123
124
|
minitest (5.26.2)
|
|
124
125
|
net-imap (0.5.12)
|
|
125
126
|
date
|
|
@@ -131,6 +132,9 @@ GEM
|
|
|
131
132
|
net-smtp (0.5.1)
|
|
132
133
|
net-protocol
|
|
133
134
|
nio4r (2.7.5)
|
|
135
|
+
nokogiri (1.18.10)
|
|
136
|
+
mini_portile2 (~> 2.8.2)
|
|
137
|
+
racc (~> 1.4)
|
|
134
138
|
nokogiri (1.18.10-aarch64-linux-gnu)
|
|
135
139
|
racc (~> 1.4)
|
|
136
140
|
nokogiri (1.18.10-aarch64-linux-musl)
|
|
@@ -235,6 +239,8 @@ GEM
|
|
|
235
239
|
rubocop-ast (>= 1.47.1, < 2.0)
|
|
236
240
|
ruby-progressbar (1.13.0)
|
|
237
241
|
securerandom (0.4.1)
|
|
242
|
+
sqlite3 (2.8.1)
|
|
243
|
+
mini_portile2 (~> 2.8.0)
|
|
238
244
|
sqlite3 (2.8.1-aarch64-linux-gnu)
|
|
239
245
|
sqlite3 (2.8.1-aarch64-linux-musl)
|
|
240
246
|
sqlite3 (2.8.1-arm-linux-gnu)
|
|
@@ -279,7 +285,7 @@ GEM
|
|
|
279
285
|
concurrent-ruby (~> 1.0)
|
|
280
286
|
unicode-display_width (3.2.0)
|
|
281
287
|
unicode-emoji (~> 4.1)
|
|
282
|
-
unicode-emoji (4.
|
|
288
|
+
unicode-emoji (4.2.0)
|
|
283
289
|
uri (1.1.1)
|
|
284
290
|
useragent (0.16.11)
|
|
285
291
|
websocket-driver (0.8.0)
|
|
@@ -345,7 +351,7 @@ CHECKSUMS
|
|
|
345
351
|
io-console (0.8.1) sha256=1e15440a6b2f67b6ea496df7c474ed62c860ad11237f29b3bd187f054b925fcb
|
|
346
352
|
irb (1.15.3) sha256=4349edff1efa7ff7bfd34cb9df74a133a588ba88c2718098b3b4468b81184aaa
|
|
347
353
|
json (2.17.1) sha256=e0e4824541336a44915436f53e7ea74c687314fb8f88080fa1456f6a34ead92e
|
|
348
|
-
kern (0.
|
|
354
|
+
kern (0.8.0)
|
|
349
355
|
language_server-protocol (3.17.0.5) sha256=fd1e39a51a28bf3eec959379985a72e296e9f9acfce46f6a79d31ca8760803cc
|
|
350
356
|
lint_roller (1.1.0) sha256=2c0c845b632a7d172cb849cc90c1bce937a28c5c8ccccb50dfd46a485003cc87
|
|
351
357
|
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
|
@@ -353,12 +359,14 @@ CHECKSUMS
|
|
|
353
359
|
mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941
|
|
354
360
|
marcel (1.1.0) sha256=fdcfcfa33cc52e93c4308d40e4090a5d4ea279e160a7f6af988260fa970e0bee
|
|
355
361
|
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
|
|
362
|
+
mini_portile2 (2.8.9) sha256=0cd7c7f824e010c072e33f68bc02d85a00aeb6fce05bb4819c03dfd3c140c289
|
|
356
363
|
minitest (5.26.2) sha256=f021118a6185b9ba9f5af71f2ba103ad770c75afde9f2ab8da512677c550cde3
|
|
357
364
|
net-imap (0.5.12) sha256=cb8cd05bd353fcc19b6cbc530a9cb06b577a969ea10b7ddb0f37787f74be4444
|
|
358
365
|
net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3
|
|
359
366
|
net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8
|
|
360
367
|
net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736
|
|
361
368
|
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
|
|
369
|
+
nokogiri (1.18.10) sha256=d5cc0731008aa3b3a87b361203ea3d19b2069628cb55e46ac7d84a0445e69cc1
|
|
362
370
|
nokogiri (1.18.10-aarch64-linux-gnu) sha256=7fb87235d729c74a2be635376d82b1d459230cc17c50300f8e4fcaabc6195344
|
|
363
371
|
nokogiri (1.18.10-aarch64-linux-musl) sha256=7e74e58314297cc8a8f1b533f7212d1999dbe2639a9ee6d97b483ea2acc18944
|
|
364
372
|
nokogiri (1.18.10-arm-linux-gnu) sha256=51f4f25ab5d5ba1012d6b16aad96b840a10b067b93f35af6a55a2c104a7ee322
|
|
@@ -395,6 +403,7 @@ CHECKSUMS
|
|
|
395
403
|
rubocop-performance (1.26.1) sha256=cd19b936ff196df85829d264b522fd4f98b6c89ad271fa52744a8c11b8f71834
|
|
396
404
|
ruby-progressbar (1.13.0) sha256=80fc9c47a9b640d6834e0dc7b3c94c9df37f08cb072b7761e4a71e22cff29b33
|
|
397
405
|
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
|
406
|
+
sqlite3 (2.8.1) sha256=acd0ac7912a4d92b2484b5befb6faa8d496497eb1e38bdbe8d7818fb8d05d726
|
|
398
407
|
sqlite3 (2.8.1-aarch64-linux-gnu) sha256=9bce166d3e3595a42fc92c28d986ea11d499b55be8bd1cd491be04af30029543
|
|
399
408
|
sqlite3 (2.8.1-aarch64-linux-musl) sha256=34912f6acf3e9c43c7998c6f99ba3146708e654cf9716b2983e260315cdeed72
|
|
400
409
|
sqlite3 (2.8.1-arm-linux-gnu) sha256=9118d6abb5ca7ea4f1b50a6c42c763e612670f5eb673bbdf12e8d3bd63339bde
|
|
@@ -423,7 +432,7 @@ CHECKSUMS
|
|
|
423
432
|
turbo-rails (2.0.20) sha256=cbcbb4dd3ce59f6471c9f911b1655b2c721998cc8303959d982da347f374ea95
|
|
424
433
|
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
|
425
434
|
unicode-display_width (3.2.0) sha256=0cdd96b5681a5949cdbc2c55e7b420facae74c4aaf9a9815eee1087cb1853c42
|
|
426
|
-
unicode-emoji (4.
|
|
435
|
+
unicode-emoji (4.2.0) sha256=519e69150f75652e40bf736106cfbc8f0f73aa3fb6a65afe62fefa7f80b0f80f
|
|
427
436
|
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
|
|
428
437
|
useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844
|
|
429
438
|
websocket-driver (0.8.0) sha256=ed0dba4b943c22f17f9a734817e808bc84cdce6a7e22045f5315aa57676d4962
|
data/README.md
CHANGED
|
@@ -138,6 +138,7 @@ Pulled from [Rails Designer's Components](https://railsdesigner.com/components/)
|
|
|
138
138
|
Some basic components are included like:
|
|
139
139
|
|
|
140
140
|
- container; keep all your app's content in check
|
|
141
|
+
- section; easily divide up your screens in sections
|
|
141
142
|
- heading; have consistent headings for each screen
|
|
142
143
|
- enhanced dialog element (works with Turbo Frames and, includes `centered` or a `drawer` variants)
|
|
143
144
|
- flash messages (notifiy your users from the bottom-right)
|
data/Rakefile
CHANGED
|
@@ -16,7 +16,7 @@ namespace :assets do
|
|
|
16
16
|
desc "Build Tailwind CSS for distribution"
|
|
17
17
|
task :precompile do
|
|
18
18
|
Dir.chdir("test/dummy") do
|
|
19
|
-
sh "bundle exec tailwindcss -i app/assets/tailwind/application.css -o app/assets/builds/tailwind.kern.css"
|
|
19
|
+
sh "bundle exec tailwindcss -i app/assets/tailwind/application.kern.css -o app/assets/builds/tailwind.kern.css"
|
|
20
20
|
|
|
21
21
|
FileUtils.mkdir_p "../../app/assets/builds"
|
|
22
22
|
FileUtils.cp(
|
|
@@ -25,8 +25,6 @@
|
|
|
25
25
|
--color-blue-800: oklch(42.4% 0.199 265.638);
|
|
26
26
|
--color-blue-900: oklch(37.9% 0.146 265.522);
|
|
27
27
|
--color-blue-950: oklch(28.2% 0.091 267.935);
|
|
28
|
-
--color-pink-200: oklch(89.9% 0.061 343.231);
|
|
29
|
-
--color-pink-800: oklch(45.9% 0.187 3.815);
|
|
30
28
|
--color-slate-50: oklch(98.4% 0.003 247.858);
|
|
31
29
|
--color-slate-100: oklch(96.8% 0.007 247.896);
|
|
32
30
|
--color-slate-200: oklch(92.9% 0.013 255.508);
|
|
@@ -78,6 +76,7 @@
|
|
|
78
76
|
--radius-lg: 0.5rem;
|
|
79
77
|
--radius-xl: 0.75rem;
|
|
80
78
|
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
|
79
|
+
--blur-sm: 8px;
|
|
81
80
|
--blur-md: 12px;
|
|
82
81
|
--default-transition-duration: 150ms;
|
|
83
82
|
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -739,6 +738,9 @@
|
|
|
739
738
|
.text-white {
|
|
740
739
|
color: var(--color-white);
|
|
741
740
|
}
|
|
741
|
+
.no-underline {
|
|
742
|
+
text-decoration-line: none;
|
|
743
|
+
}
|
|
742
744
|
.antialiased {
|
|
743
745
|
-webkit-font-smoothing: antialiased;
|
|
744
746
|
-moz-osx-font-smoothing: grayscale;
|
|
@@ -793,6 +795,11 @@
|
|
|
793
795
|
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
794
796
|
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
795
797
|
}
|
|
798
|
+
.backdrop-blur-sm {
|
|
799
|
+
--tw-backdrop-blur: blur(var(--blur-sm));
|
|
800
|
+
-webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
801
|
+
backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);
|
|
802
|
+
}
|
|
796
803
|
.transition {
|
|
797
804
|
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
|
|
798
805
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
@@ -896,20 +903,6 @@
|
|
|
896
903
|
}
|
|
897
904
|
}
|
|
898
905
|
}
|
|
899
|
-
.selection\:bg-pink-200\/40 {
|
|
900
|
-
& *::selection {
|
|
901
|
-
background-color: color-mix(in srgb, oklch(89.9% 0.061 343.231) 40%, transparent);
|
|
902
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
903
|
-
background-color: color-mix(in oklab, var(--color-pink-200) 40%, transparent);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
&::selection {
|
|
907
|
-
background-color: color-mix(in srgb, oklch(89.9% 0.061 343.231) 40%, transparent);
|
|
908
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
909
|
-
background-color: color-mix(in oklab, var(--color-pink-200) 40%, transparent);
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
906
|
.selection\:text-blue-800\/70 {
|
|
914
907
|
& *::selection {
|
|
915
908
|
color: color-mix(in srgb, oklch(42.4% 0.199 265.638) 70%, transparent);
|
|
@@ -924,20 +917,6 @@
|
|
|
924
917
|
}
|
|
925
918
|
}
|
|
926
919
|
}
|
|
927
|
-
.selection\:text-pink-800\/70 {
|
|
928
|
-
& *::selection {
|
|
929
|
-
color: color-mix(in srgb, oklch(45.9% 0.187 3.815) 70%, transparent);
|
|
930
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
931
|
-
color: color-mix(in oklab, var(--color-pink-800) 70%, transparent);
|
|
932
|
-
}
|
|
933
|
-
}
|
|
934
|
-
&::selection {
|
|
935
|
-
color: color-mix(in srgb, oklch(45.9% 0.187 3.815) 70%, transparent);
|
|
936
|
-
@supports (color: color-mix(in lab, red, red)) {
|
|
937
|
-
color: color-mix(in oklab, var(--color-pink-800) 70%, transparent);
|
|
938
|
-
}
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
920
|
.file\:mr-2 {
|
|
942
921
|
&::file-selector-button {
|
|
943
922
|
margin-right: calc(var(--spacing) * 2);
|
|
@@ -991,6 +970,11 @@
|
|
|
991
970
|
display: block;
|
|
992
971
|
}
|
|
993
972
|
}
|
|
973
|
+
.empty\:hidden {
|
|
974
|
+
&:empty {
|
|
975
|
+
display: none;
|
|
976
|
+
}
|
|
977
|
+
}
|
|
994
978
|
.hover\:scale-105 {
|
|
995
979
|
&:hover {
|
|
996
980
|
@media (hover: hover) {
|
|
@@ -1032,13 +1016,6 @@
|
|
|
1032
1016
|
}
|
|
1033
1017
|
}
|
|
1034
1018
|
}
|
|
1035
|
-
.hover\:text-gray-500 {
|
|
1036
|
-
&:hover {
|
|
1037
|
-
@media (hover: hover) {
|
|
1038
|
-
color: var(--color-gray-500);
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
1019
|
.hover\:underline {
|
|
1043
1020
|
&:hover {
|
|
1044
1021
|
@media (hover: hover) {
|
|
@@ -1142,6 +1119,11 @@
|
|
|
1142
1119
|
margin-inline: calc(var(--spacing) * 4);
|
|
1143
1120
|
}
|
|
1144
1121
|
}
|
|
1122
|
+
.md\:flex-row {
|
|
1123
|
+
@media (width >= 48rem) {
|
|
1124
|
+
flex-direction: row;
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1145
1127
|
.md\:gap-8 {
|
|
1146
1128
|
@media (width >= 48rem) {
|
|
1147
1129
|
gap: calc(var(--spacing) * 8);
|
|
@@ -1219,6 +1201,16 @@
|
|
|
1219
1201
|
width: calc(var(--spacing) * 60);
|
|
1220
1202
|
}
|
|
1221
1203
|
}
|
|
1204
|
+
.lg\:max-w-1\/4 {
|
|
1205
|
+
@media (width >= 64rem) {
|
|
1206
|
+
max-width: calc(1/4 * 100%);
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
.lg\:max-w-3\/4 {
|
|
1210
|
+
@media (width >= 64rem) {
|
|
1211
|
+
max-width: calc(3/4 * 100%);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1222
1214
|
.lg\:px-6 {
|
|
1223
1215
|
@media (width >= 64rem) {
|
|
1224
1216
|
padding-inline: calc(var(--spacing) * 6);
|
|
@@ -1268,9 +1260,9 @@
|
|
|
1268
1260
|
translate: var(--tw-translate-x) var(--tw-translate-y);
|
|
1269
1261
|
}
|
|
1270
1262
|
}
|
|
1271
|
-
.\[\&\>input\]\:mt-\[0\.
|
|
1263
|
+
.\[\&\>input\]\:mt-\[0\.17em\] {
|
|
1272
1264
|
&>input {
|
|
1273
|
-
margin-top: 0.
|
|
1265
|
+
margin-top: 0.17em;
|
|
1274
1266
|
}
|
|
1275
1267
|
}
|
|
1276
1268
|
.\[\&\[data-slot\=\'field\'\]\+\[data-slot\=\'field\'\]\]\:mt-4 {
|
|
@@ -40,6 +40,10 @@ module Authentication
|
|
|
40
40
|
session.delete(:return_to_after_authenticating) || root_url
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def redirect_to_root
|
|
44
|
+
redirect_to root_url || kern.root_url
|
|
45
|
+
end
|
|
46
|
+
|
|
43
47
|
def start_new_session_for(user)
|
|
44
48
|
user.sessions.create!(user_agent: request.user_agent.presence || "[No User Agent]", ip_address: request.remote_ip).tap do |session|
|
|
45
49
|
Current.session = session
|
|
@@ -40,6 +40,10 @@ module Authentication
|
|
|
40
40
|
session.delete(:return_to_after_authenticating) || root_url
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
+
def redirect_to_root
|
|
44
|
+
redirect_to root_url || kern.root_url
|
|
45
|
+
end
|
|
46
|
+
|
|
43
47
|
def start_new_session_for(user)
|
|
44
48
|
user.sessions.create!(user_agent: request.user_agent.presence || "[No User Agent]", ip_address: request.remote_ip).tap do |session|
|
|
45
49
|
Current.session = session
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
module Layouts
|
|
2
|
+
extend ActiveSupport::Concern
|
|
3
|
+
|
|
4
|
+
class_methods do
|
|
5
|
+
def define_layout(layout_name, namespace: "kern")
|
|
6
|
+
layout -> { resolve(layout_name, namespace) }
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def resolve(layout_name, namespace)
|
|
13
|
+
layout_name = layout_name.to_s
|
|
14
|
+
|
|
15
|
+
return layout_name if lookup_context.exists?(layout_name, ["layouts"])
|
|
16
|
+
|
|
17
|
+
namespaced = "#{namespace}/#{layout_name}"
|
|
18
|
+
return namespaced if lookup_context.exists?(namespaced, ["layouts"])
|
|
19
|
+
|
|
20
|
+
false
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
module Kern
|
|
2
2
|
class ApplicationController < ActionController::Base
|
|
3
3
|
include Authentication
|
|
4
|
+
include Layouts
|
|
5
|
+
|
|
6
|
+
define_layout :application
|
|
4
7
|
|
|
5
8
|
default_form_builder Kern::FormBuilder
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def _prefixes = [controller_name] + super
|
|
6
13
|
end
|
|
7
14
|
end
|
|
@@ -4,7 +4,7 @@ module Kern
|
|
|
4
4
|
|
|
5
5
|
before_action :redirect_to_root, if: -> { authenticated? }, only: %w[new create]
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
define_layout :auth
|
|
8
8
|
|
|
9
9
|
def new
|
|
10
10
|
@signup = Signup.new
|
|
@@ -16,7 +16,11 @@ module Kern
|
|
|
16
16
|
if @signup.save
|
|
17
17
|
start_new_session_for @signup.user
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
begin
|
|
20
|
+
redirect_to main_app.root_url
|
|
21
|
+
rescue
|
|
22
|
+
redirect_to root_url
|
|
23
|
+
end
|
|
20
24
|
else
|
|
21
25
|
render :new, status: :unprocessable_entity
|
|
22
26
|
end
|
|
@@ -5,8 +5,14 @@ class Workspace
|
|
|
5
5
|
included do
|
|
6
6
|
has_many :members, dependent: :destroy
|
|
7
7
|
has_many :users, through: :members
|
|
8
|
+
|
|
9
|
+
after_destroy_commit :purge_orphaned_users!
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def add_member(to:, role: nil) = Member::Setup.new(workspace: self, user: to, role: role).save
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def purge_orphaned_users! = User.left_joins(:members).where(members: {id: nil}).destroy_all
|
|
11
17
|
end
|
|
12
18
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%# locals: (level: :h1, breadcrumbs: [], actions: [], css: class_names("flex items-center gap-x-1 h-8 font-sans font-bold text-gray-950 *:inline-block", {"text-base font-bold tracking-tight md:text-lg": level == :h1, "text-sm font-
|
|
1
|
+
<%# locals: (level: :h1, breadcrumbs: [], actions: [], css: class_names("flex items-center gap-x-1 h-8 font-sans font-bold text-gray-950 *:inline-block", {"text-base font-bold tracking-tight md:text-lg": level == :h1, "text-sm font-bold md:text-base": level == :h2, "text-xs font-medium md:text-sm": level == :h3})) %>
|
|
2
2
|
<%= tag.header id: "heading", class: class_names("flex items-center justify-between", {"px-4 py-5 border-b border-gray-200/50": level == :h1}) do %>
|
|
3
3
|
<%= tag.send(level, class: css) do %>
|
|
4
4
|
<%= safe_join(breadcrumbs.map.with_index {|it, index| tag.span(link_to(it[:label], it[:href], class: "hover:underline", id: "header_part_link_#{index}") + tag.span("/", class: "ml-1 font-normal text-gray-400"), id: "header_part_#{index}")}) if level == :h1 %>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<%# locals: (direction: :vertical, heading: nil, description: nil, **options) %>
|
|
2
|
+
<%= tag.section class: class_names("flex pt-4 border-t border-gray-100", {"flex-col gap-2": direction == :vertical, "flex-col gap-4 md:flex-row": direction == :horizontal}) do %>
|
|
3
|
+
<div class="w-full lg:max-w-1/4">
|
|
4
|
+
<%= component("heading", level: :h2) { heading } %>
|
|
5
|
+
|
|
6
|
+
<%= tag.p description, class: "text-sm text-gray-700 md:text-base" if description.present? %>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="<%= class_names("w-full", {"lg:max-w-3/4": direction == :horizontal}) %>">
|
|
10
|
+
<%= yield %>
|
|
11
|
+
</div>
|
|
12
|
+
<% end %>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<%# locals: (type:, message:, icon: "check-circle", icon_css: class_names("size-3.5 shrink-0", {"text-emerald-300": type == "notice", "text-red-400": type == "alert"}), css: class_names("flex items-center gap-x-1.5 bg-gradient-to-b from-gray-900/80 to-gray-900
|
|
2
|
-
<li class="translate-x-0 opacity-100 transition-all duration-300 ease-in-out starting:translate-x-4 starting:opacity-0">
|
|
1
|
+
<%# locals: (type:, message:, icon: "check-circle", icon_css: class_names("size-3.5 shrink-0", {"text-emerald-300": type == "notice", "text-red-400": type == "alert"}), css: class_names("flex items-center gap-x-1.5 px-3 py-1.5 text-xs font-normal text-white bg-gradient-to-b from-gray-900/80 to-gray-900 backdrop-blur-sm ring ring-gray-700/90 rounded-md shadow-lg transition-all")) %>
|
|
2
|
+
<li data-action="element#remove:mounted" data-remove-delay="7000" class="translate-x-0 opacity-100 transition-all duration-300 ease-in-out starting:translate-x-4 starting:opacity-0">
|
|
3
3
|
<%= tag.p safe_join([(icon(icon, class: icon_css) rescue nil), message]), aria: {live: :polite}, class: css %>
|
|
4
4
|
</li>
|
|
@@ -22,25 +22,12 @@
|
|
|
22
22
|
</li>
|
|
23
23
|
|
|
24
24
|
<li>
|
|
25
|
-
override any
|
|
25
|
+
override any feature by running <code class="select-all">bin/rails generate kern:feature FEATURE FEATURE</code>
|
|
26
26
|
</li>
|
|
27
27
|
|
|
28
28
|
<li>
|
|
29
|
-
override
|
|
30
|
-
</li>
|
|
31
|
-
|
|
32
|
-
<li>
|
|
33
|
-
check out <%= link_to "Rails Designer's UI Components", "https://railsdesigner.com/components/" %>
|
|
34
|
-
</li>
|
|
35
|
-
|
|
36
|
-
<li>
|
|
37
|
-
build your SaaS
|
|
38
|
-
</li>
|
|
39
|
-
|
|
40
|
-
<li>
|
|
41
|
-
profit 🤑
|
|
29
|
+
override layouts by running <code class="select-all">bin/rails generate kern:layouts</code>
|
|
42
30
|
</li>
|
|
43
31
|
</ul>
|
|
44
|
-
|
|
45
32
|
</section>
|
|
46
33
|
</main>
|
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
<%= form_with url: session_path, class: "px-2 md:px-4" do |form| %>
|
|
5
5
|
<%= form.input :email_address, type: :email, required: true, autofocus: true, autocomplete: "username", value: params[:email_address] %>
|
|
6
6
|
|
|
7
|
-
<%= form.input :password, required: true, autocomplete: "current-password", maxlength: 72, label_suffix: link_to("Forgot password?", new_password_path, class: "
|
|
7
|
+
<%= form.input :password, required: true, autocomplete: "current-password", maxlength: 72, label_suffix: link_to("Forgot password?", new_password_path, class: "no-underline") %>
|
|
8
8
|
|
|
9
9
|
<div class="buttons">
|
|
10
10
|
<%= form.submit "Log in", data: {turbo_submits_with: "Logging in…"}, class: "btn-primary" %>
|
|
11
11
|
</div>
|
|
12
12
|
<% end %>
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
<%= link_to "No account yet?", new_signup_path, class: "block text-center text-sm text-gray-500 hover:underline" %>
|
|
16
|
-
</p>
|
|
14
|
+
<%= content_for(:alternative_action) { link_to "No account yet?", new_signup_path, class: "block text-center text-sm text-gray-500 hover:underline" } %>
|
|
@@ -13,6 +13,4 @@
|
|
|
13
13
|
</div>
|
|
14
14
|
<% end %>
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
<%= link_to "Already have an account?", new_session_path, class: "block text-center text-sm font-medium text-gray-500 hover:underline" %>
|
|
18
|
-
</p>
|
|
16
|
+
<%= content_for(:alternative_action) { link_to "Already have an account??", new_session_path, class: "block text-center text-sm font-medium text-gray-500 hover:underline" } %>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<%= csp_meta_tag %>
|
|
10
10
|
|
|
11
11
|
<%= stylesheet_link_tag "tailwind.kern", "data-turbo-track": "reload" %>
|
|
12
|
-
<script defer src="https://cdn.jsdelivr.net/npm/attractivejs@0.
|
|
12
|
+
<script defer src="https://cdn.jsdelivr.net/npm/attractivejs@0.11.0"></script>
|
|
13
13
|
</head>
|
|
14
14
|
|
|
15
15
|
<body class="<%= class_names("antialiased bg-white selection:bg-blue-200/40 selection:text-blue-800/70", yield(:body_class)) %>">
|
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
<%%= csp_meta_tag %>
|
|
10
10
|
|
|
11
11
|
<%%= stylesheet_link_tag "tailwind.kern", "data-turbo-track": "reload" %>
|
|
12
|
-
|
|
12
|
+
<%%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
|
13
|
+
<script defer src="https://cdn.jsdelivr.net/npm/attractivejs@0.11.0"></script>
|
|
13
14
|
</head>
|
|
14
15
|
|
|
15
|
-
<body class="<%%= class_names("antialiased bg-white selection:bg-
|
|
16
|
+
<body class="<%%= class_names("antialiased bg-white selection:bg-blue-200/40 selection:text-blue-800/70", yield(:body_class)) %>">
|
|
16
17
|
<div class="flex">
|
|
17
|
-
<%%= render partial: "layouts/
|
|
18
|
+
<%%= render partial: "layouts/application/navigation",
|
|
18
19
|
locals: {
|
|
19
20
|
links: [
|
|
20
21
|
{label: "Home", href: root_path, icon: "house-line"},
|
|
@@ -28,5 +29,6 @@
|
|
|
28
29
|
</div>
|
|
29
30
|
|
|
30
31
|
<%%= component "flash" %>
|
|
32
|
+
<%%= component "dialog" %>
|
|
31
33
|
</body>
|
|
32
34
|
</html>
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
<%= csp_meta_tag %>
|
|
11
11
|
|
|
12
12
|
<%= stylesheet_link_tag "tailwind.kern", "data-turbo-track": "reload" %>
|
|
13
|
+
<script defer src="https://cdn.jsdelivr.net/npm/attractivejs@0.11.0"></script>
|
|
13
14
|
</head>
|
|
14
15
|
|
|
15
16
|
<body class="relative overflow-clip antialiased bg-white selection:bg-blue-200/40 selection:text-blue-800/70">
|
|
@@ -32,6 +33,8 @@
|
|
|
32
33
|
<%= tag.h1 yield(:page_title), class: "mx-2 mt-8 font-sans text-center text-base font-bold text-gray-800 md:mx-4" %>
|
|
33
34
|
|
|
34
35
|
<%= yield %>
|
|
36
|
+
|
|
37
|
+
<%= tag.p yield(:alternative_action), class: "px-2 pt-4 pb-2 border-t border-gray-100 empty:hidden md:pb-4" %>
|
|
35
38
|
</section>
|
|
36
39
|
</div>
|
|
37
40
|
</div>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>
|
|
5
|
+
<%%= content_for?(:title)? "#{yield(:title)} - #{Rails.application.name.humanize}" : Rails.application.name.humanize %>
|
|
6
|
+
</title>
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
8
|
+
<meta name="robots" content="noindex, nofollow">
|
|
9
|
+
<%%= csrf_meta_tags %>
|
|
10
|
+
<%%= csp_meta_tag %>
|
|
11
|
+
|
|
12
|
+
<%%= stylesheet_link_tag "tailwind.kern", "data-turbo-track": "reload" %>
|
|
13
|
+
<%%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
|
14
|
+
<script defer src="https://cdn.jsdelivr.net/npm/attractivejs@0.11.0"></script>
|
|
15
|
+
</head>
|
|
16
|
+
|
|
17
|
+
<body class="relative overflow-clip antialiased bg-white selection:bg-blue-200/40 selection:text-blue-800/70">
|
|
18
|
+
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="absolute -top-[400px] -left-[350px] size-[800px] text-brand-500">
|
|
19
|
+
<path fill="currentColor" d="M42.9,-43.4C60.9,-36,84.8,-27.6,92.2,-12.2C99.8,3.1,91.2,25.4,76.1,37C61.1,48.5,39.7,49.3,21.9,52.7C4,56.1,-10.4,62,-26.6,61.1C-42.9,60.3,-61.1,52.9,-61.9,41C-62.6,28.8,-46,12.1,-42.2,-7C-38.4,-25.9,-47.4,-46.5,-42.5,-56.1C-37.6,-65.8,-18.8,-64.5,-3.2,-60.7C12.4,-57,24.9,-50.8,42.9,-43.4Z" transform="translate(100 100)" />
|
|
20
|
+
</svg>
|
|
21
|
+
|
|
22
|
+
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" class="absolute -bottom-[450px] -right-[300px] size-[800px] rotate-32 text-cyan-400">
|
|
23
|
+
<path fill="currentColor" d="M42.9,-43.4C60.9,-36,84.8,-27.6,92.2,-12.2C99.8,3.1,91.2,25.4,76.1,37C61.1,48.5,39.7,49.3,21.9,52.7C4,56.1,-10.4,62,-26.6,61.1C-42.9,60.3,-61.1,52.9,-61.9,41C-62.6,28.8,-46,12.1,-42.2,-7C-38.4,-25.9,-47.4,-46.5,-42.5,-56.1C-37.6,-65.8,-18.8,-64.5,-3.2,-60.7C12.4,-57,24.9,-50.8,42.9,-43.4Z" transform="translate(100 100)" />
|
|
24
|
+
</svg>
|
|
25
|
+
|
|
26
|
+
<main class="grid place-items-center h-screen">
|
|
27
|
+
<div class="w-full max-w-xl">
|
|
28
|
+
<%%= link_to Config::Urls.site, class: "flex justify-center items-center size-6 mx-auto text-brand-500 rounded-full transition ease-in-out hover:text-brand-800 hover:bg-brand-50 hover:scale-105" do %>
|
|
29
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" fill="currentColor" class="size-5 shrink-0 fill-brand-400"><path d="M223.85,47.12a16,16,0,0,0-15-15c-12.58-.75-44.73.4-71.41,27.07L132.69,64H74.36A15.91,15.91,0,0,0,63,68.68L28.7,103a16,16,0,0,0,9.07,27.16l38.47,5.37,44.21,44.21,5.37,38.49a15.94,15.94,0,0,0,10.78,12.92,16.11,16.11,0,0,0,5.1.83A15.91,15.91,0,0,0,153,227.3L187.32,193A15.91,15.91,0,0,0,192,181.64V123.31l4.77-4.77C223.45,91.86,224.6,59.71,223.85,47.12ZM74.36,80h42.33L77.16,119.52,40,114.34Zm74.41-9.45a76.65,76.65,0,0,1,59.11-22.47,76.46,76.46,0,0,1-22.42,59.16L128,164.68,91.32,128ZM176,181.64,141.67,216l-5.19-37.17L176,139.31Zm-74.16,9.5C97.34,201,82.29,224,40,224a8,8,0,0,1-8-8c0-42.29,23-57.34,32.86-61.85a8,8,0,0,1,6.64,14.56c-6.43,2.93-20.62,12.36-23.12,38.91,26.55-2.5,36-16.69,38.91-23.12a8,8,0,1,1,14.56,6.64Z"/></svg>
|
|
30
|
+
<%% end %>
|
|
31
|
+
|
|
32
|
+
<div class="w-full mt-6 p-2 ring ring-gray-200/50 bg-white/50 backdrop-blur-md md:rounded-xl md:shadow-lg">
|
|
33
|
+
<section class="flex flex-col gap-y-5 bg-white ring-gray-200/60 md:ring md:rounded-md md:shadow-lg">
|
|
34
|
+
<%%= tag.h1 yield(:page_title), class: "mx-2 mt-8 font-sans text-center text-base font-bold text-gray-800 md:mx-4" %>
|
|
35
|
+
|
|
36
|
+
<%%= yield %>
|
|
37
|
+
|
|
38
|
+
<%%= tag.p yield(:alternative_action), class: "px-2 pt-4 pb-2 border-t border-gray-100 empty:hidden md:pb-4" %>
|
|
39
|
+
</section>
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</main>
|
|
43
|
+
|
|
44
|
+
<%%= component "flash" %>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
data/app/webhooks/stripe/base.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Kern
|
|
|
6
6
|
template "layouts/kern/application.html.erb.tt", "app/views/layouts/application.html.erb"
|
|
7
7
|
copy_file "layouts/kern/application/_navigation.html.erb", "app/views/layouts/application/_navigation.html.erb"
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
template "layouts/kern/auth.html.erb.tt", "app/views/layouts/auth.html.erb"
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
data/lib/kern/engine.rb
CHANGED
|
@@ -13,6 +13,7 @@ module Kern
|
|
|
13
13
|
password: :password_field,
|
|
14
14
|
url: :url_field,
|
|
15
15
|
text: :text_area,
|
|
16
|
+
file: :file_field,
|
|
16
17
|
integer: :number_field,
|
|
17
18
|
float: :number_field,
|
|
18
19
|
decimal: :number_field,
|
|
@@ -29,8 +30,8 @@ module Kern
|
|
|
29
30
|
|
|
30
31
|
@template.safe_join([
|
|
31
32
|
(if label_suffix
|
|
32
|
-
@template.content_tag(:div, class:
|
|
33
|
-
@template.safe_join([label_html, @template.content_tag(:span, label_suffix.html_safe, class:
|
|
33
|
+
@template.content_tag(:div, class: label_suffix_wrapper_css) do
|
|
34
|
+
@template.safe_join([label_html, @template.content_tag(:span, label_suffix.html_safe, class: label_suffix_css)].compact)
|
|
34
35
|
end
|
|
35
36
|
end),
|
|
36
37
|
|
|
@@ -38,7 +39,7 @@ module Kern
|
|
|
38
39
|
|
|
39
40
|
input_field(attribute, options),
|
|
40
41
|
|
|
41
|
-
(@template.content_tag(:p, hint.html_safe, class:
|
|
42
|
+
(@template.content_tag(:p, hint.html_safe, class: hint_css) if hint)
|
|
42
43
|
].compact)
|
|
43
44
|
end
|
|
44
45
|
end
|
|
@@ -48,13 +49,13 @@ module Kern
|
|
|
48
49
|
label_options = options[:label] || {}
|
|
49
50
|
field_errors = @object&.errors&.where(attribute)
|
|
50
51
|
|
|
51
|
-
label_options[:class] =
|
|
52
|
+
label_options[:class] = label_css(has_errors: field_errors&.any?)
|
|
52
53
|
label_text = text || I18n.t("labels.#{attribute}", default: attribute.to_s.humanize)
|
|
53
54
|
|
|
54
55
|
super(attribute, label_options) do
|
|
55
56
|
safe_join([
|
|
56
57
|
begin
|
|
57
|
-
icon("warning-circle", class:
|
|
58
|
+
icon("warning-circle", class: label_icon_css) if field_errors&.any?
|
|
58
59
|
rescue
|
|
59
60
|
nil
|
|
60
61
|
end,
|
|
@@ -63,12 +64,8 @@ module Kern
|
|
|
63
64
|
end
|
|
64
65
|
end
|
|
65
66
|
|
|
66
|
-
def
|
|
67
|
-
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def toggle_label(method, text)
|
|
71
|
-
label(method, text.html_safe, class: toggle_label_css)
|
|
67
|
+
def toggle_label(id, text)
|
|
68
|
+
@template.label_tag(id, text.html_safe, class: toggle_label_css)
|
|
72
69
|
end
|
|
73
70
|
|
|
74
71
|
private
|
|
@@ -83,6 +80,7 @@ module Kern
|
|
|
83
80
|
return :email if attribute.to_s.end_with?("email")
|
|
84
81
|
return :password if attribute.to_s.include?("password")
|
|
85
82
|
return :url if attribute.match?(/url|website|site/)
|
|
83
|
+
return :file if attribute.match?(/hero|image|avatar/)
|
|
86
84
|
return :string unless valid?(attribute)
|
|
87
85
|
|
|
88
86
|
@object.type_for_attribute(attribute.to_s).type
|
|
@@ -5,6 +5,41 @@ module Kern
|
|
|
5
5
|
"w-full [&[data-slot='field']+[data-slot='field']]:mt-4"
|
|
6
6
|
end
|
|
7
7
|
|
|
8
|
+
def label_css(has_errors: false)
|
|
9
|
+
base = <<~CSS
|
|
10
|
+
flex items-center gap-1 text-sm font-medium
|
|
11
|
+
CSS
|
|
12
|
+
|
|
13
|
+
class_names(base, has_errors ? "text-red-600" : "text-gray-700")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def label_icon_css
|
|
17
|
+
<<~CSS
|
|
18
|
+
size-3.5
|
|
19
|
+
scale-100 transition ml-0 ease-in-out duration-300
|
|
20
|
+
starting:ml-3.5 starting:scale-0
|
|
21
|
+
CSS
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def label_suffix_wrapper_css
|
|
25
|
+
<<~CSS
|
|
26
|
+
flex items-center justify-between
|
|
27
|
+
CSS
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def label_suffix_css
|
|
31
|
+
<<~CSS
|
|
32
|
+
text-xs font-medium text-gray-500
|
|
33
|
+
CSS
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def hint_css
|
|
37
|
+
<<~CSS
|
|
38
|
+
flex items-center gap-x-1 mt-0.5 px-0.5
|
|
39
|
+
text-xs font-light text-gray-500
|
|
40
|
+
CSS
|
|
41
|
+
end
|
|
42
|
+
|
|
8
43
|
def input_css
|
|
9
44
|
<<~CSS
|
|
10
45
|
w-full px-2.5 py-1.5
|
data/lib/kern/form_builder.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
require "kern/form_builder/styles"
|
|
2
1
|
require "kern/form_builder/input"
|
|
3
2
|
|
|
4
3
|
module Kern
|
|
@@ -6,7 +5,15 @@ module Kern
|
|
|
6
5
|
include ActionView::Helpers::TagHelper
|
|
7
6
|
|
|
8
7
|
include Input
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
def self.load_styles
|
|
10
|
+
if defined?(::FormBuilder::Styles)
|
|
11
|
+
include ::FormBuilder::Styles
|
|
12
|
+
else
|
|
13
|
+
require "kern/form_builder/styles"
|
|
14
|
+
include Styles
|
|
15
|
+
end
|
|
16
|
+
end
|
|
10
17
|
|
|
11
18
|
%w[
|
|
12
19
|
text_field email_field password_field
|
|
@@ -31,9 +38,10 @@ module Kern
|
|
|
31
38
|
def check_box(method, options = {}, checked_value = "1", unchecked_value = "0", &block)
|
|
32
39
|
field_classes(options, toggle_input_css)
|
|
33
40
|
label_text = block ? @template.capture(&block) : method.to_s.humanize
|
|
41
|
+
custom_id = options[:id] || method
|
|
34
42
|
|
|
35
43
|
toggle_wrapper do
|
|
36
|
-
super(method, options, checked_value, unchecked_value) + label(
|
|
44
|
+
super(method, options, checked_value, unchecked_value) + label(custom_id, label_text)
|
|
37
45
|
end
|
|
38
46
|
end
|
|
39
47
|
alias_method :checkbox, :check_box
|
|
@@ -41,9 +49,10 @@ module Kern
|
|
|
41
49
|
def radio_button(method, tag_value, options = {}, &block)
|
|
42
50
|
field_classes(options, toggle_input_css)
|
|
43
51
|
label_text = block ? @template.capture(&block) : tag_value.to_s.humanize
|
|
52
|
+
custom_id = options[:id] || "#{method}_#{tag_value}"
|
|
44
53
|
|
|
45
54
|
toggle_wrapper do
|
|
46
|
-
super(method, tag_value, options) + toggle_label(
|
|
55
|
+
super(method, tag_value, options) + toggle_label(custom_id, label_text)
|
|
47
56
|
end
|
|
48
57
|
end
|
|
49
58
|
|
|
@@ -97,5 +106,9 @@ module Kern
|
|
|
97
106
|
options[:class] = options[:class].presence || class_names(base_css, *additional_classes, options[:additional_class])
|
|
98
107
|
options.delete(:additional_class)
|
|
99
108
|
end
|
|
109
|
+
|
|
110
|
+
def toggle_wrapper(&block)
|
|
111
|
+
content_tag(:div, yield, data: {slot: "field"}, class: "flex items-start gap-x-2 [&>input]:mt-[0.17em]")
|
|
112
|
+
end
|
|
100
113
|
end
|
|
101
114
|
end
|
data/lib/kern/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kern
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Rails Designer
|
|
@@ -38,6 +38,7 @@ files:
|
|
|
38
38
|
- app/assets/builds/tailwind.kern.css
|
|
39
39
|
- app/controllers/concerns/authentication.rb
|
|
40
40
|
- app/controllers/concerns/authentication.rb.tt
|
|
41
|
+
- app/controllers/concerns/layouts.rb
|
|
41
42
|
- app/controllers/kern/application_controller.rb
|
|
42
43
|
- app/controllers/kern/billing_profiles/subscriptions_controller.rb
|
|
43
44
|
- app/controllers/kern/billing_profiles/subscriptions_controller.rb.tt
|
|
@@ -77,6 +78,7 @@ files:
|
|
|
77
78
|
- app/views/components/_dialog.html.erb
|
|
78
79
|
- app/views/components/_flash.html.erb
|
|
79
80
|
- app/views/components/_heading.html.erb
|
|
81
|
+
- app/views/components/_section.html.erb
|
|
80
82
|
- app/views/components/flash/_message.html.erb
|
|
81
83
|
- app/views/kern/pages/welcome.html.erb
|
|
82
84
|
- app/views/kern/passwords/edit.html.erb
|
|
@@ -96,6 +98,7 @@ files:
|
|
|
96
98
|
- app/views/layouts/kern/application.html.erb.tt
|
|
97
99
|
- app/views/layouts/kern/application/_navigation.html.erb
|
|
98
100
|
- app/views/layouts/kern/auth.html.erb
|
|
101
|
+
- app/views/layouts/kern/auth.html.erb.tt
|
|
99
102
|
- app/webhooks/stripe/base.rb
|
|
100
103
|
- app/webhooks/stripe/checkout_session_completed.rb
|
|
101
104
|
- app/webhooks/stripe/customer_subscription_deleted.rb
|
|
@@ -155,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
155
158
|
- !ruby/object:Gem::Version
|
|
156
159
|
version: '0'
|
|
157
160
|
requirements: []
|
|
158
|
-
rubygems_version:
|
|
161
|
+
rubygems_version: 4.0.3
|
|
159
162
|
specification_version: 4
|
|
160
163
|
summary: Rails engine with auth, billing, and common components for SaaS apps
|
|
161
164
|
test_files: []
|