From 998d29690e3c3bde5ebf94f6105f1cfa75c32054 Mon Sep 17 00:00:00 2001 From: Bryce Date: Sat, 21 Oct 2023 20:08:08 -0700 Subject: [PATCH] animates with shake --- resources/public/output.css | 215 ++++++++---------- .../auto_ap/ssr/admin/transaction_rules.clj | 122 +++++----- src/clj/auto_ap/ssr/components/inputs.clj | 6 +- tailwind.config.js | 16 ++ 4 files changed, 178 insertions(+), 181 deletions(-) diff --git a/resources/public/output.css b/resources/public/output.css index 72b2faea..a0cad0e2 100644 --- a/resources/public/output.css +++ b/resources/public/output.css @@ -1147,14 +1147,14 @@ input:checked + .toggle-bg { grid-column-start: 1; } -.m-4 { - margin: 1rem; -} - .m-1 { margin: 0.25rem; } +.m-4 { + margin: 1rem; +} + .mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; @@ -1180,6 +1180,14 @@ input:checked + .toggle-bg { margin-bottom: 1rem; } +.\!mt-0 { + margin-top: 0px !important; +} + +.\!mt-1 { + margin-top: 0.25rem !important; +} + .-mb-1 { margin-bottom: -0.25rem; } @@ -1260,26 +1268,6 @@ input:checked + .toggle-bg { margin-top: 1.25rem; } -.\!mt-0 { - margin-top: 0px !important; -} - -.\!mt-3 { - margin-top: 0.75rem !important; -} - -.mt-3 { - margin-top: 0.75rem; -} - -.\!mt-1 { - margin-top: 0.25rem !important; -} - -.ml-64 { - margin-left: 16rem; -} - .block { display: block; } @@ -1352,10 +1340,6 @@ input:checked + .toggle-bg { height: 24rem; } -.h-\[calc\(100\%-1rem\)\] { - height: calc(100% - 1rem); -} - .h-full { height: 100%; } @@ -1428,14 +1412,14 @@ input:checked + .toggle-bg { width: 24rem; } -.w-full { - width: 100%; -} - .w-auto { width: auto; } +.w-full { + width: 100%; +} + .w-max { width: -moz-max-content; width: max-content; @@ -1497,6 +1481,16 @@ input:checked + .toggle-bg { flex-basis: 25%; } +.\!translate-y-0 { + --tw-translate-y: 0px !important; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important; +} + +.\!translate-y-32 { + --tw-translate-y: 8rem !important; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important; +} + .-translate-x-1\/2 { --tw-translate-x: -50%; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1532,16 +1526,6 @@ input:checked + .toggle-bg { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } -.\!translate-y-0 { - --tw-translate-y: 0px !important; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important; -} - -.\!translate-y-32 { - --tw-translate-y: 8rem !important; - transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)) !important; -} - .rotate-180 { --tw-rotate: 180deg; transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); @@ -1565,6 +1549,48 @@ input:checked + .toggle-bg { animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite; } +@keyframes shake { + 0% { + transform: translateX(0px); + } + + 12.5% { + transform: translateX(-5px); + } + + 25% { + transform: translateX(0px); + } + + 37.5% { + transform: translateX(5px); + } + + 50% { + transform: translateX(0px); + } + + 62.5% { + transform: translateX(-5px); + } + + 75% { + transform: translateX(5px); + } + + 87.5% { + transform: translateX(5px); + } + + 100% { + transform: translateX(0px); + } +} + +.animate-shake { + animation: shake 0.5s ease-out 1; +} + @keyframes spin { to { transform: rotate(360deg); @@ -1773,26 +1799,10 @@ input:checked + .toggle-bg { border-color: rgb(243 244 246 / var(--tw-divide-opacity)); } -.place-self-start { - place-self: start; -} - -.place-self-end { - place-self: end; -} - -.self-start { - align-self: flex-start; -} - .self-center { align-self: center; } -.justify-self-start { - justify-self: start; -} - .justify-self-end { justify-self: end; } @@ -1817,10 +1827,6 @@ input:checked + .toggle-bg { overflow-y: auto; } -.overflow-x-hidden { - overflow-x: hidden; -} - .truncate { overflow: hidden; text-overflow: ellipsis; @@ -2094,15 +2100,6 @@ input:checked + .toggle-bg { background-color: rgb(253 246 178 / var(--tw-bg-opacity)); } -.bg-gray-300 { - --tw-bg-opacity: 1; - background-color: rgb(209 213 219 / var(--tw-bg-opacity)); -} - -.bg-opacity-50 { - --tw-bg-opacity: 0.5; -} - .\!bg-opacity-0 { --tw-bg-opacity: 0 !important; } @@ -2115,10 +2112,18 @@ input:checked + .toggle-bg { --tw-bg-opacity: 0.5 !important; } +.bg-opacity-50 { + --tw-bg-opacity: 0.5; +} + .p-1 { padding: 0.25rem; } +.p-12 { + padding: 3rem; +} + .p-2 { padding: 0.5rem; } @@ -2139,10 +2144,6 @@ input:checked + .toggle-bg { padding: 1.5rem; } -.p-12 { - padding: 3rem; -} - .px-2 { padding-left: 0.5rem; padding-right: 0.5rem; @@ -2426,23 +2427,10 @@ input:checked + .toggle-bg { color: rgb(114 59 19 / var(--tw-text-opacity)); } -.text-gray-200 { - --tw-text-opacity: 1; - color: rgb(229 231 235 / var(--tw-text-opacity)); -} - .underline { text-decoration-line: underline; } -.opacity-0 { - opacity: 0; -} - -.opacity-100 { - opacity: 1; -} - .\!opacity-0 { opacity: 0 !important; } @@ -2451,6 +2439,14 @@ input:checked + .toggle-bg { opacity: 1 !important; } +.opacity-0 { + opacity: 0; +} + +.opacity-100 { + opacity: 1; +} + .shadow { --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color); @@ -2528,6 +2524,10 @@ input:checked + .toggle-bg { transition-duration: 100ms; } +.duration-200 { + transition-duration: 200ms; +} + .duration-300 { transition-duration: 300ms; } @@ -2540,8 +2540,8 @@ input:checked + .toggle-bg { transition-duration: 75ms; } -.duration-200 { - transition-duration: 200ms; +.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] { + transition-timing-function: cubic-bezier(.3,2.3,.6,1); } .ease-in-out { @@ -2552,10 +2552,6 @@ input:checked + .toggle-bg { transition-timing-function: cubic-bezier(0, 0, 0.2, 1); } -.ease-\[cubic-bezier\(\.3\2c 2\.3\2c \.6\2c 1\)\] { - transition-timing-function: cubic-bezier(.3,2.3,.6,1); -} - .htmx-added .fade-in { opacity: 0.0 !important; } @@ -2984,6 +2980,11 @@ input:checked + .toggle-bg { background-color: rgb(73 109 28 / var(--tw-bg-opacity)); } +.hover\:bg-neutral-100:hover { + --tw-bg-opacity: 1; + background-color: rgb(245 245 245 / var(--tw-bg-opacity)); +} + .hover\:bg-primary-100:hover { --tw-bg-opacity: 1; background-color: rgb(228 240 213 / var(--tw-bg-opacity)); @@ -2999,11 +3000,6 @@ input:checked + .toggle-bg { background-color: rgb(255 255 255 / var(--tw-bg-opacity)); } -.hover\:bg-neutral-100:hover { - --tw-bg-opacity: 1; - background-color: rgb(245 245 245 / var(--tw-bg-opacity)); -} - .hover\:text-blue-600:hover { --tw-text-opacity: 1; color: rgb(0 125 187 / var(--tw-text-opacity)); @@ -3547,18 +3543,10 @@ input:checked + .toggle-bg { display: block; } - .sm\:max-h-\[80vh\] { - max-height: 80vh; - } - .sm\:max-h-\[90vh\] { max-height: 90vh; } - .sm\:max-w-4xl { - max-width: 56rem; - } - .sm\:max-w-2xl { max-width: 42rem; } @@ -3583,10 +3571,6 @@ input:checked + .toggle-bg { } @media (min-width: 768px) { - .md\:inset-0 { - inset: 0px; - } - .md\:ml-2 { margin-left: 0.5rem; } @@ -3688,9 +3672,9 @@ input:checked + .toggle-bg { } } -.\[\&\.active\]\:bg-red-500.active { +.\[\&\.active\]\:bg-primary-300.active { --tw-bg-opacity: 1; - background-color: rgb(255 3 3 / var(--tw-bg-opacity)); + background-color: rgb(175 211 130 / var(--tw-bg-opacity)); } .\[\&\.active\]\:bg-primary-500.active { @@ -3698,11 +3682,6 @@ input:checked + .toggle-bg { background-color: rgb(121 181 46 / var(--tw-bg-opacity)); } -.\[\&\.active\]\:bg-primary-300.active { - --tw-bg-opacity: 1; - background-color: rgb(175 211 130 / var(--tw-bg-opacity)); -} - :is(.dark .\[\&\.active\]\:dark\:bg-primary-700).active { --tw-bg-opacity: 1; background-color: rgb(73 109 28 / var(--tw-bg-opacity)); diff --git a/src/clj/auto_ap/ssr/admin/transaction_rules.clj b/src/clj/auto_ap/ssr/admin/transaction_rules.clj index 99963ce0..4b285630 100644 --- a/src/clj/auto_ap/ssr/admin/transaction_rules.clj +++ b/src/clj/auto_ap/ssr/admin/transaction_rules.clj @@ -47,7 +47,8 @@ [hiccup2.core :as hiccup] [iol-ion.query :refer [ident]] [malli.core :as mc] - [auto-ap.cursor :as cursor])) + [auto-ap.cursor :as cursor] + [auto-ap.ssr.hiccup-helper :as hh])) ;; TODO with dependencies, I really don't like that you have to be ultra specific in what ;; you want to include, and generating the routes and interconnection is weird too. @@ -310,25 +311,26 @@ [{:keys [ name account-location client-locations value]}] (com/select {:options (into [["" ""]] (cond account-location - [[account-location account-location]] + [[account-location account-location]] - (seq client-locations) - (into [["Shared" "Shared"]] - (for [cl client-locations] - [cl cl])) - :else - [["Shared" "Shared"]])) - :name name + (seq client-locations) + (into [["Shared" "Shared"]] + (for [cl client-locations] + [cl cl])) + :else + [["Shared" "Shared"]])) + :name name :value value :class "w-full"})) (defn- account-typeahead* - [{:keys [name value client-id]}] + [{:keys [name value client-id x-model]}] [:div.flex.flex-col (com/typeahead-2 {:name name :placeholder "Search..." :url (str (bidi/path-for ssr-routes/only-routes :account-search) "?client-id=" client-id) :id name + :x-model x-model :value value :value-fn (some-fn :db/id identity) :content-fn (fn [value] @@ -338,9 +340,11 @@ (defn- transaction-rule-account-row* [transaction-rule account] - (com/data-grid-row {} + (com/data-grid-row {:x-data (hx/json {:accountId (or (:db/id (fc/field-value (:transaction-rule-account/account account))) + (fc/field-value (:transaction-rule-account/account account)))})} (let [account-name (fc/field-name (:transaction-rule-account/account account))] (list + (fc/with-field :db/id (com/hidden {:name (fc/field-name) :value (fc/field-value)})) @@ -349,44 +353,34 @@ {} (com/validated-field {:errors (fc/field-errors)} - [:div {:hx-trigger (hx/trigger-field-change :name "transaction-rule/client" - :from "#edit-form") - :hx-include "#edit-form" - :hx-vals (hx/vals {:name account-name}) - :hx-ext "rename-params" - :hx-rename-params-ex (hx/json {:transaction-rule/client "client-id" - :name "name" - account-name "value"}) - :hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead)) - :hx-swap "innerHTML"} - (account-typeahead* {:value (fc/field-value) - :client-id (:db/id (:transaction-rule/client transaction-rule)) - :name (fc/field-name)})]))) + [:div {:hx-trigger "changed" + :hx-target "next div" + :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" account-name) + :hx-get (str (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-account-typeahead)) + :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}] + (account-typeahead* {:value (fc/field-value) + :client-id (:db/id (:transaction-rule/client transaction-rule)) + :name (fc/field-name) + :x-model "accountId" + })))) (fc/with-field :transaction-rule-account/location (com/data-grid-cell {} (com/validated-field - {:errors (fc/field-errors)} - [:div [:div {:hx-trigger (hx/triggers - (hx/trigger-field-change :name "transaction-rule/client" - :from "#edit-form") - (hx/trigger-field-change :name account-name - :from "#edit-form")) - :hx-include "#edit-form" - :hx-vals (hx/vals {:name (fc/field-name)}) - :hx-ext "rename-params" - :hx-rename-params-ex (hx/json {"transaction-rule/client" "client-id" - account-name "account-id" - "name" "name" - (fc/field-name) "value"}) - :hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select) - :hx-swap "innerHTML"} - (location-select* {:name (fc/field-name) - :account-location (:account/location (cond->> (:transaction-rule-account/account @account) - (nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn) - '[:account/location]))) - :client-locations (:client/locations (:transaction-rule/client transaction-rule)) - :value (fc/field-value)})]]))) + {:errors (fc/field-errors) + :x-data (hx/json {:location (fc/field-value)})} + [:div {:hx-trigger "changed" + :hx-target "next *" + :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId || '', 'account-id': event.detail.accountId || ''}" (fc/field-name) ) + :hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-location-select) + :x-init "$watch('clientId', cid => $dispatch('changed', $data)); $watch('accountId', cid => $dispatch('changed', $data))"}] + (location-select* {:name (fc/field-name) + :account-location (:account/location (cond->> (:transaction-rule-account/account @account) + (nat-int? (:transaction-rule-account/account @account)) (dc/pull (dc/db conn) + '[:account/location]))) + :client-locations (:client/locations (:transaction-rule/client transaction-rule)) + :hx-model "location" + :value (fc/field-value)})))) (fc/with-field :transaction-rule-account/percentage (com/data-grid-cell {} @@ -414,9 +408,12 @@ :hx-swap "outerHTML swap:300ms" :hx-target "#modal-holder" :hx-target-400 "#form-errors .error-content" - :x-trap "true"} + :x-trap "true" + :class "group/form"} form-params) - [:fieldset {:class "hx-disable" :hx-disinherit "hx-target"} + [:fieldset {:class "hx-disable" :hx-disinherit "hx-target" + :x-data (hx/json {:clientId (or (:db/id (:transaction-rule/client entity)) + (:transaction-rule/client entity))})} (fc/start-form entity form-errors [:div.space-y-1 @@ -461,7 +458,7 @@ :class "w-96" :placeholder "Search..." :url (bidi/path-for ssr-routes/only-routes :company-search) - :id (str "form-client-search") + :x-model "clientId" :value (fc/field-value) :value-fn (some-fn :db/id identity) :content-fn (fn [c] (cond->> c @@ -472,23 +469,23 @@ (com/validated-field (-> {:label "Bank Account" :errors (fc/field-errors) - :x-show "bankAccountFilter"} + :x-show "bankAccountFilter" + } hx/alpine-appear) - [:div#bank-account-spot.w-96 {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead) - :hx-trigger (hx/trigger-field-change :name "transaction-rule/client" - :from "#edit-form") - :hx-swap "innerHTML" - :hx-ext "rename-params" - :hx-include "#edit-form" - :hx-vals (hx/vals {:name (fc/field-name)}) - :hx-rename-params-ex (cheshire/generate-string {"transaction-rule/client" "client-id" - "name" "name"})} + [:div.w-96 + [:div#bank-account-changer {:hx-get (bidi/path-for ssr-routes/only-routes :bank-account-typeahead) + :hx-trigger "changed" + :hx-target "next *" + :hx-include "#bank-account-changer" + :hx-swap "innerHTML" + + :hx-vals (format "js:{name: '%s', 'client-id': event.detail.clientId}" (fc/field-name)) + :x-init "$watch('clientId', cid => $dispatch('changed', $data))"}] + (bank-account-typeahead* {:client-id ((some-fn :db/id identity) (:transaction-rule/client entity)) :name (fc/field-name) :value (fc/field-value)})])) - - (com/field (-> {:label "Amount" :x-show "amountFilter"} hx/alpine-appear) @@ -557,7 +554,6 @@ (com/data-grid-cell {:colspan 4 :class "bg-gray-100"} [:div.flex.justify-center - (com/a-button {:hx-get (bidi/path-for ssr-routes/only-routes :admin-transaction-rule-new-account) :color :secondary @@ -583,7 +579,9 @@ [:div#form-errors (when (:errors fc/*form-errors*) [:span.error-content (com/errors {:errors (:errors fc/*form-errors*)})])] - (com/button {:color :primary :form "edit-form" :type "submit" :class "w-32"} + (com/button {:color :primary :form "edit-form" :type "submit" :class (cond-> "w-32" + (seq form-errors) (-> + (hh/add-class "animate-shake")))} "Save")])]] [:div]))) diff --git a/src/clj/auto_ap/ssr/components/inputs.clj b/src/clj/auto_ap/ssr/components/inputs.clj index e1de230a..fa9b8f88 100644 --- a/src/clj/auto_ap/ssr/components/inputs.clj +++ b/src/clj/auto_ap/ssr/components/inputs.clj @@ -80,7 +80,10 @@ c.clearChoices(); :active 0 :elements (if (:value params) [{:value ((:value-fn params first) (:value params)) :label ((:content-fn params second) (:value params))}] - [])})} + [])}) + :x-modelable "value.value" + :x-model (:x-model params) + } [:a {:class (-> (hh/add-class (or (:class params) "") default-input-classes) (hh/add-class "cursor-pointer")) "@click.prevent" "open = !open;" @@ -95,6 +98,7 @@ c.clearChoices(); (dissoc :content-fn) (dissoc :placeholder) + (dissoc :x-model) (assoc "x-ref" "hidden" :type "hidden" diff --git a/tailwind.config.js b/tailwind.config.js index b2056c91..dc5cc907 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -5,6 +5,22 @@ module.exports = { "./node_modules/flowbite/**/*.js"], theme: { extend: { + "keyframes": { + shake: { + '0%': { transform: 'translateX(0px)' }, + '12.5%': { transform: 'translateX(-5px)' }, + '25%': { transform: 'translateX(0px)' }, + '37.5%': { transform: 'translateX(5px)' }, + '50%': { transform: 'translateX(0px)' }, + '62.5%': { transform: 'translateX(-5px)' }, + '75%': { transform: 'translateX(5px)' }, + '87.5%': { transform: 'translateX(5px)' }, + '100%': { transform: 'translateX(0px)' }, + }, + }, + animation: { + 'shake': 'shake 0.5s ease-out 1', + }, "fontFamily": { "sans": ["Calibri", "ui-sans-serif", "system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica Neue", "Arial", "Noto Sans", "sans-serif", "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"]