Files
omarchy/shell/plugins/panels/elsewhen/Arc.js
T
David Heinemeier HanssonandClaude Opus 5.5 e7218e36f2 Move Elsewhen into Omarchy as omarchy.elsewhen (#13429)
* Move Elsewhen into Omarchy as omarchy.elsewhen

The world clock ships in the shell tree instead of its own package. A
migration renames existing bar entries with their settings and removes
the retired package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Remove Elsewhen's shelved Earth row, overlap band and sky tint

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Tidy Elsewhen's models, data helper and docs, and drop currency

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Restructure Elsewhen's panel and globe on the shared shell components

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Show Elsewhen's bar globe upright

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Use the shared city search for Elsewhen's globe jump bar

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep legacy Elsewhen entries single and retry offline geocodes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Fetch Elsewhen's weather with curl instead of a Python helper

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 21:15:00 +02:00

53 lines
1.7 KiB
JavaScript

// A line of text laid along a shallow circular arc. `widths` are character
// advances; `rise` is how far the ends sit from the middle, in pixels; `smile`
// bends the ends up. Returns { width, height, chars: [{ x, y, rotation }] }
// with each box's top-left and its turn in degrees about its center.
function layout(widths, rise, smile) {
var chars = []
var total = 0
var i
for (i = 0; i < widths.length; i++) total += widths[i]
if (total <= 0 || rise <= 0) {
var x = 0
for (i = 0; i < widths.length; i++) {
chars.push({ x: x, y: 0, rotation: 0 })
x += widths[i]
}
return { width: total, height: 0, chars: chars }
}
// Keeps the trig in range for absurd rises.
var sag = Math.min(rise, total / 4)
// Shallow-arc sagitta: R = w^2 / 8s.
var radius = (total * total) / (8 * sag)
var halfAngle = total / (2 * radius)
var maxDrop = radius * (1 - Math.cos(halfAngle))
var chordWidth = 2 * radius * Math.sin(halfAngle)
var travelled = 0
var left = 0, right = chordWidth
for (i = 0; i < widths.length; i++) {
var w = widths[i]
var a = (travelled + w / 2 - total / 2) / radius
var drop = radius * (1 - Math.cos(a))
var x = chordWidth / 2 + radius * Math.sin(a) - w / 2
chars.push({
x: x,
y: smile ? maxDrop - drop : drop,
rotation: (smile ? -a : a) * 180 / Math.PI
})
left = Math.min(left, x)
right = Math.max(right, x + w)
travelled += w
}
// End boxes hang past the chord; shift so x starts at zero and width covers them.
for (i = 0; i < chars.length; i++) chars[i].x -= left
return { width: right - left, height: maxDrop, chars: chars }
}
if (typeof module !== "undefined") module.exports = { layout: layout }