ruby_event_store-browser 2.14.0 → 2.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 40ddf557bf725810d590d3e4f46aebac4bff0abee1ec431d5a9b6aa288ea39f6
4
- data.tar.gz: 4e3c1554bc6959ad6bf8a7767baca229a8a968691343d28054c1517f69ec4f9a
3
+ metadata.gz: 9cb90a52015d1f514d68911b5c55e4f6173aa9f731d8d5996df5841b56fefd7b
4
+ data.tar.gz: bbcc7f349e97eaf69e1d4e827eb9a3439e0118305fe4528a74925f46544a8bc3
5
5
  SHA512:
6
- metadata.gz: f82a574172fae82da1aa45fff3576edf76549cb8dc8a94ac880d7b0cd211a627ada2c1fc5d7964de1c96b36305d968bc6cca119a0c63d4c983a39a4ca0736dcf
7
- data.tar.gz: 60200d7a838b660c993e931b9ae4322eb7147082d0662c8a3c1fa05410fe01ade3eb73e22bb66b4df89ac8692ceaadf0e993ff0547156442ce4c0bd768bc3431
6
+ metadata.gz: df4bcaafe58065b8da8cfe7c945cd2ebf08300b767e26f5005dd30314c6573e471e4710660826687d2cb2ca77ed3de89bd43770910a451450b3640ba2e6aa3c1
7
+ data.tar.gz: 5bb7187864197a651d79faf598ffcf80232e711f6b48191e9e75e277352ff31458d2896bfd2094e38c994e2c5ed8400f18e911773460f1a357a01a39e9daf31b
@@ -17,34 +17,47 @@ module RubyEventStore
17
17
  related_streams_query: DEFAULT_RELATED_STREAMS_QUERY
18
18
  )
19
19
  warn(<<~WARN) if environment
20
- Passing :environment to RubyEventStore::Browser::App.for is deprecated.
20
+ Passing :environment to RubyEventStore::Browser::App.for is deprecated.
21
21
 
22
- This option is no-op, has no effect and will be removed in next major release.
23
- WARN
22
+ This option is no-op, has no effect and will be removed in next major release.
23
+ WARN
24
24
  warn(<<~WARN) if host
25
- Passing :host to RubyEventStore::Browser::App.for is deprecated.
25
+ Passing :host to RubyEventStore::Browser::App.for is deprecated.
26
26
 
27
- This option will be removed in next major release.
28
-
29
- Host and mount points are correctly recognized from Rack environment
30
- and this option is redundant.
31
- WARN
27
+ This option will be removed in next major release.
28
+
29
+ Host and mount points are correctly recognized from Rack environment
30
+ and this option is redundant.
31
+ WARN
32
32
  warn(<<~WARN) if path
33
- Passing :path to RubyEventStore::Browser::App.for is deprecated.
33
+ Passing :path to RubyEventStore::Browser::App.for is deprecated.
34
34
 
35
- This option will be removed in next major release.
35
+ This option will be removed in next major release.
36
36
 
37
- Host and mount points are correctly recognized from Rack environment
38
- and this option is redundant.
39
- WARN
37
+ Host and mount points are correctly recognized from Rack environment
38
+ and this option is redundant.
39
+ WARN
40
40
 
41
41
  Rack::Builder.new do
42
42
  use Rack::Static,
43
- urls: {
44
- "/ruby_event_store_browser.js" => "ruby_event_store_browser.js",
45
- "/ruby_event_store_browser.css" => "ruby_event_store_browser.css",
46
- "/bootstrap.js" => "bootstrap.js"
47
- },
43
+ urls:
44
+ %w[
45
+ bootstrap.js
46
+ ruby_event_store_browser.css
47
+ ruby_event_store_browser.js
48
+ android-chrome-192x192.png
49
+ android-chrome-512x512.png
50
+ apple-touch-icon.png
51
+ favicon.ico
52
+ favicon-16x16.png
53
+ favicon-32x32.png
54
+ mstile-70x70.png
55
+ mstile-144x144.png
56
+ mstile-150x150.png
57
+ mstile-310x150.png
58
+ mstile-310x310.png
59
+ safari-pinned-tab.svg
60
+ ].map { |f| ["/#{f}", f] }.to_h,
48
61
  root: "#{__dir__}/../../../public"
49
62
  run App.new(
50
63
  event_store_locator: event_store_locator,
@@ -56,7 +69,13 @@ module RubyEventStore
56
69
  end
57
70
  end
58
71
 
59
- def initialize(event_store_locator:, related_streams_query:, host:, root_path:, api_url:)
72
+ def initialize(
73
+ event_store_locator:,
74
+ related_streams_query:,
75
+ host:,
76
+ root_path:,
77
+ api_url:
78
+ )
60
79
  @event_store_locator = event_store_locator
61
80
  @related_streams_query = related_streams_query
62
81
  @routing = Urls.from_configuration(host, root_path, api_url)
@@ -65,7 +84,10 @@ module RubyEventStore
65
84
  def call(env)
66
85
  router = Router.new(routing)
67
86
  router.add_route("GET", "/api/events/:event_id") do |params|
68
- json GetEvent.new(event_store: event_store, event_id: params.fetch("event_id"))
87
+ json GetEvent.new(
88
+ event_store: event_store,
89
+ event_id: params.fetch("event_id")
90
+ )
69
91
  end
70
92
  router.add_route("GET", "/api/streams/:stream_name") do |params, urls|
71
93
  json GetStream.new(
@@ -74,7 +96,10 @@ module RubyEventStore
74
96
  related_streams_query: related_streams_query
75
97
  )
76
98
  end
77
- router.add_route("GET", "/api/streams/:stream_name/relationships/events") do |params, urls|
99
+ router.add_route(
100
+ "GET",
101
+ "/api/streams/:stream_name/relationships/events"
102
+ ) do |params, urls|
78
103
  json GetEventsFromStream.new(
79
104
  event_store: event_store,
80
105
  routing: urls,
@@ -82,6 +107,7 @@ module RubyEventStore
82
107
  page: params["page"]
83
108
  )
84
109
  end
110
+
85
111
  %w[/ /events/:event_id /streams/:stream_name].each do |starting_route|
86
112
  router.add_route("GET", starting_route) do |_, urls|
87
113
  erb bootstrap_html,
@@ -116,6 +142,12 @@ module RubyEventStore
116
142
  <title>RubyEventStore::Browser</title>
117
143
  <link type="text/css" rel="stylesheet" href="<%= browser_css_src %>">
118
144
  <meta name="ruby-event-store-browser-settings" content="<%= Rack::Utils.escape_html(JSON.dump(initial_data)) %>">
145
+ <link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
146
+ <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png">
147
+ <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
148
+ <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5">
149
+ <meta name="msapplication-TileColor" content="#da532c">
150
+ <meta name="theme-color" content="#ffffff">
119
151
  </head>
120
152
  <body>
121
153
  <script type="text/javascript" src="<%= browser_js_src %>"></script>
@@ -130,11 +162,19 @@ module RubyEventStore
130
162
  end
131
163
 
132
164
  def json(body)
133
- [200, { "content-type" => "application/vnd.api+json" }, [JSON.dump(body.to_h)]]
165
+ [
166
+ 200,
167
+ { "content-type" => "application/vnd.api+json" },
168
+ [JSON.dump(body.to_h)]
169
+ ]
134
170
  end
135
171
 
136
172
  def erb(template, **locals)
137
- [200, { "content-type" => "text/html;charset=utf-8" }, [ERB.new(template).result_with_hash(locals)]]
173
+ [
174
+ 200,
175
+ { "content-type" => "text/html;charset=utf-8" },
176
+ [ERB.new(template).result_with_hash(locals)]
177
+ ]
138
178
  end
139
179
 
140
180
  def res_version
@@ -9,7 +9,9 @@ module RubyEventStore
9
9
  @path =
10
10
  load_path
11
11
  .select { |entry| String === entry }
12
- .find { |entry| entry.match? %r{ruby_event_store-browser(?:-\d+\.\d+\.\d+)?/lib\z} }
12
+ .find do |entry|
13
+ entry.match? %r{ruby_event_store-browser(?:-\d+\.\d+\.\d+)?/lib\z}
14
+ end
13
15
  end
14
16
 
15
17
  def version
@@ -20,7 +20,9 @@ module RubyEventStore
20
20
  private
21
21
 
22
22
  def streams
23
- event_store.streams_of(event_id).map { |stream| { "id" => stream.name, "type" => "streams" } }
23
+ event_store
24
+ .streams_of(event_id)
25
+ .map { |stream| { "id" => stream.name, "type" => "streams" } }
24
26
  end
25
27
 
26
28
  attr_reader :event_store, :event_id
@@ -30,7 +32,9 @@ module RubyEventStore
30
32
  end
31
33
 
32
34
  def parent_event_id
33
- event_store.read.event(event.metadata.fetch(:causation_id))&.event_id if event.metadata.has_key?(:causation_id)
35
+ if event.metadata.has_key?(:causation_id)
36
+ event_store.read.event(event.metadata.fetch(:causation_id))&.event_id
37
+ end
34
38
  end
35
39
  end
36
40
  end
@@ -47,14 +47,18 @@ module RubyEventStore
47
47
 
48
48
  def events_forward(position)
49
49
  spec = event_store.read.limit(count)
50
- spec = spec.stream(stream_name) unless stream_name.eql?(SERIALIZED_GLOBAL_STREAM_NAME)
50
+ spec = spec.stream(stream_name) unless stream_name.eql?(
51
+ SERIALIZED_GLOBAL_STREAM_NAME
52
+ )
51
53
  spec = spec.from(position) unless position.equal?(HEAD)
52
54
  spec.to_a
53
55
  end
54
56
 
55
57
  def events_backward(position)
56
58
  spec = event_store.read.limit(count).backward
57
- spec = spec.stream(stream_name) unless stream_name.eql?(SERIALIZED_GLOBAL_STREAM_NAME)
59
+ spec = spec.stream(stream_name) unless stream_name.eql?(
60
+ SERIALIZED_GLOBAL_STREAM_NAME
61
+ )
58
62
  spec = spec.from(position) unless position.equal?(HEAD)
59
63
  spec.to_a
60
64
  end
@@ -70,7 +74,12 @@ module RubyEventStore
70
74
  end
71
75
 
72
76
  def prev_page_link(event_id)
73
- routing.paginated_events_from_stream_url(id: stream_name, position: event_id, direction: :forward, count: count)
77
+ routing.paginated_events_from_stream_url(
78
+ id: stream_name,
79
+ position: event_id,
80
+ direction: :forward,
81
+ count: count
82
+ )
74
83
  end
75
84
 
76
85
  def next_page_link(event_id)
@@ -83,11 +92,21 @@ module RubyEventStore
83
92
  end
84
93
 
85
94
  def first_page_link
86
- routing.paginated_events_from_stream_url(id: stream_name, position: :head, direction: :backward, count: count)
95
+ routing.paginated_events_from_stream_url(
96
+ id: stream_name,
97
+ position: :head,
98
+ direction: :backward,
99
+ count: count
100
+ )
87
101
  end
88
102
 
89
103
  def last_page_link
90
- routing.paginated_events_from_stream_url(id: stream_name, position: :head, direction: :forward, count: count)
104
+ routing.paginated_events_from_stream_url(
105
+ id: stream_name,
106
+ position: :head,
107
+ direction: :forward,
108
+ count: count
109
+ )
91
110
  end
92
111
 
93
112
  def count
@@ -10,7 +10,14 @@ module RubyEventStore
10
10
  end
11
11
 
12
12
  def to_h
13
- { data: JsonApiStream.new(stream_name, events_from_stream_url, related_streams).to_h }
13
+ {
14
+ data:
15
+ JsonApiStream.new(
16
+ stream_name,
17
+ events_from_stream_url,
18
+ related_streams
19
+ ).to_h
20
+ }
14
21
  end
15
22
 
16
23
  private
@@ -22,7 +29,9 @@ module RubyEventStore
22
29
  end
23
30
 
24
31
  def related_streams
25
- related_streams_query.call(stream_name) unless related_streams_query.equal?(DEFAULT_RELATED_STREAMS_QUERY)
32
+ unless related_streams_query.equal?(DEFAULT_RELATED_STREAMS_QUERY)
33
+ related_streams_query.call(stream_name)
34
+ end
26
35
  end
27
36
  end
28
37
  end
@@ -14,7 +14,7 @@ module RubyEventStore
14
14
  type: "events",
15
15
  attributes: {
16
16
  event_type: event.event_type,
17
- data: event.data,
17
+ data: sanitize_infinity_values(event.data),
18
18
  metadata: metadata,
19
19
  correlation_stream_name: correlation_stream_name,
20
20
  causation_stream_name: causation_stream_name,
@@ -28,15 +28,38 @@ module RubyEventStore
28
28
 
29
29
  attr_reader :event, :parent_event_id
30
30
 
31
+ def sanitize_infinity_values(value)
32
+ case value
33
+ in Hash => hash
34
+ hash.transform_values { |v| sanitize_infinity_values(v) }
35
+ in Array => array
36
+ array.map { |v| sanitize_infinity_values(v) }
37
+ in Float => f if f.infinite?
38
+ f.positive? ? "Infinity" : "-Infinity"
39
+ in Float => f if f.nan?
40
+ "NaN"
41
+ else
42
+ value
43
+ end
44
+ end
45
+
31
46
  def metadata
32
47
  event.metadata.to_h.tap do |m|
33
- m[:timestamp] = event.metadata.fetch(:timestamp).iso8601(TIMESTAMP_PRECISION)
34
- m[:valid_at] = event.metadata.fetch(:valid_at).iso8601(TIMESTAMP_PRECISION)
48
+ m[:timestamp] = event
49
+ .metadata
50
+ .fetch(:timestamp)
51
+ .iso8601(TIMESTAMP_PRECISION)
52
+ m[:valid_at] = event
53
+ .metadata
54
+ .fetch(:valid_at)
55
+ .iso8601(TIMESTAMP_PRECISION)
35
56
  end
36
57
  end
37
58
 
38
59
  def correlation_stream_name
39
- "$by_correlation_id_#{metadata.fetch(:correlation_id)}" if metadata.has_key?(:correlation_id)
60
+ if metadata.has_key?(:correlation_id)
61
+ "$by_correlation_id_#{metadata.fetch(:correlation_id)}"
62
+ end
40
63
  end
41
64
 
42
65
  def causation_stream_name
@@ -19,7 +19,11 @@ module RubyEventStore
19
19
  return unless request.request_method.eql?(request_method)
20
20
 
21
21
  match_data = regexp.match(File.join("/", request.path_info))
22
- match_data.named_captures.transform_values { |v| Rack::Utils.unescape(v) } if match_data
22
+ if match_data
23
+ match_data.named_captures.transform_values do |v|
24
+ Rack::Utils.unescape(v)
25
+ end
26
+ end
23
27
  end
24
28
 
25
29
  def call(params, urls)
@@ -47,7 +51,14 @@ module RubyEventStore
47
51
  def handle(request)
48
52
  routes.each do |route|
49
53
  route_params = route.match(request)
50
- return route.call(request.params.merge(route_params), urls.with_request(request)) if route_params
54
+ if route_params
55
+ return(
56
+ route.call(
57
+ request.params.merge(route_params),
58
+ urls.with_request(request)
59
+ )
60
+ )
61
+ end
51
62
  end
52
63
  raise NoMatch
53
64
  end
@@ -12,7 +12,11 @@ module RubyEventStore
12
12
  end
13
13
 
14
14
  def with_request(request)
15
- Urls.new(host || request.base_url, root_path || request.script_name, api_url)
15
+ Urls.new(
16
+ host || request.base_url,
17
+ root_path || request.script_name,
18
+ api_url
19
+ )
16
20
  end
17
21
 
18
22
  attr_reader :app_url, :api_url, :host, :root_path
@@ -33,11 +37,20 @@ module RubyEventStore
33
37
  "#{api_url}/streams"
34
38
  end
35
39
 
36
- def paginated_events_from_stream_url(id:, position: nil, direction: nil, count: nil)
40
+ def paginated_events_from_stream_url(
41
+ id:,
42
+ position: nil,
43
+ direction: nil,
44
+ count: nil
45
+ )
37
46
  stream_name = Rack::Utils.escape(id)
38
47
  query_string =
39
48
  URI.encode_www_form(
40
- { "page[position]" => position, "page[direction]" => direction, "page[count]" => count }.compact
49
+ {
50
+ "page[position]" => position,
51
+ "page[direction]" => direction,
52
+ "page[count]" => count
53
+ }.compact
41
54
  )
42
55
 
43
56
  if query_string.empty?
@@ -49,20 +62,12 @@ module RubyEventStore
49
62
 
50
63
  def browser_js_url
51
64
  name = "ruby_event_store_browser.js"
52
- if gem_source.from_git?
53
- cdn_file_url(name)
54
- else
55
- local_file_url(name)
56
- end
65
+ gem_source.from_git? ? cdn_file_url(name) : local_file_url(name)
57
66
  end
58
67
 
59
68
  def browser_css_url
60
69
  name = "ruby_event_store_browser.css"
61
- if gem_source.from_git?
62
- cdn_file_url(name)
63
- else
64
- local_file_url(name)
65
- end
70
+ gem_source.from_git? ? cdn_file_url(name) : local_file_url(name)
66
71
  end
67
72
 
68
73
  def bootstrap_js_url
@@ -70,10 +75,12 @@ module RubyEventStore
70
75
  end
71
76
 
72
77
  def ==(o)
73
- self.class.eql?(o.class) && app_url.eql?(o.app_url) && api_url.eql?(o.api_url)
78
+ self.class.eql?(o.class) && app_url.eql?(o.app_url) &&
79
+ api_url.eql?(o.api_url)
74
80
  end
75
81
 
76
82
  private
83
+
77
84
  attr_reader :gem_source
78
85
 
79
86
  def local_file_url(name)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module RubyEventStore
4
4
  module Browser
5
- VERSION = "2.14.0"
5
+ VERSION = "2.16.0"
6
6
  end
7
7
  end
Binary file
Binary file
Binary file
data/public/bootstrap.js CHANGED
@@ -1,3 +1,30 @@
1
- Elm.Main.init({
2
- flags: JSON.parse(document.querySelector("meta[name='ruby-event-store-browser-settings']").getAttribute("content")),
1
+ const flags = JSON.parse(
2
+ document.querySelector("meta[name='ruby-event-store-browser-settings']").getAttribute("content")
3
+ );
4
+ flags.platform = navigator.platform;
5
+ const app = Elm.Main.init({ flags });
6
+
7
+ app.ports.copyToClipboard.subscribe(function (message) {
8
+ navigator.clipboard.writeText(message);
9
+ });
10
+
11
+ app.ports.toggleDialog.subscribe(function (id) {
12
+ const dialog = document.querySelector(`#${id}`);
13
+ dialog.open ? dialog.close() : dialog.showModal();
14
+ });
15
+
16
+ app.ports.closeSearch.subscribe(function (id) {
17
+ document.querySelector(`#${id}`).close();
18
+ });
19
+
20
+ window.addEventListener("keydown", function (event) {
21
+ if (event.key === "k" && (event.ctrlKey || event.metaKey)) {
22
+ app.ports.requestSearch.send(null);
23
+ event.preventDefault();
24
+ }
25
+
26
+ if (event.key === "Escape") {
27
+ app.ports.requestSearchClose.send(null);
28
+ event.preventDefault();
29
+ }
3
30
  });
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -1 +1 @@
1
- /*! tailwindcss v3.4.1 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:initial}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:initial;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:initial}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.absolute{position:absolute}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.ml-4{margin-left:1rem}.mr-1{margin-right:.25rem}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.h-16{height:4rem}.min-h-screen{min-height:100vh}.w-full{width:100%}.flex-1{flex:1 1 0%}.table-fixed{table-layout:fixed}.border-collapse{border-collapse:collapse}.list-disc{list-style-type:disc}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-8{gap:2rem}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.rounded{border-radius:.25rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.border-gray-50{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-red-700{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.p-0{padding:0}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-24{padding-top:6rem;padding-bottom:6rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pb-4{padding-bottom:1rem}.pl-8{padding-left:2rem}.pr-4{padding-right:1rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.no-underline{text-decoration-line:none}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:border-red-700\/50:disabled{border-color:#b91c1c80}.disabled\:text-red-700\/50:disabled{color:#b91c1c80}@media (min-width:768px){.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}
1
+ /*! tailwindcss v3.4.9 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.left-2{left:.5rem}.right-3{right:.75rem}.top-0{top:0}.top-3\.5{top:.875rem}.isolate{isolation:isolate}.z-0{z-index:0}.mx-auto{margin-left:auto;margin-right:auto}.my-10{margin-top:2.5rem;margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-4{margin-left:1rem}.mr-1{margin-right:.25rem}.block{display:block}.inline-block{display:inline-block}.flex{display:flex}.table{display:table}.grid{display:grid}.size-20{width:5rem;height:5rem}.size-3{width:.75rem;height:.75rem}.size-4{width:1rem;height:1rem}.h-16{height:4rem}.h-9{height:2.25rem}.h-full{height:100%}.min-h-11{min-height:2.75rem}.min-h-screen{min-height:100vh}.w-full{width:100%}.min-w-0{min-width:0}.max-w-96{max-width:24rem}.grow{flex-grow:1}.table-fixed{table-layout:fixed}.-translate-y-0\.5{--tw-translate-y:-0.125rem;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))}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.cursor-help{cursor:help}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.list-disc{list-style-type:disc}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.gap-8{gap:2rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.space-y-10>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(2.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2.5rem*var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-scroll{overflow-x:scroll}.whitespace-nowrap{white-space:nowrap}.break-words{overflow-wrap:break-word}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-gray-300{--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity))}.border-gray-400{--tw-border-opacity:1;border-color:rgb(156 163 175/var(--tw-border-opacity))}.border-gray-50{--tw-border-opacity:1;border-color:rgb(249 250 251/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.border-red-700\/50{border-color:rgba(185,28,28,.5)}.bg-gray-100{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.bg-gray-50{--tw-bg-opacity:1;background-color:rgb(249 250 251/var(--tw-bg-opacity))}.bg-red-700{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity))}.bg-red-800{--tw-bg-opacity:1;background-color:rgb(153 27 27/var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity))}.bg-white\/70{background-color:hsla(0,0%,100%,.7)}.fill-red-500{fill:#ef4444}.p-1{padding:.25rem}.p-4{padding:1rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-24{padding-top:6rem;padding-bottom:6rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-2{padding-bottom:.5rem}.pl-4{padding-left:1rem}.pl-8{padding-left:2rem}.pr-12{padding-right:3rem}.pr-4{padding-right:1rem}.pt-3{padding-top:.75rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.align-top{vertical-align:top}.align-middle{vertical-align:middle}.align-bottom{vertical-align:bottom}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.font-sans{font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[\.5rem\]{font-size:.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-tight{letter-spacing:-.025em}.text-gray-100{--tw-text-opacity:1;color:rgb(243 244 246/var(--tw-text-opacity))}.text-gray-200{--tw-text-opacity:1;color:rgb(229 231 235/var(--tw-text-opacity))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity))}.text-gray-700{--tw-text-opacity:1;color:rgb(55 65 81/var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity:1;color:rgb(31 41 55/var(--tw-text-opacity))}.text-red-100{--tw-text-opacity:1;color:rgb(254 226 226/var(--tw-text-opacity))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.text-red-700\/50{color:rgba(185,28,28,.5)}.no-underline{text-decoration-line:none}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}input::-webkit-calendar-picker-indicator{opacity:0}.backdrop\:bg-gray-400\/50::backdrop{background-color:rgba(156,163,175,.5)}.backdrop\:backdrop-blur::backdrop{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.hover\:bg-gray-100:hover{--tw-bg-opacity:1;background-color:rgb(243 244 246/var(--tw-bg-opacity))}.hover\:bg-red-900:hover{--tw-bg-opacity:1;background-color:rgb(127 29 29/var(--tw-bg-opacity))}.hover\:text-red-700:hover{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity))}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus\:ring-red-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(239 68 68/var(--tw-ring-opacity))}.focus\:ring-opacity-50:focus{--tw-ring-opacity:0.5}.group:hover .group-hover\:opacity-100{opacity:1}@media (min-width:640px){.sm\:overflow-visible{overflow:visible}}@media (min-width:768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:flex-nowrap{flex-wrap:nowrap}.md\:items-center{align-items:center}.md\:py-12{padding-top:3rem;padding-bottom:3rem}}@media (min-width:1024px){.lg\:w-60{width:15rem}.lg\:w-80{width:20rem}.lg\:table-fixed{table-layout:fixed}}