@extend-ai/react-pptx 0.1.0
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/CHANGELOG.md +17 -0
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/THIRD_PARTY_LICENSES/ISC.txt +15 -0
- package/THIRD_PARTY_LICENSES/MIT.txt +21 -0
- package/THIRD_PARTY_NOTICES.md +29 -0
- package/dist/chunk-YVOPQP3D.js +50 -0
- package/dist/chunk-YVOPQP3D.js.map +1 -0
- package/dist/dist-NDTOVNYD.js +373 -0
- package/dist/dist-NDTOVNYD.js.map +1 -0
- package/dist/index.css +258 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +635 -0
- package/dist/index.js +12082 -0
- package/dist/index.js.map +1 -0
- package/dist/native-parser-worker.d.ts +2 -0
- package/dist/native-parser-worker.js +299 -0
- package/dist/native-parser-worker.js.map +1 -0
- package/dist/pptx_wasm_bg.wasm +0 -0
- package/dist/region-map-atlas-S2YXLDE2.js +125 -0
- package/dist/region-map-atlas-S2YXLDE2.js.map +1 -0
- package/package.json +77 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# @extend-ai/react-pptx
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Expose consumer-owned slide thumbnail rails through `usePptxViewerThumbnails`, including stable
|
|
6
|
+
container refs, resolution bounds, render status, imperative rendering, and cleanup. Add
|
|
7
|
+
DOCX-style visible/prefetch render windows and virtualize the built-in thumbnail scrollport.
|
|
8
|
+
|
|
9
|
+
## 0.1.0
|
|
10
|
+
|
|
11
|
+
Initial public release of the React PowerPoint viewer, including:
|
|
12
|
+
|
|
13
|
+
- Browser-native PPTX and legacy PPT parsing through Rust and WebAssembly.
|
|
14
|
+
- A normalized presentation model and virtualized React viewer.
|
|
15
|
+
- Embedded and host-provided font support with missing-font diagnostics.
|
|
16
|
+
- Native legacy PowerPoint slide, drawing, text, and image fallback support.
|
|
17
|
+
- Fidelity improvements for placeholders, backgrounds, text layout, gradients, and image fills.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Extend AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
# @extend-ai/react-pptx
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@extend-ai/react-pptx)
|
|
4
|
+
|
|
5
|
+
Browser-native PowerPoint viewing for React.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @extend-ai/react-pptx
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
React and React DOM are peer dependencies already present in a React application.
|
|
12
|
+
|
|
13
|
+
## Main API
|
|
14
|
+
|
|
15
|
+
- `ReactPptxViewer` renders URLs, `Blob`, `ArrayBuffer`, `Uint8Array`, parsed presentations, or normalized documents.
|
|
16
|
+
- `parsePresentation` performs native parsing and returns the same normalized model the viewer renders.
|
|
17
|
+
- `initWasm` and `setWasmSource` support eager initialization and custom Wasm/CDN hosting.
|
|
18
|
+
- `PptxViewerController` provides navigation, zoom, fit, text search, highlighting, model access,
|
|
19
|
+
and detached thumbnail rendering.
|
|
20
|
+
|
|
21
|
+
Import `@extend-ai/react-pptx/styles.css` alongside the component; the stylesheet is emitted as
|
|
22
|
+
a separate package asset. Parsing and rendering are client-side; importing the JavaScript package
|
|
23
|
+
during SSR is safe.
|
|
24
|
+
|
|
25
|
+
Unknown or degraded content is surfaced through `onWarning` and `showDiagnostics` rather
|
|
26
|
+
than silently removed.
|
|
27
|
+
|
|
28
|
+
## Supported presentation formats
|
|
29
|
+
|
|
30
|
+
`.pptx` and legacy PowerPoint 97–2003 `.ppt` files are both accepted by the same `source`
|
|
31
|
+
prop and `parsePresentation()` API. Legacy files are opened natively from OLE compound
|
|
32
|
+
storage by the Rust/Wasm parser; the browser does not need LibreOffice, a server-side
|
|
33
|
+
conversion endpoint, or a temporary `.pptx` copy.
|
|
34
|
+
|
|
35
|
+
For `.ppt`, the parser follows the `Current User`/`UserEditAtom` edit chain and live
|
|
36
|
+
persist-object directory to recover the actual slide list. Supported OfficeArt group and
|
|
37
|
+
shape anchors, text, pictures, and referenced master drawing content are normalized into
|
|
38
|
+
the same `PresentationDocument` consumed by the React viewer. PNG/JPEG pictures render
|
|
39
|
+
directly, while decoded EMF/WMF records use a bounded browser-side image conversion for
|
|
40
|
+
static previews.
|
|
41
|
+
|
|
42
|
+
Legacy rendering is static, not full PowerPoint emulation. Advanced effects, editable
|
|
43
|
+
binary charts and tables, animations, transitions, active OLE objects, and timed media may
|
|
44
|
+
degrade to a static picture or remain unsupported. Inspect `onWarning` or enable
|
|
45
|
+
`showDiagnostics` to receive explicit `degraded-rendering` warnings:
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<ReactPptxViewer
|
|
49
|
+
source={file}
|
|
50
|
+
showDiagnostics
|
|
51
|
+
onWarning={(warning) => {
|
|
52
|
+
if (warning.code === 'degraded-rendering') {
|
|
53
|
+
console.warn(warning.message, warning.slideIndex);
|
|
54
|
+
}
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The repository regression suite opens a real three-slide PowerPoint 97–2003 file at
|
|
60
|
+
`tests/fixtures/legacy/file-example-250kb.ppt` directly in Rust and the playground. It
|
|
61
|
+
checks slide order, text, normalized nodes, thumbnail navigation, and diagnostics without
|
|
62
|
+
a conversion step.
|
|
63
|
+
|
|
64
|
+
## WebAssembly asset
|
|
65
|
+
|
|
66
|
+
Native PowerPoint parsing runs through a WebAssembly module that loads lazily. Most apps can
|
|
67
|
+
use the default loader. If your bundler or deployment needs to host the binary explicitly,
|
|
68
|
+
configure it before the first presentation is parsed:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { setWasmSource } from '@extend-ai/react-pptx';
|
|
72
|
+
|
|
73
|
+
setWasmSource('https://cdn.example.com/pptx_wasm_bg.wasm');
|
|
74
|
+
// A URL, Request, Response, ArrayBuffer/TypedArray, or WebAssembly.Module also works.
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The binary is also available as a package subpath for bundlers that support asset URL imports:
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import wasmUrl from '@extend-ai/react-pptx/pptx_wasm_bg.wasm?url';
|
|
81
|
+
import { setWasmSource } from '@extend-ai/react-pptx';
|
|
82
|
+
|
|
83
|
+
setWasmSource(wasmUrl);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Configured strings, URLs, request URLs, bytes, and `WebAssembly.Module` values are forwarded to
|
|
87
|
+
the parser worker. A `Response` is supported on the main thread because it cannot be forwarded
|
|
88
|
+
reliably to a worker. `initWasm()` optionally accepts the same source when eager initialization
|
|
89
|
+
is useful.
|
|
90
|
+
|
|
91
|
+
## Fonts
|
|
92
|
+
|
|
93
|
+
Fonts embedded in a `.pptx` are decoded by the Rust parser and registered before the first
|
|
94
|
+
slide is rendered. Applications can also provide licensed/self-hosted fonts. The viewer
|
|
95
|
+
preserves the requested PowerPoint family, then appends Office-compatible and script-complete
|
|
96
|
+
fallbacks for Latin, CJK, Arabic, Hebrew, emoji, and math glyphs.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
<ReactPptxViewer
|
|
100
|
+
source={file}
|
|
101
|
+
fonts={{
|
|
102
|
+
sources: [
|
|
103
|
+
{ family: 'Brand Sans', source: '/fonts/brand-sans.woff2' },
|
|
104
|
+
{
|
|
105
|
+
family: 'Brand Sans',
|
|
106
|
+
source: '/fonts/brand-sans-bold.woff2',
|
|
107
|
+
descriptors: { weight: '700' },
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
fallbacks: { 'Brand Sans': ['Inter', 'Arial'] },
|
|
111
|
+
fallbackFamilies: ['Noto Sans', 'Noto Sans CJK SC', 'Noto Sans Arabic'],
|
|
112
|
+
}}
|
|
113
|
+
onWarning={(warning) => {
|
|
114
|
+
if (warning.code === 'missing-font') console.warn(warning.message);
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The package does not redistribute proprietary Microsoft fonts. For identical metrics across
|
|
120
|
+
machines, self-host the fonts your license permits or install metric-compatible families such
|
|
121
|
+
as Carlito and Caladea. `resolvePptxFontFamily()` and `OFFICE_FONT_FALLBACKS` are exported for
|
|
122
|
+
applications that also render presentation text outside the viewer.
|
|
123
|
+
|
|
124
|
+
## Custom scroll areas and hooks
|
|
125
|
+
|
|
126
|
+
Pass the actual scrolling viewport through `virtualization.scrollElement`. This works with
|
|
127
|
+
Radix, Base UI, coss, or any host-owned scroll area and makes that element the observer root.
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
const [scrollElement, setScrollElement] = useState<HTMLDivElement | null>(null);
|
|
131
|
+
const viewer = usePptxViewer();
|
|
132
|
+
const parsed = usePptxPresentation(file);
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<ScrollArea.Root>
|
|
136
|
+
<ScrollArea.Viewport ref={setScrollElement}>
|
|
137
|
+
{parsed.presentation ? (
|
|
138
|
+
<ReactPptxViewer
|
|
139
|
+
ref={viewer.ref}
|
|
140
|
+
source={parsed.presentation}
|
|
141
|
+
virtualization={{ enabled: true, overscanViewport: 2, scrollElement }}
|
|
142
|
+
/>
|
|
143
|
+
) : null}
|
|
144
|
+
</ScrollArea.Viewport>
|
|
145
|
+
</ScrollArea.Root>
|
|
146
|
+
);
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
`usePptxPresentation` (`usePptxModel` alias) separates parsing from rendering, while
|
|
150
|
+
`usePptxViewer` exposes the reactive navigation/search/zoom controller. `onViewportReady`
|
|
151
|
+
provides the internal slide surface for advanced integrations and test harnesses.
|
|
152
|
+
|
|
153
|
+
## Thumbnail hook
|
|
154
|
+
|
|
155
|
+
`usePptxViewerThumbnails` exposes detached slide previews for a consumer-owned filmstrip. PPTX
|
|
156
|
+
thumbnails use the same live DOM/SVG renderer and loaded fonts as the main viewer, so attach each
|
|
157
|
+
stable `containerRef` to a regular element rather than a canvas.
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
import { ReactPptxViewer, usePptxViewer, usePptxViewerThumbnails } from '@extend-ai/react-pptx';
|
|
161
|
+
|
|
162
|
+
export function PresentationWithThumbnails({ file }: { file: ArrayBuffer }) {
|
|
163
|
+
const viewer = usePptxViewer();
|
|
164
|
+
const { thumbnails } = usePptxViewerThumbnails(viewer.controller, {
|
|
165
|
+
resolution: { maxWidth: 180, maxHeight: 120 },
|
|
166
|
+
renderWindow: {
|
|
167
|
+
visibleSlideIndexes: [0, 1, 2],
|
|
168
|
+
prefetchSlideIndexes: [3, 4, 5],
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div style={{ display: 'grid', gridTemplateColumns: '200px 1fr', gap: 16 }}>
|
|
174
|
+
<aside style={{ display: 'grid', gap: 12, alignContent: 'start' }}>
|
|
175
|
+
{thumbnails.map((thumbnail) => (
|
|
176
|
+
<button
|
|
177
|
+
key={thumbnail.slideIndex}
|
|
178
|
+
type="button"
|
|
179
|
+
onClick={() => void viewer.controller?.goToSlide(thumbnail.slideIndex)}
|
|
180
|
+
>
|
|
181
|
+
<div
|
|
182
|
+
ref={thumbnail.containerRef}
|
|
183
|
+
style={{
|
|
184
|
+
width: thumbnail.width,
|
|
185
|
+
height: thumbnail.height,
|
|
186
|
+
overflow: 'hidden',
|
|
187
|
+
}}
|
|
188
|
+
/>
|
|
189
|
+
</button>
|
|
190
|
+
))}
|
|
191
|
+
</aside>
|
|
192
|
+
<ReactPptxViewer ref={viewer.ref} source={file} mode="slide" />
|
|
193
|
+
</div>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
The result also provides `renderThumbnail(slideIndex, element)` for imperative integrations and
|
|
199
|
+
`rerenderAttachedThumbnails()` for refreshing every currently attached preview. `disabled` keeps
|
|
200
|
+
the metadata stable while pausing and disposing thumbnail rendering. For large decks, virtualize
|
|
201
|
+
the rail against its actual scroll element: mount `containerRef` only for virtual rows, pass those
|
|
202
|
+
rows through `renderWindow.visibleSlideIndexes`, and use `prefetchSlideIndexes` to warm nearby
|
|
203
|
+
slides. The built-in `showThumbnails` filmstrip follows the same windowed behavior.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) the respective authors.
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
10
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
11
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
12
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
13
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
14
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
15
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) the respective authors.
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
## Chart rendering stack (vendored from @extend-ai/react-xlsx)
|
|
4
|
+
|
|
5
|
+
The chart renderer and chart model builder in `src/charts/` are vendored from
|
|
6
|
+
[`@extend-ai/react-xlsx`](https://github.com/extend-hq/react-xlsx) (MIT) so
|
|
7
|
+
PowerPoint charts render with the same styles and colors as Excel charts.
|
|
8
|
+
|
|
9
|
+
The chart libraries `d3-scale`, `d3-shape`, `d3-hierarchy`, `d3-geo` (ISC,
|
|
10
|
+
Copyright Mike Bostock), `topojson-client` (ISC), and
|
|
11
|
+
[`regl`](https://github.com/regl-project/regl) (MIT) are declared as regular
|
|
12
|
+
package dependencies.
|
|
13
|
+
|
|
14
|
+
The published package bundles the
|
|
15
|
+
[`us-atlas`](https://github.com/topojson/us-atlas) and
|
|
16
|
+
[`world-atlas`](https://github.com/topojson/world-atlas) TopoJSON boundary data
|
|
17
|
+
(ISC License) inside a dynamically imported chunk that only loads when a
|
|
18
|
+
presentation contains an Excel map chart.
|
|
19
|
+
|
|
20
|
+
The published package includes the ISC and MIT license texts at
|
|
21
|
+
`THIRD_PARTY_LICENSES/ISC.txt` and `THIRD_PARTY_LICENSES/MIT.txt`.
|
|
22
|
+
|
|
23
|
+
## Virtualized scrolling
|
|
24
|
+
|
|
25
|
+
The continuous-scroll mode and React thumbnail rails are windowed with
|
|
26
|
+
[`@tanstack/virtual-core`](https://github.com/TanStack/virtual) and
|
|
27
|
+
[`@tanstack/react-virtual`](https://github.com/TanStack/virtual) (MIT License,
|
|
28
|
+
Copyright (c) 2021-present Tanner Linsley), declared as regular package
|
|
29
|
+
dependencies.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/charts/region-map-data.ts
|
|
2
|
+
function normalizeRegionMapKey(value) {
|
|
3
|
+
if (typeof value !== "string") {
|
|
4
|
+
return "";
|
|
5
|
+
}
|
|
6
|
+
return value.normalize("NFD").replace(/[\u0300-\u036f]/g, "").replace(/&/g, " and ").replace(/[^a-zA-Z0-9]+/g, " ").trim().toLowerCase().replace(/\s+/g, " ");
|
|
7
|
+
}
|
|
8
|
+
var REGION_MAP_COUNTRY_ALIASES = /* @__PURE__ */ new Map([
|
|
9
|
+
["us", "united states of america"],
|
|
10
|
+
["usa", "united states of america"],
|
|
11
|
+
["u s a", "united states of america"],
|
|
12
|
+
["united states", "united states of america"],
|
|
13
|
+
["united states america", "united states of america"],
|
|
14
|
+
["u s", "united states of america"],
|
|
15
|
+
["uk", "united kingdom"],
|
|
16
|
+
["u k", "united kingdom"],
|
|
17
|
+
["uae", "united arab emirates"],
|
|
18
|
+
["u a e", "united arab emirates"],
|
|
19
|
+
["south korea", "korea, south"],
|
|
20
|
+
["north korea", "korea, north"],
|
|
21
|
+
["russia", "russian federation"],
|
|
22
|
+
["vietnam", "viet nam"],
|
|
23
|
+
["czech republic", "czechia"],
|
|
24
|
+
["ivory coast", "cote d'ivoire"],
|
|
25
|
+
["c\xF4te divoire", "cote d'ivoire"]
|
|
26
|
+
]);
|
|
27
|
+
var REGION_MAP_US_STATE_ALIASES = /* @__PURE__ */ new Map([
|
|
28
|
+
["district of columbia", "district of columbia"],
|
|
29
|
+
["washington dc", "district of columbia"],
|
|
30
|
+
["washington d c", "district of columbia"],
|
|
31
|
+
["dc", "district of columbia"],
|
|
32
|
+
["d c", "district of columbia"]
|
|
33
|
+
]);
|
|
34
|
+
var loadedAtlas = null;
|
|
35
|
+
var pendingAtlas = null;
|
|
36
|
+
function getRegionMapAtlas() {
|
|
37
|
+
return loadedAtlas;
|
|
38
|
+
}
|
|
39
|
+
function loadRegionMapAtlas() {
|
|
40
|
+
if (loadedAtlas) return Promise.resolve(loadedAtlas);
|
|
41
|
+
pendingAtlas ??= import('./region-map-atlas-S2YXLDE2.js').then((module) => {
|
|
42
|
+
loadedAtlas = module.REGION_MAP_ATLAS;
|
|
43
|
+
return loadedAtlas;
|
|
44
|
+
});
|
|
45
|
+
return pendingAtlas;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export { REGION_MAP_COUNTRY_ALIASES, REGION_MAP_US_STATE_ALIASES, getRegionMapAtlas, loadRegionMapAtlas, normalizeRegionMapKey };
|
|
49
|
+
//# sourceMappingURL=chunk-YVOPQP3D.js.map
|
|
50
|
+
//# sourceMappingURL=chunk-YVOPQP3D.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/charts/region-map-data.ts"],"names":[],"mappings":";AAoBO,SAAS,sBAAsB,KAAA,EAAwB;AAC5D,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,IAAA,OAAO,EAAA;AAAA,EACT;AACA,EAAA,OAAO,KAAA,CACJ,UAAU,KAAK,CAAA,CACf,QAAQ,kBAAA,EAAoB,EAAE,CAAA,CAC9B,OAAA,CAAQ,IAAA,EAAM,OAAO,EACrB,OAAA,CAAQ,gBAAA,EAAkB,GAAG,CAAA,CAC7B,IAAA,GACA,WAAA,EAAY,CACZ,OAAA,CAAQ,MAAA,EAAQ,GAAG,CAAA;AACxB;AAEO,IAAM,0BAAA,uBAAiC,GAAA,CAAoB;AAAA,EAChE,CAAC,MAAM,0BAA0B,CAAA;AAAA,EACjC,CAAC,OAAO,0BAA0B,CAAA;AAAA,EAClC,CAAC,SAAS,0BAA0B,CAAA;AAAA,EACpC,CAAC,iBAAiB,0BAA0B,CAAA;AAAA,EAC5C,CAAC,yBAAyB,0BAA0B,CAAA;AAAA,EACpD,CAAC,OAAO,0BAA0B,CAAA;AAAA,EAClC,CAAC,MAAM,gBAAgB,CAAA;AAAA,EACvB,CAAC,OAAO,gBAAgB,CAAA;AAAA,EACxB,CAAC,OAAO,sBAAsB,CAAA;AAAA,EAC9B,CAAC,SAAS,sBAAsB,CAAA;AAAA,EAChC,CAAC,eAAe,cAAc,CAAA;AAAA,EAC9B,CAAC,eAAe,cAAc,CAAA;AAAA,EAC9B,CAAC,UAAU,oBAAoB,CAAA;AAAA,EAC/B,CAAC,WAAW,UAAU,CAAA;AAAA,EACtB,CAAC,kBAAkB,SAAS,CAAA;AAAA,EAC5B,CAAC,eAAe,eAAe,CAAA;AAAA,EAC/B,CAAC,mBAAgB,eAAe;AAClC,CAAC;AAEM,IAAM,2BAAA,uBAAkC,GAAA,CAAoB;AAAA,EACjE,CAAC,wBAAwB,sBAAsB,CAAA;AAAA,EAC/C,CAAC,iBAAiB,sBAAsB,CAAA;AAAA,EACxC,CAAC,kBAAkB,sBAAsB,CAAA;AAAA,EACzC,CAAC,MAAM,sBAAsB,CAAA;AAAA,EAC7B,CAAC,OAAO,sBAAsB;AAChC,CAAC;AAED,IAAI,WAAA,GAAqC,IAAA;AACzC,IAAI,YAAA,GAA+C,IAAA;AAG5C,SAAS,iBAAA,GAA2C;AACzD,EAAA,OAAO,WAAA;AACT;AAGO,SAAS,kBAAA,GAA8C;AAC5D,EAAA,IAAI,WAAA,EAAa,OAAO,OAAA,CAAQ,OAAA,CAAQ,WAAW,CAAA;AACnD,EAAA,YAAA,KAAiB,OAAO,gCAAoB,CAAA,CAAE,IAAA,CAAK,CAAC,MAAA,KAAW;AAC7D,IAAA,WAAA,GAAc,MAAA,CAAO,gBAAA;AACrB,IAAA,OAAO,WAAA;AAAA,EACT,CAAC,CAAA;AACD,EAAA,OAAO,YAAA;AACT","file":"chunk-YVOPQP3D.js","sourcesContent":["/**\n * Region-map registry shared by the chart renderer and the lazily loaded\n * atlas chunk. The multi-megabyte TopoJSON boundary data only loads when a\n * presentation actually contains an Excel map chart; until then the renderer\n * sees an empty registry and draws the map without shapes.\n */\nimport type { Feature, Geometry } from 'geojson';\n\nexport type RegionMapFeature = Feature<\n Geometry,\n { name?: string; regionSet?: 'country' | 'us-state'; stateCode?: string }\n>;\n\nexport interface RegionMapAtlas {\n worldCountryFeatures: RegionMapFeature[];\n usStateFeatures: RegionMapFeature[];\n countryFeaturesByKey: Map<string, RegionMapFeature>;\n usStateFeaturesByKey: Map<string, RegionMapFeature>;\n}\n\nexport function normalizeRegionMapKey(value: unknown): string {\n if (typeof value !== 'string') {\n return '';\n }\n return value\n .normalize('NFD')\n .replace(/[\\u0300-\\u036f]/g, '')\n .replace(/&/g, ' and ')\n .replace(/[^a-zA-Z0-9]+/g, ' ')\n .trim()\n .toLowerCase()\n .replace(/\\s+/g, ' ');\n}\n\nexport const REGION_MAP_COUNTRY_ALIASES = new Map<string, string>([\n ['us', 'united states of america'],\n ['usa', 'united states of america'],\n ['u s a', 'united states of america'],\n ['united states', 'united states of america'],\n ['united states america', 'united states of america'],\n ['u s', 'united states of america'],\n ['uk', 'united kingdom'],\n ['u k', 'united kingdom'],\n ['uae', 'united arab emirates'],\n ['u a e', 'united arab emirates'],\n ['south korea', 'korea, south'],\n ['north korea', 'korea, north'],\n ['russia', 'russian federation'],\n ['vietnam', 'viet nam'],\n ['czech republic', 'czechia'],\n ['ivory coast', \"cote d'ivoire\"],\n ['côte divoire', \"cote d'ivoire\"],\n]);\n\nexport const REGION_MAP_US_STATE_ALIASES = new Map<string, string>([\n ['district of columbia', 'district of columbia'],\n ['washington dc', 'district of columbia'],\n ['washington d c', 'district of columbia'],\n ['dc', 'district of columbia'],\n ['d c', 'district of columbia'],\n]);\n\nlet loadedAtlas: RegionMapAtlas | null = null;\nlet pendingAtlas: Promise<RegionMapAtlas> | null = null;\n\n/** Synchronous accessor used by the renderer; null until the chunk loads. */\nexport function getRegionMapAtlas(): RegionMapAtlas | null {\n return loadedAtlas;\n}\n\n/** Loads the atlas chunk on demand; resolves immediately once cached. */\nexport function loadRegionMapAtlas(): Promise<RegionMapAtlas> {\n if (loadedAtlas) return Promise.resolve(loadedAtlas);\n pendingAtlas ??= import('./region-map-atlas').then((module) => {\n loadedAtlas = module.REGION_MAP_ATLAS;\n return loadedAtlas;\n });\n return pendingAtlas;\n}\n"]}
|