@sqlrooms/deck 0.29.0-rc.12 → 0.29.0-rc.13

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 (55) hide show
  1. package/README.md +144 -22
  2. package/dist/DeckJsonMap.d.ts.map +1 -1
  3. package/dist/DeckJsonMap.js +58 -12
  4. package/dist/DeckJsonMap.js.map +1 -1
  5. package/dist/DeckMapBasemapSelect.d.ts +9 -0
  6. package/dist/DeckMapBasemapSelect.d.ts.map +1 -0
  7. package/dist/DeckMapBasemapSelect.js +20 -0
  8. package/dist/DeckMapBasemapSelect.js.map +1 -0
  9. package/dist/DeckMapDefaultStylesProvider.d.ts +13 -19
  10. package/dist/DeckMapDefaultStylesProvider.d.ts.map +1 -1
  11. package/dist/DeckMapDefaultStylesProvider.js +11 -18
  12. package/dist/DeckMapDefaultStylesProvider.js.map +1 -1
  13. package/dist/DeckMapsSlice.d.ts +5 -0
  14. package/dist/DeckMapsSlice.d.ts.map +1 -1
  15. package/dist/DeckMapsSlice.js +6 -3
  16. package/dist/DeckMapsSlice.js.map +1 -1
  17. package/dist/MapSettings.d.ts.map +1 -1
  18. package/dist/MapSettings.js +3 -2
  19. package/dist/MapSettings.js.map +1 -1
  20. package/dist/ai.d.ts.map +1 -1
  21. package/dist/ai.js +15 -10
  22. package/dist/ai.js.map +1 -1
  23. package/dist/basemap.d.ts +23 -0
  24. package/dist/basemap.d.ts.map +1 -0
  25. package/dist/basemap.js +23 -0
  26. package/dist/basemap.js.map +1 -0
  27. package/dist/block.d.ts.map +1 -1
  28. package/dist/block.js +12 -8
  29. package/dist/block.js.map +1 -1
  30. package/dist/index.d.ts +4 -1
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +4 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/mapAiSharedInstructions.d.ts.map +1 -1
  35. package/dist/mapAiSharedInstructions.js +1 -0
  36. package/dist/mapAiSharedInstructions.js.map +1 -1
  37. package/dist/mapConfig.d.ts +5 -0
  38. package/dist/mapConfig.d.ts.map +1 -1
  39. package/dist/mapConfig.js +28 -3
  40. package/dist/mapConfig.js.map +1 -1
  41. package/dist/mapConfigUtils.d.ts.map +1 -1
  42. package/dist/mapConfigUtils.js +7 -2
  43. package/dist/mapConfigUtils.js.map +1 -1
  44. package/dist/mapStyles.d.ts +16 -0
  45. package/dist/mapStyles.d.ts.map +1 -0
  46. package/dist/mapStyles.js +32 -0
  47. package/dist/mapStyles.js.map +1 -0
  48. package/dist/protomapsStyles.d.ts +18 -0
  49. package/dist/protomapsStyles.d.ts.map +1 -0
  50. package/dist/protomapsStyles.js +38 -0
  51. package/dist/protomapsStyles.js.map +1 -0
  52. package/dist/types.d.ts +13 -0
  53. package/dist/types.d.ts.map +1 -1
  54. package/dist/types.js.map +1 -1
  55. package/package.json +11 -9
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, useTheme, } from '@sqlrooms/ui';
3
+ import { DECK_MAP_BASEMAP_STYLES, getDeckMapStyleTheme, getDefaultDeckMapStyle, } from './mapStyles';
4
+ import { DeckMapSettingsField } from './MapSettingsControls';
5
+ /** Selects a persistent basemap independently of the app's current theme. */
6
+ export const DeckMapBasemapSelect = ({ config, onConfigChange, readOnly }) => {
7
+ const { resolvedTheme } = useTheme();
8
+ const style = config.mapStyle ?? config.mapProps?.mapStyle;
9
+ const styleTheme = getDeckMapStyleTheme(style);
10
+ const value = style
11
+ ? styleTheme
12
+ ? getDefaultDeckMapStyle(styleTheme)
13
+ : 'custom'
14
+ : getDefaultDeckMapStyle(resolvedTheme);
15
+ return (_jsx(DeckMapSettingsField, { label: "Basemap", children: _jsxs(Select, { value: value, disabled: readOnly, onValueChange: (mapStyle) => {
16
+ if (!readOnly)
17
+ onConfigChange({ ...config, mapStyle });
18
+ }, children: [_jsx(SelectTrigger, { "aria-label": "Basemap", className: "w-full text-xs", children: _jsx(SelectValue, {}) }), _jsxs(SelectContent, { children: [DECK_MAP_BASEMAP_STYLES.map(({ id, label }) => (_jsx(SelectItem, { value: id, className: "text-xs", children: label }, id))), value === 'custom' && (_jsx(SelectItem, { value: "custom", className: "text-xs", disabled: true, children: "Custom" }))] })] }) }));
19
+ };
20
+ //# sourceMappingURL=DeckMapBasemapSelect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeckMapBasemapSelect.js","sourceRoot":"","sources":["../src/DeckMapBasemapSelect.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,UAAU,EACV,aAAa,EACb,WAAW,EACX,QAAQ,GACT,MAAM,cAAc,CAAC;AAGtB,OAAO,EACL,uBAAuB,EACvB,oBAAoB,EACpB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAC,oBAAoB,EAAC,MAAM,uBAAuB,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,CAAC,MAAM,oBAAoB,GAI5B,CAAC,EAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAC,EAAE,EAAE;IAC1C,MAAM,EAAC,aAAa,EAAC,GAAG,QAAQ,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC3D,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,KAAK;QACjB,CAAC,CAAC,UAAU;YACV,CAAC,CAAC,sBAAsB,CAAC,UAAU,CAAC;YACpC,CAAC,CAAC,QAAQ;QACZ,CAAC,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC;IAE1C,OAAO,CACL,KAAC,oBAAoB,IAAC,KAAK,EAAC,SAAS,YACnC,MAAC,MAAM,IACL,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,aAAa,EAAE,CAAC,QAAQ,EAAE,EAAE;gBAC1B,IAAI,CAAC,QAAQ;oBAAE,cAAc,CAAC,EAAC,GAAG,MAAM,EAAE,QAAQ,EAAC,CAAC,CAAC;YACvD,CAAC,aAED,KAAC,aAAa,kBAAY,SAAS,EAAC,SAAS,EAAC,gBAAgB,YAC5D,KAAC,WAAW,KAAG,GACD,EAChB,MAAC,aAAa,eACX,uBAAuB,CAAC,GAAG,CAAC,CAAC,EAAC,EAAE,EAAE,KAAK,EAAC,EAAE,EAAE,CAAC,CAC5C,KAAC,UAAU,IAAU,KAAK,EAAE,EAAE,EAAE,SAAS,EAAC,SAAS,YAChD,KAAK,IADS,EAAE,CAEN,CACd,CAAC,EACD,KAAK,KAAK,QAAQ,IAAI,CACrB,KAAC,UAAU,IAAC,KAAK,EAAC,QAAQ,EAAC,SAAS,EAAC,SAAS,EAAC,QAAQ,6BAE1C,CACd,IACa,IACT,GACY,CACxB,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n useTheme,\n} from '@sqlrooms/ui';\nimport type {FC} from 'react';\nimport type {DeckMapConfig} from './mapConfig';\nimport {\n DECK_MAP_BASEMAP_STYLES,\n getDeckMapStyleTheme,\n getDefaultDeckMapStyle,\n} from './mapStyles';\nimport {DeckMapSettingsField} from './MapSettingsControls';\n\n/** Selects a persistent basemap independently of the app's current theme. */\nexport const DeckMapBasemapSelect: FC<{\n config: DeckMapConfig;\n onConfigChange: (config: DeckMapConfig) => void;\n readOnly?: boolean;\n}> = ({config, onConfigChange, readOnly}) => {\n const {resolvedTheme} = useTheme();\n const style = config.mapStyle ?? config.mapProps?.mapStyle;\n const styleTheme = getDeckMapStyleTheme(style);\n const value = style\n ? styleTheme\n ? getDefaultDeckMapStyle(styleTheme)\n : 'custom'\n : getDefaultDeckMapStyle(resolvedTheme);\n\n return (\n <DeckMapSettingsField label=\"Basemap\">\n <Select\n value={value}\n disabled={readOnly}\n onValueChange={(mapStyle) => {\n if (!readOnly) onConfigChange({...config, mapStyle});\n }}\n >\n <SelectTrigger aria-label=\"Basemap\" className=\"w-full text-xs\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {DECK_MAP_BASEMAP_STYLES.map(({id, label}) => (\n <SelectItem key={id} value={id} className=\"text-xs\">\n {label}\n </SelectItem>\n ))}\n {value === 'custom' && (\n <SelectItem value=\"custom\" className=\"text-xs\" disabled>\n Custom\n </SelectItem>\n )}\n </SelectContent>\n </Select>\n </DeckMapSettingsField>\n );\n};\n"]}
@@ -1,27 +1,21 @@
1
- import type { ResolvedTheme } from '@sqlrooms/ui';
2
- import type { MapProps } from 'react-map-gl/maplibre';
1
+ import type { DeckMapDefaultStyles } from './basemap';
3
2
  import { type FC, type PropsWithChildren } from 'react';
4
- /** A MapLibre-compatible style accepted by the Deck map renderer. */
5
- export type DeckMapStyle = NonNullable<MapProps['mapStyle']>;
6
- /** Optional host-provided basemap defaults keyed by resolved UI theme. */
7
- export type DeckMapDefaultStyles = Partial<Record<ResolvedTheme, DeckMapStyle>>;
8
3
  /**
9
4
  * Supplies host-owned, theme-aware basemap defaults without persisting them in
10
- * individual map resources. Explicit map config styles still take precedence.
5
+ * individual map resources. The required `styles` object is keyed by `light`
6
+ * and/or `dark`. Explicit map styles and basemap callbacks take precedence.
7
+ *
8
+ * @deprecated Configure `basemapProvider` on `createDeckMapsSlice` or pass it
9
+ * directly to `DeckJsonMap` instead. Retained for backward compatibility.
11
10
  */
12
11
  export declare const DeckMapDefaultStylesProvider: FC<PropsWithChildren<{
13
12
  styles: DeckMapDefaultStyles;
14
13
  }>>;
15
- /** Returns theme-aware host map defaults from the nearest provider, if any. */
16
- export declare function useDeckMapDefaultStyles(): Partial<Record<ResolvedTheme, DeckMapStyle>> | undefined;
17
- /** True for `mapbox://` style URLs (MapLibre cannot load them without a token). */
18
- export declare function isMapboxStyleUrl(style: unknown): boolean;
19
- /** Resolve map style; skips `mapbox://` so the map can still load. */
20
- export declare function resolveDeckMapStyle(options: {
21
- mapStyle?: string;
22
- mapPropsMapStyle?: MapProps['mapStyle'];
23
- hostDefaultStyles?: DeckMapDefaultStyles;
24
- resolvedTheme: ResolvedTheme;
25
- fallbackStyles: Record<ResolvedTheme, string>;
26
- }): DeckMapStyle;
14
+ /**
15
+ * Returns theme-aware host map defaults from the nearest provider, if any.
16
+ *
17
+ * @deprecated Use the room's `deckMaps.basemapProvider` or an explicitly supplied
18
+ * basemap callback instead. Retained for backward compatibility.
19
+ */
20
+ export declare function useDeckMapDefaultStyles(): Partial<Record<import("@sqlrooms/ui").ResolvedTheme, import("./basemap").DeckMapStyle>> | undefined;
27
21
  //# sourceMappingURL=DeckMapDefaultStylesProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeckMapDefaultStylesProvider.d.ts","sourceRoot":"","sources":["../src/DeckMapDefaultStylesProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAGL,KAAK,EAAE,EACP,KAAK,iBAAiB,EACvB,MAAM,OAAO,CAAC;AAEf,qEAAqE;AACrE,MAAM,MAAM,YAAY,GAAG,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;AAE7D,0EAA0E;AAC1E,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC;AAMhF;;;GAGG;AACH,eAAO,MAAM,4BAA4B,EAAE,EAAE,CAC3C,iBAAiB,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAC,CAAC,CAKlD,CAAC;AAEF,+EAA+E;AAC/E,wBAAgB,uBAAuB,6DAEtC;AAED,mFAAmF;AACnF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAExD;AASD,sEAAsE;AACtE,wBAAgB,mBAAmB,CAAC,OAAO,EAAE;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC;IACxC,iBAAiB,CAAC,EAAE,oBAAoB,CAAC;IACzC,aAAa,EAAE,aAAa,CAAC;IAC7B,cAAc,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;CAC/C,GAAG,YAAY,CAOf"}
1
+ {"version":3,"file":"DeckMapDefaultStylesProvider.d.ts","sourceRoot":"","sources":["../src/DeckMapDefaultStylesProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,oBAAoB,EAAC,MAAM,WAAW,CAAC;AACpD,OAAO,EAGL,KAAK,EAAE,EACP,KAAK,iBAAiB,EACvB,MAAM,OAAO,CAAC;AAMf;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,EAAE,EAAE,CAC3C,iBAAiB,CAAC;IAAC,MAAM,EAAE,oBAAoB,CAAA;CAAC,CAAC,CAKlD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,wGAEtC"}
@@ -3,27 +3,20 @@ import { createContext, useContext, } from 'react';
3
3
  const DeckMapDefaultStylesContext = createContext(undefined);
4
4
  /**
5
5
  * Supplies host-owned, theme-aware basemap defaults without persisting them in
6
- * individual map resources. Explicit map config styles still take precedence.
6
+ * individual map resources. The required `styles` object is keyed by `light`
7
+ * and/or `dark`. Explicit map styles and basemap callbacks take precedence.
8
+ *
9
+ * @deprecated Configure `basemapProvider` on `createDeckMapsSlice` or pass it
10
+ * directly to `DeckJsonMap` instead. Retained for backward compatibility.
7
11
  */
8
12
  export const DeckMapDefaultStylesProvider = ({ styles, children }) => (_jsx(DeckMapDefaultStylesContext.Provider, { value: styles, children: children }));
9
- /** Returns theme-aware host map defaults from the nearest provider, if any. */
13
+ /**
14
+ * Returns theme-aware host map defaults from the nearest provider, if any.
15
+ *
16
+ * @deprecated Use the room's `deckMaps.basemapProvider` or an explicitly supplied
17
+ * basemap callback instead. Retained for backward compatibility.
18
+ */
10
19
  export function useDeckMapDefaultStyles() {
11
20
  return useContext(DeckMapDefaultStylesContext);
12
21
  }
13
- /** True for `mapbox://` style URLs (MapLibre cannot load them without a token). */
14
- export function isMapboxStyleUrl(style) {
15
- return typeof style === 'string' && /^mapbox:/i.test(style.trim());
16
- }
17
- function usableMapStyle(style) {
18
- if (style == null || isMapboxStyleUrl(style))
19
- return undefined;
20
- return style;
21
- }
22
- /** Resolve map style; skips `mapbox://` so the map can still load. */
23
- export function resolveDeckMapStyle(options) {
24
- return (usableMapStyle(options.mapStyle) ??
25
- usableMapStyle(options.mapPropsMapStyle) ??
26
- usableMapStyle(options.hostDefaultStyles?.[options.resolvedTheme]) ??
27
- options.fallbackStyles[options.resolvedTheme]);
28
- }
29
22
  //# sourceMappingURL=DeckMapDefaultStylesProvider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DeckMapDefaultStylesProvider.js","sourceRoot":"","sources":["../src/DeckMapDefaultStylesProvider.tsx"],"names":[],"mappings":";AAEA,OAAO,EACL,aAAa,EACb,UAAU,GAGX,MAAM,OAAO,CAAC;AAQf,MAAM,2BAA2B,GAAG,aAAa,CAE/C,SAAS,CAAC,CAAC;AAEb;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAErC,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAC,EAAE,EAAE,CAAC,CAC1B,KAAC,2BAA2B,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YAChD,QAAQ,GAC4B,CACxC,CAAC;AAEF,+EAA+E;AAC/E,MAAM,UAAU,uBAAuB;IACrC,OAAO,UAAU,CAAC,2BAA2B,CAAC,CAAC;AACjD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AACrE,CAAC;AAED,SAAS,cAAc,CACrB,KAAgD;IAEhD,IAAI,KAAK,IAAI,IAAI,IAAI,gBAAgB,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC/D,OAAO,KAAqB,CAAC;AAC/B,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,mBAAmB,CAAC,OAMnC;IACC,OAAO,CACL,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC;QAChC,cAAc,CAAC,OAAO,CAAC,gBAAgB,CAAC;QACxC,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAClE,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,aAAa,CAAC,CAC9C,CAAC;AACJ,CAAC","sourcesContent":["import type {ResolvedTheme} from '@sqlrooms/ui';\nimport type {MapProps} from 'react-map-gl/maplibre';\nimport {\n createContext,\n useContext,\n type FC,\n type PropsWithChildren,\n} from 'react';\n\n/** A MapLibre-compatible style accepted by the Deck map renderer. */\nexport type DeckMapStyle = NonNullable<MapProps['mapStyle']>;\n\n/** Optional host-provided basemap defaults keyed by resolved UI theme. */\nexport type DeckMapDefaultStyles = Partial<Record<ResolvedTheme, DeckMapStyle>>;\n\nconst DeckMapDefaultStylesContext = createContext<\n DeckMapDefaultStyles | undefined\n>(undefined);\n\n/**\n * Supplies host-owned, theme-aware basemap defaults without persisting them in\n * individual map resources. Explicit map config styles still take precedence.\n */\nexport const DeckMapDefaultStylesProvider: FC<\n PropsWithChildren<{styles: DeckMapDefaultStyles}>\n> = ({styles, children}) => (\n <DeckMapDefaultStylesContext.Provider value={styles}>\n {children}\n </DeckMapDefaultStylesContext.Provider>\n);\n\n/** Returns theme-aware host map defaults from the nearest provider, if any. */\nexport function useDeckMapDefaultStyles() {\n return useContext(DeckMapDefaultStylesContext);\n}\n\n/** True for `mapbox://` style URLs (MapLibre cannot load them without a token). */\nexport function isMapboxStyleUrl(style: unknown): boolean {\n return typeof style === 'string' && /^mapbox:/i.test(style.trim());\n}\n\nfunction usableMapStyle(\n style: string | MapProps['mapStyle'] | undefined,\n): DeckMapStyle | undefined {\n if (style == null || isMapboxStyleUrl(style)) return undefined;\n return style as DeckMapStyle;\n}\n\n/** Resolve map style; skips `mapbox://` so the map can still load. */\nexport function resolveDeckMapStyle(options: {\n mapStyle?: string;\n mapPropsMapStyle?: MapProps['mapStyle'];\n hostDefaultStyles?: DeckMapDefaultStyles;\n resolvedTheme: ResolvedTheme;\n fallbackStyles: Record<ResolvedTheme, string>;\n}): DeckMapStyle {\n return (\n usableMapStyle(options.mapStyle) ??\n usableMapStyle(options.mapPropsMapStyle) ??\n usableMapStyle(options.hostDefaultStyles?.[options.resolvedTheme]) ??\n options.fallbackStyles[options.resolvedTheme]\n );\n}\n"]}
1
+ {"version":3,"file":"DeckMapDefaultStylesProvider.js","sourceRoot":"","sources":["../src/DeckMapDefaultStylesProvider.tsx"],"names":[],"mappings":";AACA,OAAO,EACL,aAAa,EACb,UAAU,GAGX,MAAM,OAAO,CAAC;AAEf,MAAM,2BAA2B,GAAG,aAAa,CAE/C,SAAS,CAAC,CAAC;AAEb;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAErC,CAAC,EAAC,MAAM,EAAE,QAAQ,EAAC,EAAE,EAAE,CAAC,CAC1B,KAAC,2BAA2B,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,YAChD,QAAQ,GAC4B,CACxC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB;IACrC,OAAO,UAAU,CAAC,2BAA2B,CAAC,CAAC;AACjD,CAAC","sourcesContent":["import type {DeckMapDefaultStyles} from './basemap';\nimport {\n createContext,\n useContext,\n type FC,\n type PropsWithChildren,\n} from 'react';\n\nconst DeckMapDefaultStylesContext = createContext<\n DeckMapDefaultStyles | undefined\n>(undefined);\n\n/**\n * Supplies host-owned, theme-aware basemap defaults without persisting them in\n * individual map resources. The required `styles` object is keyed by `light`\n * and/or `dark`. Explicit map styles and basemap callbacks take precedence.\n *\n * @deprecated Configure `basemapProvider` on `createDeckMapsSlice` or pass it\n * directly to `DeckJsonMap` instead. Retained for backward compatibility.\n */\nexport const DeckMapDefaultStylesProvider: FC<\n PropsWithChildren<{styles: DeckMapDefaultStyles}>\n> = ({styles, children}) => (\n <DeckMapDefaultStylesContext.Provider value={styles}>\n {children}\n </DeckMapDefaultStylesContext.Provider>\n);\n\n/**\n * Returns theme-aware host map defaults from the nearest provider, if any.\n *\n * @deprecated Use the room's `deckMaps.basemapProvider` or an explicitly supplied\n * basemap callback instead. Retained for backward compatibility.\n */\nexport function useDeckMapDefaultStyles() {\n return useContext(DeckMapDefaultStylesContext);\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { type DuckDbSliceState } from '@sqlrooms/duckdb';
2
2
  import { z } from 'zod';
3
+ import type { DeckMapBasemapProvider } from './basemap';
3
4
  import { type DeckMapConfig } from './mapConfig';
4
5
  /** Runtime schema for a durable Deck map resource entry. */
5
6
  export declare const DeckMapResourceSchema: z.ZodObject<{
@@ -70,6 +71,8 @@ export type DeckMapRuntimeIssueReporter = {
70
71
  export type DeckMapsSliceState = {
71
72
  deckMaps: {
72
73
  config: DeckMapsSliceConfig;
74
+ /** Optional runtime basemap provider shared by maps in this room. */
75
+ basemapProvider?: DeckMapBasemapProvider;
73
76
  runtime: {
74
77
  issuesByMapId: Record<string, DeckMapRuntimeIssue>;
75
78
  };
@@ -93,6 +96,8 @@ export type DeckMapsSliceState = {
93
96
  */
94
97
  export declare function createDeckMapsSlice(props?: {
95
98
  config?: Partial<DeckMapsSliceConfig>;
99
+ /** Optional host-owned basemaps. The provider is not persisted in map config. */
100
+ basemapProvider?: DeckMapBasemapProvider;
96
101
  }): import("zustand").StateCreator<DeckMapsSliceState>;
97
102
  /** Selects Deck map and DuckDB state from the current room store. */
98
103
  export declare function useStoreWithDeckMaps<T>(selector: (state: DeckMapsSliceState & DuckDbSliceState) => T): T;
@@ -1 +1 @@
1
- {"version":3,"file":"DeckMapsSlice.d.ts","sourceRoot":"","sources":["../src/DeckMapsSlice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAA2B,KAAK,aAAa,EAAC,MAAM,aAAa,CAAC;AAezE,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;iBAKhC,CAAC;AAEH,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,EACrC,QAAQ,CACT,GAAG;IACF,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;iBAE9B,CAAC;AAEH,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC3C,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EACA,WAAW,GACX,WAAW,GACX,cAAc,GACd,mBAAmB,GACnB,cAAc,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF,kFAAkF;AAClF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE;QACR,MAAM,EAAE,mBAAmB,CAAC;QAC5B,OAAO,EAAE;YAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;SAAC,CAAC;QAC9D,SAAS,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;QACjD,SAAS,EAAE,CACT,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,aAAa,CAAA;SAAC,KAC/C,IAAI,CAAC;QACV,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,eAAe,GAAG,SAAS,CAAC;QACpD,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;QACjE,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAC3D,cAAc,EAAE,CACd,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,KACtC,IAAI,CAAC;QACV,uFAAuF;QACvF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;KACzE,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CACvC,sDA0EA;AAED,qEAAqE;AACrE,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,GAAG,gBAAgB,KAAK,CAAC,GAC5D,CAAC,CAEH"}
1
+ {"version":3,"file":"DeckMapsSlice.d.ts","sourceRoot":"","sources":["../src/DeckMapsSlice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAOvD,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,WAAW,CAAC;AACtD,OAAO,EAIL,KAAK,aAAa,EACnB,MAAM,aAAa,CAAC;AAerB,4DAA4D;AAC5D,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;iBAKhC,CAAC;AAEH,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,EACrC,QAAQ,CACT,GAAG;IACF,MAAM,EAAE,aAAa,CAAC;CACvB,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;iBAE9B,CAAC;AAEH,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC3C,CAAC;AAEF,+EAA+E;AAC/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EACA,WAAW,GACX,WAAW,GACX,cAAc,GACd,mBAAmB,GACnB,cAAc,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,MAAM,2BAA2B,GAAG;IACxC,WAAW,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAClD,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB,CAAC;AAEF,kFAAkF;AAClF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE;QACR,MAAM,EAAE,mBAAmB,CAAC;QAC5B,qEAAqE;QACrE,eAAe,CAAC,EAAE,sBAAsB,CAAC;QACzC,OAAO,EAAE;YAAC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAA;SAAC,CAAC;QAC9D,SAAS,EAAE,CAAC,MAAM,EAAE,mBAAmB,KAAK,IAAI,CAAC;QACjD,SAAS,EAAE,CACT,EAAE,EAAE,MAAM,EACV,OAAO,CAAC,EAAE;YAAC,KAAK,CAAC,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,aAAa,CAAA;SAAC,KAC/C,IAAI,CAAC;QACV,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;QAChC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,eAAe,GAAG,SAAS,CAAC;QACpD,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC;QACjE,gBAAgB,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;QAC3D,cAAc,EAAE,CACd,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,KACtC,IAAI,CAAC;QACV,uFAAuF;QACvF,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,mBAAmB,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;KACzE,CAAC;CACH,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,CAAC,EAAE;IAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACtC,iFAAiF;IACjF,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C,sDAgFA;AAED,qEAAqE;AACrE,wBAAgB,oBAAoB,CAAC,CAAC,EACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,kBAAkB,GAAG,gBAAgB,KAAK,CAAC,GAC5D,CAAC,CAEH"}
@@ -1,7 +1,7 @@
1
1
  import { createSlice, useBaseRoomStore, } from '@sqlrooms/room-store';
2
2
  import { produce } from 'immer';
3
3
  import { z } from 'zod';
4
- import { createEmptyDeckMapConfig } from './mapConfig';
4
+ import { createEmptyDeckMapConfig, withDefaultDeckMapStyle, withPreservedDeckMapStyle, } from './mapConfig';
5
5
  const DeckMapConfigSchema = z.object({
6
6
  spec: z.union([z.string(), z.record(z.string(), z.unknown())]),
7
7
  datasets: z.record(z.string(), z.unknown()),
@@ -33,6 +33,7 @@ export function createDeckMapsSlice(props) {
33
33
  return createSlice((set, get) => ({
34
34
  deckMaps: {
35
35
  config: { mapsById: props?.config?.mapsById ?? {} },
36
+ basemapProvider: props?.basemapProvider,
36
37
  runtime: { issuesByMapId: {} },
37
38
  setConfig: (config) => set((state) => produce(state, (draft) => {
38
39
  draft.deckMaps.config = config;
@@ -42,7 +43,7 @@ export function createDeckMapsSlice(props) {
42
43
  draft.deckMaps.config.mapsById[id] = {
43
44
  id,
44
45
  title: options?.title ?? 'Map',
45
- config: options?.config ?? createEmptyDeckMapConfig(),
46
+ config: withDefaultDeckMapStyle(options?.config ?? createEmptyDeckMapConfig()),
46
47
  };
47
48
  }
48
49
  })),
@@ -55,7 +56,9 @@ export function createDeckMapsSlice(props) {
55
56
  const map = draft.deckMaps.config.mapsById[id];
56
57
  if (!map)
57
58
  throw new Error(`Deck map ${id} was not found`);
58
- Object.assign(map, patch, { id });
59
+ const config = patch.config &&
60
+ withPreservedDeckMapStyle({ ...patch.config }, map.config);
61
+ Object.assign(map, patch, { id }, config ? { config } : {});
59
62
  if (patch.config) {
60
63
  const issue = draft.deckMaps.runtime.issuesByMapId[id];
61
64
  if (Object.keys(patch.config.datasets).length === 0 ||
@@ -1 +1 @@
1
- {"version":3,"file":"DeckMapsSlice.js","sourceRoot":"","sources":["../src/DeckMapsSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {type DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {\n type BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport {createEmptyDeckMapConfig, type DeckMapConfig} from './mapConfig';\n\nconst DeckMapConfigSchema = z.object({\n spec: z.union([z.string(), z.record(z.string(), z.unknown())]),\n datasets: z.record(z.string(), z.unknown()),\n configMode: z.enum(['basic', 'custom']).optional(),\n mapStyle: z.string().optional(),\n mapProps: z.record(z.string(), z.unknown()).optional(),\n showLegends: z.boolean().optional(),\n interaction: z.record(z.string(), z.unknown()).optional(),\n fitToData: z.record(z.string(), z.unknown()).optional(),\n dataPolicy: z.record(z.string(), z.unknown()).optional(),\n settingsOpen: z.boolean().optional(),\n});\n\n/** Runtime schema for a durable Deck map resource entry. */\nexport const DeckMapResourceSchema = z.object({\n id: z.string(),\n title: z.string(),\n selectedTable: z.string().optional(),\n config: DeckMapConfigSchema,\n});\n\n/** A durable Deck map resource stored in the room configuration. */\nexport type DeckMapResource = Omit<\n z.infer<typeof DeckMapResourceSchema>,\n 'config'\n> & {\n config: DeckMapConfig;\n};\n\n/** Persistence schema for the Deck maps slice configuration. */\nexport const DeckMapsSliceConfig = z.object({\n mapsById: z.record(z.string(), DeckMapResourceSchema).default({}),\n});\n\n/** Persisted Deck map resources indexed by their stable resource ids. */\nexport type DeckMapsSliceConfig = {\n mapsById: Record<string, DeckMapResource>;\n};\n\n/** Ephemeral rendering or data issue associated with one Deck map resource. */\nexport type DeckMapRuntimeIssue = {\n kind:\n | 'sql-error'\n | 'fit-error'\n | 'render-error'\n | 'data-policy-error'\n | 'config-error';\n mapId: string;\n message: string;\n recoverable: boolean;\n details?: Record<string, unknown>;\n};\n\n/** Callback pair for reporting and clearing ephemeral Deck map issues. */\nexport type DeckMapRuntimeIssueReporter = {\n reportIssue: (issue: DeckMapRuntimeIssue) => void;\n clearIssue: () => void;\n};\n\n/** Room-store state and actions for durable maps and ephemeral runtime issues. */\nexport type DeckMapsSliceState = {\n deckMaps: {\n config: DeckMapsSliceConfig;\n runtime: {issuesByMapId: Record<string, DeckMapRuntimeIssue>};\n setConfig: (config: DeckMapsSliceConfig) => void;\n ensureMap: (\n id: string,\n options?: {title?: string; config?: DeckMapConfig},\n ) => void;\n removeMap: (id: string) => void;\n getMap: (id: string) => DeckMapResource | undefined;\n updateMap: (id: string, patch: Partial<DeckMapResource>) => void;\n setSelectedTable: (id: string, tableName?: string) => void;\n reportMapIssue: (\n id: string,\n issue: Omit<DeckMapRuntimeIssue, 'mapId'>,\n ) => void;\n /** Clears the current issue when its kind matches, or unconditionally when omitted. */\n clearMapIssue: (id: string, kind?: DeckMapRuntimeIssue['kind']) => void;\n };\n};\n\n/**\n * Creates the room-store slice that owns durable Deck map resources and their\n * instance-scoped runtime issues.\n */\nexport function createDeckMapsSlice(props?: {\n config?: Partial<DeckMapsSliceConfig>;\n}) {\n type RootState = BaseRoomStoreState & DuckDbSliceState & DeckMapsSliceState;\n return createSlice<DeckMapsSliceState, RootState>((set, get) => ({\n deckMaps: {\n config: {mapsById: props?.config?.mapsById ?? {}},\n runtime: {issuesByMapId: {}},\n setConfig: (config) =>\n set((state) =>\n produce(state, (draft) => {\n draft.deckMaps.config = config;\n }),\n ),\n ensureMap: (id, options) =>\n set((state) =>\n produce(state, (draft) => {\n if (!draft.deckMaps.config.mapsById[id]) {\n draft.deckMaps.config.mapsById[id] = {\n id,\n title: options?.title ?? 'Map',\n config: options?.config ?? createEmptyDeckMapConfig(),\n };\n }\n }),\n ),\n removeMap: (id) =>\n set((state) =>\n produce(state, (draft) => {\n delete draft.deckMaps.config.mapsById[id];\n delete draft.deckMaps.runtime.issuesByMapId[id];\n }),\n ),\n getMap: (id) => get().deckMaps.config.mapsById[id],\n updateMap: (id, patch) =>\n set((state) =>\n produce(state, (draft) => {\n const map = draft.deckMaps.config.mapsById[id];\n if (!map) throw new Error(`Deck map ${id} was not found`);\n Object.assign(map, patch, {id});\n if (patch.config) {\n const issue = draft.deckMaps.runtime.issuesByMapId[id];\n if (\n Object.keys(patch.config.datasets).length === 0 ||\n issue?.kind === 'render-error'\n ) {\n delete draft.deckMaps.runtime.issuesByMapId[id];\n }\n }\n }),\n ),\n setSelectedTable: (id, tableName) =>\n set((state) =>\n produce(state, (draft) => {\n const map = draft.deckMaps.config.mapsById[id];\n if (!map) throw new Error(`Deck map ${id} was not found`);\n map.selectedTable = tableName;\n }),\n ),\n reportMapIssue: (id, issue) =>\n set((state) =>\n produce(state, (draft) => {\n draft.deckMaps.runtime.issuesByMapId[id] = {...issue, mapId: id};\n }),\n ),\n clearMapIssue: (id, kind) =>\n set((state) =>\n produce(state, (draft) => {\n const issue = draft.deckMaps.runtime.issuesByMapId[id];\n if (!kind || issue?.kind === kind) {\n delete draft.deckMaps.runtime.issuesByMapId[id];\n }\n }),\n ),\n },\n }));\n}\n\n/** Selects Deck map and DuckDB state from the current room store. */\nexport function useStoreWithDeckMaps<T>(\n selector: (state: DeckMapsSliceState & DuckDbSliceState) => T,\n): T {\n return useBaseRoomStore<DeckMapsSliceState & DuckDbSliceState, T>(selector);\n}\n"]}
1
+ {"version":3,"file":"DeckMapsSlice.js","sourceRoot":"","sources":["../src/DeckMapsSlice.ts"],"names":[],"mappings":"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","sourcesContent":["import {type DuckDbSliceState} from '@sqlrooms/duckdb';\nimport {\n type BaseRoomStoreState,\n createSlice,\n useBaseRoomStore,\n} from '@sqlrooms/room-store';\nimport {produce} from 'immer';\nimport {z} from 'zod';\nimport type {DeckMapBasemapProvider} from './basemap';\nimport {\n createEmptyDeckMapConfig,\n withDefaultDeckMapStyle,\n withPreservedDeckMapStyle,\n type DeckMapConfig,\n} from './mapConfig';\n\nconst DeckMapConfigSchema = z.object({\n spec: z.union([z.string(), z.record(z.string(), z.unknown())]),\n datasets: z.record(z.string(), z.unknown()),\n configMode: z.enum(['basic', 'custom']).optional(),\n mapStyle: z.string().optional(),\n mapProps: z.record(z.string(), z.unknown()).optional(),\n showLegends: z.boolean().optional(),\n interaction: z.record(z.string(), z.unknown()).optional(),\n fitToData: z.record(z.string(), z.unknown()).optional(),\n dataPolicy: z.record(z.string(), z.unknown()).optional(),\n settingsOpen: z.boolean().optional(),\n});\n\n/** Runtime schema for a durable Deck map resource entry. */\nexport const DeckMapResourceSchema = z.object({\n id: z.string(),\n title: z.string(),\n selectedTable: z.string().optional(),\n config: DeckMapConfigSchema,\n});\n\n/** A durable Deck map resource stored in the room configuration. */\nexport type DeckMapResource = Omit<\n z.infer<typeof DeckMapResourceSchema>,\n 'config'\n> & {\n config: DeckMapConfig;\n};\n\n/** Persistence schema for the Deck maps slice configuration. */\nexport const DeckMapsSliceConfig = z.object({\n mapsById: z.record(z.string(), DeckMapResourceSchema).default({}),\n});\n\n/** Persisted Deck map resources indexed by their stable resource ids. */\nexport type DeckMapsSliceConfig = {\n mapsById: Record<string, DeckMapResource>;\n};\n\n/** Ephemeral rendering or data issue associated with one Deck map resource. */\nexport type DeckMapRuntimeIssue = {\n kind:\n | 'sql-error'\n | 'fit-error'\n | 'render-error'\n | 'data-policy-error'\n | 'config-error';\n mapId: string;\n message: string;\n recoverable: boolean;\n details?: Record<string, unknown>;\n};\n\n/** Callback pair for reporting and clearing ephemeral Deck map issues. */\nexport type DeckMapRuntimeIssueReporter = {\n reportIssue: (issue: DeckMapRuntimeIssue) => void;\n clearIssue: () => void;\n};\n\n/** Room-store state and actions for durable maps and ephemeral runtime issues. */\nexport type DeckMapsSliceState = {\n deckMaps: {\n config: DeckMapsSliceConfig;\n /** Optional runtime basemap provider shared by maps in this room. */\n basemapProvider?: DeckMapBasemapProvider;\n runtime: {issuesByMapId: Record<string, DeckMapRuntimeIssue>};\n setConfig: (config: DeckMapsSliceConfig) => void;\n ensureMap: (\n id: string,\n options?: {title?: string; config?: DeckMapConfig},\n ) => void;\n removeMap: (id: string) => void;\n getMap: (id: string) => DeckMapResource | undefined;\n updateMap: (id: string, patch: Partial<DeckMapResource>) => void;\n setSelectedTable: (id: string, tableName?: string) => void;\n reportMapIssue: (\n id: string,\n issue: Omit<DeckMapRuntimeIssue, 'mapId'>,\n ) => void;\n /** Clears the current issue when its kind matches, or unconditionally when omitted. */\n clearMapIssue: (id: string, kind?: DeckMapRuntimeIssue['kind']) => void;\n };\n};\n\n/**\n * Creates the room-store slice that owns durable Deck map resources and their\n * instance-scoped runtime issues.\n */\nexport function createDeckMapsSlice(props?: {\n config?: Partial<DeckMapsSliceConfig>;\n /** Optional host-owned basemaps. The provider is not persisted in map config. */\n basemapProvider?: DeckMapBasemapProvider;\n}) {\n type RootState = BaseRoomStoreState & DuckDbSliceState & DeckMapsSliceState;\n return createSlice<DeckMapsSliceState, RootState>((set, get) => ({\n deckMaps: {\n config: {mapsById: props?.config?.mapsById ?? {}},\n basemapProvider: props?.basemapProvider,\n runtime: {issuesByMapId: {}},\n setConfig: (config) =>\n set((state) =>\n produce(state, (draft) => {\n draft.deckMaps.config = config;\n }),\n ),\n ensureMap: (id, options) =>\n set((state) =>\n produce(state, (draft) => {\n if (!draft.deckMaps.config.mapsById[id]) {\n draft.deckMaps.config.mapsById[id] = {\n id,\n title: options?.title ?? 'Map',\n config: withDefaultDeckMapStyle(\n options?.config ?? createEmptyDeckMapConfig(),\n ),\n };\n }\n }),\n ),\n removeMap: (id) =>\n set((state) =>\n produce(state, (draft) => {\n delete draft.deckMaps.config.mapsById[id];\n delete draft.deckMaps.runtime.issuesByMapId[id];\n }),\n ),\n getMap: (id) => get().deckMaps.config.mapsById[id],\n updateMap: (id, patch) =>\n set((state) =>\n produce(state, (draft) => {\n const map = draft.deckMaps.config.mapsById[id];\n if (!map) throw new Error(`Deck map ${id} was not found`);\n const config =\n patch.config &&\n withPreservedDeckMapStyle({...patch.config}, map.config);\n Object.assign(map, patch, {id}, config ? {config} : {});\n if (patch.config) {\n const issue = draft.deckMaps.runtime.issuesByMapId[id];\n if (\n Object.keys(patch.config.datasets).length === 0 ||\n issue?.kind === 'render-error'\n ) {\n delete draft.deckMaps.runtime.issuesByMapId[id];\n }\n }\n }),\n ),\n setSelectedTable: (id, tableName) =>\n set((state) =>\n produce(state, (draft) => {\n const map = draft.deckMaps.config.mapsById[id];\n if (!map) throw new Error(`Deck map ${id} was not found`);\n map.selectedTable = tableName;\n }),\n ),\n reportMapIssue: (id, issue) =>\n set((state) =>\n produce(state, (draft) => {\n draft.deckMaps.runtime.issuesByMapId[id] = {...issue, mapId: id};\n }),\n ),\n clearMapIssue: (id, kind) =>\n set((state) =>\n produce(state, (draft) => {\n const issue = draft.deckMaps.runtime.issuesByMapId[id];\n if (!kind || issue?.kind === kind) {\n delete draft.deckMaps.runtime.issuesByMapId[id];\n }\n }),\n ),\n },\n }));\n}\n\n/** Selects Deck map and DuckDB state from the current room store. */\nexport function useStoreWithDeckMaps<T>(\n selector: (state: DeckMapsSliceState & DuckDbSliceState) => T,\n): T {\n return useBaseRoomStore<DeckMapsSliceState & DuckDbSliceState, T>(selector);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"MapSettings.d.ts","sourceRoot":"","sources":["../src/MapSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,EAQH,MAAM,OAAO,CAAC;AACf,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAW1B,OAAO,KAAK,EAAC,gBAAgB,EAAmB,MAAM,wBAAwB,CAAC;AAqB/E,OAAO,EAA8B,KAAK,aAAa,EAAC,MAAM,aAAa,CAAC;AAmG5E,oEAAoE;AACpE,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,EAC7B,aAAa,EAAE,gBAAgB,CAAC,MAAM,CAAC,EACvC,cAAc,CAAC,EAAE,MAAM,GACtB;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;CAAC,GAAG,SAAS,CAW7D;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,cAAc,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA80BD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,yBAAyB,CAq+B9D,CAAC"}
1
+ {"version":3,"file":"MapSettings.d.ts","sourceRoot":"","sources":["../src/MapSettings.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,EAAE,EAQH,MAAM,OAAO,CAAC;AACf,OAAO,EAGL,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAC;AAW1B,OAAO,KAAK,EAAC,gBAAgB,EAAmB,MAAM,wBAAwB,CAAC;AAsB/E,OAAO,EAA8B,KAAK,aAAa,EAAC,MAAM,aAAa,CAAC;AAmG5E,oEAAoE;AACpE,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,EAC7B,aAAa,EAAE,gBAAgB,CAAC,MAAM,CAAC,EACvC,cAAc,CAAC,EAAE,MAAM,GACtB;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;CAAC,GAAG,SAAS,CAW7D;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,aAAa,CAAC;IACtB,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAC;IAC1C,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,cAAc,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iFAAiF;IACjF,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA80BD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,yBAAyB,CA++B9D,CAAC"}
@@ -4,6 +4,7 @@ import { getTableIdentity, resolveTableReference, } from '@sqlrooms/duckdb';
4
4
  import { binnedNumericSchemes, categoricalSchemeColors, categoricalSchemes, continuousDivergingInterpolators, continuousDivergingSchemes, continuousSequentialSchemes, continuousSequentialInterpolators, parseColorString, } from '@sqlrooms/color-scales';
5
5
  import { cn, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Slider, ScrollArea, SettingsPanelHeader, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Tooltip, TooltipContent, TooltipTrigger, } from '@sqlrooms/ui';
6
6
  import { AlertTriangleIcon } from 'lucide-react';
7
+ import { DeckMapBasemapSelect } from './DeckMapBasemapSelect';
7
8
  import { isDeckMapTableDatasetSource } from './mapConfig';
8
9
  import { clearDeckMapLayerColorScale, createDeckMapLayerColorScale, DECK_MAP_COLOR_SCALE_TYPE_OPTIONS, DECK_MAP_DEFAULT_LAYER_COLOR, DECK_MAP_DEFAULT_STROKE_COLOR, DECK_MAP_LAYER_TYPE_OPTIONS, deckMapRgbaToHex, getDeckMapColorAccessorOptions, getDeckMapLayerDatasetId, getDeckMapLayerColorScale, getDeckMapLayerExtruded, getDeckMapLayerFlatColor, getDeckMapLayerRecords, setDeckMapLayerFlatColor, setDeckMapLayerGeometryColumn, setDeckMapLayerHexagonColumn, setDeckMapLayerArcColumns, setDeckMapLayerTimestampColumn, setDeckMapLayerType, setDeckMapLayerColumnRadius, updateDeckMapLayer, usesGeometryColumnSetting, usesH3ColumnSetting, usesArcColumnSetting, usesRadiusSetting, usesColumnRadiusSetting, usesTripsSettings, usesExtrusionSettings, usesStrokeSetting, usesStrokeExtrusionWarning, getDeckMapLayerStrokeDefault, getDeckMapColorScaleOpacity, getDeckMapLayerChannelOpacityPercent, detachDeckMapLayerOpacity, replaceDeckMapLayerColorScalesWithFlat, replaceDeckMapLayerColorScaleWithFlat, } from './mapLayerConfigUtils';
9
10
  import { DeckMapCodeViewerPanel, DeckMapCodeViewToggleButton, DeckMapColumnSelector as ColumnSelector, DeckMapColumnsProvider as ColumnsProvider, DeckMapSettingsField as Field, DeckMapTableSelector as DataTableSelector, filterDeckMapColumns, isDeckMapCategoricalColorColumn, } from './MapSettingsControls';
@@ -594,12 +595,12 @@ export const DeckMapSettingsPanel = ({ title, selectedTable, config, tables, onC
594
595
  radiusStep: 1,
595
596
  }
596
597
  : {};
597
- return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx(SettingsPanelHeader, { title: "Map settings", className: "shrink-0 p-2", actions: customConfig ? undefined : (_jsx(DeckMapCodeViewToggleButton, { label: showCode ? 'Show settings' : 'View code', selected: showCode, onClick: () => setViewMode((currentViewMode) => currentViewMode === 'code' ? 'settings' : 'code') })), onClose: onClose, closeLabel: "Close map settings" }), showCode ? (_jsx(DeckMapCodeViewerPanel, { value: serializedMapConfig, copyTooltipLabel: "Copy map config" })) : (_jsx(ScrollArea, { className: "min-h-0 flex-1 [&_[data-radix-scroll-area-viewport]>div]:!block", children: _jsxs("div", { className: "flex flex-col gap-2 p-2 pt-0", children: [_jsx(Field, { label: "Title", children: _jsx("input", { value: title, onChange: (e) => onTitleChange(e.target.value), placeholder: "Map title", disabled: readOnly, className: "border-input placeholder:text-muted-foreground focus-visible:ring-ring h-8 w-full rounded-md border bg-transparent px-3 py-2 text-xs font-medium shadow-sm outline-hidden transition-colors focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50" }) }), _jsx(Field, { label: "Dataset", required: true, children: _jsx(DataTableSelector, { onChange: handleTableChange, tables: tables, value: sourceDataTable, disabled: readOnly }) }), layers.length > 0 && (_jsxs("div", { className: "flex flex-col gap-3", children: [layers.length > 1 && (_jsx(Field, { label: "Layer", children: _jsxs(Select, { value: String(activeLayerIndex), onValueChange: (value) => setLayerIndex(Number(value)), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: layers.map((layer, index) => (_jsx(SelectItem, { value: String(index), children: String(layer.id ?? `Layer ${index + 1}`) }, index))) })] }) })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-xs font-medium", children: "Visible" }), _jsx(Switch, { checked: activeLayer?.visible !== false, onCheckedChange: (checked) => applyConfig(updateDeckMapLayer(mapConfig, activeLayerIndex, (layer) => ({
598
+ return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx(SettingsPanelHeader, { title: "Map settings", className: "shrink-0 p-2", actions: customConfig ? undefined : (_jsx(DeckMapCodeViewToggleButton, { label: showCode ? 'Show settings' : 'View code', selected: showCode, onClick: () => setViewMode((currentViewMode) => currentViewMode === 'code' ? 'settings' : 'code') })), onClose: onClose, closeLabel: "Close map settings" }), _jsxs("div", { className: "flex shrink-0 flex-col gap-2 px-2 pb-2", children: [_jsx(Field, { label: "Title", children: _jsx("input", { value: title, onChange: (e) => onTitleChange(e.target.value), placeholder: "Map title", disabled: readOnly, className: "border-input placeholder:text-muted-foreground focus-visible:ring-ring h-8 w-full rounded-md border bg-transparent px-3 py-2 text-xs font-medium shadow-sm outline-hidden transition-colors focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50" }) }), _jsx(DeckMapBasemapSelect, { config: config, onConfigChange: onConfigChange, readOnly: readOnly })] }), showCode ? (_jsx(DeckMapCodeViewerPanel, { value: serializedMapConfig, copyTooltipLabel: "Copy map config" })) : (_jsx(ScrollArea, { className: "min-h-0 flex-1 [&_[data-radix-scroll-area-viewport]>div]:!block", children: _jsxs("div", { className: "flex flex-col gap-2 p-2 pt-0", children: [_jsx(Field, { label: "Dataset", required: true, children: _jsx(DataTableSelector, { onChange: handleTableChange, tables: tables, value: sourceDataTable, disabled: readOnly }) }), layers.length > 0 && (_jsxs("div", { className: "flex flex-col gap-3", children: [layers.length > 1 && (_jsx(Field, { label: "Layer", children: _jsxs(Select, { value: String(activeLayerIndex), onValueChange: (value) => setLayerIndex(Number(value)), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: layers.map((layer, index) => (_jsx(SelectItem, { value: String(index), children: String(layer.id ?? `Layer ${index + 1}`) }, index))) })] }) })), _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("span", { className: "text-xs font-medium", children: "Visible" }), _jsx(Switch, { checked: activeLayer?.visible !== false, onCheckedChange: (checked) => applyConfig(updateDeckMapLayer(mapConfig, activeLayerIndex, (layer) => ({
598
599
  ...layer,
599
600
  visible: checked,
600
601
  }))) })] }), _jsx(Field, { label: "Layer type", children: _jsxs(Select, { value: typeof activeLayer?.['@@type'] === 'string'
601
602
  ? activeLayer['@@type']
602
- : undefined, onValueChange: (value) => applyConfig(setDeckMapLayerType(mapConfig, activeLayerIndex, value)), children: [_jsx(SelectTrigger, { className: "w-full", children: _jsx(SelectValue, { placeholder: "Select layer type" }) }), _jsx(SelectContent, { children: layerTypeOptions.map((option) => (_jsx(SelectItem, { value: option.value, children: option.label }, option.value))) })] }) }), (datasetSchema.isLoading || datasetSchemaErrorMessage) && (_jsx("div", { className: "text-muted-foreground rounded-md border px-2 py-1.5 text-xs", children: datasetSchema.isLoading
603
+ : undefined, onValueChange: (value) => applyConfig(setDeckMapLayerType(mapConfig, activeLayerIndex, value)), children: [_jsx(SelectTrigger, { className: "w-full text-xs", children: _jsx(SelectValue, { placeholder: "Select layer type" }) }), _jsx(SelectContent, { children: layerTypeOptions.map((option) => (_jsx(SelectItem, { value: option.value, className: "text-xs", children: option.label }, option.value))) })] }) }), (datasetSchema.isLoading || datasetSchemaErrorMessage) && (_jsx("div", { className: "text-muted-foreground rounded-md border px-2 py-1.5 text-xs", children: datasetSchema.isLoading
603
604
  ? 'Inspecting dataset schema...'
604
605
  : `Dataset schema unavailable: ${datasetSchemaErrorMessage}` })), showAppearanceCard && (_jsx(Field, { label: "Appearance", children: _jsx("div", { className: "flex flex-col gap-2 rounded-md border p-2", children: isHeatmapLayer ? (_jsxs(_Fragment, { children: [_jsx(SettingsSliderField, { label: `Radius: ${activeLayer?.radiusPixels ?? 30}px`, children: _jsx(Slider, { min: 1, max: 100, step: 1, value: [
605
606
  activeLayer?.radiusPixels ?? 30,