Packages

phoenix_kit

1.7.200
1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

221 Versions

Jump to

Compare versions

23 files changed
+113 additions
-8 deletions
unknownCHANGELOG.md
File is too large to be displayed (100 KB limit).
  @@ -1,6 +1,6 @@
1 1 {<<"links">>,[{<<"GitHub">>,<<"https://github.com/BeamLabEU/phoenix_kit">>}]}.
2 2 {<<"name">>,<<"phoenix_kit">>}.
3 - {<<"version">>,<<"1.7.199">>}.
3 + {<<"version">>,<<"1.7.200">>}.
4 4 {<<"description">>,
5 5 <<65,32,102,111,117,110,100,97,116,105,111,110,32,102,111,114,32,98,117,105,
6 6 108,100,105,110,103,32,69,108,105,120,105,114,32,80,104,111,101,110,105,
unknownlib/modules/storage/storage.ex
File is too large to be displayed (100 KB limit).
  @@ -99,4 +99,79 @@ defmodule PhoenixKitWeb.Components.Core.MediaThumbnail do
99 99 end
100 100
101 101 def resolve_url(_, _), do: nil
102 +
103 + @doc """
104 + Tailwind class rotating a thumbnail to the image's saved orientation.
105 +
106 + The orientation lives on the file row (`metadata["rotation"]`, written by
107 + the viewer's `persist_rotation` bridge) and applies to the whole image, so
108 + every rendering of it — canvas *and* thumbnail — should honor it. Baked
109 + variants stay unrotated: rendering the saved angle with a CSS transform
110 + costs nothing, needs no re-encode, and keeps annotations (which live in
111 + the image's own coordinate space) aligned as they rotate along.
112 +
113 + In a **square** box (`aspect-square` cards, `w-10 h-10` list cells) a
114 + quarter turn needs nothing else: rotating a square leaves the same square,
115 + and because `object-cover` crops about the center — which rotation maps
116 + onto itself — cropping-then-rotating shows exactly what
117 + rotating-then-cropping would.
118 +
119 + A **non-square** box needs the quarter turn to scale back up, or the
120 + covered image (now turned onto its side) would letterbox: pass `box:` and
121 + the scale rides along. Half turns never need it. The scale literal per box
122 + shape is hardcoded rather than computed — Tailwind only emits arbitrary
123 + values it can *see* in source, so an interpolated `scale-[…]` would
124 + silently render as no scale at all.
125 +
126 + Nil-tolerant: unrotated, garbage, and maps carrying no `:rotation` at all
127 + return `nil`.
128 +
129 + ## Options
130 +
131 + * `:box` — the thumbnail box's aspect: `:square` (default) or
132 + `:landscape_4_3` (the stacks preview pile's `w-32 h-24`).
133 +
134 + ## Examples
135 +
136 + <img src={url} class={["w-full h-full object-cover", rotation_class(file)]} />
137 +
138 + <img src={url} class={["w-full h-full object-cover",
139 + rotation_class(file, box: :landscape_4_3)]} />
140 + """
141 + @spec rotation_class(map(), keyword()) :: String.t() | nil
142 + def rotation_class(file, opts \\ [])
143 +
144 + def rotation_class(file, opts) when is_map(file) do
145 + case normalize_rotation(Map.get(file, :rotation)) do
146 + 90 -> quarter_turn("rotate-90", opts)
147 + 180 -> "rotate-180"
148 + 270 -> quarter_turn("-rotate-90", opts)
149 + _ -> nil
150 + end
151 + end
152 +
153 + def rotation_class(_, _), do: nil
154 +
155 + defp quarter_turn(rotate, opts) do
156 + case Keyword.get(opts, :box, :square) do
157 + :square -> rotate
158 + # A quarter turn leaves a 4:3-covered image standing 3:4 inside the
159 + # 4:3 box; scaling by 4/3 makes it cover again.
160 + :landscape_4_3 -> rotate <> " scale-[1.3334]"
161 + end
162 + end
163 +
164 + # Mirrors MediaCanvasViewer's own normalization: only the four snapped
165 + # angles Fresco emits count; anything else (nil, garbage, a legacy string)
166 + # reads as unrotated.
167 + defp normalize_rotation(deg) when is_integer(deg), do: Integer.mod(deg, 360)
168 +
169 + defp normalize_rotation(deg) when is_binary(deg) do
170 + case Integer.parse(deg) do
171 + {n, _} -> normalize_rotation(n)
172 + :error -> 0
173 + end
174 + end
175 +
176 + defp normalize_rotation(_), do: 0
102 177 end
unknownlib/phoenix_kit_web/components/media_browser.ex
File is too large to be displayed (100 KB limit).
Loading more files…