Packages

phoenix_kit

1.7.118
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

16 files changed
+163 additions
-66 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.117">>}.
3 + {<<"version">>,<<"1.7.118">>}.
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,
  @@ -124,12 +124,24 @@ defmodule PhoenixKit.Modules.AI.Translation do
124 124 # not an input-shape question — fail fast on bad args either way.
125 125 with :ok <- validate_uuid(endpoint_uuid, :no_endpoint),
126 126 :ok <- validate_uuid(prompt_uuid, :missing_prompt),
127 + :ok <- validate_non_empty(fields),
127 128 :ok <- validate_unique_markers(Map.keys(fields)),
128 129 :ok <- ensure_available() do
129 130 do_translate(endpoint_uuid, prompt_uuid, source_lang, target_lang, fields, opts)
130 131 end
131 132 end
132 133
134 + # Short-circuit before dispatching to the AI plugin — an empty
135 + # `fields` map would render a prompt with no field variables, spend
136 + # real tokens on a `PhoenixKitAI.ask_with_prompt/4` call, and then
137 + # fail downstream in `parse_response/2` with `:no_markers`. Cheap to
138 + # reject up front. The error sentinel mirrors `parse_response/2`'s
139 + # shape so callers don't have to branch on a new error class.
140 + defp validate_non_empty(fields) when map_size(fields) == 0,
141 + do: {:error, {:parse_error, :no_markers}}
142 +
143 + defp validate_non_empty(_fields), do: :ok
144 +
133 145 defp validate_uuid(value, error) when is_binary(value) do
134 146 if String.trim(value) == "", do: {:error, error}, else: :ok
135 147 end
  @@ -186,11 +198,8 @@ defmodule PhoenixKit.Modules.AI.Translation do
186 198 # which `rescue` alone wouldn't catch.
187 199 try do
188 200 case PhoenixKitAI.ask_with_prompt(endpoint_uuid, prompt_uuid, variables, ai_opts) do
189 - {:ok, response} when is_binary(response) ->
190 - parse_response(response, Map.keys(fields))
191 -
192 - {:ok, other} ->
193 - {:error, {:ai_error, {:unexpected_response, other}}}
201 + {:ok, response} ->
202 + handle_ai_response(response, fields)
194 203
195 204 {:error, reason} ->
196 205 {:error, {:ai_error, reason}}
  @@ -206,6 +215,35 @@ defmodule PhoenixKit.Modules.AI.Translation do
206 215 end
207 216 end
208 217
218 + # `PhoenixKitAI.ask_with_prompt/4` returns the full OpenAI-shaped
219 + # response map (`%{"choices" => [%{"message" => %{"content" => "..."}}]}`),
220 + # not a raw string. Reach for `PhoenixKitAI.Completion.extract_content/1`
221 + # to pull the assistant's content out — same helper publishing's
222 + # `TranslatePostWorker` already uses for its post-translate AI call.
223 + # Older versions of the plugin (or test stubs) may still return a
224 + # plain binary; the second clause keeps that working.
225 + @compile {:no_warn_undefined, [{PhoenixKitAI.Completion, :extract_content, 1}]}
226 + defp handle_ai_response(response, fields) when is_map(response) do
227 + case PhoenixKitAI.Completion.extract_content(response) do
228 + {:ok, content} when is_binary(content) ->
229 + parse_response(content, Map.keys(fields))
230 +
231 + {:ok, _other} ->
232 + {:error, {:ai_error, {:unexpected_response, response}}}
233 +
234 + {:error, reason} ->
235 + {:error, {:ai_error, reason}}
236 + end
237 + end
238 +
239 + defp handle_ai_response(response, fields) when is_binary(response) do
240 + parse_response(response, Map.keys(fields))
241 + end
242 +
243 + defp handle_ai_response(other, _fields) do
244 + {:error, {:ai_error, {:unexpected_response, other}}}
245 + end
246 +
209 247 @doc """
210 248 Parses a structured `---FIELD_NAME---` response into a field map.
  @@ -84,7 +84,12 @@ defmodule PhoenixKitWeb.Components.Core.DraggableList do
84 84
85 85 attr :on_reorder, :string, required: true, doc: "Event name to send on reorder"
86 86 attr :layout, :atom, default: :grid, values: [:grid, :list], doc: "Layout mode"
87 - attr :cols, :integer, default: 4, doc: "Number of grid columns (only for layout={:grid})"
87 +
88 + attr :cols, :any,
89 + default: 4,
90 + doc:
91 + "Grid columns (only for layout={:grid}). Either an integer 1..6 (mapped to a static `grid-cols-N`), or a string of Tailwind grid-column classes used verbatim — e.g. `\"grid-cols-4 lg:grid-cols-6 2xl:grid-cols-8\"` — for a responsive grid. The string form must be a literal in a Tailwind-scanned source so the classes are compiled. Any other value (out-of-range integer, atom, etc.) falls back to `grid-cols-4`."
92 +
88 93 attr :gap, :string, default: "gap-2", doc: "Gap between items (Tailwind class)"
89 94 attr :class, :string, default: "", doc: "Additional CSS classes for the container"
90 95 attr :item_class, :string, default: "", doc: "Additional CSS classes for each item wrapper"
  @@ -159,7 +164,10 @@ defmodule PhoenixKitWeb.Components.Core.DraggableList do
159 164 """
160 165 end
161 166
162 - # Map column count to Tailwind class (must be static for Tailwind to recognize)
167 + # Map column count to Tailwind class (must be static for Tailwind to recognize).
168 + # A string is taken verbatim so consumers can pass responsive grid-column
169 + # classes (e.g. "grid-cols-4 lg:grid-cols-6 3xl:grid-cols-8").
170 + defp cols_to_class(cols) when is_binary(cols), do: cols
163 171 defp cols_to_class(1), do: "grid-cols-1"
164 172 defp cols_to_class(2), do: "grid-cols-2"
165 173 defp cols_to_class(3), do: "grid-cols-3"
  @@ -120,6 +120,11 @@ defmodule PhoenixKitWeb.Components.Core.TableDefault do
120 120 attr :storage_key, :string, default: nil
121 121 attr :wrapper_class, :string, default: "rounded-lg shadow-md overflow-x-auto overflow-y-clip"
122 122
123 + attr :card_grid_class, :string,
124 + default: "gap-4 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4",
125 + doc:
126 + "Layout classes for the card-view grid (column density, gaps). Must NOT include a `display` utility (`grid`/`hidden`) — the component sets `display` per view-mode branch so controlled table mode can emit `hidden` cleanly. Override to change column count, e.g. a denser `gap-4 grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5`. Must be a literal in a Tailwind-scanned source so the classes are compiled — a dynamically-built string won't be in the generated CSS."
127 +
123 128 attr :view_mode, :string,
124 129 default: nil,
125 130 values: [nil, "card", "table"],
  @@ -325,7 +330,7 @@ defmodule PhoenixKitWeb.Components.Core.TableDefault do
325 330 # Layout-only classes (no `display`) are always safe; the `display`
326 331 # utility is set per-branch so controlled "table" mode emits only
327 332 # `hidden` — no reliance on Tailwind's hidden-beats-grid source order.
328 - "gap-4 md:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4",
333 + @card_grid_class,
329 334 is_nil(@view_mode) && "grid md:hidden",
330 335 @view_mode == "card" && "grid",
331 336 @view_mode == "table" && "hidden"
Loading more files…