@protobase/ui 0.12.17 → 0.12.19
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.
- package/dist/app/map/map-section.js +38 -0
- package/dist/app/map/record-map.js +39 -0
- package/dist/app/map/record-position.js +19 -0
- package/dist/app/record-page.js +16 -4
- package/dist/data/meta-data.d.ts +4 -0
- package/dist/data/use-meta.js +1 -0
- package/dist/package.js +1 -1
- package/dist/shell/assets/app-UZDmvzr8.js +66 -0
- package/dist/shell/assets/{index-BWjIBuyP.js → index-B5suH4n_.js} +1 -1
- package/dist/shell/assets/index-UCjnDdFX.css +2 -0
- package/dist/shell/assets/maplibre-gl-D_Fikah0.js +1 -0
- package/dist/shell/assets/maplibre-gl-worker-Bh1S--WG.js +10 -0
- package/dist/shell/assets/record-map-2lnuZ7x0.js +814 -0
- package/dist/shell/assets/record-map-DBE96hFo.css +1 -0
- package/dist/shell/assets/{shared-protobase-ui-D71B9VKk.js → shared-protobase-ui-BxNF84PM.js} +1 -1
- package/dist/shell/index.html +4 -4
- package/dist/shell/protobase.shell.json +1 -1
- package/package.json +7 -4
- package/dist/shell/assets/app-CtlU7t0k.js +0 -65
- package/dist/shell/assets/index-BDDeq8hJ.css +0 -2
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { useAdminMeta } from "../meta-gate.js";
|
|
2
|
+
import { Section } from "../../record-view/section.js";
|
|
3
|
+
import { SidebarCard } from "../../record-view/record-sidebar.js";
|
|
4
|
+
import { recordPosition } from "./record-position.js";
|
|
5
|
+
import { Suspense, lazy } from "react";
|
|
6
|
+
import { jsx } from "react/jsx-runtime";
|
|
7
|
+
//#region src/app/map/map-section.tsx
|
|
8
|
+
const RecordMap = lazy(() => import("./record-map.js").then((module) => ({ default: module.RecordMap })));
|
|
9
|
+
const defaultZoom = 15;
|
|
10
|
+
/**
|
|
11
|
+
* A map of the record's position (`l.map`), in a section or a sidebar card under its title, drawn with the map style
|
|
12
|
+
* `/meta` names. Without a style, or for a record without a position, there is nothing to draw and no section.
|
|
13
|
+
*/
|
|
14
|
+
const MapSection = ({ item, record }) => {
|
|
15
|
+
const style = useAdminMeta().maps?.style;
|
|
16
|
+
const position = recordPosition(record, item);
|
|
17
|
+
if (!style || !position) return null;
|
|
18
|
+
const map = /* @__PURE__ */ jsx("div", {
|
|
19
|
+
className: `overflow-hidden rounded-lg border border-border bg-muted ${item.sidebar ? "h-48" : "h-64 md:h-80"}`,
|
|
20
|
+
children: /* @__PURE__ */ jsx(Suspense, {
|
|
21
|
+
fallback: null,
|
|
22
|
+
children: /* @__PURE__ */ jsx(RecordMap, {
|
|
23
|
+
style,
|
|
24
|
+
position,
|
|
25
|
+
zoom: item.zoom ?? defaultZoom
|
|
26
|
+
}, `${position.latitude},${position.longitude}`)
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
return item.sidebar ? /* @__PURE__ */ jsx(SidebarCard, {
|
|
30
|
+
title: item.title,
|
|
31
|
+
children: map
|
|
32
|
+
}) : /* @__PURE__ */ jsx(Section, {
|
|
33
|
+
title: item.title,
|
|
34
|
+
children: map
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { MapSection };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { MapPin } from "lucide-react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as maplibre from "maplibre-gl";
|
|
4
|
+
import workerUrl from "maplibre-gl/dist/maplibre-gl-worker.mjs?worker&url";
|
|
5
|
+
import "maplibre-gl/dist/maplibre-gl.css";
|
|
6
|
+
import { Protocol } from "pmtiles";
|
|
7
|
+
import { Map, Marker, NavigationControl } from "react-map-gl/maplibre";
|
|
8
|
+
//#region src/app/map/record-map.tsx
|
|
9
|
+
maplibre.setWorkerUrl(workerUrl);
|
|
10
|
+
maplibre.addProtocol("pmtiles", new Protocol().tile);
|
|
11
|
+
/**
|
|
12
|
+
* A map of `style` centred on `position` at `zoom`, with a pin on it. It pans and zooms with two fingers on a phone and
|
|
13
|
+
* with Ctrl or Cmd and the wheel, so scrolling the page past it does not move it.
|
|
14
|
+
*/
|
|
15
|
+
const RecordMap = ({ style, position, zoom }) => /* @__PURE__ */ jsxs(Map, {
|
|
16
|
+
mapLib: maplibre,
|
|
17
|
+
mapStyle: style,
|
|
18
|
+
initialViewState: {
|
|
19
|
+
...position,
|
|
20
|
+
zoom
|
|
21
|
+
},
|
|
22
|
+
cooperativeGestures: true,
|
|
23
|
+
style: {
|
|
24
|
+
width: "100%",
|
|
25
|
+
height: "100%"
|
|
26
|
+
},
|
|
27
|
+
children: [/* @__PURE__ */ jsx(NavigationControl, { showCompass: false }), /* @__PURE__ */ jsx(Marker, {
|
|
28
|
+
latitude: position.latitude,
|
|
29
|
+
longitude: position.longitude,
|
|
30
|
+
anchor: "bottom",
|
|
31
|
+
children: /* @__PURE__ */ jsx(MapPin, {
|
|
32
|
+
"aria-hidden": true,
|
|
33
|
+
className: "size-8 fill-primary text-primary-foreground drop-shadow",
|
|
34
|
+
strokeWidth: 1.5
|
|
35
|
+
})
|
|
36
|
+
})]
|
|
37
|
+
});
|
|
38
|
+
//#endregion
|
|
39
|
+
export { RecordMap };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/app/map/record-position.ts
|
|
2
|
+
const degrees = (value) => {
|
|
3
|
+
if (typeof value === "number") return value;
|
|
4
|
+
if (typeof value !== "string" || value.trim() === "") return void 0;
|
|
5
|
+
return Number(value);
|
|
6
|
+
};
|
|
7
|
+
/** The record's position from its two fields, when both hold degrees on the globe; none otherwise, so no map is drawn. */
|
|
8
|
+
const recordPosition = (record, fields) => {
|
|
9
|
+
const latitude = degrees(record[fields.latitude]);
|
|
10
|
+
const longitude = degrees(record[fields.longitude]);
|
|
11
|
+
if (latitude === void 0 || longitude === void 0) return void 0;
|
|
12
|
+
if (!(Math.abs(latitude) <= 90 && Math.abs(longitude) <= 180)) return void 0;
|
|
13
|
+
return {
|
|
14
|
+
latitude,
|
|
15
|
+
longitude
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
//#endregion
|
|
19
|
+
export { recordPosition };
|
package/dist/app/record-page.js
CHANGED
|
@@ -26,6 +26,7 @@ import { useRestore } from "./delete/use-restore.js";
|
|
|
26
26
|
import { ValueBadge } from "./value-badge.js";
|
|
27
27
|
import { auditField } from "../live/audit-fields.js";
|
|
28
28
|
import { CustomSection } from "./custom-section.js";
|
|
29
|
+
import { MapSection } from "./map/map-section.js";
|
|
29
30
|
import { RecordActions } from "./pages/record-actions.js";
|
|
30
31
|
import { RecordLines, findLinesResource } from "./record-lines.js";
|
|
31
32
|
import { draftStorageKey } from "./draft-storage.js";
|
|
@@ -297,6 +298,10 @@ const LoadedRecord = ({ model, recordKey, stored }) => {
|
|
|
297
298
|
item,
|
|
298
299
|
scope
|
|
299
300
|
}, `custom:${index}`)];
|
|
301
|
+
if (item.kind === "map") return item.sidebar ? [] : [/* @__PURE__ */ jsx(MapSection, {
|
|
302
|
+
item,
|
|
303
|
+
record: stored.record
|
|
304
|
+
}, `map:${index}`)];
|
|
300
305
|
if (item.kind !== "section") return [];
|
|
301
306
|
const fields = item.fields.filter((name) => model.fields[name] && visible(name));
|
|
302
307
|
if (fields.length === 0) return [];
|
|
@@ -323,10 +328,17 @@ const LoadedRecord = ({ model, recordKey, stored }) => {
|
|
|
323
328
|
recordKey
|
|
324
329
|
}),
|
|
325
330
|
firstSidebar === -1 && summary,
|
|
326
|
-
layout.map((item, index) =>
|
|
327
|
-
item,
|
|
328
|
-
|
|
329
|
-
|
|
331
|
+
layout.map((item, index) => {
|
|
332
|
+
if (item.kind === "custom" && item.sidebar) return /* @__PURE__ */ jsx(CustomSection, {
|
|
333
|
+
item,
|
|
334
|
+
scope
|
|
335
|
+
}, `custom:${index}`);
|
|
336
|
+
if (item.kind === "map" && item.sidebar) return /* @__PURE__ */ jsx(MapSection, {
|
|
337
|
+
item,
|
|
338
|
+
record: stored.record
|
|
339
|
+
}, `map:${index}`);
|
|
340
|
+
return index === firstSidebar ? /* @__PURE__ */ jsx(Fragment, { children: summary }, "summary") : null;
|
|
341
|
+
}),
|
|
330
342
|
/* @__PURE__ */ jsx(MetadataCard, {
|
|
331
343
|
title: "Details",
|
|
332
344
|
rows: [auditField(model, "created"), updatedAt].flatMap((name) => {
|
package/dist/data/meta-data.d.ts
CHANGED
|
@@ -25,6 +25,10 @@ export type MetaData = {
|
|
|
25
25
|
dsn: string;
|
|
26
26
|
environment?: string;
|
|
27
27
|
};
|
|
28
|
+
/** The map style the record page's maps are drawn with, when the app has one (see `MapSection`). */
|
|
29
|
+
maps?: {
|
|
30
|
+
style: string;
|
|
31
|
+
};
|
|
28
32
|
/** The plugins the app loads for the user (see `PluginGate`). */
|
|
29
33
|
plugins?: PluginRef[];
|
|
30
34
|
/** The other APIs the app draws resources from for the user, and how far their `/meta` has loaded (see `withSources`). */
|
package/dist/data/use-meta.js
CHANGED
|
@@ -35,6 +35,7 @@ const useMeta = () => {
|
|
|
35
35
|
...result.meta.assistant && { assistant: result.meta.assistant },
|
|
36
36
|
...result.meta.runtime && { runtime: result.meta.runtime },
|
|
37
37
|
...result.meta.errorReporting && { errorReporting: result.meta.errorReporting },
|
|
38
|
+
...result.meta.maps && { maps: result.meta.maps },
|
|
38
39
|
...result.meta.plugins && { plugins: result.meta.plugins },
|
|
39
40
|
...result.meta.sources && { sources: result.meta.sources.map((source) => ({
|
|
40
41
|
source,
|
package/dist/package.js
CHANGED