activeadmin 4.0.0.beta2 → 4.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b52dc94714f4ab0451a27a11870164d4d9423326ef9c4b9eab899555c0cb2ece
4
- data.tar.gz: 5896f35ef16279d25de84bdd5ca94953c95119ea94eab47478cf966921f24c08
3
+ metadata.gz: e198e3bd4e5f7b52e3f191631988c775aa5f9e20f0ecfd2077f0e877b21c371d
4
+ data.tar.gz: d84fdfbd6bb62bd3b0858c8e7eabb4ccd48fa7e925f93a84515df5304d946ae0
5
5
  SHA512:
6
- metadata.gz: cd49148d1d8cd9ea69574847938e2d5e4cc025c10b1585dde009388fb481cd4bd3528f425e035d920dac4f7c6e02beec28dc66eb64a515b8619e1b29b1242000
7
- data.tar.gz: 88e26278700d4f906f44bbb601e1048c6f85b4eed501507238cee43a4b51aadc4a83868782767c6f4269b2cf664e81db89059130fd748c478b1ecff25bf494e8
6
+ metadata.gz: 8824403283f1e085cee125f52536b43de4e863d1ec481b568af7e04c169d79c4a69ff54327e9569ef78c73b3ebca64ffadffbe49fa83eec0a0606833d5ea3d73
7
+ data.tar.gz: 4f1dd3d73411c0040931c7215c423a04084f3b242048d8b6734813a8f97709d748c283d0a57c867f3a3e430ee62edbd5415f3eda665f251655d8a0022e9ca129
data/CHANGELOG.md CHANGED
@@ -1,6 +1,22 @@
1
1
  # Changelog
2
2
 
3
- ## Unreleased
3
+ [Future changelogs have moved to GitHub Releases](https://github.com/activeadmin/activeadmin/releases)
4
+
5
+ ## 3.2.0 [☰](https://github.com/activeadmin/activeadmin/compare/v3.1.0..v3.2.0)
6
+
7
+ ### Security Fixes
8
+
9
+ * Backport protect against CSV Injection. [#8167] by [@mgrunberg]
10
+
11
+ ### Enhancements
12
+
13
+ * Backport support citext column type in string filter. [#8165] by [@mgrunberg]
14
+ * Backport provide detail in DB statement timeout error for filters. [#8163] by [@mgrunberg]
15
+
16
+ ### Bug Fixes
17
+
18
+ * Backport make sure menu creation does not modify menu options. [#8166] by [@mgrunberg]
19
+ * Backport ransack error with filters when ActiveStorage is used. [#8164] by [@mgrunberg]
4
20
 
5
21
  ## 3.1.0 [☰](https://github.com/activeadmin/activeadmin/compare/v3.0.0..v3.1.0)
6
22
 
data/CONTRIBUTING.md CHANGED
@@ -92,15 +92,11 @@ A PR can only be merged into master by a maintainer if: CI is passing, approved
92
92
 
93
93
  Maintainers need to do the following to push out a release:
94
94
 
95
- * Switch to the master branch and make sure it's up to date.
96
- * Make sure you have [chandler] properly configured. Chandler is used to
97
- automatically submit github release notes from the changelog right after
98
- pushing the gem to rubygems.
99
- * Update the version in the `lib/active_admin/version.rb` file.
100
- * Run `bin/bundle` to update all gemfiles.
101
- * Update the `package.json` version. [Prerelease format is 1.0.0-beta1](https://github.com/rails/rails/blob/0d0c30e534af7f80ec8b18eb946aaa613ca30444/tasks/release.rb#L26).
102
- * Review and merge the PR. The generated changelog in the PR should include all user visible changes you intend to ship.
103
- * Run `bin/rake release` from the target branch once the PR is merged.
104
-
105
- [chandler]: https://github.com/mattbrictson/chandler#2-configure-credentials
95
+ * Create a feature branch from master and make sure it's up to date.
96
+ * Run `bin/prep-release [version]` and commit the changes. Use Ruby version format. NPM is handled automatically.
97
+ * Optional: To confirm the release contents, run `gem build` (extract contents) and `npm publish --dry-run`.
98
+ * Review and merge the PR.
99
+ * Run `bin/rake release` from the default branch once the PR is merged.
100
+ * [Create a GitHub Release](https://github.com/activeadmin/activeadmin/releases/new) by selecting the tag and generating the release notes.
101
+
106
102
  [new issue]: https://github.com/activeadmin/activeadmin/issues/new
data/UPGRADING.md ADDED
@@ -0,0 +1,226 @@
1
+ # Upgrading Guide
2
+
3
+ ## From v3 to v4 (beta)
4
+
5
+ ActiveAdmin v4 uses TailwindCSS. It has **mobile web, dark mode and RTL support** with a default theme that can be customized through partials and CSS. This release assumes `cssbundling-rails` and `importmap-rails` is installed and configured in the host app. Partials can be modified to include a different asset library, e.g. shakapacker.
6
+
7
+ **IMPORTANT**: there is **no sortable functionality for has-many forms** in this release so if needed, **do not upgrade**. We are [open to community proposals](https://github.com/activeadmin/activeadmin/discussions/new?category=ideas). The add/remove functionality for has-many forms remains supported.
8
+
9
+ These instructions assume the `cssbundling-rails` and `importmap-rails` gems are already installed and you have run their install commands in your app. If you haven't done so, please do before continuing.
10
+
11
+ Update your `Gemfile` with `gem "activeadmin", "4.0.0.beta3"` and then run `gem install activeadmin --pre`.
12
+
13
+ Now, run `rails generate active_admin:assets` to replace the old assets with the new files.
14
+
15
+ Then add the npm package and update the `build:css` script.
16
+
17
+ ```
18
+ yarn add @activeadmin/activeadmin@4.0.0-beta3
19
+ npm pkg set scripts.build:css="tailwindcss -i ./app/assets/stylesheets/active_admin.css -o ./app/assets/builds/active_admin.css --minify -c tailwind-active_admin.config.js"
20
+ ```
21
+
22
+ If you are already using Tailwind in your app, then update the `build:css` script to chain the above command to your existing one, e.g. `"tailwindcss ... && tailwindcss ..."`, so both stylesheets are generated.
23
+
24
+ Many configs have been removed (meta tags, asset registration, utility nav, etc.) that can now be modified more naturally through partials.
25
+
26
+ Open the `config/initializers/active_admin.rb` file and remove these deleted configs.
27
+
28
+ ```
29
+ site_title_link
30
+ site_title_image
31
+ logout_link_method
32
+ favicon
33
+ meta_tags
34
+ meta_tags_for_logged_out_pages
35
+ register_stylesheet
36
+ register_javascript
37
+ head
38
+ footer
39
+ use_webpacker
40
+ ```
41
+
42
+ Now, run `rails g active_admin:views` which will copy the partials to your app so you can customize if needed.
43
+
44
+ Note that the templates can and will change across releases. There are additional partials that can be copied but they are considered private so you do so at your own risk. You will have to keep those up to date per release.
45
+
46
+ **IMPORTANT**: if your project has copied any ActiveAdmin, Devise, or Kaminari templates from earlier releases, those templates must be updated from this release to avoid potential errors. Path helpers in Devise templates may require using the `main_app` proxy. The Kaminari templates have moved to `app/views/active_admin/kaminari`.
47
+
48
+ With the setup complete, please review the Breaking Changes section and resolve any that may or may not impact your integration.
49
+
50
+ ### Breaking Changes
51
+ - jQuery and jQuery UI have been removed.
52
+ - The `columns` component has been removed. Use `div`'s with Tailwind classes for modern, responsive layout.
53
+
54
+ <details>
55
+ <summary>Columns Component Migration Alternative</summary>
56
+
57
+ If you did not specify any parameters for `column` and if all you need is equal width columns, then this single component will restore that functionality for any number of columns.
58
+
59
+ ```ruby
60
+ # app/admin/components/columns.rb
61
+ class Columns < ActiveAdmin::Component
62
+ builder_method :columns
63
+
64
+ def build(*args)
65
+ super
66
+ add_class "grid auto-cols-fr grid-flow-col gap-4 mb-4"
67
+ end
68
+
69
+ def column(*args, &block)
70
+ insert_tag Arbre::HTML::Div, *args, &block
71
+ end
72
+ end
73
+ ```
74
+
75
+ Using Tailwind modifiers you can further customize the number of columns for responsive/mobile support.
76
+ </details>
77
+
78
+ - Replace `default_main_content` with `render "show_default"`.
79
+
80
+ <details>
81
+ <summary>Show Default Alternative</summary>
82
+
83
+ If block form `default_main_content do ... end` was used or looking for a partial file
84
+ alternative, then replace with existing, public methods.
85
+
86
+ ```ruby
87
+ attributes_table_for(resource) do
88
+ rows *active_admin_config.resource_columns
89
+ row :a
90
+ row :b
91
+ # ...
92
+ end
93
+ active_admin_comments_for(resource) if active_admin_config.comments?
94
+ ```
95
+ </details>
96
+
97
+ - Replace `as: :datepicker` with Formtastic's `as: :date_picker` for native HTML date input.
98
+ - Replace `active_admin_comments` with `active_admin_comments_for(resource)`.
99
+ - In a sidebar section, replace `attributes_table` with `attributes_table_for(resource)`.
100
+ - The `IndexAsBlog`, `IndexAsBlock` and `IndexAsGrid` components have been removed. Please create your own custom index-as components which remain supported.
101
+ - Batch Actions Form DSL has been replaced with Rails partial support so you can supply your own custom form and modal.
102
+
103
+ <details>
104
+ <summary>Batch Action Partial Example</summary>
105
+
106
+ Assuming a Post resource (in the default namespace) with a `mark_published` batch action, we set the partial name and a set of HTML data attributes to trigger a modal using Flowbite which is included by default.
107
+
108
+ Note that you can use any modal JS library you want as long as it can be triggered to open using data attributes. Flowbite usage is not a requirement.
109
+
110
+ ```ruby
111
+ batch_action(
112
+ :mark_published,
113
+ partial: "mark_published_batch_action",
114
+ link_html_options: {
115
+ "data-modal-target": "mark-published-modal",
116
+ "data-modal-show": "mark-published-modal"
117
+ }
118
+ ) do |ids, inputs|
119
+ # ...
120
+ end
121
+ ```
122
+
123
+ In the `app/views/admin/posts` directory, create a `_mark_published_batch_action.html.erb` partial file which will be rendered and included automatically in the posts index admin page.
124
+
125
+ Now add the modal HTML where the `id` attribute must match the data attributes supplied in the `batch_action` example. The form must have an empty `data-batch-action-form` attribute.
126
+
127
+ ```
128
+ <div id="mark-published-modal" class="hidden fixed top-0 ..." aria-hidden="true" ...>
129
+ <!-- ... other modal content --->
130
+ <%= form_tag false, "data-batch-action-form": "" do %>
131
+ <!-- Declare your form inputs. You can use a different form builder too. -->
132
+ <% end %>
133
+ </div>
134
+ ```
135
+
136
+ The `data-batch-action-form` attribute is a hook for a delegated JS event so when you submit the form, it will post and run your batch action block with the supplied form data, functioning as it did before.
137
+ </details>
138
+
139
+ - Deeply nested submenus has been reverted. Only one level nested menu, e.g. `menu parent: "Administrative"`, is supported.
140
+ - Removed `Panel#header_action` method.
141
+ - Removed `index_column` method from index table.
142
+
143
+ <details>
144
+ <summary>Implementation Example</summary>
145
+
146
+ You can re-implement this column with the following:
147
+
148
+ ```ruby
149
+ column "Number", sortable: false do |item|
150
+ @collection.offset_value + @collection.index(item) + 1
151
+ end
152
+ ```
153
+ </details>
154
+
155
+ #### Resource named methods
156
+
157
+ With the extraction to partials, resource named methods, e.g. `post` or `posts`, used in blocks for `action_item` and `sidebar` will raise an error. You must use the `resource` or `collection` public helper method instead. For example:
158
+
159
+ ```ruby
160
+ action_item :view, if: ->{ post.published? } do link_to(resource) end
161
+ sidebar :author, if: ->{ post.published? }
162
+ # The above must now change to the following:
163
+ action_item :view, if: ->{ resource.published? } do link_to(resource) end
164
+ sidebar :author, if: ->{ resource.published? }
165
+ ```
166
+
167
+ Note that `@post` can also be used here but make sure to call `authorize!` on it if using the authorization feature. The `post` usage would continue to work for `sidebar :name do ... end` content blocks because they can include Arbre but we advise using `resource` or `collection` instead where possible. This may impact other DSL's.
168
+
169
+ ### Visual Related Changes
170
+ - The `sidebar do ... end` contents and the show resource `attributes_table`, are no longer wrapped in a panel so they can be customized.
171
+ - Links in custom `action_item`'s have no default styles. Apply your own or use the library's default `action-item-button` class.
172
+ - The index table `actions dropdown: true` option will be ignored, reverting to original output.
173
+ - An `Arbre::Component` will no longer add a CSS class using the component class name by default.
174
+ - Typographic elements (other than links in main content) [are not styled by default](https://tailwindcss.com/docs/preflight). Use the `@tailwindcss/typography` plugin or apply your own CSS alternative.
175
+
176
+ ### Enhancements
177
+ - Dark mode support.
178
+ - Mobile web support. For responsive `table_for`'s, wrap them in a div with overflow for horizontal scrolling.
179
+ - Customizable admin theme, including main menu and user menu, all through partials.
180
+ - RTL support improved. Now using CSS Logical Properties.
181
+ - Kaminari templates now consolidated into a single set you can customize.
182
+ - Datepicker's now use the native HTML date input. Apply a custom datepicker of your choosing.
183
+ - Batch Actions Form DSL has been replaced with partials and form builder for more customization. Please refer to earlier example.
184
+ - The `status_tag` component now uses unique labels for `false` and `nil` values.
185
+ - Several components: `table_for`, `status_tag`, etc. now use data attributes instead of classes for metadata: status, sort direction, column, etc.
186
+ - Arbre builder methods have been reduced to the minimum so you can use elements or DSLs without clashing e.g. `header`, `footer`, `columns`, etc.
187
+ - The [app-helpers-not-reloading bug has been fixed](https://github.com/activeadmin/activeadmin/pull/8180) and the engine namespace is now isolated.
188
+
189
+ ### Localization Updates
190
+
191
+ This release includes several locale changes. Please [reivew the en.yml locale](https://github.com/activeadmin/activeadmin/blob/master/config/locales/en.yml) for the latest translations.
192
+
193
+ - The `dashboard_welcome`, `dropdown_actions`, `main_content` and `unsupported_browser` keys have been removed.
194
+ - The `active_admin.pagination` keys have been rewritten to be less verbose and include new entries: next and previous.
195
+
196
+ ```diff
197
+ - one: "Displaying <b>1</b> %{model}"
198
+ + one: "Showing <b>1</b> of <b>1</b>"
199
+ - one_page: "Displaying <b>all %{n}</b> %{model}"
200
+ + one_page: "Showing <b>all %{n}</b>"
201
+ - multiple: "Displaying %{model} <b>%{from}&nbsp;-&nbsp;%{to}</b> of <b>%{total}</b> in total"
202
+ + multiple: "Showing <b>%{from}-%{to}</b> of <b>%{total}</b>"
203
+ - multiple_without_total: "Displaying %{model} <b>%{from}&nbsp;-&nbsp;%{to}</b>"
204
+ + multiple_without_total: "Showing <b>%{from}-%{to}</b>"
205
+ - per_page: "Per page: "
206
+ + per_page: "Per page "
207
+ + previous: "Previous"
208
+ + next: "Next"
209
+ ```
210
+
211
+ - The `search_status` key contents has multiple, breaking changes:
212
+
213
+ ```diff
214
+ - headline: "Search status:"
215
+ - current_scope: "Scope:"
216
+ - current_filters: "Current filters:"
217
+ + title: "Active Search"
218
+ + title_with_scope: "Active Search for %{name}"
219
+ - no_current_filters: "None"
220
+ + no_current_filters: "No filters applied"
221
+ ```
222
+
223
+ - The value for the `status_tag.unset` key has changed from "No" to "Unknown".
224
+ - The `comments.title_content` text has been updated with an "All " prefix.
225
+ - The `comments.delete_confirmation` text has been fixed to use singular form.
226
+ - Inconsistent use of login/sign-in related terms so text now uses "Sign in", Sign out", and "Sign up" throughout.
@@ -40,7 +40,7 @@ module ActiveAdmin
40
40
  case params[:action].to_sym
41
41
  when :index
42
42
  active_admin_config.get_page_presenter(params[:action], params[:as])
43
- when :new, :edit
43
+ when :new, :edit, :create, :update
44
44
  active_admin_config.get_page_presenter(:form)
45
45
  end || super
46
46
  end
@@ -8,7 +8,7 @@
8
8
  -%>
9
9
  <% unless current_page.last? %>
10
10
  <%= link_to url, rel: 'next', remote: remote, class: "flex items-center justify-center px-2.5 py-3 h-8 leading-tight text-gray-500 dark:text-gray-400 hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-800 dark:hover:text-white rounded no-underline" do %>
11
- <span class="sr-only"><%= t('views.pagination.next').html_safe %></span>
11
+ <span class="sr-only"><%= t('active_admin.pagination.next') %></span>
12
12
  <svg class="w-2.5 h-2.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
13
13
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 9 4-4-4-4"/>
14
14
  </svg>
@@ -8,7 +8,7 @@
8
8
  -%>
9
9
  <% unless current_page.first? %>
10
10
  <%= link_to url, rel: 'prev', remote: remote, class: "flex items-center justify-center px-2.5 py-3 h-8 leading-tight text-gray-500 dark:text-gray-400 hover:bg-gray-100 hover:text-gray-700 dark:hover:bg-gray-800 dark:hover:text-white rounded no-underline" do %>
11
- <span class="sr-only"><%= t('views.pagination.previous').html_safe %></span>
11
+ <span class="sr-only"><%= t('active_admin.pagination.previous') %></span>
12
12
  <svg class="w-2.5 h-2.5 rtl:rotate-180" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 6 10">
13
13
  <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 1 1 5l4 4"/>
14
14
  </svg>
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+ pin "flowbite", preload: true # downloaded from https://cdnjs.cloudflare.com/ajax/libs/flowbite/2.2.1/flowbite.min.js
3
+ pin "@rails/ujs", to: "rails_ujs_esm.js", preload: true # downloaded from https://cdn.jsdelivr.net/npm/@rails/ujs@7.1.2/+esm
4
+ pin "active_admin", to: "active_admin.js", preload: true
5
+ pin_all_from File.expand_path("../app/javascript/active_admin", __dir__), under: "active_admin", preload: true
@@ -1,8 +1,4 @@
1
1
  en:
2
- views:
3
- pagination:
4
- previous: "Previous"
5
- next: "Next"
6
2
  activerecord:
7
3
  models:
8
4
  comment:
@@ -68,6 +64,8 @@ en:
68
64
  multiple: "Showing <b>%{from}-%{to}</b> of <b>%{total}</b>"
69
65
  multiple_without_total: "Showing <b>%{from}-%{to}</b>"
70
66
  per_page: "Per page "
67
+ previous: "Previous"
68
+ next: "Next"
71
69
  entry:
72
70
  one: "entry"
73
71
  other: "entries"
@@ -1,8 +1,4 @@
1
1
  fr:
2
- views:
3
- pagination:
4
- previous: "Précédent"
5
- next: "Suivant"
6
2
  activerecord:
7
3
  models:
8
4
  comment:
@@ -65,6 +61,8 @@ fr:
65
61
  multiple: "Affichage de <b>%{from}-%{to}</b> sur <b>%{total}</b>"
66
62
  multiple_without_total: "Affichage de <b>%{from}-%{to}</b>"
67
63
  per_page: "Par page "
64
+ previous: "Précédent"
65
+ next: "Suivant"
68
66
  entry:
69
67
  one: "entrée"
70
68
  other: "entrées"
@@ -1,8 +1,4 @@
1
1
  nl:
2
- views:
3
- pagination:
4
- previous: "Vorige"
5
- next: "Volgende"
6
2
  active_admin:
7
3
  dashboard: Dashboard
8
4
  view: "Bekijk"
@@ -52,6 +48,8 @@ nl:
52
48
  multiple: "Toont <b>%{from}-%{to}</b> van <b>%{total}</b>"
53
49
  multiple_without_total: "Toont <b>%{from}-%{to}</b>"
54
50
  per_page: "Per pagina: "
51
+ previous: "Vorige"
52
+ next: "Volgende"
55
53
  entry:
56
54
  one: "entry"
57
55
  other: "entries"
@@ -15,7 +15,10 @@ module ActiveAdmin
15
15
  end
16
16
  end
17
17
 
18
- initializer "active_admin.importmap", before: "importmap" do |app|
18
+ initializer "active_admin.importmap", after: "importmap" do |app|
19
+ # Skip if importmap-rails is not installed
20
+ next unless app.config.respond_to?(:importmap)
21
+
19
22
  ActiveAdmin.importmap.draw(Engine.root.join("config", "importmap.rb"))
20
23
  package_path = Engine.root.join("app/javascript")
21
24
  if app.config.respond_to?(:assets)
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module ActiveAdmin
3
- VERSION = "4.0.0.beta2"
3
+ VERSION = "4.0.0.beta4"
4
4
  end
data/lib/active_admin.rb CHANGED
@@ -9,6 +9,12 @@ require "formtastic_i18n"
9
9
  require "inherited_resources"
10
10
  require "arbre"
11
11
 
12
+ begin
13
+ require "importmap-rails"
14
+ rescue LoadError
15
+ # importmap-rails is optional
16
+ end
17
+
12
18
  module ActiveAdmin
13
19
 
14
20
  autoload :VERSION, "active_admin/version"
@@ -57,7 +63,6 @@ module ActiveAdmin
57
63
  end
58
64
 
59
65
  def importmap
60
- require "importmap-rails"
61
66
  @importmap ||= Importmap::Map.new
62
67
  end
63
68
 
@@ -16,8 +16,12 @@ module ActiveAdmin
16
16
  @attributes ||= class_name.constantize.new.attributes.keys
17
17
  end
18
18
 
19
+ def primary_key
20
+ @primary_key ||= [class_name.constantize.primary_key].flatten
21
+ end
22
+
19
23
  def assignable_attributes
20
- @assignable_attributes ||= attributes - %w(id created_at updated_at)
24
+ @assignable_attributes ||= attributes - primary_key - %w(created_at updated_at)
21
25
  end
22
26
 
23
27
  def permit_params
@@ -33,7 +37,7 @@ module ActiveAdmin
33
37
  end
34
38
 
35
39
  def columns
36
- attributes.map { |a| column(a) }.join("\n ")
40
+ (attributes - primary_key).map { |a| column(a) }.join("\n ")
37
41
  end
38
42
 
39
43
  def column(name)
data/plugin.js ADDED
@@ -0,0 +1,550 @@
1
+ const plugin = require('tailwindcss/plugin')
2
+ const defaultTheme = require('tailwindcss/defaultTheme');
3
+ const colors = require('tailwindcss/colors');
4
+ const { spacing, borderWidth, borderRadius } = defaultTheme;
5
+
6
+ // https://github.com/tailwindlabs/tailwindcss/discussions/9336
7
+ // https://github.com/tailwindlabs/tailwindcss/discussions/2049
8
+ // https://github.com/tailwindlabs/tailwindcss/discussions/2049#discussioncomment-45546
9
+
10
+ const svgToTinyDataUri = (() => {
11
+ // Source: https://github.com/tigt/mini-svg-data-uri
12
+ const reWhitespace = /\s+/g,
13
+ reUrlHexPairs = /%[\dA-F]{2}/g,
14
+ hexDecode = { '%20': ' ', '%3D': '=', '%3A': ':', '%2F': '/' },
15
+ specialHexDecode = match => hexDecode[match] || match.toLowerCase(),
16
+ svgToTinyDataUri = svg => {
17
+ svg = String(svg);
18
+ if (svg.charCodeAt(0) === 0xfeff) svg = svg.slice(1);
19
+ svg = svg
20
+ .trim()
21
+ .replace(reWhitespace, ' ')
22
+ .replaceAll('"', '\'');
23
+ svg = encodeURIComponent(svg);
24
+ svg = svg.replace(reUrlHexPairs, specialHexDecode);
25
+ return 'data:image/svg+xml,' + svg;
26
+ };
27
+ svgToTinyDataUri.toSrcset = svg => svgToTinyDataUri(svg).replace(/ /g, '%20');
28
+ return svgToTinyDataUri;
29
+ })();
30
+
31
+ module.exports = plugin(
32
+ function({ addBase, addComponents, theme }) {
33
+ addBase({
34
+ [[
35
+ "[type='text']",
36
+ "[type='email']",
37
+ "[type='url']",
38
+ "[type='password']",
39
+ "[type='number']",
40
+ "[type='date']",
41
+ "[type='datetime-local']",
42
+ "[type='month']",
43
+ "[type='search']",
44
+ "[type='tel']",
45
+ "[type='time']",
46
+ "[type='week']",
47
+ '[multiple]',
48
+ 'textarea',
49
+ 'select',
50
+ ]]: {
51
+ appearance: 'none',
52
+ 'background-color': '#fff',
53
+ 'border-color': theme('colors.gray.500', colors.gray[500]),
54
+ 'border-width': borderWidth['DEFAULT'],
55
+ 'border-radius': borderRadius.none,
56
+ 'padding-top': spacing[2],
57
+ 'padding-right': spacing[3],
58
+ 'padding-bottom': spacing[2],
59
+ 'padding-left': spacing[3],
60
+ '--tw-shadow': '0 0 #0000',
61
+ '&:focus': {
62
+ outline: '2px solid transparent',
63
+ 'outline-offset': '2px',
64
+ '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
65
+ '--tw-ring-offset-width': '0px',
66
+ '--tw-ring-offset-color': '#fff',
67
+ '--tw-ring-color': theme(
68
+ 'colors.blue.600',
69
+ colors.blue[600]
70
+ ),
71
+ '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`,
72
+ '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)`,
73
+ 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`,
74
+ 'border-color': theme('colors.blue.600', colors.blue[600]),
75
+ },
76
+ },
77
+ [['input::placeholder', 'textarea::placeholder']]: {
78
+ color: theme('colors.gray.500', colors.gray[500]),
79
+ opacity: '1',
80
+ },
81
+ ['::-webkit-datetime-edit']: {
82
+ display: 'inline-flex',
83
+ },
84
+ [[
85
+ '::-webkit-datetime-edit',
86
+ '::-webkit-datetime-edit-year-field',
87
+ '::-webkit-datetime-edit-month-field',
88
+ '::-webkit-datetime-edit-day-field',
89
+ '::-webkit-datetime-edit-hour-field',
90
+ '::-webkit-datetime-edit-minute-field',
91
+ '::-webkit-datetime-edit-second-field',
92
+ '::-webkit-datetime-edit-millisecond-field',
93
+ '::-webkit-datetime-edit-meridiem-field',
94
+ ]]: {
95
+ 'padding-bottom': '0',
96
+ 'padding-top': '0',
97
+ },
98
+ ['::-webkit-date-and-time-value']: {
99
+ 'min-height': '1.5em',
100
+ 'text-align': 'inherit',
101
+ },
102
+ ['select']: {
103
+ 'background-image': `url("${svgToTinyDataUri(
104
+ `<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
105
+ <path stroke="${theme('colors.gray.500', colors.gray[500])}" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
106
+ </svg>`
107
+ )}")`,
108
+ 'background-position': `right ${spacing[3]} center`,
109
+ 'background-repeat': `no-repeat`,
110
+ 'background-size': `0.75em 0.75em`,
111
+ 'padding-inline-end': spacing[8],
112
+ 'print-color-adjust': `exact`,
113
+ },
114
+ [':is(:where([dir=rtl]) select)']: {
115
+ 'background-position': `left ${spacing[3]} center`,
116
+ },
117
+ ['[multiple]']: {
118
+ 'background-image': 'initial',
119
+ 'background-position': 'initial',
120
+ 'background-repeat': 'unset',
121
+ 'background-size': 'initial',
122
+ 'padding-inline-end': spacing[3],
123
+ 'print-color-adjust': 'unset',
124
+ },
125
+ [[`[type='checkbox']`, `[type='radio']`]]: {
126
+ appearance: 'none',
127
+ padding: '0',
128
+ 'print-color-adjust': 'exact',
129
+ display: 'inline-block',
130
+ 'vertical-align': 'middle',
131
+ 'background-origin': 'border-box',
132
+ 'user-select': 'none',
133
+ 'flex-shrink': '0',
134
+ height: spacing[4],
135
+ width: spacing[4],
136
+ color: theme('colors.blue.600', colors.blue[600]),
137
+ 'background-color': '#fff',
138
+ 'border-color': theme('colors.gray.500', colors.gray[500]),
139
+ 'border-width': borderWidth['DEFAULT'],
140
+ '--tw-shadow': '0 0 #0000',
141
+ },
142
+ [`[type='checkbox']`]: {
143
+ 'border-radius': borderRadius['none'],
144
+ },
145
+ [`[type='radio']`]: {
146
+ 'border-radius': '100%',
147
+ },
148
+ [[`[type='checkbox']:focus`, `[type='radio']:focus`]]: {
149
+ outline: '2px solid transparent',
150
+ 'outline-offset': '2px',
151
+ '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
152
+ '--tw-ring-offset-width': '2px',
153
+ '--tw-ring-offset-color': '#fff',
154
+ '--tw-ring-color': theme('colors.blue.600', colors.blue[600]),
155
+ '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`,
156
+ '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)`,
157
+ 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`,
158
+ },
159
+ [[
160
+ `[type='checkbox']:checked`,
161
+ `[type='radio']:checked`,
162
+ `.dark [type='checkbox']:checked`,
163
+ `.dark [type='checkbox']:indeterminate`,
164
+ `.dark [type='radio']:checked`,
165
+ ]]: {
166
+ 'border-color': `transparent`,
167
+ 'background-color': `currentColor`,
168
+ 'background-size': `0.65rem 0.65rem`,
169
+ 'background-position': `center`,
170
+ 'background-repeat': `no-repeat`,
171
+ },
172
+ [`[type='checkbox']:checked`]: {
173
+ 'background-image': `url("${svgToTinyDataUri(
174
+ `<svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 12">
175
+ <path stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="3" d="M1 5.917 5.724 10.5 15 1.5"/>
176
+ </svg>`
177
+ )}")`,
178
+ 'background-repeat': `no-repeat`,
179
+ 'background-size': `0.65rem 0.65rem`,
180
+ 'print-color-adjust': `exact`,
181
+ },
182
+ [`[type='radio']:checked`]: {
183
+ 'background-image': `url("${svgToTinyDataUri(
184
+ `<svg viewBox="0 0 16 16" fill="white" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" r="3"/></svg>`
185
+ )}")`,
186
+ 'background-size': `1rem 1rem`,
187
+ },
188
+ [`.dark [type='radio']:checked`]: {
189
+ 'background-image': `url("${svgToTinyDataUri(
190
+ `<svg viewBox="0 0 16 16" fill="white" xmlns="http://www.w3.org/2000/svg"><circle cx="8" cy="8" r="3"/></svg>`
191
+ )}")`,
192
+ 'background-size': `1rem 1rem`,
193
+ },
194
+ [`[type='checkbox']:indeterminate`]: {
195
+ 'background-image': `url("${svgToTinyDataUri(
196
+ `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16"><path stroke="white" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M2 8h12"/></svg>`
197
+ )}")`,
198
+ 'background-color': `currentColor`,
199
+ 'border-color': `transparent`,
200
+ 'background-position': `center`,
201
+ 'background-repeat': `no-repeat`,
202
+ 'background-size': `.65rem .65rem`,
203
+ 'print-color-adjust': `exact`,
204
+ },
205
+ [[
206
+ `[type='checkbox']:indeterminate:hover`,
207
+ `[type='checkbox']:indeterminate:focus`,
208
+ ]]: {
209
+ 'border-color': 'transparent',
210
+ 'background-color': 'currentColor',
211
+ },
212
+ [`[type='file']`]: {
213
+ background: 'unset',
214
+ 'border-color': 'inherit',
215
+ 'border-width': '0',
216
+ 'border-radius': '0',
217
+ padding: '0',
218
+ 'font-size': 'unset',
219
+ 'line-height': 'inherit',
220
+ },
221
+ [`[type='file']:focus`]: {
222
+ outline: `1px auto inherit`,
223
+ },
224
+ [[`input[type=file]::file-selector-button`]]: {
225
+ color: 'white',
226
+ background: theme('colors.gray.800', colors.gray[800]),
227
+ border: 0,
228
+ 'font-weight': theme('fontWeight.medium'),
229
+ 'font-size': theme('fontSize.sm'),
230
+ cursor: 'pointer',
231
+ 'padding-top': spacing[2.5],
232
+ 'padding-bottom': spacing[2.5],
233
+ 'padding-inline-start': spacing[8],
234
+ 'padding-inline-end': spacing[4],
235
+ 'margin-inline-start': '-1rem',
236
+ 'margin-inline-end': '1rem',
237
+ '&:hover': {
238
+ background: theme('colors.gray.700', colors.gray[700]),
239
+ },
240
+ },
241
+ [[`.dark input[type=file]::file-selector-button`]]: {
242
+ color: 'white',
243
+ background: theme('colors.gray.600', colors.gray[600]),
244
+ '&:hover': {
245
+ background: theme('colors.gray.500', colors.gray[500]),
246
+ },
247
+ },
248
+ [['.tooltip-arrow', '.tooltip-arrow:before']]: {
249
+ position: 'absolute',
250
+ width: '8px',
251
+ height: '8px',
252
+ background: 'inherit',
253
+ },
254
+ ['.tooltip-arrow']: {
255
+ visibility: 'hidden',
256
+ },
257
+ ['.tooltip-arrow:before']: {
258
+ content: '""',
259
+ visibility: 'visible',
260
+ transform: 'rotate(45deg)',
261
+ },
262
+ [`.tooltip[data-popper-placement^='top'] > .tooltip-arrow`]: {
263
+ bottom: '-4px',
264
+ },
265
+ [`.tooltip[data-popper-placement^='bottom'] > .tooltip-arrow`]: {
266
+ top: '-4px',
267
+ },
268
+ [`.tooltip[data-popper-placement^='left'] > .tooltip-arrow`]: {
269
+ right: '-4px',
270
+ },
271
+ [`.tooltip[data-popper-placement^='right'] > .tooltip-arrow`]: {
272
+ left: '-4px',
273
+ },
274
+ ['.tooltip.invisible > .tooltip-arrow:before']: {
275
+ visibility: 'hidden',
276
+ },
277
+ [['[data-popper-arrow]', '[data-popper-arrow]:before']]: {
278
+ position: 'absolute',
279
+ width: '8px',
280
+ height: '8px',
281
+ background: 'inherit',
282
+ },
283
+ ['[data-popper-arrow]']: {
284
+ visibility: 'hidden',
285
+ },
286
+ ['[data-popper-arrow]:before']: {
287
+ content: '""',
288
+ visibility: 'visible',
289
+ transform: 'rotate(45deg)',
290
+ },
291
+ [`[data-popover][role="tooltip"][data-popper-placement^='top'] > [data-popper-arrow]`]:
292
+ {
293
+ bottom: '-5px',
294
+ },
295
+ [`[data-popover][role="tooltip"][data-popper-placement^='bottom'] > [data-popper-arrow]`]:
296
+ {
297
+ top: '-5px',
298
+ },
299
+ [`[data-popover][role="tooltip"][data-popper-placement^='left'] > [data-popper-arrow]`]:
300
+ {
301
+ right: '-5px',
302
+ },
303
+ [`[data-popover][role="tooltip"][data-popper-placement^='right'] > [data-popper-arrow]`]:
304
+ {
305
+ left: '-5px',
306
+ },
307
+ ['[role="tooltip"].invisible > [data-popper-arrow]:before']: {
308
+ visibility: 'hidden',
309
+ },
310
+ '[type=checkbox]': {
311
+ '@apply w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600': {}
312
+ },
313
+ '[type=radio]': {
314
+ '@apply w-4 h-4 border-gray-300 focus:ring-2 focus:ring-blue-300 dark:focus:ring-blue-600 dark:focus:bg-blue-600 dark:bg-gray-700 dark:border-gray-600': {}
315
+ },
316
+ [['[type=date]', '[type=email]', '[type=number]', '[type=password]', '[type=tel]', '[type=text]', '[type=time]', '[type=url]', 'select', 'textarea']]: {
317
+ '@apply bg-gray-50 border border-gray-300 text-gray-900 rounded-md focus:ring-blue-500 focus:border-blue-500 w-full dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500': {}
318
+ },
319
+ 'a': {
320
+ '@apply text-blue-600 underline underline-offset-[.2rem]': {}
321
+ },
322
+ });
323
+ addComponents({
324
+ '.action-item-button': {
325
+ '@apply py-2 px-3 text-sm font-medium no-underline text-gray-900 focus:outline-none bg-white rounded-md border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700': {}
326
+ },
327
+ '.index-data-table-toolbar': {
328
+ '@apply flex flex-col lg:flex-row gap-4 mb-4': {}
329
+ },
330
+ '.scopes': {
331
+ '@apply flex flex-wrap gap-1.5': {}
332
+ },
333
+ '.index-button-group': {
334
+ '@apply inline-flex flex-wrap items-stretch rounded-md': {}
335
+ },
336
+ // Prevent double borders when buttons are next to each other
337
+ '.index-button-group > :where(*:not(:first-child))': {
338
+ '@apply -ms-px my-0': {}
339
+ },
340
+ '.index-button': {
341
+ '@apply inline-flex items-center justify-center px-3 py-2 text-sm font-medium no-underline text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 first:rounded-s-md last:rounded-e-md dark:bg-gray-900 dark:border-gray-700 dark:text-gray-100 dark:hover:text-gray-200 dark:hover:bg-gray-800 dark:focus:ring-blue-500 dark:focus:text-white': {}
342
+ },
343
+ '.index-button-selected': {
344
+ '@apply bg-gray-100 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-800': {}
345
+ },
346
+ '.scopes-count': {
347
+ '@apply inline-flex items-center justify-center rounded-full bg-indigo-200/80 text-indigo-800 dark:bg-indigo-800 dark:text-indigo-200 px-1.5 py-1 text-xs font-normal ms-2 leading-none': {}
348
+ },
349
+ '.paginated-collection': {
350
+ '@apply border border-gray-200 dark:border-gray-800 rounded-md shadow-sm overflow-hidden': {}
351
+ },
352
+ '.paginated-collection-contents': {
353
+ '@apply overflow-x-auto': {}
354
+ },
355
+ '.paginated-collection-pagination': {
356
+ '@apply p-2 lg:p-3 flex flex-col-reverse lg:flex-row gap-4 items-center justify-between': {}
357
+ },
358
+ '.paginated-collection-footer': {
359
+ '@apply p-3 flex gap-2 items-center justify-between text-sm border-t border-gray-200 dark:border-gray-800': {}
360
+ },
361
+ '.pagination-per-page': {
362
+ '@apply text-sm py-1 pe-7 w-auto w-min': {}
363
+ },
364
+ '.index-as-table': {
365
+ '@apply relative overflow-x-auto': {}
366
+ },
367
+ '.data-table': {
368
+ '@apply w-full text-sm text-gray-800 dark:text-gray-300': {}
369
+ },
370
+ '.data-table :where(thead > tr > th)': {
371
+ '@apply px-3 py-3.5 whitespace-nowrap font-semibold text-start text-xs uppercase border-b text-gray-700 bg-gray-50 dark:bg-gray-950/50 dark:border-gray-800 dark:text-white': {}
372
+ },
373
+ '.data-table :where(thead > tr > th > a)': {
374
+ '@apply text-inherit no-underline inline-flex items-center gap-2': {}
375
+ },
376
+ '.data-table-sorted-icon': {
377
+ '@apply invisible w-[8px] h-[5px]': {}
378
+ },
379
+ ':where(th[data-sort-direction]) .data-table-sorted-icon': {
380
+ '@apply visible': {}
381
+ },
382
+ ':where(th[data-sort-direction="asc"]) .data-table-sorted-icon': {
383
+ '@apply rotate-180': {}
384
+ },
385
+ '.data-table :where(tbody > tr)': {
386
+ '@apply border-b dark:border-gray-800': {}
387
+ },
388
+ '.data-table :where(td)': {
389
+ '@apply px-3 py-4': {}
390
+ },
391
+ '.data-table-resource-actions': {
392
+ '@apply flex gap-2': {}
393
+ },
394
+ '.filters-form': {
395
+ '@apply text-sm mb-6': {}
396
+ },
397
+ '.filters-form-title': {
398
+ '@apply text-gray-700 dark:text-gray-200 font-bold text-lg mb-4': {}
399
+ },
400
+ '.filters-form :where(.label)': {
401
+ '@apply block mb-1.5 text-sm': {}
402
+ },
403
+ '.filters-form-input-group': {
404
+ '@apply grid grid-cols-2 gap-2': {}
405
+ },
406
+ '.filters-form-field': {
407
+ '@apply mb-4': {}
408
+ },
409
+ '.filters-form-field :where(.choices > label)': {
410
+ '@apply flex gap-2 items-center mb-1': {}
411
+ },
412
+ '.filters-form-buttons': {
413
+ '@apply flex gap-2 items-center': {}
414
+ },
415
+ '.filters-form-submit': {
416
+ '@apply min-w-[6rem] font-bold text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-md px-3 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 cursor-pointer': {}
417
+ },
418
+ '.filters-form-clear': {
419
+ '@apply rounded-md px-3 py-2 font-semibold text-gray-700 hover:bg-gray-100 no-underline dark:text-gray-400 dark:hover:bg-inherit dark:hover:text-gray-100 dark:focus:ring-blue-800': {}
420
+ },
421
+ '.active-filters-title': {
422
+ '@apply text-gray-700 dark:text-gray-200 font-bold text-lg mb-4': {}
423
+ },
424
+ '.active-filters-list': {
425
+ '@apply ps-5 list-disc space-y-1 text-gray-700 dark:text-gray-200': {}
426
+ },
427
+ '.batch-actions-dropdown': {
428
+ '@apply relative': {}
429
+ },
430
+ '.batch-actions-dropdown-toggle': {
431
+ '@apply transition-opacity rounded-md inline-flex items-center justify-center gap-2 px-3 py-2 text-sm font-medium text-gray-900 bg-white border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:hover:text-white dark:hover:bg-gray-600 dark:focus:ring-blue-500 dark:focus:text-white disabled:text-gray-400 disabled:border-gray-200/70 dark:disabled:bg-gray-900 dark:disabled:text-gray-700 dark:disabled:border-gray-800 disabled:pointer-events-none': {}
432
+ },
433
+ '.batch-actions-dropdown-arrow': {
434
+ '@apply w-2.5 h-2.5': {}
435
+ },
436
+ '.batch-actions-dropdown-menu': {
437
+ '@apply z-10 hidden min-w-[7rem] bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none dark:bg-gray-700 py-1 text-sm text-gray-700 dark:text-gray-200': {}
438
+ },
439
+ '.batch-actions-dropdown-menu :where(li > a)': {
440
+ '@apply block px-2.5 py-2 no-underline text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-white dark:hover:bg-gray-600 dark:hover:text-white': {}
441
+ },
442
+ '.panel': {
443
+ '@apply mb-6 border border-gray-200 rounded-md shadow-sm dark:border-gray-800': {}
444
+ },
445
+ '.panel-title': {
446
+ '@apply font-bold bg-gray-100 dark:bg-gray-900 rounded-t-md p-3': {}
447
+ },
448
+ '.panel-body': {
449
+ '@apply py-5 px-3': {}
450
+ },
451
+ '.attributes-table': {
452
+ '@apply overflow-hidden mb-6 border border-gray-200 rounded-md shadow-sm dark:border-gray-800': {}
453
+ },
454
+ '.attributes-table > :where(table)': {
455
+ '@apply w-full text-sm text-gray-800 dark:text-gray-300': {}
456
+ },
457
+ '.attributes-table :where(tbody > tr)': {
458
+ '@apply border-b dark:border-gray-800': {}
459
+ },
460
+ '.attributes-table :where(tbody > tr > th)': {
461
+ '@apply w-32 sm:w-40 text-start text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-800/60 dark:text-gray-300': {}
462
+ },
463
+ '.attributes-table :where(tbody > tr > th, tbody > tr > td)': {
464
+ '@apply p-3': {}
465
+ },
466
+ '.attributes-table-empty-value': {
467
+ '@apply text-gray-400/50 dark:text-gray-700/60 text-xs uppercase font-semibold': {}
468
+ },
469
+ '.status-tag': {
470
+ '@apply bg-gray-200 text-gray-600 dark:bg-gray-700 dark:text-gray-400 inline-flex items-center rounded-full text-sm font-medium px-2.5 py-0.5 whitespace-nowrap': {}
471
+ },
472
+ '.status-tag:where([data-status=yes])': {
473
+ '@apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300': {}
474
+ },
475
+ '.tabs-nav': {
476
+ '@apply flex flex-wrap mb-2 text-sm font-medium text-center border-b border-gray-200 dark:border-gray-700': {}
477
+ },
478
+ '.tabs-nav > :where(button)': {
479
+ '@apply inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300': {}
480
+ },
481
+ '.tabs-content': {
482
+ '@apply p-4 mb-6': {}
483
+ },
484
+ // Forms
485
+ '.formtastic': {
486
+ '@apply text-sm': {}
487
+ },
488
+ '.formtastic :where(.fieldset-title, .has-many-fields-title)': {
489
+ '@apply block w-full mb-3 border-b font-bold text-lg': {}
490
+ },
491
+ '.formtastic :where(.label)': {
492
+ '@apply block mb-1.5': {}
493
+ },
494
+ '.formtastic :where(.label abbr)': {
495
+ '@apply ms-1 no-underline': {}
496
+ },
497
+ '.formtastic :where(.input)': {
498
+ '@apply py-3': {}
499
+ },
500
+ '.formtastic :where(.choice)': {
501
+ '@apply mb-1': {}
502
+ },
503
+ '.formtastic :where(.boolean label, .choice label)': {
504
+ '@apply flex gap-2 items-center': {}
505
+ },
506
+ '.formtastic :where(.fragments-group)': {
507
+ '@apply inline-flex flex-wrap gap-1': {}
508
+ },
509
+ '.formtastic :where(.fragment label)': {
510
+ '@apply sr-only': {}
511
+ },
512
+ '.formtastic :where(.inline-hints)': {
513
+ '@apply text-gray-500 mt-2': {}
514
+ },
515
+ '.formtastic :where(.errors)': {
516
+ '@apply p-4 mb-6 rounded-md space-y-2 bg-red-50 text-red-800 dark:bg-red-800 dark:text-red-300': {}
517
+ },
518
+ '.formtastic :where(.errors > li)': {
519
+ '@apply list-disc ms-4': {}
520
+ },
521
+ '.formtastic :where(.inline-errors)': {
522
+ '@apply font-bold mt-2 text-red-600 dark:text-red-300': {}
523
+ },
524
+ '.formtastic :where(.error [type=email], .error [type=number], .error [type=password], .error [type=tel], .error [type=text], .error [type=url], .error textarea)': {
525
+ '@apply border-red-500': {}
526
+ },
527
+ '.formtastic :where(.buttons, .actions)': {
528
+ '@apply mt-3': {}
529
+ },
530
+ '.formtastic :where(.actions > ol)': {
531
+ '@apply flex items-center gap-6': {}
532
+ },
533
+ '.formtastic :where([type=submit], [type=button], button)': {
534
+ '@apply font-bold text-white bg-blue-600 hover:bg-blue-700 focus:ring-4 focus:outline-none focus:ring-blue-300 rounded-lg px-4 py-2 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 cursor-pointer': {}
535
+ },
536
+ '.formtastic :where(.actions .cancel-link)': {
537
+ '@apply font-semibold leading-6 text-gray-900 dark:text-white no-underline': {}
538
+ },
539
+ '.formtastic :where(.has-many-add)': {
540
+ '@apply inline-block py-3': {}
541
+ },
542
+ '.formtastic :where(.has-many-container)': {
543
+ '@apply space-y-8': {}
544
+ },
545
+ '.formtastic :where(.has-many-fields)': {
546
+ '@apply ps-3 border-s-4 border-s-gray-200 dark:border-s-gray-700': {}
547
+ }
548
+ });
549
+ }
550
+ )
@@ -0,0 +1 @@
1
+ const t="a[data-confirm], a[data-method], a[data-remote]:not([disabled]), a[data-disable-with], a[data-disable]",e={selector:"button[data-remote]:not([form]), button[data-confirm]:not([form])",exclude:"form button"},n="select[data-remote], input[data-remote], textarea[data-remote]",a="form:not([data-turbo=true])",o="form:not([data-turbo=true]) input[type=submit], form:not([data-turbo=true]) input[type=image], form:not([data-turbo=true]) button[type=submit], form:not([data-turbo=true]) button:not([type]), input[type=submit][form], input[type=image][form], button[type=submit][form], button[form]:not([type])",r="input[data-disable-with]:enabled, button[data-disable-with]:enabled, textarea[data-disable-with]:enabled, input[data-disable]:enabled, button[data-disable]:enabled, textarea[data-disable]:enabled",i="input[data-disable-with]:disabled, button[data-disable-with]:disabled, textarea[data-disable-with]:disabled, input[data-disable]:disabled, button[data-disable]:disabled, textarea[data-disable]:disabled",u="a[data-disable-with], a[data-disable]",c="button[data-remote][data-disable-with], button[data-remote][data-disable]";let s=null;const l=()=>{const t=document.querySelector("meta[name=csp-nonce]");return s=t&&t.content},d=()=>s||l(),m=Element.prototype.matches||Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector,p=function(t,e){return e.exclude?m.call(t,e.selector)&&!m.call(t,e.exclude):m.call(t,e)},f="_ujsData",b=(t,e)=>t[f]?t[f][e]:void 0,h=function(t,e,n){return t[f]||(t[f]={}),t[f][e]=n},y=t=>Array.prototype.slice.call(document.querySelectorAll(t)),j=function(t){var e=!1;do{if(t.isContentEditable){e=!0;break}t=t.parentElement}while(t);return e},v=()=>{const t=document.querySelector("meta[name=csrf-token]");return t&&t.content},E=()=>{const t=document.querySelector("meta[name=csrf-param]");return t&&t.content},g=t=>{const e=v();if(e)return t.setRequestHeader("X-CSRF-Token",e)},w=()=>{const t=v(),e=E();if(t&&e)return y('form input[name="'+e+'"]').forEach((e=>e.value=t))},x={"*":"*/*",text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript",script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},S=t=>{t=k(t);var e=C(t,(function(){const n=T(null!=e.response?e.response:e.responseText,e.getResponseHeader("Content-Type"));return 2===Math.floor(e.status/100)?"function"==typeof t.success&&t.success(n,e.statusText,e):"function"==typeof t.error&&t.error(n,e.statusText,e),"function"==typeof t.complete?t.complete(e,e.statusText):void 0}));return!(t.beforeSend&&!t.beforeSend(e,t))&&(e.readyState===XMLHttpRequest.OPENED?e.send(t.data):void 0)};var k=function(t){return t.url=t.url||location.href,t.type=t.type.toUpperCase(),"GET"===t.type&&t.data&&(t.url.indexOf("?")<0?t.url+="?"+t.data:t.url+="&"+t.data),t.dataType in x||(t.dataType="*"),t.accept=x[t.dataType],"*"!==t.dataType&&(t.accept+=", */*; q=0.01"),t},C=function(t,e){const n=new XMLHttpRequest;return n.open(t.type,t.url,!0),n.setRequestHeader("Accept",t.accept),"string"==typeof t.data&&n.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8"),t.crossDomain||(n.setRequestHeader("X-Requested-With","XMLHttpRequest"),g(n)),n.withCredentials=!!t.withCredentials,n.onreadystatechange=function(){if(n.readyState===XMLHttpRequest.DONE)return e(n)},n},T=function(t,e){if("string"==typeof t&&"string"==typeof e)if(e.match(/\bjson\b/))try{t=JSON.parse(t)}catch(t){}else if(e.match(/\b(?:java|ecma)script\b/)){const e=document.createElement("script");e.setAttribute("nonce",d()),e.text=t,document.head.appendChild(e).parentNode.removeChild(e)}else if(e.match(/\b(xml|html|svg)\b/)){const n=new DOMParser;e=e.replace(/;.+/,"");try{t=n.parseFromString(t,e)}catch(t){}}return t};const A=function(t){const e=document.createElement("a");e.href=location.href;const n=document.createElement("a");try{return n.href=t,!((!n.protocol||":"===n.protocol)&&!n.host||e.protocol+"//"+e.host==n.protocol+"//"+n.host)}catch(t){return!0}};let D,{CustomEvent:M}=window;"function"!=typeof M&&(M=function(t,e){const n=document.createEvent("CustomEvent");return n.initCustomEvent(t,e.bubbles,e.cancelable,e.detail),n},M.prototype=window.Event.prototype,({preventDefault:D}=M.prototype),M.prototype.preventDefault=function(){const t=D.call(this);return this.cancelable&&!this.defaultPrevented&&Object.defineProperty(this,"defaultPrevented",{get:()=>!0}),t});const L=(t,e,n)=>{const a=new M(e,{bubbles:!0,cancelable:!0,detail:n});return t.dispatchEvent(a),!a.defaultPrevented},R=t=>{L(t.target,"ujs:everythingStopped"),t.preventDefault(),t.stopPropagation(),t.stopImmediatePropagation()},q=(t,e,n,a)=>t.addEventListener(n,(function(t){let{target:n}=t;for(;n instanceof Element&&!p(n,e);)n=n.parentNode;n instanceof Element&&!1===a.call(n,t)&&(t.preventDefault(),t.stopPropagation())})),H=t=>Array.prototype.slice.call(t),P=(t,e)=>{let n=[t];p(t,"form")&&(n=H(t.elements));const a=[];return n.forEach((function(t){t.name&&!t.disabled&&(p(t,"fieldset[disabled] *")||(p(t,"select")?H(t.options).forEach((function(e){e.selected&&a.push({name:t.name,value:e.value})})):(t.checked||-1===["radio","checkbox","submit"].indexOf(t.type))&&a.push({name:t.name,value:t.value})))})),e&&a.push(e),a.map((function(t){return t.name?`${encodeURIComponent(t.name)}=${encodeURIComponent(t.value)}`:t})).join("&")},O=(t,e)=>p(t,"form")?H(t.elements).filter((t=>p(t,e))):H(t.querySelectorAll(e));var I=function(t,e){let n;const a=t.getAttribute("data-confirm");if(!a)return!0;let o=!1;if(L(t,"confirm")){try{o=e.confirm(a,t)}catch(t){}n=L(t,"confirm:complete",[o])}return o&&n};const N=function(t){this.disabled&&R(t)},X=t=>{let e;if(t instanceof Event){if(K(t))return;e=t.target}else e=t;if(!j(e))return p(e,u)?F(e):p(e,c)||p(e,i)?z(e):p(e,a)?G(e):void 0},$=t=>{const e=t instanceof Event?t.target:t;if(!j(e))return p(e,u)?_(e):p(e,c)||p(e,r)?U(e):p(e,a)?Q(e):void 0};var _=function(t){if(b(t,"ujs:disabled"))return;const e=t.getAttribute("data-disable-with");return null!=e&&(h(t,"ujs:enable-with",t.innerHTML),t.innerHTML=e),t.addEventListener("click",R),h(t,"ujs:disabled",!0)},F=function(t){const e=b(t,"ujs:enable-with");return null!=e&&(t.innerHTML=e,h(t,"ujs:enable-with",null)),t.removeEventListener("click",R),h(t,"ujs:disabled",null)},Q=t=>O(t,r).forEach(U),U=function(t){if(b(t,"ujs:disabled"))return;const e=t.getAttribute("data-disable-with");return null!=e&&(p(t,"button")?(h(t,"ujs:enable-with",t.innerHTML),t.innerHTML=e):(h(t,"ujs:enable-with",t.value),t.value=e)),t.disabled=!0,h(t,"ujs:disabled",!0)},G=t=>O(t,i).forEach((t=>z(t))),z=function(t){const e=b(t,"ujs:enable-with");return null!=e&&(p(t,"button")?t.innerHTML=e:t.value=e,h(t,"ujs:enable-with",null)),t.disabled=!1,h(t,"ujs:disabled",null)},K=function(t){const e=t.detail?t.detail[0]:void 0;return e&&e.getResponseHeader("X-Xhr-Redirect")};const B=function(t){const e=this,{form:n}=e;if(n)return e.name&&h(n,"ujs:submit-button",{name:e.name,value:e.value}),h(n,"ujs:formnovalidate-button",e.formNoValidate),h(n,"ujs:submit-button-formaction",e.getAttribute("formaction")),h(n,"ujs:submit-button-formmethod",e.getAttribute("formmethod"))},J=function(t){const e=(this.getAttribute("data-method")||"GET").toUpperCase(),n=this.getAttribute("data-params"),a=(t.metaKey||t.ctrlKey)&&"GET"===e&&!n;(null!=t.button&&0!==t.button||a)&&t.stopImmediatePropagation()},V={$:y,ajax:S,buttonClickSelector:e,buttonDisableSelector:c,confirm:(t,e)=>window.confirm(t),cspNonce:d,csrfToken:v,csrfParam:E,CSRFProtection:g,delegate:q,disableElement:$,enableElement:X,fileInputSelector:"input[name][type=file]:not([disabled])",fire:L,formElements:O,formEnableSelector:i,formDisableSelector:r,formInputClickSelector:o,formSubmitButtonClick:B,formSubmitSelector:a,getData:b,handleDisabledElement:N,href:t=>t.href,inputChangeSelector:n,isCrossDomain:A,linkClickSelector:t,linkDisableSelector:u,loadCSPNonce:l,matches:p,preventInsignificantClick:J,refreshCSRFTokens:w,serializeElement:P,setData:h,stopEverything:R},W=(Y=V,function(t){I(this,Y)||R(t)});var Y;V.handleConfirm=W;const Z=(t=>function(e){const n=this,a=n.getAttribute("data-method");if(!a)return;if(j(this))return;const o=t.href(n),r=v(),i=E(),u=document.createElement("form");let c=`<input name='_method' value='${a}' type='hidden' />`;i&&r&&!A(o)&&(c+=`<input name='${i}' value='${r}' type='hidden' />`),c+='<input type="submit" />',u.method="post",u.action=o,u.target=n.target,u.innerHTML=c,u.style.display="none",document.body.appendChild(u),u.querySelector('[type="submit"]').click(),R(e)})(V);V.handleMethod=Z;const tt=(t=>function(o){let r,i,u;const c=this;if(!function(t){const e=t.getAttribute("data-remote");return null!=e&&"false"!==e}(c))return!0;if(!L(c,"ajax:before"))return L(c,"ajax:stopped"),!1;if(j(c))return L(c,"ajax:stopped"),!1;const s=c.getAttribute("data-with-credentials"),l=c.getAttribute("data-type")||"script";if(p(c,a)){const t=b(c,"ujs:submit-button");i=b(c,"ujs:submit-button-formmethod")||c.getAttribute("method")||"get",u=b(c,"ujs:submit-button-formaction")||c.getAttribute("action")||location.href,"GET"===i.toUpperCase()&&(u=u.replace(/\?.*$/,"")),"multipart/form-data"===c.enctype?(r=new FormData(c),null!=t&&r.append(t.name,t.value)):r=P(c,t),h(c,"ujs:submit-button",null),h(c,"ujs:submit-button-formmethod",null),h(c,"ujs:submit-button-formaction",null)}else p(c,e)||p(c,n)?(i=c.getAttribute("data-method"),u=c.getAttribute("data-url"),r=P(c,c.getAttribute("data-params"))):(i=c.getAttribute("data-method"),u=t.href(c),r=c.getAttribute("data-params"));S({type:i||"GET",url:u,data:r,dataType:l,beforeSend:(t,e)=>L(c,"ajax:beforeSend",[t,e])?L(c,"ajax:send",[t]):(L(c,"ajax:stopped"),!1),success:(...t)=>L(c,"ajax:success",t),error:(...t)=>L(c,"ajax:error",t),complete:(...t)=>L(c,"ajax:complete",t),crossDomain:A(u),withCredentials:null!=s&&"false"!==s}),R(o)})(V);V.handleRemote=tt;if(V.start=function(){if(window._rails_loaded)throw new Error("rails-ujs has already been loaded!");return window.addEventListener("pageshow",(function(){y(i).forEach((function(t){b(t,"ujs:disabled")&&X(t)})),y(u).forEach((function(t){b(t,"ujs:disabled")&&X(t)}))})),q(document,u,"ajax:complete",X),q(document,u,"ajax:stopped",X),q(document,c,"ajax:complete",X),q(document,c,"ajax:stopped",X),q(document,t,"click",J),q(document,t,"click",N),q(document,t,"click",W),q(document,t,"click",$),q(document,t,"click",tt),q(document,t,"click",Z),q(document,e,"click",J),q(document,e,"click",N),q(document,e,"click",W),q(document,e,"click",$),q(document,e,"click",tt),q(document,n,"change",N),q(document,n,"change",W),q(document,n,"change",tt),q(document,a,"submit",N),q(document,a,"submit",W),q(document,a,"submit",tt),q(document,a,"submit",(t=>setTimeout((()=>$(t)),13))),q(document,a,"ajax:send",$),q(document,a,"ajax:complete",X),q(document,o,"click",J),q(document,o,"click",N),q(document,o,"click",W),q(document,o,"click",B),document.addEventListener("DOMContentLoaded",w),document.addEventListener("DOMContentLoaded",l),window._rails_loaded=!0},"undefined"!=typeof jQuery&&jQuery&&jQuery.ajax){if(jQuery.rails)throw new Error("If you load both jquery_ujs and rails-ujs, use rails-ujs only.");jQuery.rails=V,jQuery.ajaxPrefilter((function(t,e,n){if(!t.crossDomain)return g(n)}))}export{V as default};
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activeadmin
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.beta2
4
+ version: 4.0.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Charles Maresh
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2024-01-06 00:00:00.000000000 Z
18
+ date: 2024-01-17 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: arbre
@@ -125,12 +125,14 @@ extra_rdoc_files:
125
125
  - CODE_OF_CONDUCT.md
126
126
  - CONTRIBUTING.md
127
127
  - README.md
128
+ - UPGRADING.md
128
129
  files:
129
130
  - CHANGELOG.md
130
131
  - CODE_OF_CONDUCT.md
131
132
  - CONTRIBUTING.md
132
133
  - LICENSE
133
134
  - README.md
135
+ - UPGRADING.md
134
136
  - app/assets/config/active_admin_manifest.js
135
137
  - app/controllers/active_admin/base_controller.rb
136
138
  - app/controllers/active_admin/base_controller/authorization.rb
@@ -201,6 +203,7 @@ files:
201
203
  - app/views/active_admin/shared/_sidebar_sections.html.erb
202
204
  - app/views/layouts/active_admin.html.erb
203
205
  - app/views/layouts/active_admin_logged_out.html.erb
206
+ - config/importmap.rb
204
207
  - config/locales/ar.yml
205
208
  - config/locales/az.yml
206
209
  - config/locales/bg.yml
@@ -359,7 +362,9 @@ files:
359
362
  - lib/generators/active_admin/resource/resource_generator.rb
360
363
  - lib/generators/active_admin/resource/templates/resource.rb.erb
361
364
  - lib/generators/active_admin/views_generator.rb
365
+ - plugin.js
362
366
  - vendor/javascript/flowbite.js
367
+ - vendor/javascript/rails_ujs_esm.js
363
368
  homepage: https://activeadmin.info
364
369
  licenses:
365
370
  - MIT