kaze 0.5.0 → 0.6.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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/lib/kaze/commands/install_command.rb +8 -0
  3. data/lib/kaze/commands/installs_hotwire_stack.rb +5 -2
  4. data/lib/kaze/commands/installs_inertia_stacks.rb +13 -3
  5. data/lib/kaze/version.rb +1 -1
  6. data/stubs/default/app/forms/auth/login_form.rb +2 -8
  7. data/stubs/default/app/forms/update_profile_information_form.rb +1 -1
  8. data/stubs/default/app/models/auth.rb +57 -0
  9. data/stubs/default/app/models/current.rb +1 -1
  10. data/stubs/default/app/validators/current_password_validator.rb +1 -1
  11. data/stubs/default/app/views/layouts/mailer.html.erb +367 -372
  12. data/stubs/default/app/views/layouts/mailer.text.erb +1 -4
  13. data/stubs/default/app/views/user_mailer/reset_password.html.erb +21 -26
  14. data/stubs/default/test/factories/users.rb +7 -0
  15. data/stubs/default/test/integration/auth/authentication_test.rb +43 -0
  16. data/stubs/default/test/integration/auth/password_reset_test.rb +41 -0
  17. data/stubs/default/test/integration/auth/registration_test.rb +21 -0
  18. data/stubs/default/test/integration/password_update_test.rb +28 -0
  19. data/stubs/default/test/integration/profile_test.rb +51 -0
  20. data/stubs/default/test/test_helper.rb +38 -0
  21. data/stubs/hotwire/app/components/dropdown_component.html.erb +17 -18
  22. data/stubs/hotwire/app/components/modal_component.html.erb +55 -59
  23. data/stubs/hotwire/app/controllers/application_controller.rb +1 -0
  24. data/stubs/hotwire/app/controllers/auth/authenticated_session_controller.rb +10 -7
  25. data/stubs/hotwire/app/controllers/auth/new_password_controller.rb +3 -1
  26. data/stubs/hotwire/app/controllers/auth/password_reset_link_controller.rb +3 -1
  27. data/stubs/hotwire/app/controllers/auth/registered_user_controller.rb +4 -2
  28. data/stubs/hotwire/app/controllers/concerns/authenticate.rb +5 -20
  29. data/stubs/hotwire/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
  30. data/stubs/hotwire/app/controllers/concerns/set_current_auth.rb +9 -0
  31. data/stubs/hotwire/app/controllers/password_controller.rb +1 -1
  32. data/stubs/hotwire/app/controllers/profile_controller.rb +6 -4
  33. data/stubs/hotwire/app/controllers/welcome_controller.rb +1 -1
  34. data/stubs/hotwire/app/javascript/application.js +3 -3
  35. data/stubs/hotwire/app/views/auth/forgot_password.html.erb +12 -17
  36. data/stubs/hotwire/app/views/auth/login.html.erb +0 -9
  37. data/stubs/hotwire/app/views/auth/register.html.erb +0 -13
  38. data/stubs/hotwire/app/views/auth/reset_password.html.erb +0 -7
  39. data/stubs/hotwire/app/views/dashboard/index.html.erb +9 -10
  40. data/stubs/hotwire/app/views/layouts/_navigation.html.erb +77 -87
  41. data/stubs/hotwire/app/views/layouts/application.html.erb +0 -9
  42. data/stubs/hotwire/app/views/layouts/guest.html.erb +0 -6
  43. data/stubs/hotwire/app/views/profile/edit.html.erb +19 -22
  44. data/stubs/hotwire/app/views/profile/partials/_delete_user_form.html.erb +32 -42
  45. data/stubs/hotwire/app/views/profile/partials/_update_password_form.html.erb +42 -55
  46. data/stubs/hotwire/app/views/profile/partials/_update_profile_information_form.html.erb +36 -46
  47. data/stubs/hotwire/app/views/welcome/index.html.erb +34 -46
  48. data/stubs/hotwire/config/tailwind.config.js +2 -2
  49. data/stubs/inertia-common/app/controllers/application_controller.rb +1 -0
  50. data/stubs/inertia-common/app/controllers/auth/authenticated_session_controller.rb +10 -7
  51. data/stubs/inertia-common/app/controllers/auth/new_password_controller.rb +3 -1
  52. data/stubs/inertia-common/app/controllers/auth/password_reset_link_controller.rb +3 -1
  53. data/stubs/inertia-common/app/controllers/auth/registered_user_controller.rb +4 -2
  54. data/stubs/inertia-common/app/controllers/concerns/authenticate.rb +5 -20
  55. data/stubs/inertia-common/app/controllers/concerns/handle_inertia_requests.rb +1 -1
  56. data/stubs/inertia-common/app/controllers/concerns/redirect_if_authenticated.rb +19 -0
  57. data/stubs/inertia-common/app/controllers/concerns/set_current_auth.rb +9 -0
  58. data/stubs/inertia-common/app/controllers/password_controller.rb +1 -1
  59. data/stubs/inertia-common/app/controllers/profile_controller.rb +5 -3
  60. data/stubs/inertia-common/app/controllers/welcome_controller.rb +1 -1
  61. data/stubs/inertia-common/test/integration/password_update_test.rb +28 -0
  62. data/stubs/inertia-common/test/integration/profile_test.rb +51 -0
  63. data/stubs/inertia-react-ts/app/javascript/Components/ApplicationLogo.tsx +13 -9
  64. data/stubs/inertia-react-ts/app/javascript/Components/Checkbox.tsx +15 -12
  65. data/stubs/inertia-react-ts/app/javascript/Components/DangerButton.tsx +20 -15
  66. data/stubs/inertia-react-ts/app/javascript/Components/Dropdown.tsx +119 -87
  67. data/stubs/inertia-react-ts/app/javascript/Components/InputError.tsx +14 -7
  68. data/stubs/inertia-react-ts/app/javascript/Components/InputLabel.tsx +18 -7
  69. data/stubs/inertia-react-ts/app/javascript/Components/Modal.tsx +60 -60
  70. data/stubs/inertia-react-ts/app/javascript/Components/NavLink.tsx +21 -16
  71. data/stubs/inertia-react-ts/app/javascript/Components/PrimaryButton.tsx +20 -15
  72. data/stubs/inertia-react-ts/app/javascript/Components/ResponsiveNavLink.tsx +19 -14
  73. data/stubs/inertia-react-ts/app/javascript/Components/SecondaryButton.tsx +22 -16
  74. data/stubs/inertia-react-ts/app/javascript/Components/TextInput.tsx +35 -24
  75. data/stubs/inertia-react-ts/app/javascript/Layouts/AuthenticatedLayout.tsx +157 -117
  76. data/stubs/inertia-react-ts/app/javascript/Layouts/GuestLayout.tsx +15 -15
  77. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ForgotPassword.tsx +52 -49
  78. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Login.tsx +90 -82
  79. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/Register.tsx +118 -115
  80. data/stubs/inertia-react-ts/app/javascript/Pages/Auth/ResetPassword.tsx +63 -60
  81. data/stubs/inertia-react-ts/app/javascript/Pages/Dashboard.tsx +23 -17
  82. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Edit.tsx +31 -27
  83. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.tsx +109 -99
  84. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.tsx +121 -113
  85. data/stubs/inertia-react-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.tsx +76 -69
  86. data/stubs/inertia-react-ts/app/javascript/Pages/Welcome.tsx +87 -63
  87. data/stubs/inertia-react-ts/app/javascript/entrypoints/application.tsx +32 -25
  88. data/stubs/inertia-react-ts/app/views/layouts/application.html.erb +0 -4
  89. data/stubs/inertia-react-ts/config/tailwind.config.js +2 -2
  90. data/stubs/inertia-react-ts/vite.config.ts +2 -5
  91. data/stubs/inertia-vue-ts/app/javascript/Components/ApplicationLogo.vue +10 -6
  92. data/stubs/inertia-vue-ts/app/javascript/Components/Checkbox.vue +18 -18
  93. data/stubs/inertia-vue-ts/app/javascript/Components/DangerButton.vue +5 -5
  94. data/stubs/inertia-vue-ts/app/javascript/Components/Dropdown.vue +60 -57
  95. data/stubs/inertia-vue-ts/app/javascript/Components/DropdownLink.vue +9 -9
  96. data/stubs/inertia-vue-ts/app/javascript/Components/InputError.vue +7 -7
  97. data/stubs/inertia-vue-ts/app/javascript/Components/InputLabel.vue +6 -6
  98. data/stubs/inertia-vue-ts/app/javascript/Components/Modal.vue +84 -74
  99. data/stubs/inertia-vue-ts/app/javascript/Components/NavLink.vue +12 -12
  100. data/stubs/inertia-vue-ts/app/javascript/Components/PrimaryButton.vue +5 -5
  101. data/stubs/inertia-vue-ts/app/javascript/Components/ResponsiveNavLink.vue +12 -12
  102. data/stubs/inertia-vue-ts/app/javascript/Components/SecondaryButton.vue +13 -13
  103. data/stubs/inertia-vue-ts/app/javascript/Components/TextInput.vue +13 -13
  104. data/stubs/inertia-vue-ts/app/javascript/Layouts/AuthenticatedLayout.vue +168 -136
  105. data/stubs/inertia-vue-ts/app/javascript/Layouts/GuestLayout.vue +15 -13
  106. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ForgotPassword.vue +56 -49
  107. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Login.vue +78 -72
  108. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/Register.vue +101 -97
  109. data/stubs/inertia-vue-ts/app/javascript/Pages/Auth/ResetPassword.vue +71 -68
  110. data/stubs/inertia-vue-ts/app/javascript/Pages/Dashboard.vue +22 -14
  111. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Edit.vue +34 -30
  112. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/DeleteUserForm.vue +87 -83
  113. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdatePasswordForm.vue +105 -98
  114. data/stubs/inertia-vue-ts/app/javascript/Pages/Profile/Partials/UpdateProfileInformationForm.vue +69 -59
  115. data/stubs/inertia-vue-ts/app/javascript/Pages/Welcome.vue +74 -47
  116. data/stubs/inertia-vue-ts/app/views/layouts/application.html.erb +0 -4
  117. data/stubs/inertia-vue-ts/config/tailwind.config.js +2 -2
  118. data/stubs/inertia-vue-ts/vite.config.ts +2 -5
  119. metadata +18 -6
  120. data/stubs/hotwire/bin/vite +0 -27
  121. data/stubs/inertia-common/Procfile.dev +0 -3
  122. /data/stubs/{hotwire → default}/Procfile.dev +0 -0
  123. /data/stubs/hotwire/app/javascript/{alpinejs.js → alpinejs.stub} +0 -0
@@ -1,12 +1,16 @@
1
- import { SVGAttributes } from 'react';
1
+ import { SVGAttributes } from 'react'
2
2
 
3
3
  export default function ApplicationLogo(props: SVGAttributes<SVGElement>) {
4
- return (
5
- <svg {...props} viewBox="0 -6 32 32" xmlns="http://www.w3.org/2000/svg">
6
- <g fill="none" fillRule="evenodd">
7
- <path d="M0-6h32v32H0z"/>
8
- <path fill="#c00" fillRule="nonzero" d="M.985 19.636s.422-4.163 3.375-9.087c2.954-4.924 7.99-8.65 12.083-9.017 8.144-.816 15.46 6.485 15.46 6.485s-.24.168-.494.38C23.42 2.49 18.54 5.274 17.005 6.02c-7.033 3.925-4.91 13.616-4.91 13.616H.987zM24.137 2.32c-.45-.182-.9-.35-1.364-.505l.056-.93c.885.254 1.237.423 1.363.493l-.056.943zM22.8 5.304c.45.028.915.084 1.393.183l-.056.872c-.464-.1-.928-.155-1.392-.17l.056-.885zM17.597.913c-.407 0-.815.015-1.223.058l-.268-.83c.465-.056.915-.084 1.35-.084l.282.858h-.14zm.676 5.178c.35-.154.76-.31 1.237-.45l.31.93c-.41.125-.817.294-1.225.49l-.323-.97zm-6.386-3.7c-.366.184-.718.395-1.083.62l-.647-.985c.38-.225.745-.42 1.097-.604l.633.97zm2.883 6.33c.252-.323.548-.646.87-.942l.634.957c-.31.323-.59.647-.83 1L14.77 8.72zm-2.04 4.53c.112-.506.24-1.027.422-1.547l1.012.802c-.14.548-.24 1.097-.295 1.645l-1.14-.9zM6.57 6.57c-.34.35-.662.73-.958 1.11L4.53 6.752c.323-.352.674-.704 1.04-1.055l1 .872zm-4.25 6.286c-.224.52-.52 1.21-.702 1.688L0 13.954c.14-.38.436-1.084.703-1.69l1.618.592zm10.2 3.967l1.518.548c.084.663.21 1.28.337 1.83l-1.688-.605c-.07-.422-.14-1.027-.168-1.772z"/>
9
- </g>
10
- </svg>
11
- );
4
+ return (
5
+ <svg {...props} viewBox="0 -6 32 32" xmlns="http://www.w3.org/2000/svg">
6
+ <g fill="none" fillRule="evenodd">
7
+ <path d="M0-6h32v32H0z" />
8
+ <path
9
+ fill="#c00"
10
+ fillRule="nonzero"
11
+ d="M.985 19.636s.422-4.163 3.375-9.087c2.954-4.924 7.99-8.65 12.083-9.017 8.144-.816 15.46 6.485 15.46 6.485s-.24.168-.494.38C23.42 2.49 18.54 5.274 17.005 6.02c-7.033 3.925-4.91 13.616-4.91 13.616H.987zM24.137 2.32c-.45-.182-.9-.35-1.364-.505l.056-.93c.885.254 1.237.423 1.363.493l-.056.943zM22.8 5.304c.45.028.915.084 1.393.183l-.056.872c-.464-.1-.928-.155-1.392-.17l.056-.885zM17.597.913c-.407 0-.815.015-1.223.058l-.268-.83c.465-.056.915-.084 1.35-.084l.282.858h-.14zm.676 5.178c.35-.154.76-.31 1.237-.45l.31.93c-.41.125-.817.294-1.225.49l-.323-.97zm-6.386-3.7c-.366.184-.718.395-1.083.62l-.647-.985c.38-.225.745-.42 1.097-.604l.633.97zm2.883 6.33c.252-.323.548-.646.87-.942l.634.957c-.31.323-.59.647-.83 1L14.77 8.72zm-2.04 4.53c.112-.506.24-1.027.422-1.547l1.012.802c-.14.548-.24 1.097-.295 1.645l-1.14-.9zM6.57 6.57c-.34.35-.662.73-.958 1.11L4.53 6.752c.323-.352.674-.704 1.04-1.055l1 .872zm-4.25 6.286c-.224.52-.52 1.21-.702 1.688L0 13.954c.14-.38.436-1.084.703-1.69l1.618.592zm10.2 3.967l1.518.548c.084.663.21 1.28.337 1.83l-1.688-.605c-.07-.422-.14-1.027-.168-1.772z"
12
+ />
13
+ </g>
14
+ </svg>
15
+ )
12
16
  }
@@ -1,14 +1,17 @@
1
- import { InputHTMLAttributes } from 'react';
1
+ import { InputHTMLAttributes } from 'react'
2
2
 
3
- export default function Checkbox({ className = '', ...props }: InputHTMLAttributes<HTMLInputElement>) {
4
- return (
5
- <input
6
- {...props}
7
- type="checkbox"
8
- className={
9
- 'rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800 ' +
10
- className
11
- }
12
- />
13
- );
3
+ export default function Checkbox({
4
+ className = '',
5
+ ...props
6
+ }: InputHTMLAttributes<HTMLInputElement>) {
7
+ return (
8
+ <input
9
+ {...props}
10
+ type="checkbox"
11
+ className={
12
+ 'rounded dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-indigo-600 shadow-sm focus:ring-indigo-500 dark:focus:ring-indigo-600 dark:focus:ring-offset-gray-800 ' +
13
+ className
14
+ }
15
+ />
16
+ )
14
17
  }
@@ -1,17 +1,22 @@
1
- import { ButtonHTMLAttributes } from 'react';
1
+ import { ButtonHTMLAttributes } from 'react'
2
2
 
3
- export default function DangerButton({ className = '', disabled, children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {
4
- return (
5
- <button
6
- {...props}
7
- className={
8
- `inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 ${
9
- disabled && 'opacity-25'
10
- } ` + className
11
- }
12
- disabled={disabled}
13
- >
14
- {children}
15
- </button>
16
- );
3
+ export default function DangerButton({
4
+ className = '',
5
+ disabled,
6
+ children,
7
+ ...props
8
+ }: ButtonHTMLAttributes<HTMLButtonElement>) {
9
+ return (
10
+ <button
11
+ {...props}
12
+ className={
13
+ `inline-flex items-center px-4 py-2 bg-red-600 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-red-500 active:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 ${
14
+ disabled && 'opacity-25'
15
+ } ` + className
16
+ }
17
+ disabled={disabled}
18
+ >
19
+ {children}
20
+ </button>
21
+ )
17
22
  }
@@ -1,99 +1,131 @@
1
- import { useState, createContext, useContext, Fragment, PropsWithChildren, Dispatch, SetStateAction } from 'react';
2
- import { Link, InertiaLinkProps } from '@inertiajs/react';
3
- import { Transition } from '@headlessui/react';
1
+ import {
2
+ useState,
3
+ createContext,
4
+ useContext,
5
+ Fragment,
6
+ PropsWithChildren,
7
+ Dispatch,
8
+ SetStateAction,
9
+ } from 'react'
10
+ import { Link, InertiaLinkProps } from '@inertiajs/react'
11
+ import { Transition } from '@headlessui/react'
4
12
 
5
13
  const DropDownContext = createContext<{
6
- open: boolean;
7
- setOpen: Dispatch<SetStateAction<boolean>>;
8
- toggleOpen: () => void;
14
+ open: boolean
15
+ setOpen: Dispatch<SetStateAction<boolean>>
16
+ toggleOpen: () => void
9
17
  }>({
10
- open: false,
11
- setOpen: () => {},
12
- toggleOpen: () => {},
13
- });
18
+ open: false,
19
+ setOpen: () => {},
20
+ toggleOpen: () => {},
21
+ })
14
22
 
15
23
  const Dropdown = ({ children }: PropsWithChildren) => {
16
- const [open, setOpen] = useState(false);
24
+ const [open, setOpen] = useState(false)
17
25
 
18
- const toggleOpen = () => {
19
- setOpen((previousState) => !previousState);
20
- };
26
+ const toggleOpen = () => {
27
+ setOpen((previousState) => !previousState)
28
+ }
21
29
 
22
- return (
23
- <DropDownContext.Provider value={{ open, setOpen, toggleOpen }}>
24
- <div className="relative">{children}</div>
25
- </DropDownContext.Provider>
26
- );
27
- };
30
+ return (
31
+ <DropDownContext.Provider value={{ open, setOpen, toggleOpen }}>
32
+ <div className="relative">{children}</div>
33
+ </DropDownContext.Provider>
34
+ )
35
+ }
28
36
 
29
37
  const Trigger = ({ children }: PropsWithChildren) => {
30
- const { open, setOpen, toggleOpen } = useContext(DropDownContext);
31
-
32
- return (
33
- <>
34
- <div onClick={toggleOpen}>{children}</div>
35
-
36
- {open && <div className="fixed inset-0 z-40" onClick={() => setOpen(false)}></div>}
37
- </>
38
- );
39
- };
40
-
41
- const Content = ({ align = 'right', width = '48', contentClasses = 'py-1 bg-white dark:bg-gray-700', children }: PropsWithChildren<{ align?: 'left'|'right', width?: '48', contentClasses?: string }>) => {
42
- const { open, setOpen } = useContext(DropDownContext);
43
-
44
- let alignmentClasses = 'origin-top';
45
-
46
- if (align === 'left') {
47
- alignmentClasses = 'ltr:origin-top-left rtl:origin-top-right start-0';
48
- } else if (align === 'right') {
49
- alignmentClasses = 'ltr:origin-top-right rtl:origin-top-left end-0';
50
- }
51
-
52
- let widthClasses = '';
53
-
54
- if (width === '48') {
55
- widthClasses = 'w-48';
56
- }
57
-
58
- return (
59
- <>
60
- <Transition
61
- as={Fragment}
62
- show={open}
63
- enter="transition ease-out duration-200"
64
- enterFrom="opacity-0 scale-95"
65
- enterTo="opacity-100 scale-100"
66
- leave="transition ease-in duration-75"
67
- leaveFrom="opacity-100 scale-100"
68
- leaveTo="opacity-0 scale-95"
69
- >
70
- <div
71
- className={`absolute z-50 mt-2 rounded-md shadow-lg ${alignmentClasses} ${widthClasses}`}
72
- onClick={() => setOpen(false)}
73
- >
74
- <div className={`rounded-md ring-1 ring-black ring-opacity-5 ` + contentClasses}>{children}</div>
75
- </div>
76
- </Transition>
77
- </>
78
- );
79
- };
80
-
81
- const DropdownLink = ({ className = '', children, ...props }: InertiaLinkProps) => {
82
- return (
83
- <Link
84
- {...props}
38
+ const { open, setOpen, toggleOpen } = useContext(DropDownContext)
39
+
40
+ return (
41
+ <>
42
+ <div onClick={toggleOpen}>{children}</div>
43
+
44
+ {open && (
45
+ <div
46
+ className="fixed inset-0 z-40"
47
+ onClick={() => setOpen(false)}
48
+ ></div>
49
+ )}
50
+ </>
51
+ )
52
+ }
53
+
54
+ const Content = ({
55
+ align = 'right',
56
+ width = '48',
57
+ contentClasses = 'py-1 bg-white dark:bg-gray-700',
58
+ children,
59
+ }: PropsWithChildren<{
60
+ align?: 'left' | 'right'
61
+ width?: '48'
62
+ contentClasses?: string
63
+ }>) => {
64
+ const { open, setOpen } = useContext(DropDownContext)
65
+
66
+ let alignmentClasses = 'origin-top'
67
+
68
+ if (align === 'left') {
69
+ alignmentClasses = 'ltr:origin-top-left rtl:origin-top-right start-0'
70
+ } else if (align === 'right') {
71
+ alignmentClasses = 'ltr:origin-top-right rtl:origin-top-left end-0'
72
+ }
73
+
74
+ let widthClasses = ''
75
+
76
+ if (width === '48') {
77
+ widthClasses = 'w-48'
78
+ }
79
+
80
+ return (
81
+ <>
82
+ <Transition
83
+ as={Fragment}
84
+ show={open}
85
+ enter="transition ease-out duration-200"
86
+ enterFrom="opacity-0 scale-95"
87
+ enterTo="opacity-100 scale-100"
88
+ leave="transition ease-in duration-75"
89
+ leaveFrom="opacity-100 scale-100"
90
+ leaveTo="opacity-0 scale-95"
91
+ >
92
+ <div
93
+ className={`absolute z-50 mt-2 rounded-md shadow-lg ${alignmentClasses} ${widthClasses}`}
94
+ onClick={() => setOpen(false)}
95
+ >
96
+ <div
85
97
  className={
86
- 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out ' +
87
- className
98
+ `rounded-md ring-1 ring-black ring-opacity-5 ` + contentClasses
88
99
  }
89
- >
100
+ >
90
101
  {children}
91
- </Link>
92
- );
93
- };
94
-
95
- Dropdown.Trigger = Trigger;
96
- Dropdown.Content = Content;
97
- Dropdown.Link = DropdownLink;
98
-
99
- export default Dropdown;
102
+ </div>
103
+ </div>
104
+ </Transition>
105
+ </>
106
+ )
107
+ }
108
+
109
+ const DropdownLink = ({
110
+ className = '',
111
+ children,
112
+ ...props
113
+ }: InertiaLinkProps) => {
114
+ return (
115
+ <Link
116
+ {...props}
117
+ className={
118
+ 'block w-full px-4 py-2 text-start text-sm leading-5 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-800 transition duration-150 ease-in-out ' +
119
+ className
120
+ }
121
+ >
122
+ {children}
123
+ </Link>
124
+ )
125
+ }
126
+
127
+ Dropdown.Trigger = Trigger
128
+ Dropdown.Content = Content
129
+ Dropdown.Link = DropdownLink
130
+
131
+ export default Dropdown
@@ -1,9 +1,16 @@
1
- import { HTMLAttributes } from 'react';
1
+ import { HTMLAttributes } from 'react'
2
2
 
3
- export default function InputError({ message, className = '', ...props }: HTMLAttributes<HTMLParagraphElement> & { message?: string }) {
4
- return message ? (
5
- <p {...props} className={'text-sm text-red-600 dark:text-red-400 ' + className}>
6
- {message}
7
- </p>
8
- ) : null;
3
+ export default function InputError({
4
+ message,
5
+ className = '',
6
+ ...props
7
+ }: HTMLAttributes<HTMLParagraphElement> & { message?: string }) {
8
+ return message ? (
9
+ <p
10
+ {...props}
11
+ className={'text-sm text-red-600 dark:text-red-400 ' + className}
12
+ >
13
+ {message}
14
+ </p>
15
+ ) : null
9
16
  }
@@ -1,9 +1,20 @@
1
- import { LabelHTMLAttributes } from 'react';
1
+ import { LabelHTMLAttributes } from 'react'
2
2
 
3
- export default function InputLabel({ value, className = '', children, ...props }: LabelHTMLAttributes<HTMLLabelElement> & { value?: string }) {
4
- return (
5
- <label {...props} className={`block font-medium text-sm text-gray-700 dark:text-gray-300 ` + className}>
6
- {value ? value : children}
7
- </label>
8
- );
3
+ export default function InputLabel({
4
+ value,
5
+ className = '',
6
+ children,
7
+ ...props
8
+ }: LabelHTMLAttributes<HTMLLabelElement> & { value?: string }) {
9
+ return (
10
+ <label
11
+ {...props}
12
+ className={
13
+ `block font-medium text-sm text-gray-700 dark:text-gray-300 ` +
14
+ className
15
+ }
16
+ >
17
+ {value ? value : children}
18
+ </label>
19
+ )
9
20
  }
@@ -1,68 +1,68 @@
1
- import { Fragment, PropsWithChildren } from 'react';
2
- import { Dialog, Transition } from '@headlessui/react';
1
+ import { Fragment, PropsWithChildren } from 'react'
2
+ import { Dialog, Transition } from '@headlessui/react'
3
3
 
4
4
  export default function Modal({
5
- children,
6
- show = false,
7
- maxWidth = '2xl',
8
- closeable = true,
9
- onClose = () => {},
5
+ children,
6
+ show = false,
7
+ maxWidth = '2xl',
8
+ closeable = true,
9
+ onClose = () => {},
10
10
  }: PropsWithChildren<{
11
- show: boolean;
12
- maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
13
- closeable?: boolean;
14
- onClose: CallableFunction;
11
+ show: boolean
12
+ maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl'
13
+ closeable?: boolean
14
+ onClose: CallableFunction
15
15
  }>) {
16
- const close = () => {
17
- if (closeable) {
18
- onClose();
19
- }
20
- };
16
+ const close = () => {
17
+ if (closeable) {
18
+ onClose()
19
+ }
20
+ }
21
21
 
22
- const maxWidthClass = {
23
- sm: 'sm:max-w-sm',
24
- md: 'sm:max-w-md',
25
- lg: 'sm:max-w-lg',
26
- xl: 'sm:max-w-xl',
27
- '2xl': 'sm:max-w-2xl',
28
- }[maxWidth];
22
+ const maxWidthClass = {
23
+ sm: 'sm:max-w-sm',
24
+ md: 'sm:max-w-md',
25
+ lg: 'sm:max-w-lg',
26
+ xl: 'sm:max-w-xl',
27
+ '2xl': 'sm:max-w-2xl',
28
+ }[maxWidth]
29
29
 
30
- return (
31
- <Transition show={show} as={Fragment} leave="duration-200">
32
- <Dialog
33
- as="div"
34
- id="modal"
35
- className="fixed inset-0 flex overflow-y-auto px-4 py-6 sm:px-0 items-center z-50 transform transition-all"
36
- onClose={close}
37
- >
38
- <Transition.Child
39
- as={Fragment}
40
- enter="ease-out duration-300"
41
- enterFrom="opacity-0"
42
- enterTo="opacity-100"
43
- leave="ease-in duration-200"
44
- leaveFrom="opacity-100"
45
- leaveTo="opacity-0"
46
- >
47
- <div className="absolute inset-0 bg-gray-500/75 dark:bg-gray-900/75" />
48
- </Transition.Child>
30
+ return (
31
+ <Transition show={show} as={Fragment} leave="duration-200">
32
+ <Dialog
33
+ as="div"
34
+ id="modal"
35
+ className="fixed inset-0 flex overflow-y-auto px-4 py-6 sm:px-0 items-center z-50 transform transition-all"
36
+ onClose={close}
37
+ >
38
+ <Transition.Child
39
+ as={Fragment}
40
+ enter="ease-out duration-300"
41
+ enterFrom="opacity-0"
42
+ enterTo="opacity-100"
43
+ leave="ease-in duration-200"
44
+ leaveFrom="opacity-100"
45
+ leaveTo="opacity-0"
46
+ >
47
+ <div className="absolute inset-0 bg-gray-500/75 dark:bg-gray-900/75" />
48
+ </Transition.Child>
49
49
 
50
- <Transition.Child
51
- as={Fragment}
52
- enter="ease-out duration-300"
53
- enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
54
- enterTo="opacity-100 translate-y-0 sm:scale-100"
55
- leave="ease-in duration-200"
56
- leaveFrom="opacity-100 translate-y-0 sm:scale-100"
57
- leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
58
- >
59
- <Dialog.Panel
60
- className={`mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full sm:mx-auto ${maxWidthClass}`}
61
- >
62
- {children}
63
- </Dialog.Panel>
64
- </Transition.Child>
65
- </Dialog>
66
- </Transition>
67
- );
50
+ <Transition.Child
51
+ as={Fragment}
52
+ enter="ease-out duration-300"
53
+ enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
54
+ enterTo="opacity-100 translate-y-0 sm:scale-100"
55
+ leave="ease-in duration-200"
56
+ leaveFrom="opacity-100 translate-y-0 sm:scale-100"
57
+ leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
58
+ >
59
+ <Dialog.Panel
60
+ className={`mb-6 bg-white dark:bg-gray-800 rounded-lg overflow-hidden shadow-xl transform transition-all sm:w-full sm:mx-auto ${maxWidthClass}`}
61
+ >
62
+ {children}
63
+ </Dialog.Panel>
64
+ </Transition.Child>
65
+ </Dialog>
66
+ </Transition>
67
+ )
68
68
  }
@@ -1,18 +1,23 @@
1
- import { Link, InertiaLinkProps } from '@inertiajs/react';
1
+ import { Link, InertiaLinkProps } from '@inertiajs/react'
2
2
 
3
- export default function NavLink({ active = false, className = '', children, ...props }: InertiaLinkProps & { active: boolean }) {
4
- return (
5
- <Link
6
- {...props}
7
- className={
8
- 'inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium leading-5 transition duration-150 ease-in-out focus:outline-none ' +
9
- (active
10
- ? 'border-indigo-400 dark:border-indigo-600 text-gray-900 dark:text-gray-100 focus:border-indigo-700 '
11
- : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 ') +
12
- className
13
- }
14
- >
15
- {children}
16
- </Link>
17
- );
3
+ export default function NavLink({
4
+ active = false,
5
+ className = '',
6
+ children,
7
+ ...props
8
+ }: InertiaLinkProps & { active: boolean }) {
9
+ return (
10
+ <Link
11
+ {...props}
12
+ className={
13
+ 'inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium leading-5 transition duration-150 ease-in-out focus:outline-none ' +
14
+ (active
15
+ ? 'border-indigo-400 dark:border-indigo-600 text-gray-900 dark:text-gray-100 focus:border-indigo-700 '
16
+ : 'border-transparent text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 hover:border-gray-300 dark:hover:border-gray-700 focus:text-gray-700 dark:focus:text-gray-300 focus:border-gray-300 dark:focus:border-gray-700 ') +
17
+ className
18
+ }
19
+ >
20
+ {children}
21
+ </Link>
22
+ )
18
23
  }
@@ -1,17 +1,22 @@
1
- import { ButtonHTMLAttributes } from 'react';
1
+ import { ButtonHTMLAttributes } from 'react'
2
2
 
3
- export default function PrimaryButton({ className = '', disabled, children, ...props }: ButtonHTMLAttributes<HTMLButtonElement>) {
4
- return (
5
- <button
6
- {...props}
7
- className={
8
- `inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 ${
9
- disabled && 'opacity-25'
10
- } ` + className
11
- }
12
- disabled={disabled}
13
- >
14
- {children}
15
- </button>
16
- );
3
+ export default function PrimaryButton({
4
+ className = '',
5
+ disabled,
6
+ children,
7
+ ...props
8
+ }: ButtonHTMLAttributes<HTMLButtonElement>) {
9
+ return (
10
+ <button
11
+ {...props}
12
+ className={
13
+ `inline-flex items-center px-4 py-2 bg-gray-800 dark:bg-gray-200 border border-transparent rounded-md font-semibold text-xs text-white dark:text-gray-800 uppercase tracking-widest hover:bg-gray-700 dark:hover:bg-white focus:bg-gray-700 dark:focus:bg-white active:bg-gray-900 dark:active:bg-gray-300 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2 dark:focus:ring-offset-gray-800 transition ease-in-out duration-150 ${
14
+ disabled && 'opacity-25'
15
+ } ` + className
16
+ }
17
+ disabled={disabled}
18
+ >
19
+ {children}
20
+ </button>
21
+ )
17
22
  }
@@ -1,16 +1,21 @@
1
- import { Link, InertiaLinkProps } from '@inertiajs/react';
1
+ import { Link, InertiaLinkProps } from '@inertiajs/react'
2
2
 
3
- export default function ResponsiveNavLink({ active = false, className = '', children, ...props }: InertiaLinkProps & { active?: boolean }) {
4
- return (
5
- <Link
6
- {...props}
7
- className={`w-full flex items-start ps-3 pe-4 py-2 border-l-4 ${
8
- active
9
- ? 'border-indigo-400 dark:border-indigo-600 text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300'
10
- : 'border-transparent text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600'
11
- } text-base font-medium focus:outline-none transition duration-150 ease-in-out ${className}`}
12
- >
13
- {children}
14
- </Link>
15
- );
3
+ export default function ResponsiveNavLink({
4
+ active = false,
5
+ className = '',
6
+ children,
7
+ ...props
8
+ }: InertiaLinkProps & { active?: boolean }) {
9
+ return (
10
+ <Link
11
+ {...props}
12
+ className={`w-full flex items-start ps-3 pe-4 py-2 border-l-4 ${
13
+ active
14
+ ? 'border-indigo-400 dark:border-indigo-600 text-indigo-700 dark:text-indigo-300 bg-indigo-50 dark:bg-indigo-900/50 focus:text-indigo-800 dark:focus:text-indigo-200 focus:bg-indigo-100 dark:focus:bg-indigo-900 focus:border-indigo-700 dark:focus:border-indigo-300'
15
+ : 'border-transparent text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 hover:bg-gray-50 dark:hover:bg-gray-700 hover:border-gray-300 dark:hover:border-gray-600 focus:text-gray-800 dark:focus:text-gray-200 focus:bg-gray-50 dark:focus:bg-gray-700 focus:border-gray-300 dark:focus:border-gray-600'
16
+ } text-base font-medium focus:outline-none transition duration-150 ease-in-out ${className}`}
17
+ >
18
+ {children}
19
+ </Link>
20
+ )
16
21
  }