@protobase/ui 0.23.6 → 0.23.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/app/current-address.d.ts +4 -3
  2. package/dist/app/current-address.js +1 -0
  3. package/dist/app/displays/calendar-controls.js +17 -49
  4. package/dist/app/displays/calendar-event.js +2 -2
  5. package/dist/app/displays/calendar-range.js +19 -9
  6. package/dist/app/displays/display-controls.js +2 -1
  7. package/dist/app/displays/list-displays.js +8 -1
  8. package/dist/app/displays/period-controls.js +55 -0
  9. package/dist/app/displays/timeline-display.js +225 -0
  10. package/dist/app/displays/timeline-range.js +140 -0
  11. package/dist/app/displays/timeline-row.js +42 -0
  12. package/dist/app/displays/timeline-scale.js +50 -0
  13. package/dist/app/embedded-list/embedded-list.js +7 -0
  14. package/dist/app/index.html +2 -0
  15. package/dist/app/list-page.js +11 -1
  16. package/dist/format/date.js +6 -1
  17. package/dist/package.js +1 -1
  18. package/dist/shell/assets/app-BaOeRmvJ.js +69 -0
  19. package/dist/shell/assets/{index-CY5B9PIg.js → index-BSpJh7ky.js} +1 -1
  20. package/dist/shell/assets/index-Br0ZlvVS.css +2 -0
  21. package/dist/shell/assets/{maplibre-D4ace4wn.js → maplibre--RHVslik.js} +1 -1
  22. package/dist/shell/assets/{markdown-content-JU2jw1Kr.js → markdown-content-CNP__2Lb.js} +1 -1
  23. package/dist/shell/assets/{record-map-B8GB--Ku.js → record-map-CS2kj78D.js} +1 -1
  24. package/dist/shell/assets/{records-map-BUfPiD0T.js → records-map-D66qm5NI.js} +1 -1
  25. package/dist/shell/assets/{shared-protobase-ui-C0Ld98uO.js → shared-protobase-ui-C2BPkI-k.js} +1 -1
  26. package/dist/shell/index.html +7 -4
  27. package/dist/shell/protobase.shell.json +3 -2
  28. package/dist/shell/protobase.sw.js +33 -0
  29. package/package.json +4 -4
  30. package/dist/shell/assets/app-ByxJ0Flo.js +0 -69
  31. package/dist/shell/assets/index-B-IciGPG.css +0 -2
@@ -0,0 +1,42 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { CalendarEvent, eventTitle } from "./calendar-event.js";
3
+ import { barOf } from "./timeline-range.js";
4
+ import { share, timelineGrid } from "./timeline-scale.js";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/app/displays/timeline-row.tsx
7
+ /**
8
+ * A record of a timeline: its title, and its bar over the days it is on, an event chip as wide as those days, cut
9
+ * square where it goes on before or after them. The bar is the link to the record, and is picked up to move it.
10
+ */
11
+ const TimelineRow = ({ model, view, display, row, days, movable, dragged }) => {
12
+ const bar = barOf(row.record, display, model, days);
13
+ return /* @__PURE__ */ jsxs("div", {
14
+ className: cn(timelineGrid, "relative border-b border-border last:border-b-0"),
15
+ children: [/* @__PURE__ */ jsx("span", {
16
+ "aria-hidden": true,
17
+ className: "truncate px-2 pt-1 text-xs sm:py-1.5",
18
+ children: eventTitle(model, view, display, row)
19
+ }), /* @__PURE__ */ jsx("div", {
20
+ className: "relative h-7",
21
+ children: bar && /* @__PURE__ */ jsx("div", {
22
+ className: "absolute top-1/2 -translate-y-1/2",
23
+ style: {
24
+ left: share(bar.first, days.length),
25
+ width: share(bar.last - bar.first + 1, days.length)
26
+ },
27
+ children: /* @__PURE__ */ jsx(CalendarEvent, {
28
+ model,
29
+ view,
30
+ display,
31
+ row,
32
+ day: bar.start,
33
+ movable,
34
+ dragged,
35
+ className: cn(bar.before && "rounded-l-none border-l-0", bar.after && "rounded-r-none border-r-0")
36
+ })
37
+ })
38
+ })]
39
+ });
40
+ };
41
+ //#endregion
42
+ export { TimelineRow };
@@ -0,0 +1,50 @@
1
+ import { cn } from "../../lib/cn.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/app/displays/timeline-scale.tsx
4
+ /** A timeline's columns: the records' titles beside their bars, above them on a phone. */
5
+ const timelineGrid = "grid grid-cols-1 sm:grid-cols-[12rem_minmax(0,1fr)]";
6
+ /** Where `count` days of `total` end, as a share of the bars' width. */
7
+ const share = (count, total) => `${count / total * 100}%`;
8
+ /** The scale over a timeline's rows: the marks of its days or months, today's marked. */
9
+ const TimelineScale = ({ ticks, days, today, label, trackRef }) => /* @__PURE__ */ jsxs("div", {
10
+ className: cn(timelineGrid, "border-b border-border bg-surface"),
11
+ children: [/* @__PURE__ */ jsx("span", {
12
+ className: "hidden truncate px-2 py-1 text-xs font-medium text-muted-foreground sm:block",
13
+ children: label
14
+ }), /* @__PURE__ */ jsx("div", {
15
+ ref: trackRef,
16
+ "aria-hidden": true,
17
+ className: "relative h-6",
18
+ children: ticks.map((tick) => /* @__PURE__ */ jsx("span", {
19
+ className: cn("absolute inset-y-0 items-center truncate px-1 text-xs tabular-nums text-muted-foreground", tick.index > 0 ? "border-l border-border" : "border-border sm:border-l", tick.minor ? "hidden sm:flex" : "flex", tick.span === 1 && days[tick.index] === today && "font-medium text-primary"),
20
+ style: {
21
+ left: share(tick.index, days.length),
22
+ width: share(tick.span, days.length)
23
+ },
24
+ children: tick.label
25
+ }, tick.index))
26
+ })]
27
+ });
28
+ /** The lines behind a timeline's rows where each mark starts, and today's day shaded. */
29
+ const TimelineLines = ({ ticks, days, today }) => {
30
+ const at = days.indexOf(today);
31
+ return /* @__PURE__ */ jsxs("div", {
32
+ "aria-hidden": true,
33
+ className: cn(timelineGrid, "pointer-events-none absolute inset-0"),
34
+ children: [/* @__PURE__ */ jsx("span", { className: "hidden sm:block" }), /* @__PURE__ */ jsxs("div", {
35
+ className: "relative",
36
+ children: [at >= 0 && /* @__PURE__ */ jsx("span", {
37
+ className: "absolute inset-y-0 bg-primary/10",
38
+ style: {
39
+ left: share(at, days.length),
40
+ width: share(1, days.length)
41
+ }
42
+ }), ticks.map((tick) => /* @__PURE__ */ jsx("span", {
43
+ className: cn("absolute inset-y-0 w-px bg-border", (tick.minor || tick.index === 0) && "hidden sm:block"),
44
+ style: { left: share(tick.index, days.length) }
45
+ }, tick.index))]
46
+ })]
47
+ });
48
+ };
49
+ //#endregion
50
+ export { TimelineLines, TimelineScale, share, timelineGrid };
@@ -13,6 +13,7 @@ import { DataGrid } from "../../data-grid/data-grid.js";
13
13
  import { viewAllAddress } from "./embedded-display.js";
14
14
  import { BoardDisplay } from "../displays/board-display.js";
15
15
  import { CalendarDisplay } from "../displays/calendar-display.js";
16
+ import { TimelineDisplay } from "../displays/timeline-display.js";
16
17
  import { CardsDisplay } from "../displays/cards-display.js";
17
18
  import { CustomDisplay } from "../displays/custom-display.js";
18
19
  import { MapDisplay } from "../displays/map-display.js";
@@ -181,6 +182,12 @@ const EmbeddedList = ({ model, view, filter, sort, columns, limit, display, empt
181
182
  display: shown,
182
183
  fields,
183
184
  filter
185
+ }) : shown.kind === "timeline" ? /* @__PURE__ */ jsx(TimelineDisplay, {
186
+ model,
187
+ view,
188
+ display: shown,
189
+ fields,
190
+ filter
184
191
  }) : /* @__PURE__ */ jsx(CustomDisplay, {
185
192
  display: shown,
186
193
  list
@@ -4,6 +4,8 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
6
  <title>Protobase</title>
7
+ <!-- Makes the app installable, named for the app: the server answers it, as it alone knows the name. -->
8
+ <link rel="manifest" href="/api/manifest.webmanifest" />
7
9
  <!-- The theme before the first paint, so a dark page never flashes light: as theme/theme-preference.ts resolves it, the choice stored in this browser, else the system's. -->
8
10
  <script>
9
11
  var stored = null
@@ -34,6 +34,7 @@ import { listHandOrder } from "./hand-order/hand-order.js";
34
34
  import { useDisplayRows } from "./displays/use-display-rows.js";
35
35
  import { BoardDisplay } from "./displays/board-display.js";
36
36
  import { CalendarDisplay } from "./displays/calendar-display.js";
37
+ import { TimelineDisplay } from "./displays/timeline-display.js";
37
38
  import { CustomDisplay } from "./displays/custom-display.js";
38
39
  import { MapDisplay } from "./displays/map-display.js";
39
40
  import { DisplaySwitch, SortMenu } from "./displays/display-controls.js";
@@ -213,7 +214,7 @@ const LoadedList = ({ model, address, scope, heading }) => {
213
214
  setFilter(state, text ? [...others, where$1.search(text)] : others);
214
215
  };
215
216
  const plural = view?.names?.plural ?? humanize(resource);
216
- const sorted = display?.kind === "calendar" || display?.kind === "board" && boardRank(model) ? void 0 : display;
217
+ const sorted = display?.kind === "calendar" || display?.kind === "timeline" || display?.kind === "board" && boardRank(model) ? void 0 : display;
217
218
  const sortMenu = sorted && /* @__PURE__ */ jsx(SortMenu, {
218
219
  model,
219
220
  view,
@@ -446,6 +447,15 @@ const LoadedList = ({ model, address, scope, heading }) => {
446
447
  at: address.calendar,
447
448
  linkTo: (calendar) => listTo({ calendar })
448
449
  });
450
+ if (display.kind === "timeline") return /* @__PURE__ */ jsx(TimelineDisplay, {
451
+ model,
452
+ view,
453
+ display,
454
+ fields: loaded,
455
+ filter: loadFilter,
456
+ at: address.timeline,
457
+ linkTo: (timeline) => listTo({ timeline })
458
+ });
449
459
  return /* @__PURE__ */ jsx(CustomDisplay, {
450
460
  display,
451
461
  list: displayRows
@@ -19,6 +19,7 @@ const month = dateFormat("month", {
19
19
  month: "long",
20
20
  year: "numeric"
21
21
  });
22
+ const monthName = dateFormat("monthName", { month: "long" });
22
23
  const weekday = dateFormat("weekday", { weekday: "short" });
23
24
  const weekdayDate = dateFormat("weekdayDate", {
24
25
  weekday: "long",
@@ -49,6 +50,10 @@ const formatDateTime = (ms, zone = viewerZone()) => {
49
50
  };
50
51
  /** "October 2026". */
51
52
  const formatMonth = (ms) => month().format(ms);
53
+ /** "October". */
54
+ const formatMonthName = (ms) => monthName().format(ms);
55
+ /** "October – December 2026": the months from `from` to `to`, both included. */
56
+ const formatMonthRange = (from, to) => month().formatRange(from, to);
52
57
  /** "Mon". */
53
58
  const formatWeekday = (ms) => weekday().format(ms);
54
59
  /** "Monday, 12 Oct 2026". */
@@ -79,4 +84,4 @@ const formatRelativeTime = (seconds) => {
79
84
  return relative().format(-Math.sign(seconds) * Math.floor(away / size), unit);
80
85
  };
81
86
  //#endregion
82
- export { formatAgo, formatDate, formatDateTime, formatDayRange, formatDayShort, formatMonth, formatRelativeTime, formatTime, formatWeekday, formatWeekdayDate };
87
+ export { formatAgo, formatDate, formatDateTime, formatDayRange, formatDayShort, formatMonth, formatMonthName, formatMonthRange, formatRelativeTime, formatTime, formatWeekday, formatWeekdayDate };
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.23.6";
2
+ var version = "0.23.8";
3
3
  var protobase = { "pluginApi": 1 };
4
4
  //#endregion
5
5
  export { protobase, version };