Skip to content

Commit 96ee706

Browse files
committed
first commit
0 parents  commit 96ee706

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+2075
-0
lines changed

.formatter.exs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[
2+
import_deps: [:phoenix],
3+
plugins: [Phoenix.LiveView.HTMLFormatter],
4+
inputs: ["*.{heex,ex,exs}", "{config,lib,test}/**/*.{heex,ex,exs}"]
5+
]

.gitignore

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# The directory Mix will write compiled artifacts to.
2+
/_build/
3+
4+
# If you run "mix test --cover", coverage assets end up here.
5+
/cover/
6+
7+
# The directory Mix downloads your dependencies sources to.
8+
/deps/
9+
10+
# Where 3rd-party dependencies like ExDoc output generated docs.
11+
/doc/
12+
13+
# Ignore .fetch files in case you like to edit your project deps locally.
14+
/.fetch
15+
16+
# If the VM crashes, it generates a dump, let's ignore it too.
17+
erl_crash.dump
18+
19+
# Also ignore archive artifacts (built via "mix archive.build").
20+
*.ez
21+
22+
# Temporary files, for example, from tests.
23+
/tmp/
24+
25+
# Ignore package tarball (built via "mix hex.build").
26+
my_blog-*.tar
27+
28+
# Ignore assets that are produced by build tools.
29+
/priv/static/assets/
30+
31+
# Ignore digested assets cache.
32+
/priv/static/cache_manifest.json
33+
34+
# In case you use Node.js/npm, you want to ignore these.
35+
npm-debug.log
36+
/assets/node_modules/
37+

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# MyBlog
2+
3+
To start your Phoenix server:
4+
5+
* Run `mix setup` to install and setup dependencies
6+
* Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
7+
8+
Now you can visit [`localhost:4000`](http://localhost:4000) from your browser.
9+
10+
Ready to run in production? Please [check our deployment guides](https://hexdocs.pm/phoenix/deployment.html).
11+
12+
## Learn more
13+
14+
* Official website: https://www.phoenixframework.org/
15+
* Guides: https://hexdocs.pm/phoenix/overview.html
16+
* Docs: https://hexdocs.pm/phoenix
17+
* Forum: https://elixirforum.com/c/phoenix-forum
18+
* Source: https://github.com/phoenixframework/phoenix

assets/css/app.css

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@import "tailwindcss/base";
2+
@import "tailwindcss/components";
3+
@import "tailwindcss/utilities";
4+
5+
/* This file is for your main application CSS */

assets/js/app.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// If you want to use Phoenix channels, run `mix help phx.gen.channel`
2+
// to get started and then uncomment the line below.
3+
// import "./user_socket.js"
4+
5+
// You can include dependencies in two ways.
6+
//
7+
// The simplest option is to put them in assets/vendor and
8+
// import them using relative paths:
9+
//
10+
// import "../vendor/some-package.js"
11+
//
12+
// Alternatively, you can `npm install some-package --prefix assets` and import
13+
// them using a path starting with the package name:
14+
//
15+
// import "some-package"
16+
//
17+
18+
// Include phoenix_html to handle method=PUT/DELETE in forms and buttons.
19+
import "phoenix_html"
20+
// Establish Phoenix Socket and LiveView configuration.
21+
// import {Socket} from "phoenix"
22+
// import {LiveSocket} from "phoenix_live_view"
23+
// import topbar from "../vendor/topbar"
24+
25+
// let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
26+
// let liveSocket = new LiveSocket("/live", Socket, {
27+
// longPollFallbackMs: 2500,
28+
// params: {_csrf_token: csrfToken}
29+
// })
30+
31+
// Show progress bar on live navigation and form submits
32+
// topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"})
33+
// window.addEventListener("phx:page-loading-start", _info => topbar.show(300))
34+
// window.addEventListener("phx:page-loading-stop", _info => topbar.hide())
35+
36+
// connect if there are any LiveViews on the page
37+
// liveSocket.connect()
38+
39+
// expose liveSocket on window for web console debug logs and latency simulation:
40+
// >> liveSocket.enableDebug()
41+
// >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session
42+
// >> liveSocket.disableLatencySim()
43+
// window.liveSocket = liveSocket
44+

assets/tailwind.config.js

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// See the Tailwind configuration guide for advanced usage
2+
// https://tailwindcss.com/docs/configuration
3+
4+
const plugin = require("tailwindcss/plugin")
5+
const fs = require("fs")
6+
const path = require("path")
7+
8+
module.exports = {
9+
content: [
10+
"./js/**/*.js",
11+
"../lib/my_blog_web.ex",
12+
"../lib/my_blog_web/**/*.*ex"
13+
],
14+
theme: {
15+
extend: {
16+
colors: {
17+
brand: "#FD4F00",
18+
}
19+
},
20+
},
21+
plugins: [
22+
require("@tailwindcss/forms"),
23+
// Allows prefixing tailwind classes with LiveView classes to add rules
24+
// only when LiveView classes are applied, for example:
25+
//
26+
// <div class="phx-click-loading:animate-ping">
27+
//
28+
plugin(({addVariant}) => addVariant("phx-click-loading", [".phx-click-loading&", ".phx-click-loading &"])),
29+
plugin(({addVariant}) => addVariant("phx-submit-loading", [".phx-submit-loading&", ".phx-submit-loading &"])),
30+
plugin(({addVariant}) => addVariant("phx-change-loading", [".phx-change-loading&", ".phx-change-loading &"])),
31+
32+
// Embeds Heroicons (https://heroicons.com) into your app.css bundle
33+
// See your `CoreComponents.icon/1` for more information.
34+
//
35+
plugin(function({matchComponents, theme}) {
36+
let iconsDir = path.join(__dirname, "../deps/heroicons/optimized")
37+
let values = {}
38+
let icons = [
39+
["", "/24/outline"],
40+
["-solid", "/24/solid"],
41+
["-mini", "/20/solid"],
42+
["-micro", "/16/solid"]
43+
]
44+
icons.forEach(([suffix, dir]) => {
45+
fs.readdirSync(path.join(iconsDir, dir)).forEach(file => {
46+
let name = path.basename(file, ".svg") + suffix
47+
values[name] = {name, fullPath: path.join(iconsDir, dir, file)}
48+
})
49+
})
50+
matchComponents({
51+
"hero": ({name, fullPath}) => {
52+
let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, "")
53+
let size = theme("spacing.6")
54+
if (name.endsWith("-mini")) {
55+
size = theme("spacing.5")
56+
} else if (name.endsWith("-micro")) {
57+
size = theme("spacing.4")
58+
}
59+
return {
60+
[`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
61+
"-webkit-mask": `var(--hero-${name})`,
62+
"mask": `var(--hero-${name})`,
63+
"mask-repeat": "no-repeat",
64+
"background-color": "currentColor",
65+
"vertical-align": "middle",
66+
"display": "inline-block",
67+
"width": size,
68+
"height": size
69+
}
70+
}
71+
}, {values})
72+
})
73+
]
74+
}

assets/vendor/topbar.js

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/**
2+
* @license MIT
3+
* topbar 2.0.0, 2023-02-04
4+
* https://buunguyen.github.io/topbar
5+
* Copyright (c) 2021 Buu Nguyen
6+
*/
7+
(function (window, document) {
8+
"use strict";
9+
10+
// https://gist.github.com/paulirish/1579671
11+
(function () {
12+
var lastTime = 0;
13+
var vendors = ["ms", "moz", "webkit", "o"];
14+
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
15+
window.requestAnimationFrame =
16+
window[vendors[x] + "RequestAnimationFrame"];
17+
window.cancelAnimationFrame =
18+
window[vendors[x] + "CancelAnimationFrame"] ||
19+
window[vendors[x] + "CancelRequestAnimationFrame"];
20+
}
21+
if (!window.requestAnimationFrame)
22+
window.requestAnimationFrame = function (callback, element) {
23+
var currTime = new Date().getTime();
24+
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
25+
var id = window.setTimeout(function () {
26+
callback(currTime + timeToCall);
27+
}, timeToCall);
28+
lastTime = currTime + timeToCall;
29+
return id;
30+
};
31+
if (!window.cancelAnimationFrame)
32+
window.cancelAnimationFrame = function (id) {
33+
clearTimeout(id);
34+
};
35+
})();
36+
37+
var canvas,
38+
currentProgress,
39+
showing,
40+
progressTimerId = null,
41+
fadeTimerId = null,
42+
delayTimerId = null,
43+
addEvent = function (elem, type, handler) {
44+
if (elem.addEventListener) elem.addEventListener(type, handler, false);
45+
else if (elem.attachEvent) elem.attachEvent("on" + type, handler);
46+
else elem["on" + type] = handler;
47+
},
48+
options = {
49+
autoRun: true,
50+
barThickness: 3,
51+
barColors: {
52+
0: "rgba(26, 188, 156, .9)",
53+
".25": "rgba(52, 152, 219, .9)",
54+
".50": "rgba(241, 196, 15, .9)",
55+
".75": "rgba(230, 126, 34, .9)",
56+
"1.0": "rgba(211, 84, 0, .9)",
57+
},
58+
shadowBlur: 10,
59+
shadowColor: "rgba(0, 0, 0, .6)",
60+
className: null,
61+
},
62+
repaint = function () {
63+
canvas.width = window.innerWidth;
64+
canvas.height = options.barThickness * 5; // need space for shadow
65+
66+
var ctx = canvas.getContext("2d");
67+
ctx.shadowBlur = options.shadowBlur;
68+
ctx.shadowColor = options.shadowColor;
69+
70+
var lineGradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
71+
for (var stop in options.barColors)
72+
lineGradient.addColorStop(stop, options.barColors[stop]);
73+
ctx.lineWidth = options.barThickness;
74+
ctx.beginPath();
75+
ctx.moveTo(0, options.barThickness / 2);
76+
ctx.lineTo(
77+
Math.ceil(currentProgress * canvas.width),
78+
options.barThickness / 2
79+
);
80+
ctx.strokeStyle = lineGradient;
81+
ctx.stroke();
82+
},
83+
createCanvas = function () {
84+
canvas = document.createElement("canvas");
85+
var style = canvas.style;
86+
style.position = "fixed";
87+
style.top = style.left = style.right = style.margin = style.padding = 0;
88+
style.zIndex = 100001;
89+
style.display = "none";
90+
if (options.className) canvas.classList.add(options.className);
91+
document.body.appendChild(canvas);
92+
addEvent(window, "resize", repaint);
93+
},
94+
topbar = {
95+
config: function (opts) {
96+
for (var key in opts)
97+
if (options.hasOwnProperty(key)) options[key] = opts[key];
98+
},
99+
show: function (delay) {
100+
if (showing) return;
101+
if (delay) {
102+
if (delayTimerId) return;
103+
delayTimerId = setTimeout(() => topbar.show(), delay);
104+
} else {
105+
showing = true;
106+
if (fadeTimerId !== null) window.cancelAnimationFrame(fadeTimerId);
107+
if (!canvas) createCanvas();
108+
canvas.style.opacity = 1;
109+
canvas.style.display = "block";
110+
topbar.progress(0);
111+
if (options.autoRun) {
112+
(function loop() {
113+
progressTimerId = window.requestAnimationFrame(loop);
114+
topbar.progress(
115+
"+" + 0.05 * Math.pow(1 - Math.sqrt(currentProgress), 2)
116+
);
117+
})();
118+
}
119+
}
120+
},
121+
progress: function (to) {
122+
if (typeof to === "undefined") return currentProgress;
123+
if (typeof to === "string") {
124+
to =
125+
(to.indexOf("+") >= 0 || to.indexOf("-") >= 0
126+
? currentProgress
127+
: 0) + parseFloat(to);
128+
}
129+
currentProgress = to > 1 ? 1 : to;
130+
repaint();
131+
return currentProgress;
132+
},
133+
hide: function () {
134+
clearTimeout(delayTimerId);
135+
delayTimerId = null;
136+
if (!showing) return;
137+
showing = false;
138+
if (progressTimerId != null) {
139+
window.cancelAnimationFrame(progressTimerId);
140+
progressTimerId = null;
141+
}
142+
(function loop() {
143+
if (topbar.progress("+.1") >= 1) {
144+
canvas.style.opacity -= 0.05;
145+
if (canvas.style.opacity <= 0.05) {
146+
canvas.style.display = "none";
147+
fadeTimerId = null;
148+
return;
149+
}
150+
}
151+
fadeTimerId = window.requestAnimationFrame(loop);
152+
})();
153+
},
154+
};
155+
156+
if (typeof module === "object" && typeof module.exports === "object") {
157+
module.exports = topbar;
158+
} else if (typeof define === "function" && define.amd) {
159+
define(function () {
160+
return topbar;
161+
});
162+
} else {
163+
this.topbar = topbar;
164+
}
165+
}.call(this, window, document));

0 commit comments

Comments
 (0)