mirror of
https://github.com/woutdp/live_svelte
synced 2026-05-24 09:28:21 +00:00
chore: update example project
This commit is contained in:
parent
af0c4ccf82
commit
8a4714ecaf
12 changed files with 23 additions and 244 deletions
2
example_project/.gitignore
vendored
2
example_project/.gitignore
vendored
|
|
@ -33,7 +33,7 @@ example-*.tar
|
|||
|
||||
# In case you use Node.js/npm, you want to ignore these.
|
||||
npm-debug.log
|
||||
/assets/node_modules/
|
||||
node_modules/
|
||||
|
||||
# Ignore automatically generated Svelte files by the ~V sigil
|
||||
/assets/svelte/_build/
|
||||
|
|
|
|||
|
|
@ -1,62 +0,0 @@
|
|||
// Client-side entry point for both Vite dev server (HMR) and production builds.
|
||||
// Uses virtual:live-svelte-components (provided by liveSveltePlugin) instead of
|
||||
// the esbuild-plugin-import-glob glob syntax used by the old esbuild app.js entry.
|
||||
|
||||
import "phoenix_html"
|
||||
import {Socket} from "phoenix"
|
||||
import {LiveSocket} from "phoenix_live_view"
|
||||
import topbar from "../vendor/topbar"
|
||||
import {getHooks} from "live_svelte"
|
||||
import Components from "virtual:live-svelte-components"
|
||||
|
||||
function formatPayload(str) {
|
||||
if (!str || str === "—") return "—"
|
||||
try {
|
||||
return JSON.stringify(JSON.parse(str), null, 2)
|
||||
} catch {
|
||||
return str
|
||||
}
|
||||
}
|
||||
|
||||
const PropsDiffPayloadDisplay = {
|
||||
mounted() {
|
||||
this.updateDisplays()
|
||||
const root = this.el
|
||||
const diffOnEl = root.querySelector("[data-name='PropsDiffDemo'][data-use-diff='true']")
|
||||
const diffOffEl = root.querySelector("[data-name='PropsDiffDemo'][data-use-diff='false']")
|
||||
const observer = new MutationObserver(() => this.updateDisplays())
|
||||
if (diffOnEl) observer.observe(diffOnEl, {attributes: true, attributeFilter: ["data-props"]})
|
||||
if (diffOffEl) observer.observe(diffOffEl, {attributes: true, attributeFilter: ["data-props"]})
|
||||
this._observer = observer
|
||||
},
|
||||
updated() {
|
||||
this.updateDisplays()
|
||||
},
|
||||
destroyed() {
|
||||
this._observer?.disconnect()
|
||||
},
|
||||
updateDisplays() {
|
||||
const root = this.el
|
||||
const diffOnEl = root.querySelector("[data-name='PropsDiffDemo'][data-use-diff='true']")
|
||||
const diffOffEl = root.querySelector("[data-name='PropsDiffDemo'][data-use-diff='false']")
|
||||
const preOn = root.querySelector("#payload-display-diff-on")
|
||||
const preOff = root.querySelector("#payload-display-diff-off")
|
||||
if (preOn) preOn.textContent = formatPayload(diffOnEl?.getAttribute("data-props") ?? "—")
|
||||
if (preOff) preOff.textContent = formatPayload(diffOffEl?.getAttribute("data-props") ?? "—")
|
||||
},
|
||||
}
|
||||
|
||||
const Hooks = {
|
||||
...getHooks(Components),
|
||||
PropsDiffPayloadDisplay,
|
||||
}
|
||||
|
||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||
let liveSocket = new LiveSocket("/live", Socket, {hooks: Hooks, params: {_csrf_token: csrfToken}})
|
||||
|
||||
topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
|
||||
window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
|
||||
window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
|
||||
|
||||
liveSocket.connect()
|
||||
window.liveSocket = liveSocket
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
// Vite SSR entry point for liveSveltePlugin's /ssr_render endpoint.
|
||||
// Uses Vite-native import.meta.glob instead of the esbuild-plugin-import-glob
|
||||
// syntax used by server.js. Configured via vite.config.js:
|
||||
// liveSveltePlugin({ entrypoint: './js/server.vite.js' })
|
||||
import { getRender } from "live_svelte"
|
||||
import Components from "virtual:live-svelte-components"
|
||||
|
||||
export const render = getRender(Components)
|
||||
152
example_project/assets/vendor/topbar.js
vendored
152
example_project/assets/vendor/topbar.js
vendored
|
|
@ -1,152 +0,0 @@
|
|||
/**
|
||||
* @license MIT
|
||||
* topbar 2.0.0, 2023-02-04
|
||||
* https://buunguyen.github.io/topbar
|
||||
* Copyright (c) 2021 Buu Nguyen
|
||||
*/
|
||||
;(function (window, document) {
|
||||
"use strict"
|
||||
|
||||
// https://gist.github.com/paulirish/1579671
|
||||
;(function () {
|
||||
var lastTime = 0
|
||||
var vendors = ["ms", "moz", "webkit", "o"]
|
||||
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
|
||||
window.requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"]
|
||||
window.cancelAnimationFrame = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"]
|
||||
}
|
||||
if (!window.requestAnimationFrame)
|
||||
window.requestAnimationFrame = function (callback, element) {
|
||||
var currTime = new Date().getTime()
|
||||
var timeToCall = Math.max(0, 16 - (currTime - lastTime))
|
||||
var id = window.setTimeout(function () {
|
||||
callback(currTime + timeToCall)
|
||||
}, timeToCall)
|
||||
lastTime = currTime + timeToCall
|
||||
return id
|
||||
}
|
||||
if (!window.cancelAnimationFrame)
|
||||
window.cancelAnimationFrame = function (id) {
|
||||
clearTimeout(id)
|
||||
}
|
||||
})()
|
||||
|
||||
var canvas,
|
||||
currentProgress,
|
||||
showing,
|
||||
progressTimerId = null,
|
||||
fadeTimerId = null,
|
||||
delayTimerId = null,
|
||||
addEvent = function (elem, type, handler) {
|
||||
if (elem.addEventListener) elem.addEventListener(type, handler, false)
|
||||
else if (elem.attachEvent) elem.attachEvent("on" + type, handler)
|
||||
else elem["on" + type] = handler
|
||||
},
|
||||
options = {
|
||||
autoRun: true,
|
||||
barThickness: 3,
|
||||
barColors: {
|
||||
0: "rgba(26, 188, 156, .9)",
|
||||
".25": "rgba(52, 152, 219, .9)",
|
||||
".50": "rgba(241, 196, 15, .9)",
|
||||
".75": "rgba(230, 126, 34, .9)",
|
||||
"1.0": "rgba(211, 84, 0, .9)",
|
||||
},
|
||||
shadowBlur: 10,
|
||||
shadowColor: "rgba(0, 0, 0, .6)",
|
||||
className: null,
|
||||
},
|
||||
repaint = function () {
|
||||
canvas.width = window.innerWidth
|
||||
canvas.height = options.barThickness * 5 // need space for shadow
|
||||
|
||||
var ctx = canvas.getContext("2d")
|
||||
ctx.shadowBlur = options.shadowBlur
|
||||
ctx.shadowColor = options.shadowColor
|
||||
|
||||
var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0)
|
||||
for (var stop in options.barColors) lineGradient.addColorStop(stop, options.barColors[stop])
|
||||
ctx.lineWidth = options.barThickness
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(0, options.barThickness / 2)
|
||||
ctx.lineTo(Math.ceil(currentProgress * canvas.width), options.barThickness / 2)
|
||||
ctx.strokeStyle = lineGradient
|
||||
ctx.stroke()
|
||||
},
|
||||
createCanvas = function () {
|
||||
canvas = document.createElement("canvas")
|
||||
var style = canvas.style
|
||||
style.position = "fixed"
|
||||
style.top = style.left = style.right = style.margin = style.padding = 0
|
||||
style.zIndex = 100001
|
||||
style.display = "none"
|
||||
if (options.className) canvas.classList.add(options.className)
|
||||
document.body.appendChild(canvas)
|
||||
addEvent(window, "resize", repaint)
|
||||
},
|
||||
topbar = {
|
||||
config: function (opts) {
|
||||
for (var key in opts) if (options.hasOwnProperty(key)) options[key] = opts[key]
|
||||
},
|
||||
show: function (delay) {
|
||||
if (showing) return
|
||||
if (delay) {
|
||||
if (delayTimerId) return
|
||||
delayTimerId = setTimeout(() => topbar.show(), delay)
|
||||
} else {
|
||||
showing = true
|
||||
if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId)
|
||||
if (!canvas) createCanvas()
|
||||
canvas.style.opacity = 1
|
||||
canvas.style.display = "block"
|
||||
topbar.progress(0)
|
||||
if (options.autoRun) {
|
||||
;(function loop() {
|
||||
progressTimerId = window.requestAnimationFrame(loop)
|
||||
topbar.progress("+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2))
|
||||
})()
|
||||
}
|
||||
}
|
||||
},
|
||||
progress: function (to) {
|
||||
if (typeof to === "undefined") return currentProgress
|
||||
if (typeof to === "string") {
|
||||
to = (to.indexOf("+") >= 0 || to.indexOf("-") >= 0 ? currentProgress : 0) + parseFloat(to)
|
||||
}
|
||||
currentProgress = to > 1 ? 1 : to
|
||||
repaint()
|
||||
return currentProgress
|
||||
},
|
||||
hide: function () {
|
||||
clearTimeout(delayTimerId)
|
||||
delayTimerId = null
|
||||
if (!showing) return
|
||||
showing = false
|
||||
if (progressTimerId != null) {
|
||||
window.cancelAnimationFrame(progressTimerId)
|
||||
progressTimerId = null
|
||||
}
|
||||
;(function loop() {
|
||||
if (topbar.progress("+.1") >= 1) {
|
||||
canvas.style.opacity -= 0.05
|
||||
if (canvas.style.opacity <= 0.05) {
|
||||
canvas.style.display = "none"
|
||||
fadeTimerId = null
|
||||
return
|
||||
}
|
||||
}
|
||||
fadeTimerId = window.requestAnimationFrame(loop)
|
||||
})()
|
||||
},
|
||||
}
|
||||
|
||||
if (typeof module === "object" && typeof module.exports === "object") {
|
||||
module.exports = topbar
|
||||
} else if (typeof define === "function" && define.amd) {
|
||||
define(function () {
|
||||
return topbar
|
||||
})
|
||||
} else {
|
||||
this.topbar = topbar
|
||||
}
|
||||
}).call(this, window, document)
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
import Config
|
||||
|
||||
config :phoenix_vite, PhoenixVite.Npm,
|
||||
assets: [args: [], cd: __DIR__],
|
||||
assets: [args: [], cd: Path.expand("..", __DIR__)],
|
||||
vite: [
|
||||
args: ~w(exec -- vite),
|
||||
cd: Path.expand("../assets", __DIR__),
|
||||
|
|
@ -38,17 +38,6 @@ config :example, ExampleWeb.Endpoint,
|
|||
# at the `config/runtime.exs`.
|
||||
config :example, Example.Mailer, adapter: Swoosh.Adapters.Local
|
||||
|
||||
# Configure tailwind (the version is required)
|
||||
config :tailwind,
|
||||
version: "4.1.10",
|
||||
default: [
|
||||
args: ~w(
|
||||
--input=css/app.css
|
||||
--output=../priv/static/assets/app.css
|
||||
),
|
||||
cd: Path.expand("../assets", __DIR__)
|
||||
]
|
||||
|
||||
# Configures Elixir's Logger
|
||||
config :logger, :console,
|
||||
format: "$time $metadata[$level] $message\n",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ config :example, ExampleWeb.Endpoint,
|
|||
secret_key_base: "cZ19cfxyAQ7Nr/qlKBKxr/jRRgW6wk8MQEgJrMNFjfOPEo6hSY1v50sFb0vIjv3P",
|
||||
static_url: [host: "localhost", port: 5173],
|
||||
watchers: [
|
||||
tailwind: {Tailwind, :install_and_run, [:default, ~w(--watch)]},
|
||||
vite: {PhoenixVite.Npm, :run, [:vite, ~w(dev)]}
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -19,3 +19,8 @@ config :logger, level: :info
|
|||
|
||||
# Runtime production configuration, including reading
|
||||
# of environment variables, is done on config/runtime.exs.
|
||||
|
||||
# Production SSR via NodeJS
|
||||
config :live_svelte,
|
||||
ssr_module: LiveSvelte.SSR.NodeJS,
|
||||
ssr: true
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ config :phoenix_test, :endpoint, ExampleWeb.Endpoint
|
|||
|
||||
# Disable LiveSvelte SSR in test so E2E tests run against the client-side bundle.
|
||||
# Otherwise server-rendered HTML can mask client-only bugs (e.g. hardcoded props).
|
||||
config :live_svelte, ssr: false
|
||||
# Explicit ssr_module so NodeJS.Supervisor starts (needed by phoenix_test SSR tests
|
||||
# that temporarily enable SSR via Application.put_env/3).
|
||||
config :live_svelte,
|
||||
ssr: false,
|
||||
ssr_module: LiveSvelte.SSR.NodeJS
|
||||
|
||||
# In test we don't send emails.
|
||||
config :example, Example.Mailer, adapter: Swoosh.Adapters.Test
|
||||
|
|
|
|||
|
|
@ -7,8 +7,14 @@ defmodule Example.Application do
|
|||
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
children = [
|
||||
{NodeJS.Supervisor, [path: LiveSvelte.SSR.NodeJS.server_path(), pool_size: 4]},
|
||||
node_js_children =
|
||||
if Application.get_env(:live_svelte, :ssr_module, nil) == LiveSvelte.SSR.NodeJS do
|
||||
[{NodeJS.Supervisor, [path: LiveSvelte.SSR.NodeJS.server_path(), pool_size: 4]}]
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
||||
children = node_js_children ++ [
|
||||
# Start the Telemetry supervisor
|
||||
ExampleWeb.Telemetry,
|
||||
# Start the Ecto repository
|
||||
|
|
|
|||
|
|
@ -53,8 +53,7 @@ defmodule Example.MixProject do
|
|||
{:wallaby, "~> 0.30", runtime: false, only: :test},
|
||||
{:phoenix_test, "~> 0.9", only: :test},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_vite, "~> 0.4"},
|
||||
{:tailwind, "~> 0.3", runtime: Mix.env() == :dev}
|
||||
{:phoenix_vite, "~> 0.4"}
|
||||
]
|
||||
end
|
||||
|
||||
|
|
@ -70,7 +69,7 @@ defmodule Example.MixProject do
|
|||
"ecto.setup": ["ecto.create", "ecto.migrate", "run priv/repo/seeds.exs"],
|
||||
"ecto.reset": ["ecto.drop", "ecto.setup"],
|
||||
test: ["ecto.create --quiet", "ecto.migrate --quiet", "test"],
|
||||
"assets.setup": ["phoenix_vite.npm assets install", "tailwind.install --if-missing"],
|
||||
"assets.setup": ["phoenix_vite.npm assets install"],
|
||||
"assets.build": [
|
||||
"phoenix_vite.npm vite build --manifest --emptyOutDir true",
|
||||
"phoenix_vite.npm vite build --ssrManifest --emptyOutDir false --ssr js/server.js --outDir ../priv/svelte"
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
||||
"swoosh": {:hex, :swoosh, "1.21.0", "9f4fa629447774cfc9ad684d8a87a85384e8fce828b6390dd535dfbd43c9ee2a", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, "~> 1.9", [hex: :hackney, repo: "hexpm", optional: true]}, {:idna, "~> 6.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9127157bfb33b7e154d0f1ba4e888e14b08ede84e81dedcb318a2f33dbc6db51"},
|
||||
"tailwind": {:hex, :tailwind, "0.4.1", "e7bcc222fe96a1e55f948e76d13dd84a1a7653fb051d2a167135db3b4b08d3e9", [:mix], [], "hexpm", "6249d4f9819052911120dbdbe9e532e6bd64ea23476056adb7f730aa25c220d1"},
|
||||
"telemetry": {:hex, :telemetry, "1.4.1", "ab6de178e2b29b58e8256b92b382ea3f590a47152ca3651ea857a6cae05ac423", [:rebar3], [], "hexpm", "2172e05a27531d3d31dd9782841065c50dd5c3c7699d95266b2edd54c2dafa1c"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.2", "2caabe9344ec17eafe5403304771c3539f3b6e2f7fb6a6f602558c825d0d0bfb", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9b43db0dc33863930b9ef9d27137e78974756f5f198cae18409970ed6fa5b561"},
|
||||
"telemetry_poller": {:hex, :telemetry_poller, "1.3.0", "d5c46420126b5ac2d72bc6580fb4f537d35e851cc0f8dbd571acf6d6e10f5ec7", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "51f18bed7128544a50f75897db9974436ea9bfba560420b646af27a9a9b35211"},
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
"isDynamicEntry": true
|
||||
},
|
||||
"css/app.css": {
|
||||
"file": "assets/app-CLO35oKD.css",
|
||||
"file": "assets/app-DAL7h2-Q.css",
|
||||
"name": "app",
|
||||
"names": [
|
||||
"app.css"
|
||||
|
|
|
|||
Loading…
Reference in a new issue