/+ sr=sortug |_ =bowl:gall ++ css ^~ %- trip ''' body { font-family: system-ui, -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif; margin: 10vh auto; max-width: 120ch; background: #fffff4; color: #140; } h1 { font-size: 1.2rem; font-weight: bold; } input, button { border: none; color: inherit; font: inherit; } input { background: none; } input:focus-visible { outline: solid 1px #140; } button { background: #261; color: white; font-weight: bold; border-radius: 0.25rem; } button:hover, button:focus-visible { background: #483; } .month-control { display: flex; } .month-control h2 { font-size: 1rem; font-weight: bold; margin: 0; margin-inline-end: auto; } .month-control a { flex: 0 1 6ch; text-align: end; font-weight: bold; color: inherit; } table { padding: 0; width: 100%; height: 100%; & th{ opacity: 0.6; text-align: center; padding: 0.5rem 0; } & td{ border-top: solid 1px currentColor; min-width: 0; min-height: 8rem; height: 4rem; } } .day-weekend { color: #c88; } .day-past { color: #2423; } .date { height: 100%; display: flex; flex-direction: column; } .date ul { padding: 0; list-style: none; } .date-num { aspect-ratio: 1; border-radius: 100rem; background: #fffff4; position: absolute; z-index: 1; } .day-today .date-num { padding: 0 0.125em; background: #220; color: white; } .create-event-form { flex: 1 1 auto; margin: 0; } .create-event { background: none; color: transparent; width: 100%; height: 100%; cursor: crosshair; } .create-event:hover, .create-event:focus-visible { background: #efe4; } .create-event:focus-visible { color: #140; } .event { margin: 0.25rem 0.5rem; } .event:first-child { margin-top: 0.5rem; } .event > form { display: flex; margin: 0; } .event-button { position: relative; flex: 1 1 auto; padding: 0.25rem; background: white; color: #000b; border-radius: 0.25rem; text-wrap: nowrap; text-overflow: ellipsis; overflow: hidden; text-align: start; font-size: 0.8rem; font-weight: bold; text-decoration: none; } .event-button::after { content: ""; position: absolute; inset: 0; } .event-button:hover::after, .event-button:focus-visible::after { background: #fff4; } .day-past .event:not(:focus-within):not(:has(dialog[open])) .event-button { opacity: 0.4; } .event dialog { inset: unset; margin-top: 0.3rem; padding: 0.75rem; background: white; border: solid 1px #ceb; box-shadow: 0 0.25rem 0.5rem #0301, 0 0rem 2rem #0301; z-index: 9999; } .event dialog::after { content: ''; position: absolute; left: 0.4rem; top: calc(-0.3rem - 2px); width: 0.6rem; height: 0.6rem; transform: rotate(45deg); background: inherit; border: inherit; border-right: none; border-bottom: none; } .event dialog form { margin: 0; display: flex; flex-direction: column; gap: 0.5rem; } .event-dialog-row { display: flex; gap: 0.5rem; } .event input[type="text"] { border-bottom: solid 1px currentColor; max-width: 15ch; } .delete-button { background: #820; } .delete-button:hover, .delete-button:focus-visible { background: #a42; } ''' ++ html |= time=@da ^- manx =, chrono:userlib =/ dat (yore time) =+ [[a y] m [d h mm s f]]=dat =/ mon %+ snag (dec m) mon:yu =/ nmon %+ snag m mon:yu =/ pmon =/ ind ?: .=(1 m) 11 (sub m 2) %+ snag ind mon:yu =/ year (scow:parsing:sr %ud y) =/ nyear (scow:parsing:sr %ud +(y)) =/ pyear (scow:parsing:sr %ud (dec y)) =/ weekday %+ snag (daws dat) wik:yu :: =/ weeknames (snoc +.wik:yu -.wik:yu) =/ weeknames wik:yu =/ first-of-month dat(d.t 1) =/ month-starts-at (daws first-of-month) ;div#month.month ;style: {css} ;div.month-control ;h2.current-month:"{mon} {year}" ;a/"":"<- {pmon}" ;a/"":"{nmon} ->" == ;table ;tr ;* %+ turn weeknames |= t=tape ;th.wday-name:"{t}" == ;* %+ turn (get-nums time) |= l=(list date) ;tr ;* %+ turn l cell == == == +$ row (list date) ++ get-nums |= =time ^- (list row) =, chrono:userlib =/ =date (yore time) =+ [[a y] m [d h mm s f]]=date =/ first-of-month date(d.t 1) =/ first-day (year first-of-month) =/ month-start (daws first-of-month) ~& month-start=month-start =| l=(list row) =| i=@ud |- =/ dat ?: (gth month-start i) =/ diff (sub month-start i) =/ back (sub first-day (mul ~d1 diff)) (yore back) =/ curr (sub i month-start) (yore (add first-day (mul ~d1 curr))) :: =/ nm m.added :: =/ to-next-month (gth nm m) :: ?: to-next-month added curr ?~ l $(l [~[dat] l], i +(i)) ?. .=(0 (mod i 7)) =. i.l [dat i.l] $(i +(i)) =. i.l (flop i.l) =/ curr (sub i month-start) =/ added (yore (add first-day (mul ~d1 curr))) =/ nm m.added =/ to-next-month (gth nm m) ?: to-next-month (flop l) =/ nrow ~[added] $(l [nrow l], i +(i)) :: exit-condition ++ cell |= =date ^- manx =/ [faded=? today=?] [.n .n] =/ nums (scow %ud d.t.date) ?: faded :: ;td.faded ;div:"{nums}" == ?: today ;td.today ;div:"{nums}" == :: ;td ;div:"{nums}" == :: ++ get-num |= [feira=@ud =time] ^- @ud =, chrono:userlib =/ date (yore time) =/ first-of-month date(d.t 1) =/ month-starts-at (daws first-of-month) ?: (lth feira month-starts-at) =/ diff (sub month-starts-at feira) =/ back (sub time (mul ~d1 diff)) d.t:(yore back) :: e.g. month starts in day 3 (thu) and we're in day 4 (fri) =/ diff (sub feira month-starts-at) +(diff) --