pptx-angular-viewer 3.3.0 → 3.4.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.
@@ -2868,7 +2868,7 @@ function paintedStrokeWidth(style) {
2868
2868
  * including a short 3-digit `#RGB` shorthand, which this does NOT expand)
2869
2869
  * produces `0`, matching every prior copy's behaviour exactly.
2870
2870
  */
2871
- function hexToRgbUnit$1(hex) {
2871
+ function hexToRgbUnit(hex) {
2872
2872
  const clean = hex.replace(/^#/u, '');
2873
2873
  const r = Number.parseInt(clean.substring(0, 2), 16) / 255;
2874
2874
  const g = Number.parseInt(clean.substring(2, 4), 16) / 255;
@@ -3620,8 +3620,8 @@ function getDuotoneSvgFilter(style, elementId) {
3620
3620
  return undefined;
3621
3621
  }
3622
3622
  const id = getDuotoneFilterId(elementId);
3623
- const c1 = hexToRgbUnit$1(style.dagDuotone.color1);
3624
- const c2 = hexToRgbUnit$1(style.dagDuotone.color2);
3623
+ const c1 = hexToRgbUnit(style.dagDuotone.color1);
3624
+ const c2 = hexToRgbUnit(style.dagDuotone.color2);
3625
3625
  const grayscaleMatrix = [
3626
3626
  0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0, 0,
3627
3627
  0, 1, 0,
@@ -3685,8 +3685,8 @@ function getSoftEdgeSvgFilter(style, elementId) {
3685
3685
  * @param color2 - Highlight colour (hex).
3686
3686
  */
3687
3687
  function getDuotoneSvgFilterMarkup(filterId, color1, color2) {
3688
- const c1 = hexToRgbUnit$1(color1);
3689
- const c2 = hexToRgbUnit$1(color2);
3688
+ const c1 = hexToRgbUnit(color1);
3689
+ const c2 = hexToRgbUnit(color2);
3690
3690
  const grayscaleMatrix = [
3691
3691
  0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0.2126, 0.7152, 0.0722, 0, 0, 0, 0,
3692
3692
  0, 1, 0,
@@ -5712,8 +5712,8 @@ const GRAYSCALE_LUMINANCE_MATRIX = [
5712
5712
  * (highlights) per channel. Mirrors React's `renderDuotoneSvgFilter`.
5713
5713
  */
5714
5714
  function buildDuotoneFilterMarkup(color1, color2) {
5715
- const c1 = hexToRgbUnit$1(color1);
5716
- const c2 = hexToRgbUnit$1(color2);
5715
+ const c1 = hexToRgbUnit(color1);
5716
+ const c2 = hexToRgbUnit(color2);
5717
5717
  return (`<feColorMatrix type="matrix" values="${GRAYSCALE_LUMINANCE_MATRIX}"/>` +
5718
5718
  '<feComponentTransfer>' +
5719
5719
  `<feFuncR type="linear" slope="${c2.r - c1.r}" intercept="${c1.r}"/>` +
@@ -5845,7 +5845,7 @@ function buildImageAlphaFilterMarkup(effects) {
5845
5845
  '</feComponentTransfer>');
5846
5846
  }
5847
5847
  if (effects.clrRepl) {
5848
- const c = hexToRgbUnit$1(effects.clrRepl.color);
5848
+ const c = hexToRgbUnit(effects.clrRepl.color);
5849
5849
  next((inp, out) => `<feColorMatrix in="${inp}" result="${out}" type="matrix" ` +
5850
5850
  `values="0 0 0 0 ${c.r} 0 0 0 0 ${c.g} 0 0 0 0 ${c.b} 0 0 0 1 0"/>`);
5851
5851
  }
@@ -35112,6 +35112,7 @@ const translationsEn = {
35112
35112
  'pptx.effects.blur': 'Blur',
35113
35113
  'pptx.effects.distance': 'Distance',
35114
35114
  'pptx.effects.angle': 'Angle',
35115
+ 'pptx.effects.rotateWithShape': 'Rotate with Shape',
35115
35116
  'pptx.effects.outerGlow': 'Outer Glow',
35116
35117
  'pptx.effects.radius': 'Radius',
35117
35118
  'pptx.effects.shapeOnlyNote': 'Shadow and glow are only available on shape-like elements.',
@@ -40605,12 +40606,17 @@ function getKinsokuLineBreakStyles(textStyle) {
40605
40606
  return {};
40606
40607
  }
40607
40608
  const result = {};
40608
- // East Asian line break: when eaLineBreak is true (the default in most CJK
40609
- // presentations), allow standard CJK line breaks between characters. When
40610
- // false, use strict mode to prevent breaks at kinsoku characters.
40609
+ // East Asian line break (ECMA-376 21.1.2.2.7 `eaLnBrk`): when true, an East
40610
+ // Asian word may be broken between characters, which is exactly what the
40611
+ // browser's default `word-break: normal` already does for CJK runs. It says
40612
+ // NOTHING about Latin words: `eaLnBrk="1"` is the default in every
40613
+ // PowerPoint master, so mapping it to `break-all` (as this once did) split
40614
+ // every Latin paragraph mid-word ("electro / nic"). Only `latinLnBrk`
40615
+ // licenses mid-word breaks in Latin text (below). When false, use strict
40616
+ // mode to prevent breaks at kinsoku characters.
40611
40617
  if (textStyle.eaLineBreak === true) {
40612
40618
  result.lineBreak = 'normal';
40613
- result.wordBreak = 'break-all';
40619
+ result.wordBreak = 'normal';
40614
40620
  result.overflowWrap = 'break-word';
40615
40621
  }
40616
40622
  else if (textStyle.eaLineBreak === false) {
@@ -57131,7 +57137,7 @@ function extraConnectionCount(data) {
57131
57137
  * No framework imports - the React, Vue, and Angular bindings can all mount it.
57132
57138
  */
57133
57139
  /** Default MIME for GLB binaries when the element omits `modelMimeType`. */
57134
- const DEFAULT_MODEL_MIME$1 = 'model/gltf-binary';
57140
+ const DEFAULT_MODEL_MIME = 'model/gltf-binary';
57135
57141
  /**
57136
57142
  * Convert a base64 `modelData` data URL to a blob (object) URL the GLTF
57137
57143
  * loader can fetch. Returns `undefined` for missing / non-base64 data URLs.
@@ -57156,7 +57162,7 @@ function modelDataToBlobUrl(dataUrl, mimeType) {
57156
57162
  // `Uint8Array<ArrayBufferLike>`, which TS does not accept as a `BlobPart`
57157
57163
  // (the backing buffer could in theory be a SharedArrayBuffer).
57158
57164
  const bytes = new Uint8Array(parsed.bytes);
57159
- const blob = new Blob([bytes], { type: mimeType ?? DEFAULT_MODEL_MIME$1 });
57165
+ const blob = new Blob([bytes], { type: mimeType ?? DEFAULT_MODEL_MIME });
57160
57166
  return URL.createObjectURL(blob);
57161
57167
  }
57162
57168
  /**
@@ -57346,7 +57352,7 @@ async function mountModel3D(container, modelUrl, options) {
57346
57352
 
57347
57353
  var model3dScene = /*#__PURE__*/Object.freeze({
57348
57354
  __proto__: null,
57349
- DEFAULT_MODEL_MIME: DEFAULT_MODEL_MIME$1,
57355
+ DEFAULT_MODEL_MIME: DEFAULT_MODEL_MIME,
57350
57356
  THREE_UNAVAILABLE: THREE_UNAVAILABLE,
57351
57357
  modelDataToBlobUrl: modelDataToBlobUrl,
57352
57358
  mountModel3D: mountModel3D
@@ -60876,6 +60882,1967 @@ function buildEmbeddedFontStyles(fonts, mintObjectUrl) {
60876
60882
  return { fontFaceCss, fontFamilies, objectUrls };
60877
60883
  }
60878
60884
 
60885
+ /**
60886
+ * GENERATED by scripts/update-google-fonts-catalogue.mjs on 2026-09-02; do not
60887
+ * edit by hand. Every family name the Google Fonts CSS2 API served on that
60888
+ * date, in the API's own spelling (family names are matched case-insensitively
60889
+ * and requested with this canonical spelling).
60890
+ *
60891
+ * Refresh with `bun run fonts:catalogue` when a deck references a family
60892
+ * Google has added since.
60893
+ */
60894
+ /** Date the catalogue was last regenerated (ISO yyyy-mm-dd). */
60895
+ const GOOGLE_FONTS_CATALOGUE_DATE = '2026-09-02';
60896
+ /** Family names served by the Google Fonts CSS2 API, sorted. */
60897
+ const GOOGLE_FONTS_FAMILIES = [
60898
+ 'ABeeZee',
60899
+ 'Abel',
60900
+ 'Abhaya Libre',
60901
+ 'Aboreto',
60902
+ 'Abril Fatface',
60903
+ 'Abyssinica SIL',
60904
+ 'Aclonica',
60905
+ 'Acme',
60906
+ 'Actor',
60907
+ 'Adamina',
60908
+ 'ADLaM Display',
60909
+ 'Advent Pro',
60910
+ 'Afacad',
60911
+ 'Afacad Flux',
60912
+ 'Agbalumo',
60913
+ 'Agdasima',
60914
+ 'Agu Display',
60915
+ 'Aguafina Script',
60916
+ 'Akatab',
60917
+ 'Akaya Kanadaka',
60918
+ 'Akaya Telivigala',
60919
+ 'Akronim',
60920
+ 'Akshar',
60921
+ 'Akt',
60922
+ 'Aladin',
60923
+ 'Alan Sans',
60924
+ 'Alata',
60925
+ 'Alatsi',
60926
+ 'Albert Sans',
60927
+ 'Aldrich',
60928
+ 'Alef',
60929
+ 'Alegreya',
60930
+ 'Alegreya Sans',
60931
+ 'Alegreya Sans SC',
60932
+ 'Alegreya SC',
60933
+ 'Aleo',
60934
+ 'Alex Brush',
60935
+ 'Alexandria',
60936
+ 'Alfa Slab One',
60937
+ 'Alice',
60938
+ 'Alien Block',
60939
+ 'Alike',
60940
+ 'Alike Angular',
60941
+ 'Alkalami',
60942
+ 'Alkatra',
60943
+ 'Allan',
60944
+ 'Allerta',
60945
+ 'Allerta Stencil',
60946
+ 'Allison',
60947
+ 'Allkin',
60948
+ 'Allura',
60949
+ 'Almarai',
60950
+ 'Almendra',
60951
+ 'Almendra Display',
60952
+ 'Almendra SC',
60953
+ 'Alumni Sans',
60954
+ 'Alumni Sans Collegiate One',
60955
+ 'Alumni Sans Inline One',
60956
+ 'Alumni Sans Pinstripe',
60957
+ 'Alumni Sans SC',
60958
+ 'Alyamama',
60959
+ 'Amarante',
60960
+ 'Amaranth',
60961
+ 'Amarna',
60962
+ 'Amatic SC',
60963
+ 'Amethysta',
60964
+ 'Amiko',
60965
+ 'Amiri',
60966
+ 'Amiri Quran',
60967
+ 'Amita',
60968
+ 'Anaheim',
60969
+ 'Ancizar Sans',
60970
+ 'Ancizar Serif',
60971
+ 'Andada Pro',
60972
+ 'Andika',
60973
+ 'Anek Bangla',
60974
+ 'Anek Devanagari',
60975
+ 'Anek Gujarati',
60976
+ 'Anek Gurmukhi',
60977
+ 'Anek Kannada',
60978
+ 'Anek Latin',
60979
+ 'Anek Malayalam',
60980
+ 'Anek Odia',
60981
+ 'Anek Tamil',
60982
+ 'Anek Telugu',
60983
+ 'Angkor',
60984
+ 'Annapurna SIL',
60985
+ 'Annie Use Your Telescope',
60986
+ 'Anonymous Pro',
60987
+ 'Anta',
60988
+ 'Antic',
60989
+ 'Antic Didone',
60990
+ 'Antic Slab',
60991
+ 'Anton',
60992
+ 'Anton SC',
60993
+ 'Antonio',
60994
+ 'Anuphan',
60995
+ 'Anybody',
60996
+ 'Aoboshi One',
60997
+ 'AR One Sans',
60998
+ 'Arapey',
60999
+ 'Arbutus',
61000
+ 'Arbutus Slab',
61001
+ 'Architects Daughter',
61002
+ 'Archivo',
61003
+ 'Archivo Black',
61004
+ 'Archivo Narrow',
61005
+ 'Are You Serious',
61006
+ 'Aref Ruqaa',
61007
+ 'Aref Ruqaa Ink',
61008
+ 'Arima',
61009
+ 'Arimo',
61010
+ 'Arizonia',
61011
+ 'Armata',
61012
+ 'Arsenal',
61013
+ 'Arsenal SC',
61014
+ 'Artifika',
61015
+ 'Arvo',
61016
+ 'Arya',
61017
+ 'Asap',
61018
+ 'Asap Condensed',
61019
+ 'Asap Sharp',
61020
+ 'Asar',
61021
+ 'Asimovian',
61022
+ 'Asset',
61023
+ 'Assistant',
61024
+ 'Asta Sans',
61025
+ 'Astloch',
61026
+ 'Asul',
61027
+ 'Athiti',
61028
+ 'Atkinson Hyperlegible',
61029
+ 'Atkinson Hyperlegible Mono',
61030
+ 'Atkinson Hyperlegible Next',
61031
+ 'Atma',
61032
+ 'Atomic Age',
61033
+ 'Aubrey',
61034
+ 'Audiowide',
61035
+ 'Autour One',
61036
+ 'Average',
61037
+ 'Average Sans',
61038
+ 'Averia Gruesa Libre',
61039
+ 'Averia Libre',
61040
+ 'Averia Sans Libre',
61041
+ 'Averia Serif Libre',
61042
+ 'Azeret Mono',
61043
+ 'B612',
61044
+ 'B612 Mono',
61045
+ 'Babylonica',
61046
+ 'Bacasime Antique',
61047
+ 'Bad Script',
61048
+ 'Badeen Display',
61049
+ 'Bagel Fat One',
61050
+ 'Bahiana',
61051
+ 'Bahianita',
61052
+ 'Bai Jamjuree',
61053
+ 'Bakbak One',
61054
+ 'Ballet',
61055
+ 'Baloo 2',
61056
+ 'Baloo Bhai 2',
61057
+ 'Baloo Bhaijaan 2',
61058
+ 'Baloo Bhaina 2',
61059
+ 'Baloo Chettan 2',
61060
+ 'Baloo Da 2',
61061
+ 'Baloo Paaji 2',
61062
+ 'Baloo Tamma 2',
61063
+ 'Baloo Tammudu 2',
61064
+ 'Baloo Thambi 2',
61065
+ 'Balsamiq Sans',
61066
+ 'Balthazar',
61067
+ 'Bangers',
61068
+ 'Barlow',
61069
+ 'Barlow Condensed',
61070
+ 'Barlow Semi Condensed',
61071
+ 'Barriecito',
61072
+ 'Barrio',
61073
+ 'Basic',
61074
+ 'Baskervville',
61075
+ 'Baskervville SC',
61076
+ 'Battambang',
61077
+ 'Baumans',
61078
+ 'Bayon',
61079
+ 'BBH Bartle',
61080
+ 'BBH Bogle',
61081
+ 'BBH Hegarty',
61082
+ 'Be Vietnam Pro',
61083
+ 'Beau Rivage',
61084
+ 'Bebas Neue',
61085
+ 'Beiruti',
61086
+ 'Belanosima',
61087
+ 'Belgrano',
61088
+ 'Bellefair',
61089
+ 'Belleza',
61090
+ 'Bellota',
61091
+ 'Bellota Text',
61092
+ 'BenchNine',
61093
+ 'Benne',
61094
+ 'Bentham',
61095
+ 'Berkshire Swash',
61096
+ 'Besley',
61097
+ 'Betania Patmos',
61098
+ 'Betania Patmos GDL',
61099
+ 'Betania Patmos In',
61100
+ 'Betania Patmos In GDL',
61101
+ 'Beth Ellen',
61102
+ 'Bevan',
61103
+ 'BhuTuka Expanded One',
61104
+ 'Big Shoulders',
61105
+ 'Big Shoulders Inline',
61106
+ 'Big Shoulders Stencil',
61107
+ 'Bigelow Rules',
61108
+ 'Bigshot One',
61109
+ 'Bilbo',
61110
+ 'Bilbo Swash Caps',
61111
+ 'BioRhyme',
61112
+ 'BioRhyme Expanded',
61113
+ 'Birthstone',
61114
+ 'Birthstone Bounce',
61115
+ 'Biryani',
61116
+ 'Bitcount',
61117
+ 'Bitcount Grid Double',
61118
+ 'Bitcount Grid Double Ink',
61119
+ 'Bitcount Grid Single',
61120
+ 'Bitcount Grid Single Ink',
61121
+ 'Bitcount Ink',
61122
+ 'Bitcount Prop Double',
61123
+ 'Bitcount Prop Double Ink',
61124
+ 'Bitcount Prop Single',
61125
+ 'Bitcount Prop Single Ink',
61126
+ 'Bitcount Single',
61127
+ 'Bitcount Single Ink',
61128
+ 'Bitter',
61129
+ 'BIZ UDGothic',
61130
+ 'BIZ UDMincho',
61131
+ 'BIZ UDPGothic',
61132
+ 'BIZ UDPMincho',
61133
+ 'BJCree',
61134
+ 'Black And White Picture',
61135
+ 'Black Han Sans',
61136
+ 'Black Ops One',
61137
+ 'Blaka',
61138
+ 'Blaka Hollow',
61139
+ 'Blaka Ink',
61140
+ 'Blinker',
61141
+ 'Bodoni Moda',
61142
+ 'Bodoni Moda SC',
61143
+ 'Bokor',
61144
+ 'Boldonse',
61145
+ 'Bona Nova',
61146
+ 'Bona Nova SC',
61147
+ 'Bonbon',
61148
+ 'Bonheur Royale',
61149
+ 'Boogaloo',
61150
+ 'Borel',
61151
+ 'Bowlby One',
61152
+ 'Bowlby One SC',
61153
+ 'Bpmf Huninn',
61154
+ 'Bpmf Iansui',
61155
+ 'Bpmf Zihi Kai Std',
61156
+ 'Braah One',
61157
+ 'Brawler',
61158
+ 'Bree Serif',
61159
+ 'Bricolage Grotesque',
61160
+ 'Bruno Ace',
61161
+ 'Bruno Ace SC',
61162
+ 'Brygada 1918',
61163
+ 'Bubblegum Sans',
61164
+ 'Bubbler One',
61165
+ 'Buda',
61166
+ 'Buenard',
61167
+ 'Bungee',
61168
+ 'Bungee Hairline',
61169
+ 'Bungee Inline',
61170
+ 'Bungee Outline',
61171
+ 'Bungee Shade',
61172
+ 'Bungee Spice',
61173
+ 'Bungee Tint',
61174
+ 'Butcherman',
61175
+ 'Butterfly Kids',
61176
+ 'Bytesized',
61177
+ 'Caacupe One',
61178
+ 'Cabin',
61179
+ 'Cabin Condensed',
61180
+ 'Cabin Sketch',
61181
+ 'Cactus Classical Serif',
61182
+ 'Caesar Dressing',
61183
+ 'Cagliostro',
61184
+ 'Cairo',
61185
+ 'Cairo Play',
61186
+ 'Cal Sans',
61187
+ 'Caladea',
61188
+ 'Calistoga',
61189
+ 'Calligraffitti',
61190
+ 'Cambay',
61191
+ 'Cambo',
61192
+ 'Candal',
61193
+ 'Cantarell',
61194
+ 'Cantata One',
61195
+ 'Cantora One',
61196
+ 'Caprasimo',
61197
+ 'Capriola',
61198
+ 'Caramel',
61199
+ 'Carattere',
61200
+ 'Cardo',
61201
+ 'Carlito',
61202
+ 'Carme',
61203
+ 'Carrois Gothic',
61204
+ 'Carrois Gothic SC',
61205
+ 'Carter One',
61206
+ 'Cascadia Code',
61207
+ 'Cascadia Mono',
61208
+ 'Castoro',
61209
+ 'Castoro Titling',
61210
+ 'Catamaran',
61211
+ 'Caudex',
61212
+ 'Cause',
61213
+ 'Caveat',
61214
+ 'Caveat Brush',
61215
+ 'Cedarville Cursive',
61216
+ 'Ceviche One',
61217
+ 'Chakra Petch',
61218
+ 'Changa',
61219
+ 'Changa One',
61220
+ 'Chango',
61221
+ 'Charis SIL',
61222
+ 'Charm',
61223
+ 'Charmonman',
61224
+ 'Chathura',
61225
+ 'Chau Philomene One',
61226
+ 'Chela One',
61227
+ 'Chelsea Market',
61228
+ 'Chenla',
61229
+ 'Cherish',
61230
+ 'Cherry Bomb One',
61231
+ 'Cherry Cream Soda',
61232
+ 'Cherry Swash',
61233
+ 'Chewy',
61234
+ 'Chicle',
61235
+ 'Chilanka',
61236
+ 'Chiron GoRound TC',
61237
+ 'Chiron Hei HK',
61238
+ 'Chiron Sung HK',
61239
+ 'Chivo',
61240
+ 'Chivo Mono',
61241
+ 'Chocolate Classical Sans',
61242
+ 'Chokokutai',
61243
+ 'Chonburi',
61244
+ 'Cinzel',
61245
+ 'Cinzel Decorative',
61246
+ 'Clicker Script',
61247
+ 'Climate Crisis',
61248
+ 'Coda',
61249
+ 'Codystar',
61250
+ 'Coiny',
61251
+ 'Combo',
61252
+ 'Comfortaa',
61253
+ 'Comforter',
61254
+ 'Comforter Brush',
61255
+ 'Comic Neue',
61256
+ 'Comic Relief',
61257
+ 'Coming Soon',
61258
+ 'Comme',
61259
+ 'Commissioner',
61260
+ 'Concert One',
61261
+ 'Condiment',
61262
+ 'Content',
61263
+ 'Contrail One',
61264
+ 'Convergence',
61265
+ 'Cookie',
61266
+ 'Copse',
61267
+ 'Coral Pixels',
61268
+ 'Corben',
61269
+ 'Corinthia',
61270
+ 'Cormorant',
61271
+ 'Cormorant Garamond',
61272
+ 'Cormorant Infant',
61273
+ 'Cormorant SC',
61274
+ 'Cormorant Unicase',
61275
+ 'Cormorant Upright',
61276
+ 'Cossette Texte',
61277
+ 'Cossette Titre',
61278
+ 'Courgette',
61279
+ 'Courier Prime',
61280
+ 'Cousine',
61281
+ 'Coustard',
61282
+ 'Covered By Your Grace',
61283
+ 'Crafty Girls',
61284
+ 'Creepster',
61285
+ 'Crete Round',
61286
+ 'Crimson Pro',
61287
+ 'Crimson Text',
61288
+ 'Croissant One',
61289
+ 'Crushed',
61290
+ 'Cuprum',
61291
+ 'Cute Font',
61292
+ 'Cutive',
61293
+ 'Cutive Mono',
61294
+ 'Dai Banna SIL',
61295
+ 'Damion',
61296
+ 'Dancing Script',
61297
+ 'Danfo',
61298
+ 'Dangrek',
61299
+ 'Darker Grotesque',
61300
+ 'Darumadrop One',
61301
+ 'Datatype',
61302
+ 'David Libre',
61303
+ 'Dawning of a New Day',
61304
+ 'Days One',
61305
+ 'Dekko',
61306
+ 'Dela Gothic One',
61307
+ 'Delicious Handrawn',
61308
+ 'Delius',
61309
+ 'Delius Swash Caps',
61310
+ 'Delius Unicase',
61311
+ 'Della Respira',
61312
+ 'Denk One',
61313
+ 'Devonshire',
61314
+ 'Dhurjati',
61315
+ 'Didact Gothic',
61316
+ 'Diphylleia',
61317
+ 'Diplomata',
61318
+ 'Diplomata SC',
61319
+ 'DM Mono',
61320
+ 'DM Sans',
61321
+ 'DM Serif Display',
61322
+ 'DM Serif Text',
61323
+ 'Do Hyeon',
61324
+ 'Dokdo',
61325
+ 'Domine',
61326
+ 'Donegal One',
61327
+ 'Dongle',
61328
+ 'Doppio One',
61329
+ 'Dorsa',
61330
+ 'Dosis',
61331
+ 'DotGothic16',
61332
+ 'Doto',
61333
+ 'Dr Sugiyama',
61334
+ 'Duru Sans',
61335
+ 'Dynalight',
61336
+ 'DynaPuff',
61337
+ 'Eagle Lake',
61338
+ 'East Sea Dokdo',
61339
+ 'Eater',
61340
+ 'EB Garamond',
61341
+ 'Economica',
61342
+ 'Eczar',
61343
+ 'Edu AU VIC WA NT Arrows',
61344
+ 'Edu AU VIC WA NT Dots',
61345
+ 'Edu AU VIC WA NT Guides',
61346
+ 'Edu AU VIC WA NT Hand',
61347
+ 'Edu AU VIC WA NT Pre',
61348
+ 'Edu NSW ACT Cursive',
61349
+ 'Edu NSW ACT Foundation',
61350
+ 'Edu NSW ACT Hand Pre',
61351
+ 'Edu QLD Beginner',
61352
+ 'Edu QLD Hand',
61353
+ 'Edu SA Beginner',
61354
+ 'Edu SA Hand',
61355
+ 'Edu TAS Beginner',
61356
+ 'Edu VIC WA NT Beginner',
61357
+ 'Edu VIC WA NT Hand',
61358
+ 'Edu VIC WA NT Hand Pre',
61359
+ 'El Messiri',
61360
+ 'Electrolize',
61361
+ 'Elms Sans',
61362
+ 'Elsie',
61363
+ 'Elsie Swash Caps',
61364
+ 'Emblema One',
61365
+ 'Emilys Candy',
61366
+ 'Encode Sans',
61367
+ 'Encode Sans Condensed',
61368
+ 'Encode Sans Expanded',
61369
+ 'Encode Sans SC',
61370
+ 'Encode Sans Semi Condensed',
61371
+ 'Encode Sans Semi Expanded',
61372
+ 'Engagement',
61373
+ 'Englebert',
61374
+ 'Enriqueta',
61375
+ 'Ephesis',
61376
+ 'Epilogue',
61377
+ 'Epunda Sans',
61378
+ 'Epunda Slab',
61379
+ 'Erica One',
61380
+ 'Esteban',
61381
+ 'Estedad',
61382
+ 'Estonia',
61383
+ 'Euphoria Script',
61384
+ 'Ewert',
61385
+ 'Exile',
61386
+ 'Exo',
61387
+ 'Exo 2',
61388
+ 'Expletus Sans',
61389
+ 'Explora',
61390
+ 'Faculty Glyphic',
61391
+ 'Fahkwang',
61392
+ 'Familjen Grotesk',
61393
+ 'Fanwood Text',
61394
+ 'Farro',
61395
+ 'Farsan',
61396
+ 'Fascinate',
61397
+ 'Fascinate Inline',
61398
+ 'Faster One',
61399
+ 'Fasthand',
61400
+ 'Fauna One',
61401
+ 'Faustina',
61402
+ 'Federant',
61403
+ 'Federo',
61404
+ 'Felipa',
61405
+ 'Fenix',
61406
+ 'Festive',
61407
+ 'Figtree',
61408
+ 'Finger Paint',
61409
+ 'Finlandica Headline',
61410
+ 'Finlandica Text',
61411
+ 'Fira Code',
61412
+ 'Fira Mono',
61413
+ 'Fira Sans',
61414
+ 'Fira Sans Condensed',
61415
+ 'Fira Sans Extra Condensed',
61416
+ 'Fjalla One',
61417
+ 'Fjord One',
61418
+ 'Flamenco',
61419
+ 'Flavors',
61420
+ 'Fleur De Leah',
61421
+ 'Flow Block',
61422
+ 'Flow Circular',
61423
+ 'Flow Rounded',
61424
+ 'Foldit',
61425
+ 'Fondamento',
61426
+ 'Fontdiner Swanky',
61427
+ 'Forum',
61428
+ 'Fragment Mono',
61429
+ 'Francois One',
61430
+ 'Frank Ruhl Libre',
61431
+ 'Fraunces',
61432
+ 'Freckle Face',
61433
+ 'Fredericka the Great',
61434
+ 'Fredoka',
61435
+ 'Freehand',
61436
+ 'Freeman',
61437
+ 'Fresca',
61438
+ 'Frijole',
61439
+ 'Fruktur',
61440
+ 'Fugaz One',
61441
+ 'Fuggles',
61442
+ 'Funnel Display',
61443
+ 'Funnel Sans',
61444
+ 'Fustat',
61445
+ 'Fuzzy Bubbles',
61446
+ 'Ga Maamli',
61447
+ 'Gabarito',
61448
+ 'Gabriela',
61449
+ 'Gaegu',
61450
+ 'Gafata',
61451
+ 'Gajraj One',
61452
+ 'Galada',
61453
+ 'Galdeano',
61454
+ 'Galindo',
61455
+ 'Gamja Flower',
61456
+ 'Gantari',
61457
+ 'Gasoek One',
61458
+ 'Gayathri',
61459
+ 'Geist',
61460
+ 'Geist Mono',
61461
+ 'Geist Pixel',
61462
+ 'Gelasio',
61463
+ 'Gemunu Libre',
61464
+ 'Genos',
61465
+ 'Gentium Book Plus',
61466
+ 'Gentium Plus',
61467
+ 'Geo',
61468
+ 'Geologica',
61469
+ 'Geom',
61470
+ 'Geomini',
61471
+ 'Georama',
61472
+ 'Geostar',
61473
+ 'Geostar Fill',
61474
+ 'Germania One',
61475
+ 'GFS Didot',
61476
+ 'GFS Neohellenic',
61477
+ 'Gideon Roman',
61478
+ 'Gidole',
61479
+ 'Gidugu',
61480
+ 'Gilda Display',
61481
+ 'Girassol',
61482
+ 'Give You Glory',
61483
+ 'Glass Antiqua',
61484
+ 'Glegoo',
61485
+ 'Gloock',
61486
+ 'Gloria Hallelujah',
61487
+ 'Glory',
61488
+ 'Gluten',
61489
+ 'Goblin One',
61490
+ 'Gochi Hand',
61491
+ 'Goldman',
61492
+ 'Golos Text',
61493
+ 'Google Sans',
61494
+ 'Google Sans Code',
61495
+ 'Google Sans Flex',
61496
+ 'Gorditas',
61497
+ 'Gothic A1',
61498
+ 'Gotu',
61499
+ 'Goudy Bookletter 1911',
61500
+ 'Gowun Batang',
61501
+ 'Gowun Dodum',
61502
+ 'Graduate',
61503
+ 'Grand Hotel',
61504
+ 'Grandiflora One',
61505
+ 'Grandstander',
61506
+ 'Grape Nuts',
61507
+ 'Gravitas One',
61508
+ 'Great Vibes',
61509
+ 'Grechen Fuemen',
61510
+ 'Grenze',
61511
+ 'Grenze Gotisch',
61512
+ 'Grey Qo',
61513
+ 'Griffy',
61514
+ 'Gruppo',
61515
+ 'Gudea',
61516
+ 'Gugi',
61517
+ 'Gulzar',
61518
+ 'Gupter',
61519
+ 'Gurajada',
61520
+ 'Gveret Levin',
61521
+ 'Gwendolyn',
61522
+ 'Habibi',
61523
+ 'Hachi Maru Pop',
61524
+ 'Hahmlet',
61525
+ 'Halant',
61526
+ 'Hammersmith One',
61527
+ 'Hanalei',
61528
+ 'Hanalei Fill',
61529
+ 'Handjet',
61530
+ 'Handlee',
61531
+ 'Hanken Grotesk',
61532
+ 'Hanuman',
61533
+ 'Happy Monkey',
61534
+ 'Harmattan',
61535
+ 'Headland One',
61536
+ 'Hedvig Letters Sans',
61537
+ 'Hedvig Letters Serif',
61538
+ 'Heebo',
61539
+ 'Henny Penny',
61540
+ 'Hepta Slab',
61541
+ 'Herr Von Muellerhoff',
61542
+ 'Hi Melody',
61543
+ 'Hibur Mono',
61544
+ 'Hina Mincho',
61545
+ 'Hind',
61546
+ 'Hind Guntur',
61547
+ 'Hind Madurai',
61548
+ 'Hind Mysuru',
61549
+ 'Hind Siliguri',
61550
+ 'Hind Vadodara',
61551
+ 'Holtwood One SC',
61552
+ 'Homemade Apple',
61553
+ 'Homenaje',
61554
+ 'Honk',
61555
+ 'Host Grotesk',
61556
+ 'Hubballi',
61557
+ 'Hubot Sans',
61558
+ 'Huninn',
61559
+ 'Hurricane',
61560
+ 'Iansui',
61561
+ 'Ibarra Real Nova',
61562
+ 'IBM Plex Mono',
61563
+ 'IBM Plex Sans',
61564
+ 'IBM Plex Sans Arabic',
61565
+ 'IBM Plex Sans Condensed',
61566
+ 'IBM Plex Sans Devanagari',
61567
+ 'IBM Plex Sans Hebrew',
61568
+ 'IBM Plex Sans JP',
61569
+ 'IBM Plex Sans KR',
61570
+ 'IBM Plex Sans Thai',
61571
+ 'IBM Plex Sans Thai Looped',
61572
+ 'IBM Plex Serif',
61573
+ 'Iceberg',
61574
+ 'Iceland',
61575
+ 'Idiqlat',
61576
+ 'IM Fell Double Pica',
61577
+ 'IM Fell Double Pica SC',
61578
+ 'IM Fell DW Pica',
61579
+ 'IM Fell DW Pica SC',
61580
+ 'IM Fell English',
61581
+ 'IM Fell English SC',
61582
+ 'IM Fell French Canon',
61583
+ 'IM Fell French Canon SC',
61584
+ 'IM Fell Great Primer',
61585
+ 'IM Fell Great Primer SC',
61586
+ 'Imbue',
61587
+ 'Imperial Script',
61588
+ 'Imprima',
61589
+ 'Inclusive Sans',
61590
+ 'Inconsolata',
61591
+ 'Inder',
61592
+ 'Indie Flower',
61593
+ 'Ingrid Darling',
61594
+ 'Inika',
61595
+ 'Inknut Antiqua',
61596
+ 'Inria Sans',
61597
+ 'Inria Serif',
61598
+ 'Inspiration',
61599
+ 'Instrument Sans',
61600
+ 'Instrument Serif',
61601
+ 'Intel One Mono',
61602
+ 'Inter',
61603
+ 'Inter Tight',
61604
+ 'Iosevka Charon',
61605
+ 'Iosevka Charon Mono',
61606
+ 'Irish Grover',
61607
+ 'Island Moments',
61608
+ 'Istok Web',
61609
+ 'Italiana',
61610
+ 'Italianno',
61611
+ 'Itim',
61612
+ 'Jacquard 12',
61613
+ 'Jacquard 12 Charted',
61614
+ 'Jacquard 24',
61615
+ 'Jacquard 24 Charted',
61616
+ 'Jacquarda Bastarda 9',
61617
+ 'Jacquarda Bastarda 9 Charted',
61618
+ 'Jacques Francois',
61619
+ 'Jacques Francois Shadow',
61620
+ 'Jaini',
61621
+ 'Jaini Purva',
61622
+ 'Jaldi',
61623
+ 'Jaro',
61624
+ 'Jersey 10',
61625
+ 'Jersey 10 Charted',
61626
+ 'Jersey 15',
61627
+ 'Jersey 15 Charted',
61628
+ 'Jersey 20',
61629
+ 'Jersey 20 Charted',
61630
+ 'Jersey 25',
61631
+ 'Jersey 25 Charted',
61632
+ 'JetBrains Mono',
61633
+ 'Jim Nightshade',
61634
+ 'Joan',
61635
+ 'Jockey One',
61636
+ 'Jolly Lodger',
61637
+ 'Jomhuria',
61638
+ 'Jomolhari',
61639
+ 'Josefin Sans',
61640
+ 'Josefin Slab',
61641
+ 'Jost',
61642
+ 'Joti One',
61643
+ 'Jua',
61644
+ 'Judson',
61645
+ 'Julee',
61646
+ 'Julius Sans One',
61647
+ 'Junge',
61648
+ 'Jura',
61649
+ 'Just Another Hand',
61650
+ 'Just Me Again Down Here',
61651
+ 'K2D',
61652
+ 'Kablammo',
61653
+ 'Kadwa',
61654
+ 'Kaisei Decol',
61655
+ 'Kaisei HarunoUmi',
61656
+ 'Kaisei Opti',
61657
+ 'Kaisei Tokumin',
61658
+ 'Kalam',
61659
+ 'Kalnia',
61660
+ 'Kalnia Glaze',
61661
+ 'Kameron',
61662
+ 'Kanchenjunga',
61663
+ 'Kanit',
61664
+ 'Kantumruy Pro',
61665
+ 'Kapakana',
61666
+ 'Karantina',
61667
+ 'Karla',
61668
+ 'Karla Tamil Inclined',
61669
+ 'Karla Tamil Upright',
61670
+ 'Karma',
61671
+ 'Katibeh',
61672
+ 'Kaushan Script',
61673
+ 'Kavivanar',
61674
+ 'Kavoon',
61675
+ 'Kay Pho Du',
61676
+ 'Kdam Thmor Pro',
61677
+ 'Keania One',
61678
+ 'Kedebideri',
61679
+ 'Kelly Slab',
61680
+ 'Kenia',
61681
+ 'Khand',
61682
+ 'Khmer',
61683
+ 'Khula',
61684
+ 'Kings',
61685
+ 'Kirang Haerang',
61686
+ 'Kite One',
61687
+ 'Kiwi Maru',
61688
+ 'Klee One',
61689
+ 'Knewave',
61690
+ 'Kodchasan',
61691
+ 'Kode Mono',
61692
+ 'Koh Santepheap',
61693
+ 'KoHo',
61694
+ 'Kolker Brush',
61695
+ 'Konkhmer Sleokchher',
61696
+ 'Kosugi',
61697
+ 'Kosugi Maru',
61698
+ 'Kotta One',
61699
+ 'Koulen',
61700
+ 'Kranky',
61701
+ 'Kreon',
61702
+ 'Kristi',
61703
+ 'Krona One',
61704
+ 'Krub',
61705
+ 'Kufam',
61706
+ 'Kulim Park',
61707
+ 'Kumar One',
61708
+ 'Kumar One Outline',
61709
+ 'Kumbh Sans',
61710
+ 'Kurale',
61711
+ 'La Belle Aurore',
61712
+ 'Labrada',
61713
+ 'Lacquer',
61714
+ 'Laila',
61715
+ 'Lakki Reddy',
61716
+ 'Lalezar',
61717
+ 'Lancelot',
61718
+ 'Langar',
61719
+ 'Lateef',
61720
+ 'Lato',
61721
+ 'Lavishly Yours',
61722
+ 'League Gothic',
61723
+ 'League Script',
61724
+ 'League Spartan',
61725
+ 'Leckerli One',
61726
+ 'Ledger',
61727
+ 'Lekton',
61728
+ 'Lemon',
61729
+ 'Lemonada',
61730
+ 'Lexend',
61731
+ 'Lexend Deca',
61732
+ 'Lexend Exa',
61733
+ 'Lexend Giga',
61734
+ 'Lexend Mega',
61735
+ 'Lexend Peta',
61736
+ 'Lexend Tera',
61737
+ 'Lexend Zetta',
61738
+ 'Libertinus Keyboard',
61739
+ 'Libertinus Math',
61740
+ 'Libertinus Mono',
61741
+ 'Libertinus Sans',
61742
+ 'Libertinus Serif',
61743
+ 'Libertinus Serif Display',
61744
+ 'Libre Barcode 128',
61745
+ 'Libre Barcode 128 Text',
61746
+ 'Libre Barcode 39',
61747
+ 'Libre Barcode 39 Extended',
61748
+ 'Libre Barcode 39 Extended Text',
61749
+ 'Libre Barcode 39 Text',
61750
+ 'Libre Barcode EAN13 Text',
61751
+ 'Libre Baskerville',
61752
+ 'Libre Bodoni',
61753
+ 'Libre Caslon Display',
61754
+ 'Libre Caslon Text',
61755
+ 'Libre Franklin',
61756
+ 'Licorice',
61757
+ 'Life Savers',
61758
+ 'Lilex',
61759
+ 'Lilita One',
61760
+ 'Lily Script One',
61761
+ 'Limelight',
61762
+ 'Linden Hill',
61763
+ 'LINE Seed JP',
61764
+ 'Linefont',
61765
+ 'Lisu Bosa',
61766
+ 'Liter',
61767
+ 'Literata',
61768
+ 'Liu Jian Mao Cao',
61769
+ 'Livvic',
61770
+ 'Lobster',
61771
+ 'Lobster Two',
61772
+ 'Londrina Outline',
61773
+ 'Londrina Shadow',
61774
+ 'Londrina Sketch',
61775
+ 'Londrina Solid',
61776
+ 'Long Cang',
61777
+ 'Lora',
61778
+ 'Love Light',
61779
+ 'Love Ya Like A Sister',
61780
+ 'Loved by the King',
61781
+ 'Lovers Quarrel',
61782
+ 'Luckiest Guy',
61783
+ 'Lugrasimo',
61784
+ 'Lumanosimo',
61785
+ 'Lunasima',
61786
+ 'Lusitana',
61787
+ 'Lustria',
61788
+ 'Luxurious Roman',
61789
+ 'Luxurious Script',
61790
+ 'LXGW Marker Gothic',
61791
+ 'LXGW WenKai Mono TC',
61792
+ 'LXGW WenKai TC',
61793
+ 'M PLUS 1',
61794
+ 'M PLUS 1 Code',
61795
+ 'M PLUS 1p',
61796
+ 'M PLUS 2',
61797
+ 'M PLUS Code Latin',
61798
+ 'M PLUS Rounded 1c',
61799
+ 'M PLUS U',
61800
+ 'Ma Shan Zheng',
61801
+ 'Macondo',
61802
+ 'Macondo Swash Caps',
61803
+ 'Mada',
61804
+ 'Madimi One',
61805
+ 'Magra',
61806
+ 'Maiden Orange',
61807
+ 'Maitree',
61808
+ 'Major Mono Display',
61809
+ 'Mako',
61810
+ 'Mali',
61811
+ 'Mallanna',
61812
+ 'Maname',
61813
+ 'Mandali',
61814
+ 'Manjari',
61815
+ 'Manrope',
61816
+ 'Mansalva',
61817
+ 'Manuale',
61818
+ 'Manufacturing Consent',
61819
+ 'Marcellus',
61820
+ 'Marcellus SC',
61821
+ 'Marck Script',
61822
+ 'Margarine',
61823
+ 'Marhey',
61824
+ 'Markazi Text',
61825
+ 'Marko One',
61826
+ 'Marmelad',
61827
+ 'Martel',
61828
+ 'Martel Sans',
61829
+ 'Martian Mono',
61830
+ 'Marvel',
61831
+ 'Matangi',
61832
+ 'Mate',
61833
+ 'Mate SC',
61834
+ 'Matemasie',
61835
+ 'Maven Pro',
61836
+ 'McLaren',
61837
+ 'Mea Culpa',
61838
+ 'Meddon',
61839
+ 'MedievalSharp',
61840
+ 'Medula One',
61841
+ 'Meera Inimai',
61842
+ 'Megrim',
61843
+ 'Meie Script',
61844
+ 'Menbere',
61845
+ 'Meow Script',
61846
+ 'Merienda',
61847
+ 'Merriweather',
61848
+ 'Merriweather Sans',
61849
+ 'Metal',
61850
+ 'Metal Mania',
61851
+ 'Metamorphous',
61852
+ 'Metrophobic',
61853
+ 'Michroma',
61854
+ 'Micro 5',
61855
+ 'Micro 5 Charted',
61856
+ 'Milonga',
61857
+ 'Miltonian',
61858
+ 'Miltonian Tattoo',
61859
+ 'Mina',
61860
+ 'Mingzat',
61861
+ 'Miniver',
61862
+ 'Miranda Sans',
61863
+ 'Miriam Libre',
61864
+ 'Mirza',
61865
+ 'Miss Fajardose',
61866
+ 'Mitr',
61867
+ 'Mochiy Pop One',
61868
+ 'Mochiy Pop P One',
61869
+ 'Modak',
61870
+ 'Modern Antiqua',
61871
+ 'Moderustic',
61872
+ 'Mogra',
61873
+ 'Mohave',
61874
+ 'Moirai One',
61875
+ 'Molengo',
61876
+ 'Molle',
61877
+ 'Momo Signature',
61878
+ 'Momo Trust Display',
61879
+ 'Momo Trust Sans',
61880
+ 'Mona Sans',
61881
+ 'Monda',
61882
+ 'Monofett',
61883
+ 'Monomakh',
61884
+ 'Monomaniac One',
61885
+ 'Monoton',
61886
+ 'Monsieur La Doulaise',
61887
+ 'Montaga',
61888
+ 'Montagu Slab',
61889
+ 'MonteCarlo',
61890
+ 'Montenegrin Gothic One',
61891
+ 'Montez',
61892
+ 'Montserrat',
61893
+ 'Montserrat Alternates',
61894
+ 'Montserrat Underline',
61895
+ 'Moo Lah Lah',
61896
+ 'Mooli',
61897
+ 'Moon Dance',
61898
+ 'Moul',
61899
+ 'Moulpali',
61900
+ 'Mountains of Christmas',
61901
+ 'Mouse Memoirs',
61902
+ 'Mozilla Headline',
61903
+ 'Mozilla Text',
61904
+ 'Mr Bedfort',
61905
+ 'Mr Dafoe',
61906
+ 'Mr De Haviland',
61907
+ 'Mrs Saint Delafield',
61908
+ 'Mrs Sheppards',
61909
+ 'Ms Madi',
61910
+ 'Mukta',
61911
+ 'Mukta Mahee',
61912
+ 'Mukta Malar',
61913
+ 'Mukta Vaani',
61914
+ 'Mulish',
61915
+ 'Murecho',
61916
+ 'MuseoModerno',
61917
+ 'My Soul',
61918
+ 'Mynerve',
61919
+ 'Mystery Quest',
61920
+ 'Nabla',
61921
+ 'Namdhinggo',
61922
+ 'Nanum Brush Script',
61923
+ 'Nanum Gothic',
61924
+ 'Nanum Gothic Coding',
61925
+ 'Nanum Myeongjo',
61926
+ 'Nanum Pen Script',
61927
+ 'Narnoor',
61928
+ 'Nata Sans',
61929
+ 'National Park',
61930
+ 'Neonderthaw',
61931
+ 'Nerko One',
61932
+ 'Neucha',
61933
+ 'Neuton',
61934
+ 'New Amsterdam',
61935
+ 'New Rocker',
61936
+ 'New Tegomin',
61937
+ 'News Cycle',
61938
+ 'Newsreader',
61939
+ 'Niconne',
61940
+ 'Niramit',
61941
+ 'Nixie One',
61942
+ 'Nobile',
61943
+ 'Nokora',
61944
+ 'Norican',
61945
+ 'Nosifer',
61946
+ 'Notable',
61947
+ 'Nothing You Could Do',
61948
+ 'Noticia Text',
61949
+ 'Noto Color Emoji',
61950
+ 'Noto Emoji',
61951
+ 'Noto Kufi Arabic',
61952
+ 'Noto Music',
61953
+ 'Noto Naskh Arabic',
61954
+ 'Noto Nastaliq Urdu',
61955
+ 'Noto Rashi Hebrew',
61956
+ 'Noto Sans',
61957
+ 'Noto Sans Adlam',
61958
+ 'Noto Sans Adlam Unjoined',
61959
+ 'Noto Sans Anatolian Hieroglyphs',
61960
+ 'Noto Sans Arabic',
61961
+ 'Noto Sans Armenian',
61962
+ 'Noto Sans Avestan',
61963
+ 'Noto Sans Balinese',
61964
+ 'Noto Sans Bamum',
61965
+ 'Noto Sans Bassa Vah',
61966
+ 'Noto Sans Batak',
61967
+ 'Noto Sans Bengali',
61968
+ 'Noto Sans Bhaiksuki',
61969
+ 'Noto Sans Brahmi',
61970
+ 'Noto Sans Buginese',
61971
+ 'Noto Sans Buhid',
61972
+ 'Noto Sans Canadian Aboriginal',
61973
+ 'Noto Sans Carian',
61974
+ 'Noto Sans Caucasian Albanian',
61975
+ 'Noto Sans Chakma',
61976
+ 'Noto Sans Cham',
61977
+ 'Noto Sans Cherokee',
61978
+ 'Noto Sans Chorasmian',
61979
+ 'Noto Sans Coptic',
61980
+ 'Noto Sans Cuneiform',
61981
+ 'Noto Sans Cypriot',
61982
+ 'Noto Sans Cypro Minoan',
61983
+ 'Noto Sans Deseret',
61984
+ 'Noto Sans Devanagari',
61985
+ 'Noto Sans Display',
61986
+ 'Noto Sans Duployan',
61987
+ 'Noto Sans Egyptian Hieroglyphs',
61988
+ 'Noto Sans Elbasan',
61989
+ 'Noto Sans Elymaic',
61990
+ 'Noto Sans Ethiopic',
61991
+ 'Noto Sans Georgian',
61992
+ 'Noto Sans Glagolitic',
61993
+ 'Noto Sans Gothic',
61994
+ 'Noto Sans Grantha',
61995
+ 'Noto Sans Gujarati',
61996
+ 'Noto Sans Gunjala Gondi',
61997
+ 'Noto Sans Gurmukhi',
61998
+ 'Noto Sans Hanifi Rohingya',
61999
+ 'Noto Sans Hanunoo',
62000
+ 'Noto Sans Hatran',
62001
+ 'Noto Sans Hebrew',
62002
+ 'Noto Sans HK',
62003
+ 'Noto Sans Imperial Aramaic',
62004
+ 'Noto Sans Indic Siyaq Numbers',
62005
+ 'Noto Sans Inscriptional Pahlavi',
62006
+ 'Noto Sans Inscriptional Parthian',
62007
+ 'Noto Sans Javanese',
62008
+ 'Noto Sans JP',
62009
+ 'Noto Sans Kaithi',
62010
+ 'Noto Sans Kannada',
62011
+ 'Noto Sans Kawi',
62012
+ 'Noto Sans Kayah Li',
62013
+ 'Noto Sans Kharoshthi',
62014
+ 'Noto Sans Khmer',
62015
+ 'Noto Sans Khojki',
62016
+ 'Noto Sans Khudawadi',
62017
+ 'Noto Sans KR',
62018
+ 'Noto Sans Lao',
62019
+ 'Noto Sans Lao Looped',
62020
+ 'Noto Sans Lepcha',
62021
+ 'Noto Sans Limbu',
62022
+ 'Noto Sans Linear A',
62023
+ 'Noto Sans Linear B',
62024
+ 'Noto Sans Lisu',
62025
+ 'Noto Sans Lycian',
62026
+ 'Noto Sans Lydian',
62027
+ 'Noto Sans Mahajani',
62028
+ 'Noto Sans Malayalam',
62029
+ 'Noto Sans Mandaic',
62030
+ 'Noto Sans Manichaean',
62031
+ 'Noto Sans Marchen',
62032
+ 'Noto Sans Masaram Gondi',
62033
+ 'Noto Sans Math',
62034
+ 'Noto Sans Mayan Numerals',
62035
+ 'Noto Sans Medefaidrin',
62036
+ 'Noto Sans Meetei Mayek',
62037
+ 'Noto Sans Mende Kikakui',
62038
+ 'Noto Sans Meroitic',
62039
+ 'Noto Sans Miao',
62040
+ 'Noto Sans Modi',
62041
+ 'Noto Sans Mongolian',
62042
+ 'Noto Sans Mono',
62043
+ 'Noto Sans Mro',
62044
+ 'Noto Sans Multani',
62045
+ 'Noto Sans Myanmar',
62046
+ 'Noto Sans Nabataean',
62047
+ 'Noto Sans Nag Mundari',
62048
+ 'Noto Sans Nandinagari',
62049
+ 'Noto Sans New Tai Lue',
62050
+ 'Noto Sans Newa',
62051
+ 'Noto Sans NKo',
62052
+ 'Noto Sans NKo Unjoined',
62053
+ 'Noto Sans Nushu',
62054
+ 'Noto Sans Ogham',
62055
+ 'Noto Sans Ol Chiki',
62056
+ 'Noto Sans Old Hungarian',
62057
+ 'Noto Sans Old Italic',
62058
+ 'Noto Sans Old North Arabian',
62059
+ 'Noto Sans Old Permic',
62060
+ 'Noto Sans Old Persian',
62061
+ 'Noto Sans Old Sogdian',
62062
+ 'Noto Sans Old South Arabian',
62063
+ 'Noto Sans Old Turkic',
62064
+ 'Noto Sans Oriya',
62065
+ 'Noto Sans Osage',
62066
+ 'Noto Sans Osmanya',
62067
+ 'Noto Sans Pahawh Hmong',
62068
+ 'Noto Sans Palmyrene',
62069
+ 'Noto Sans Pau Cin Hau',
62070
+ 'Noto Sans PhagsPa',
62071
+ 'Noto Sans Phoenician',
62072
+ 'Noto Sans Psalter Pahlavi',
62073
+ 'Noto Sans Rejang',
62074
+ 'Noto Sans Runic',
62075
+ 'Noto Sans Samaritan',
62076
+ 'Noto Sans Saurashtra',
62077
+ 'Noto Sans SC',
62078
+ 'Noto Sans Sharada',
62079
+ 'Noto Sans Shavian',
62080
+ 'Noto Sans Siddham',
62081
+ 'Noto Sans SignWriting',
62082
+ 'Noto Sans Sinhala',
62083
+ 'Noto Sans Sogdian',
62084
+ 'Noto Sans Sora Sompeng',
62085
+ 'Noto Sans Soyombo',
62086
+ 'Noto Sans Sundanese',
62087
+ 'Noto Sans Sunuwar',
62088
+ 'Noto Sans Syloti Nagri',
62089
+ 'Noto Sans Symbols',
62090
+ 'Noto Sans Symbols 2',
62091
+ 'Noto Sans Syriac',
62092
+ 'Noto Sans Syriac Eastern',
62093
+ 'Noto Sans Syriac Western',
62094
+ 'Noto Sans Tagalog',
62095
+ 'Noto Sans Tagbanwa',
62096
+ 'Noto Sans Tai Le',
62097
+ 'Noto Sans Tai Tham',
62098
+ 'Noto Sans Tai Viet',
62099
+ 'Noto Sans Takri',
62100
+ 'Noto Sans Tamil',
62101
+ 'Noto Sans Tamil Supplement',
62102
+ 'Noto Sans Tangsa',
62103
+ 'Noto Sans TC',
62104
+ 'Noto Sans Telugu',
62105
+ 'Noto Sans Thaana',
62106
+ 'Noto Sans Thai',
62107
+ 'Noto Sans Thai Looped',
62108
+ 'Noto Sans Tifinagh',
62109
+ 'Noto Sans Tirhuta',
62110
+ 'Noto Sans Ugaritic',
62111
+ 'Noto Sans Vai',
62112
+ 'Noto Sans Vithkuqi',
62113
+ 'Noto Sans Wancho',
62114
+ 'Noto Sans Warang Citi',
62115
+ 'Noto Sans Yi',
62116
+ 'Noto Sans Zanabazar Square',
62117
+ 'Noto Serif',
62118
+ 'Noto Serif Ahom',
62119
+ 'Noto Serif Armenian',
62120
+ 'Noto Serif Balinese',
62121
+ 'Noto Serif Bengali',
62122
+ 'Noto Serif Devanagari',
62123
+ 'Noto Serif Display',
62124
+ 'Noto Serif Dives Akuru',
62125
+ 'Noto Serif Dogra',
62126
+ 'Noto Serif Ethiopic',
62127
+ 'Noto Serif Georgian',
62128
+ 'Noto Serif Grantha',
62129
+ 'Noto Serif Gujarati',
62130
+ 'Noto Serif Gurmukhi',
62131
+ 'Noto Serif Hebrew',
62132
+ 'Noto Serif Hentaigana',
62133
+ 'Noto Serif HK',
62134
+ 'Noto Serif JP',
62135
+ 'Noto Serif Kannada',
62136
+ 'Noto Serif Khitan Small Script',
62137
+ 'Noto Serif Khmer',
62138
+ 'Noto Serif Khojki',
62139
+ 'Noto Serif KR',
62140
+ 'Noto Serif Lao',
62141
+ 'Noto Serif Makasar',
62142
+ 'Noto Serif Malayalam',
62143
+ 'Noto Serif Myanmar',
62144
+ 'Noto Serif NP Hmong',
62145
+ 'Noto Serif Old Uyghur',
62146
+ 'Noto Serif Oriya',
62147
+ 'Noto Serif Ottoman Siyaq',
62148
+ 'Noto Serif SC',
62149
+ 'Noto Serif Sinhala',
62150
+ 'Noto Serif Tamil',
62151
+ 'Noto Serif Tangut',
62152
+ 'Noto Serif TC',
62153
+ 'Noto Serif Telugu',
62154
+ 'Noto Serif Thai',
62155
+ 'Noto Serif Tibetan',
62156
+ 'Noto Serif Todhri',
62157
+ 'Noto Serif Toto',
62158
+ 'Noto Serif Vithkuqi',
62159
+ 'Noto Serif Yezidi',
62160
+ 'Noto Traditional Nushu',
62161
+ 'Noto Znamenny Musical Notation',
62162
+ 'Nova Cut',
62163
+ 'Nova Flat',
62164
+ 'Nova Mono',
62165
+ 'Nova Oval',
62166
+ 'Nova Round',
62167
+ 'Nova Script',
62168
+ 'Nova Slim',
62169
+ 'Nova Square',
62170
+ 'NTR',
62171
+ 'Numans',
62172
+ 'Nunito',
62173
+ 'Nunito Sans',
62174
+ 'Nuosu SIL',
62175
+ 'Odibee Sans',
62176
+ 'Odor Mean Chey',
62177
+ 'Offside',
62178
+ 'Oi',
62179
+ 'Ojuju',
62180
+ 'Old Standard TT',
62181
+ 'Oldenburg',
62182
+ 'Ole',
62183
+ 'Oleo Script',
62184
+ 'Oleo Script Swash Caps',
62185
+ 'Onest',
62186
+ 'Oooh Baby',
62187
+ 'Open Sans',
62188
+ 'Oranienbaum',
62189
+ 'Orbit',
62190
+ 'Orbitron',
62191
+ 'Oregano',
62192
+ 'Orelega One',
62193
+ 'Orienta',
62194
+ 'Original Surfer',
62195
+ 'Oswald',
62196
+ 'Outfit',
62197
+ 'Over the Rainbow',
62198
+ 'Overlock',
62199
+ 'Overlock SC',
62200
+ 'Overpass',
62201
+ 'Overpass Mono',
62202
+ 'Ovo',
62203
+ 'Oxanium',
62204
+ 'Oxygen',
62205
+ 'Oxygen Mono',
62206
+ 'Pacifico',
62207
+ 'Padauk',
62208
+ 'Padyakke Expanded One',
62209
+ 'Palanquin',
62210
+ 'Palanquin Dark',
62211
+ 'Palette Mosaic',
62212
+ 'Pangolin',
62213
+ 'Paprika',
62214
+ 'Parastoo',
62215
+ 'Parisienne',
62216
+ 'Parkinsans',
62217
+ 'Passero One',
62218
+ 'Passion One',
62219
+ 'Passions Conflict',
62220
+ 'Pathway Extreme',
62221
+ 'Pathway Gothic One',
62222
+ 'Patrick Hand',
62223
+ 'Patrick Hand SC',
62224
+ 'Pattaya',
62225
+ 'Patua One',
62226
+ 'Pavanam',
62227
+ 'Paytone One',
62228
+ 'Peddana',
62229
+ 'Peralta',
62230
+ 'Permanent Marker',
62231
+ 'Petemoss',
62232
+ 'Petit Formal Script',
62233
+ 'Petrona',
62234
+ 'Phetsarath',
62235
+ 'Philosopher',
62236
+ 'Phudu',
62237
+ 'Piazzolla',
62238
+ 'Piedra',
62239
+ 'Pinyon Script',
62240
+ 'Pirata One',
62241
+ 'Pixelify Sans',
62242
+ 'Plaster',
62243
+ 'Platypi',
62244
+ 'Play',
62245
+ 'Playball',
62246
+ 'Playfair',
62247
+ 'Playfair Display',
62248
+ 'Playfair Display SC',
62249
+ 'Playpen Sans',
62250
+ 'Playpen Sans Arabic',
62251
+ 'Playpen Sans Deva',
62252
+ 'Playpen Sans Hebrew',
62253
+ 'Playpen Sans Thai',
62254
+ 'Playwrite AR',
62255
+ 'Playwrite AR Guides',
62256
+ 'Playwrite AT',
62257
+ 'Playwrite AT Guides',
62258
+ 'Playwrite AU NSW',
62259
+ 'Playwrite AU NSW Guides',
62260
+ 'Playwrite AU QLD',
62261
+ 'Playwrite AU QLD Guides',
62262
+ 'Playwrite AU SA',
62263
+ 'Playwrite AU SA Guides',
62264
+ 'Playwrite AU TAS',
62265
+ 'Playwrite AU TAS Guides',
62266
+ 'Playwrite AU VIC',
62267
+ 'Playwrite AU VIC Guides',
62268
+ 'Playwrite BE VLG',
62269
+ 'Playwrite BE VLG Guides',
62270
+ 'Playwrite BE WAL',
62271
+ 'Playwrite BE WAL Guides',
62272
+ 'Playwrite BR',
62273
+ 'Playwrite BR Guides',
62274
+ 'Playwrite CA',
62275
+ 'Playwrite CA Guides',
62276
+ 'Playwrite CL',
62277
+ 'Playwrite CL Guides',
62278
+ 'Playwrite CO',
62279
+ 'Playwrite CO Guides',
62280
+ 'Playwrite CU',
62281
+ 'Playwrite CU Guides',
62282
+ 'Playwrite CZ',
62283
+ 'Playwrite CZ Guides',
62284
+ 'Playwrite DE Grund',
62285
+ 'Playwrite DE Grund Guides',
62286
+ 'Playwrite DE LA',
62287
+ 'Playwrite DE LA Guides',
62288
+ 'Playwrite DE SAS',
62289
+ 'Playwrite DE SAS Guides',
62290
+ 'Playwrite DE VA',
62291
+ 'Playwrite DE VA Guides',
62292
+ 'Playwrite DK Loopet',
62293
+ 'Playwrite DK Loopet Guides',
62294
+ 'Playwrite DK Uloopet',
62295
+ 'Playwrite DK Uloopet Guides',
62296
+ 'Playwrite ES',
62297
+ 'Playwrite ES Deco',
62298
+ 'Playwrite ES Deco Guides',
62299
+ 'Playwrite ES Guides',
62300
+ 'Playwrite FR Moderne',
62301
+ 'Playwrite FR Moderne Guides',
62302
+ 'Playwrite FR Trad',
62303
+ 'Playwrite FR Trad Guides',
62304
+ 'Playwrite GB J',
62305
+ 'Playwrite GB J Guides',
62306
+ 'Playwrite GB S',
62307
+ 'Playwrite GB S Guides',
62308
+ 'Playwrite HR',
62309
+ 'Playwrite HR Guides',
62310
+ 'Playwrite HR Lijeva',
62311
+ 'Playwrite HR Lijeva Guides',
62312
+ 'Playwrite HU',
62313
+ 'Playwrite HU Guides',
62314
+ 'Playwrite ID',
62315
+ 'Playwrite ID Guides',
62316
+ 'Playwrite IE',
62317
+ 'Playwrite IE Guides',
62318
+ 'Playwrite IN',
62319
+ 'Playwrite IN Guides',
62320
+ 'Playwrite IS',
62321
+ 'Playwrite IS Guides',
62322
+ 'Playwrite IT Moderna',
62323
+ 'Playwrite IT Moderna Guides',
62324
+ 'Playwrite IT Trad',
62325
+ 'Playwrite IT Trad Guides',
62326
+ 'Playwrite MX',
62327
+ 'Playwrite MX Guides',
62328
+ 'Playwrite NG Modern',
62329
+ 'Playwrite NG Modern Guides',
62330
+ 'Playwrite NL',
62331
+ 'Playwrite NL Guides',
62332
+ 'Playwrite NO',
62333
+ 'Playwrite NO Guides',
62334
+ 'Playwrite NZ',
62335
+ 'Playwrite NZ Basic',
62336
+ 'Playwrite NZ Basic Guides',
62337
+ 'Playwrite NZ Guides',
62338
+ 'Playwrite PE',
62339
+ 'Playwrite PE Guides',
62340
+ 'Playwrite PL',
62341
+ 'Playwrite PL Guides',
62342
+ 'Playwrite PT',
62343
+ 'Playwrite PT Guides',
62344
+ 'Playwrite RO',
62345
+ 'Playwrite RO Guides',
62346
+ 'Playwrite SK',
62347
+ 'Playwrite SK Guides',
62348
+ 'Playwrite TZ',
62349
+ 'Playwrite TZ Guides',
62350
+ 'Playwrite US Modern',
62351
+ 'Playwrite US Modern Guides',
62352
+ 'Playwrite US Trad',
62353
+ 'Playwrite US Trad Guides',
62354
+ 'Playwrite VN',
62355
+ 'Playwrite VN Guides',
62356
+ 'Playwrite ZA',
62357
+ 'Playwrite ZA Guides',
62358
+ 'Pliant',
62359
+ 'Plus Jakarta Sans',
62360
+ 'Pochaevsk',
62361
+ 'Podkova',
62362
+ 'Poetsen One',
62363
+ 'Poiret One',
62364
+ 'Poller One',
62365
+ 'Poltawski Nowy',
62366
+ 'Poly',
62367
+ 'Pompiere',
62368
+ 'Ponnala',
62369
+ 'Ponomar',
62370
+ 'Pontano Sans',
62371
+ 'Poor Story',
62372
+ 'Poppins',
62373
+ 'Port Lligat Sans',
62374
+ 'Port Lligat Slab',
62375
+ 'Potta One',
62376
+ 'Pragati Narrow',
62377
+ 'Praise',
62378
+ 'Prata',
62379
+ 'Preahvihear',
62380
+ 'Press Start 2P',
62381
+ 'Pridi',
62382
+ 'Princess Sofia',
62383
+ 'Prociono',
62384
+ 'Prompt',
62385
+ 'Prosto One',
62386
+ 'Protest Guerrilla',
62387
+ 'Protest Revolution',
62388
+ 'Protest Riot',
62389
+ 'Protest Strike',
62390
+ 'Proza Libre',
62391
+ 'PT Mono',
62392
+ 'PT Sans',
62393
+ 'PT Sans Caption',
62394
+ 'PT Sans Narrow',
62395
+ 'PT Serif',
62396
+ 'PT Serif Caption',
62397
+ 'Public Sans',
62398
+ 'Puppies Play',
62399
+ 'Puritan',
62400
+ 'Purple Purse',
62401
+ 'Qahiri',
62402
+ 'Quando',
62403
+ 'Quantico',
62404
+ 'Quattrocento',
62405
+ 'Quattrocento Sans',
62406
+ 'Questrial',
62407
+ 'Quicksand',
62408
+ 'Quintessential',
62409
+ 'Qwigley',
62410
+ 'Qwitcher Grypen',
62411
+ 'Racing Sans One',
62412
+ 'Radio Canada',
62413
+ 'Radio Canada Big',
62414
+ 'Radley',
62415
+ 'Rajdhani',
62416
+ 'Rakkas',
62417
+ 'Raleway',
62418
+ 'Raleway Dots',
62419
+ 'Ramabhadra',
62420
+ 'Ramaraja',
62421
+ 'Rambla',
62422
+ 'Rammetto One',
62423
+ 'Rampart One',
62424
+ 'Ramsina',
62425
+ 'Ranchers',
62426
+ 'Rancho',
62427
+ 'Ranga',
62428
+ 'Rasa',
62429
+ 'Rationale',
62430
+ 'Ravi Prakash',
62431
+ 'Readex Pro',
62432
+ 'Recursive',
62433
+ 'Red Hat Display',
62434
+ 'Red Hat Mono',
62435
+ 'Red Hat Text',
62436
+ 'Red Rose',
62437
+ 'Redacted',
62438
+ 'Redacted Script',
62439
+ 'Reddit Mono',
62440
+ 'Reddit Sans',
62441
+ 'Reddit Sans Condensed',
62442
+ 'Redressed',
62443
+ 'Reem Kufi',
62444
+ 'Reem Kufi Fun',
62445
+ 'Reem Kufi Ink',
62446
+ 'Reenie Beanie',
62447
+ 'Reggae One',
62448
+ 'REM',
62449
+ 'Rethink Sans',
62450
+ 'Revalia',
62451
+ 'Rhodium Libre',
62452
+ 'Ribeye',
62453
+ 'Ribeye Marrow',
62454
+ 'Righteous',
62455
+ 'Risque',
62456
+ 'Road Rage',
62457
+ 'Roboto',
62458
+ 'Roboto Condensed',
62459
+ 'Roboto Flex',
62460
+ 'Roboto Mono',
62461
+ 'Roboto Serif',
62462
+ 'Roboto Slab',
62463
+ 'Rochester',
62464
+ 'Rock 3D',
62465
+ 'Rock Salt',
62466
+ 'RocknRoll One',
62467
+ 'Rokkitt',
62468
+ 'Romanesco',
62469
+ 'Ropa Sans',
62470
+ 'Rosario',
62471
+ 'Rosarivo',
62472
+ 'Rouge Script',
62473
+ 'Rowdies',
62474
+ 'Rozha One',
62475
+ 'Rubik',
62476
+ 'Rubik 80s Fade',
62477
+ 'Rubik Beastly',
62478
+ 'Rubik Broken Fax',
62479
+ 'Rubik Bubbles',
62480
+ 'Rubik Burned',
62481
+ 'Rubik Dirt',
62482
+ 'Rubik Distressed',
62483
+ 'Rubik Doodle Shadow',
62484
+ 'Rubik Doodle Triangles',
62485
+ 'Rubik Gemstones',
62486
+ 'Rubik Glitch',
62487
+ 'Rubik Glitch Pop',
62488
+ 'Rubik Iso',
62489
+ 'Rubik Lines',
62490
+ 'Rubik Maps',
62491
+ 'Rubik Marker Hatch',
62492
+ 'Rubik Maze',
62493
+ 'Rubik Microbe',
62494
+ 'Rubik Mono One',
62495
+ 'Rubik Moonrocks',
62496
+ 'Rubik Pixels',
62497
+ 'Rubik Puddles',
62498
+ 'Rubik Scribble',
62499
+ 'Rubik Spray Paint',
62500
+ 'Rubik Storm',
62501
+ 'Rubik Vinyl',
62502
+ 'Rubik Wet Paint',
62503
+ 'Ruda',
62504
+ 'Rufina',
62505
+ 'Ruge Boogie',
62506
+ 'Ruluko',
62507
+ 'Rum Raisin',
62508
+ 'Ruslan Display',
62509
+ 'Russo One',
62510
+ 'Ruthie',
62511
+ 'Ruwudu',
62512
+ 'Rye',
62513
+ 'Sacramento',
62514
+ 'Sahitya',
62515
+ 'Sail',
62516
+ 'Saira',
62517
+ 'Saira Condensed',
62518
+ 'Saira Extra Condensed',
62519
+ 'Saira Semi Condensed',
62520
+ 'Saira Stencil',
62521
+ 'Salsa',
62522
+ 'Sanchez',
62523
+ 'Sancreek',
62524
+ 'Sankofa Display',
62525
+ 'Sansation',
62526
+ 'Sansita',
62527
+ 'Sansita Swashed',
62528
+ 'Sarabun',
62529
+ 'Sarala',
62530
+ 'Sarina',
62531
+ 'Sarpanch',
62532
+ 'Sassy Frass',
62533
+ 'Satisfy',
62534
+ 'Savate',
62535
+ 'Sawarabi Gothic',
62536
+ 'Sawarabi Mincho',
62537
+ 'Scada',
62538
+ 'Scheherazade New',
62539
+ 'Schibsted Grotesk',
62540
+ 'Schoolbell',
62541
+ 'Science Gothic',
62542
+ 'Scope One',
62543
+ 'Scoutie Sans',
62544
+ 'Seaweed Script',
62545
+ 'Secular One',
62546
+ 'Sedan',
62547
+ 'Sedan SC',
62548
+ 'Sedgwick Ave',
62549
+ 'Sedgwick Ave Display',
62550
+ 'Sekuya',
62551
+ 'Sen',
62552
+ 'Send Flowers',
62553
+ 'Sevillana',
62554
+ 'Seymour One',
62555
+ 'Shadows Into Light',
62556
+ 'Shadows Into Light Two',
62557
+ 'Shafarik',
62558
+ 'Shalimar',
62559
+ 'Shantell Sans',
62560
+ 'Shanti',
62561
+ 'Share',
62562
+ 'Share Tech',
62563
+ 'Share Tech Mono',
62564
+ 'Shippori Antique',
62565
+ 'Shippori Antique B1',
62566
+ 'Shippori Mincho',
62567
+ 'Shippori Mincho B1',
62568
+ 'Shizuru',
62569
+ 'Shojumaru',
62570
+ 'Short Stack',
62571
+ 'Shrikhand',
62572
+ 'Siemreap',
62573
+ 'Sigmar',
62574
+ 'Sigmar One',
62575
+ 'Signika',
62576
+ 'Signika Negative',
62577
+ 'Silkscreen',
62578
+ 'Simonetta',
62579
+ 'Single Day',
62580
+ 'Sintony',
62581
+ 'Sirin Stencil',
62582
+ 'Sirivennela',
62583
+ 'Six Caps',
62584
+ 'Sixtyfour',
62585
+ 'Sixtyfour Convergence',
62586
+ 'Skranji',
62587
+ 'Slabo 13px',
62588
+ 'Slabo 27px',
62589
+ 'Slackey',
62590
+ 'Slackside One',
62591
+ 'Smokum',
62592
+ 'Smooch',
62593
+ 'Smooch Sans',
62594
+ 'Smythe',
62595
+ 'SN Pro',
62596
+ 'Sniglet',
62597
+ 'Snippet',
62598
+ 'Snowburst One',
62599
+ 'Sofadi One',
62600
+ 'Sofia',
62601
+ 'Sofia Sans',
62602
+ 'Sofia Sans Condensed',
62603
+ 'Sofia Sans Extra Condensed',
62604
+ 'Sofia Sans Semi Condensed',
62605
+ 'Solitreo',
62606
+ 'Solway',
62607
+ 'Sometype Mono',
62608
+ 'Song Myung',
62609
+ 'Sono',
62610
+ 'Sonsie One',
62611
+ 'Sora',
62612
+ 'Sorts Mill Goudy',
62613
+ 'Sour Gummy',
62614
+ 'Source Code Pro',
62615
+ 'Source Sans 3',
62616
+ 'Source Serif 4',
62617
+ 'Space Grotesk',
62618
+ 'Space Mono',
62619
+ 'Special Elite',
62620
+ 'Special Gothic',
62621
+ 'Special Gothic Condensed One',
62622
+ 'Special Gothic Expanded One',
62623
+ 'Spectral',
62624
+ 'Spectral SC',
62625
+ 'Spicy Rice',
62626
+ 'Spinnaker',
62627
+ 'Spirax',
62628
+ 'Splash',
62629
+ 'Spline Sans',
62630
+ 'Spline Sans Mono',
62631
+ 'Squada One',
62632
+ 'Square Peg',
62633
+ 'Sree Krushnadevaraya',
62634
+ 'Sriracha',
62635
+ 'Srisakdi',
62636
+ 'Staatliches',
62637
+ 'Stack Sans Headline',
62638
+ 'Stack Sans Notch',
62639
+ 'Stack Sans Text',
62640
+ 'Stalemate',
62641
+ 'Stalinist One',
62642
+ 'Stardos Stencil',
62643
+ 'Stick',
62644
+ 'Stick No Bills',
62645
+ 'Stint Ultra Condensed',
62646
+ 'Stint Ultra Expanded',
62647
+ 'STIX Two Math',
62648
+ 'STIX Two Text',
62649
+ 'Stoke',
62650
+ 'Story Script',
62651
+ 'Strait',
62652
+ 'Strichpunkt Sans',
62653
+ 'Style Script',
62654
+ 'Stylish',
62655
+ 'Sue Ellen Francisco',
62656
+ 'Suez One',
62657
+ 'Sulphur Point',
62658
+ 'Sumana',
62659
+ 'Sunflower',
62660
+ 'Sunshiney',
62661
+ 'Supermercado One',
62662
+ 'Sura',
62663
+ 'Suranna',
62664
+ 'Suravaram',
62665
+ 'SUSE',
62666
+ 'SUSE Mono',
62667
+ 'Suwannaphum',
62668
+ 'Swanky and Moo Moo',
62669
+ 'Syncopate',
62670
+ 'Syne',
62671
+ 'Syne Mono',
62672
+ 'Syne Tactile',
62673
+ 'Tac One',
62674
+ 'Tagesschrift',
62675
+ 'Tai Heritage Pro',
62676
+ 'Tajawal',
62677
+ 'Tangerine',
62678
+ 'Tapestry',
62679
+ 'Taprom',
62680
+ 'TASA Explorer',
62681
+ 'TASA Orbiter',
62682
+ 'Tauri',
62683
+ 'Taviraj',
62684
+ 'Teachers',
62685
+ 'Teko',
62686
+ 'Tektur',
62687
+ 'Telex',
62688
+ 'Tenali Ramakrishna',
62689
+ 'Tenor Sans',
62690
+ 'Text Me One',
62691
+ 'Texturina',
62692
+ 'Thasadith',
62693
+ 'The Girl Next Door',
62694
+ 'The Nautigal',
62695
+ 'Tienne',
62696
+ 'TikTok Sans',
62697
+ 'Tillana',
62698
+ 'Tilt Neon',
62699
+ 'Tilt Prism',
62700
+ 'Tilt Warp',
62701
+ 'Timmana',
62702
+ 'Tinos',
62703
+ 'Tiny5',
62704
+ 'Tiro Bangla',
62705
+ 'Tiro Devanagari Hindi',
62706
+ 'Tiro Devanagari Marathi',
62707
+ 'Tiro Devanagari Sanskrit',
62708
+ 'Tiro Gurmukhi',
62709
+ 'Tiro Kannada',
62710
+ 'Tiro Tamil',
62711
+ 'Tiro Telugu',
62712
+ 'Tirra',
62713
+ 'Titan One',
62714
+ 'Titillium Web',
62715
+ 'Tomorrow',
62716
+ 'Tourney',
62717
+ 'Trade Winds',
62718
+ 'Train One',
62719
+ 'Triodion',
62720
+ 'Trirong',
62721
+ 'Trispace',
62722
+ 'Trocchi',
62723
+ 'Trochut',
62724
+ 'Truculenta',
62725
+ 'Trykker',
62726
+ 'Tsukimi Rounded',
62727
+ 'Tuffy',
62728
+ 'Tulpen One',
62729
+ 'Turret Road',
62730
+ 'Twinkle Star',
62731
+ 'Ubuntu',
62732
+ 'Ubuntu Condensed',
62733
+ 'Ubuntu Mono',
62734
+ 'Ubuntu Sans',
62735
+ 'Ubuntu Sans Mono',
62736
+ 'Uchen',
62737
+ 'Ultra',
62738
+ 'Unbounded',
62739
+ 'Uncial Antiqua',
62740
+ 'Underdog',
62741
+ 'Unica One',
62742
+ 'UnifrakturCook',
62743
+ 'UnifrakturMaguntia',
62744
+ 'Unkempt',
62745
+ 'Unlock',
62746
+ 'Unna',
62747
+ 'UoqMunThenKhung',
62748
+ 'Updock',
62749
+ 'Urbanist',
62750
+ 'Valley Sans',
62751
+ 'Vampiro One',
62752
+ 'Varela',
62753
+ 'Varela Round',
62754
+ 'Varta',
62755
+ 'Vast Shadow',
62756
+ 'Vazirmatn',
62757
+ 'Vend Sans',
62758
+ 'Vesper Libre',
62759
+ 'Viaoda Libre',
62760
+ 'Vibes',
62761
+ 'Vibur',
62762
+ 'Victor Mono',
62763
+ 'Vidaloka',
62764
+ 'Viga',
62765
+ 'Vina Sans',
62766
+ 'Voces',
62767
+ 'Volkhov',
62768
+ 'Vollkorn',
62769
+ 'Vollkorn SC',
62770
+ 'Voltaire',
62771
+ 'VT323',
62772
+ 'Vujahday Script',
62773
+ 'Waiting for the Sunrise',
62774
+ 'Wallpoet',
62775
+ 'Walter Turncoat',
62776
+ 'Warnes',
62777
+ 'Water Brush',
62778
+ 'Waterfall',
62779
+ 'Wavefont',
62780
+ 'WDXL Lubrifont JP N',
62781
+ 'WDXL Lubrifont SC',
62782
+ 'WDXL Lubrifont TC',
62783
+ 'Wellfleet',
62784
+ 'Wendy One',
62785
+ 'Whisper',
62786
+ 'WindSong',
62787
+ 'Winky Rough',
62788
+ 'Winky Sans',
62789
+ 'Wire One',
62790
+ 'Wittgenstein',
62791
+ 'Wix Madefor Display',
62792
+ 'Wix Madefor Text',
62793
+ 'Work Sans',
62794
+ 'Workbench',
62795
+ 'Xanh Mono',
62796
+ 'Yaldevi',
62797
+ 'Yanone Kaffeesatz',
62798
+ 'Yantramanav',
62799
+ 'Yarndings 12',
62800
+ 'Yarndings 12 Charted',
62801
+ 'Yarndings 20',
62802
+ 'Yarndings 20 Charted',
62803
+ 'Yatra One',
62804
+ 'Yellowtail',
62805
+ 'Yeon Sung',
62806
+ 'Yeseva One',
62807
+ 'Yesteryear',
62808
+ 'Yomogi',
62809
+ 'Young Serif',
62810
+ 'Yrsa',
62811
+ 'Ysabeau',
62812
+ 'Ysabeau Infant',
62813
+ 'Ysabeau Office',
62814
+ 'Ysabeau SC',
62815
+ 'Yuji Boku',
62816
+ 'Yuji Hentaigana Akari',
62817
+ 'Yuji Hentaigana Akebono',
62818
+ 'Yuji Mai',
62819
+ 'Yuji Syuku',
62820
+ 'Yusei Magic',
62821
+ 'Yuyu',
62822
+ 'Yuyu Short',
62823
+ 'Zain',
62824
+ 'Zalando Sans',
62825
+ 'Zalando Sans Expanded',
62826
+ 'Zalando Sans SemiExpanded',
62827
+ 'ZCOOL KuaiLe',
62828
+ 'ZCOOL QingKe HuangYou',
62829
+ 'ZCOOL XiaoWei',
62830
+ 'Zen Antique',
62831
+ 'Zen Antique Soft',
62832
+ 'Zen Dots',
62833
+ 'Zen Kaku Gothic Antique',
62834
+ 'Zen Kaku Gothic New',
62835
+ 'Zen Kurenaido',
62836
+ 'Zen Loop',
62837
+ 'Zen Maru Gothic',
62838
+ 'Zen Old Mincho',
62839
+ 'Zen Tokyo Zoo',
62840
+ 'Zeyada',
62841
+ 'Zhi Mang Xing',
62842
+ 'Zilla Slab',
62843
+ 'Zilla Slab Highlight',
62844
+ ];
62845
+
60879
62846
  /**
60880
62847
  * google-webfonts.ts: Google Fonts webfont fallback for referenced font
60881
62848
  * families, shared by every binding.
@@ -60888,29 +62855,25 @@ function buildEmbeddedFontStyles(fonts, mintObjectUrl) {
60888
62855
  * `<link rel="stylesheet">` so the text renders with the intended face
60889
62856
  * anyway.
60890
62857
  *
60891
- * There is no hard-coded family list: the API itself is the source of truth.
60892
- * Each candidate family is probed with a `fetch` (the endpoint answers 400
60893
- * for families it does not serve, and silently serves only the weights and
60894
- * styles that DO exist for families it does, so one universal axis spec is
60895
- * safe for every family). Verified families are combined into a single css2
60896
- * URL. Probe results are cached for the page session, and a family that
60897
- * fails both probe attempts is never re-requested.
60898
- *
60899
- * Families detected as locally installed are dropped BEFORE any network
60900
- * request is made, so the API only ever learns the names of families the
60901
- * reader's machine is actually missing. That residual disclosure is the
60902
- * accepted cost of the dynamic probe (a family can only be matched against
60903
- * the catalogue by naming it); a build-time-generated family list would avoid
60904
- * it entirely at the price of losing every family the list does not know.
60905
- *
60906
- * Everything except the probe is pure; the DOM side effect (injecting /
60907
- * updating / removing the managed `<link>` element) stays in each binding,
60908
- * and the element id is binding-specific.
62858
+ * Which families the API serves is answered by the bundled catalogue
62859
+ * (`google-fonts-catalogue.ts`, regenerated from Google's own metadata feed
62860
+ * by `bun run fonts:catalogue`), never by probing the API per family: a
62861
+ * probe of an unknown family answers 400 without CORS headers, which the
62862
+ * browser reports as an uncatchable console error, and it discloses every
62863
+ * missing family name to Google. With the catalogue the only request ever
62864
+ * made is the stylesheet for families already known to be served. The API is
62865
+ * lenient about weights and styles (it serves only the ones a family has),
62866
+ * so one universal axis spec is safe for every catalogue family.
62867
+ *
62868
+ * Families detected as locally installed are dropped before the href is
62869
+ * built, so an installed face is used as-is. Everything here is pure; the DOM
62870
+ * side effect (injecting / updating / removing the managed `<link>` element)
62871
+ * stays in each binding, and the element id is binding-specific.
60909
62872
  */
60910
62873
  /** Base URL of the Google Fonts CSS2 API. */
60911
62874
  const GOOGLE_FONTS_CSS2_BASE = 'https://fonts.googleapis.com/css2';
60912
62875
  /**
60913
- * Axis spec requested for every probed family. The API is lenient: it serves
62876
+ * Axis spec requested for every catalogue family. The API is lenient: it serves
60914
62877
  * only the weights/styles the family actually has (verified for single-style
60915
62878
  * families), so this one fragment is safe to request universally and yields
60916
62879
  * real bold + italic faces where they exist.
@@ -60944,7 +62907,7 @@ function collectReferencedFontFamilies(slides) {
60944
62907
  return families;
60945
62908
  }
60946
62909
  /**
60947
- * Pick the referenced families this runtime should probe for: everything not
62910
+ * Pick the referenced families this runtime should look up: everything not
60948
62911
  * already satisfied by an embedded font, and (when the caller supplies the
60949
62912
  * check) everything not available locally, so an installed family is used
60950
62913
  * as-is and its name never reaches the API.
@@ -60963,7 +62926,7 @@ function selectGoogleWebfontFamilies(referenced, embedded, isLocallyInstalled) {
60963
62926
  }
60964
62927
  return selected;
60965
62928
  }
60966
- /** Text measured for the local-availability probe (mixed glyph widths). */
62929
+ /** Text measured for the local-availability check (mixed glyph widths). */
60967
62930
  const INSTALLED_FONT_TEST_STRING = 'mmmmmmmmmmllww';
60968
62931
  /**
60969
62932
  * Best-effort "is this family available without any network fetch?" check.
@@ -60976,9 +62939,8 @@ const INSTALLED_FONT_TEST_STRING = 'mmmmmmmmmmllww';
60976
62939
  * provides renders with different metrics for at least one common fallback
60977
62940
  * class, while a missing family renders exactly like the fallback and is
60978
62941
  * reported as absent. False negatives (a family metrically identical to
60979
- * every fallback class) are safe: the caller then probes the API for a
60980
- * family it may not have needed to, which is exactly the pre-check
60981
- * behaviour.
62942
+ * every fallback class) are safe: the caller then loads a catalogue face it
62943
+ * may not have needed to, which is exactly the pre-check behaviour.
60982
62944
  */
60983
62945
  function isFontFamilyInstalledLocally(family) {
60984
62946
  if (typeof document === 'undefined') {
@@ -61029,80 +62991,65 @@ function buildGoogleFontsHref(fragments) {
61029
62991
  const query = fragments.map((fragment) => `family=${encodeURIComponent(fragment)}`).join('&');
61030
62992
  return `${GOOGLE_FONTS_CSS2_BASE}?${query}&${DISPLAY_PARAM}`;
61031
62993
  }
61032
- /** Session cache: family -> probe promise resolving to its fragment or null. */
61033
- const probeCache = new Map();
61034
- /** Reset the session probe cache (test isolation). */
61035
- function resetGoogleWebfontProbeCache() {
61036
- probeCache.clear();
61037
- }
61038
- function fetchLike() {
61039
- return typeof fetch === 'function' ? fetch : undefined;
61040
- }
62994
+ /** Lower-cased catalogue name -> canonical Google Fonts spelling (lazy). */
62995
+ let catalogueIndex;
61041
62996
  /**
61042
- * Request `family` from the css2 API and return the query fragment that
61043
- * worked: the full axis spec, a bare fallback (in case a future API change
61044
- * makes the axis spec strict for some family), or `null` when the family is
61045
- * not served at all. Network failures count as "not served": an offline
61046
- * browser could not load the stylesheet either.
62997
+ * Canonical Google Fonts spelling for `family`, or `null` when the CSS2 API
62998
+ * does not serve it. Matching is case-insensitive and whitespace-normalised
62999
+ * because PowerPoint stores the name as the author typed it.
61047
63000
  */
61048
- async function probeFamily(family, doFetch) {
61049
- const withAxis = buildGoogleFontsFragment(family);
61050
- if (await probeUrl(doFetch, `family=${encodeURIComponent(withAxis)}`)) {
61051
- return withAxis;
61052
- }
61053
- if (await probeUrl(doFetch, `family=${encodeURIComponent(family)}`)) {
61054
- return family;
63001
+ function findGoogleFontsFamily(family) {
63002
+ if (!catalogueIndex) {
63003
+ catalogueIndex = new Map(GOOGLE_FONTS_FAMILIES.map((name) => [normaliseFamily(name), name]));
61055
63004
  }
61056
- return null;
63005
+ return catalogueIndex.get(normaliseFamily(family)) ?? null;
61057
63006
  }
61058
- async function probeUrl(doFetch, familyParam) {
61059
- try {
61060
- const response = await doFetch(`${GOOGLE_FONTS_CSS2_BASE}?${familyParam}&${DISPLAY_PARAM}`);
61061
- return response.status === 200;
61062
- }
61063
- catch {
61064
- return false;
61065
- }
63007
+ function normaliseFamily(family) {
63008
+ return family.trim().replace(/\s+/gu, ' ').toLowerCase();
61066
63009
  }
61067
63010
  /**
61068
- * Probe the candidate families (in parallel, session-cached) and return the
61069
- * query fragments the Google Fonts API serves.
63011
+ * Families this session has already resolved against the catalogue (by
63012
+ * their referenced spelling). Once the injected stylesheet has loaded, the
63013
+ * webfont itself satisfies the canvas measurement, so re-running the local
63014
+ * check would report the family as installed, drop it from the href, remove
63015
+ * the very `<link>` that made it available, and find it missing again on the
63016
+ * next call: an oscillation that re-fetches the stylesheet on every edit.
61070
63017
  */
61071
- function probeGoogleWebfontFragments(families, doFetch = fetchLike()) {
61072
- const effective = typeof doFetch === 'function' ? doFetch : undefined;
61073
- if (!effective) {
61074
- return Promise.resolve([]);
61075
- }
61076
- const probes = families.map(async (family) => {
61077
- let probe = probeCache.get(family);
61078
- if (!probe) {
61079
- probe = probeFamily(family, effective);
61080
- probeCache.set(family, probe);
63018
+ const resolvedFamilies = new Set();
63019
+ /** Reset the session cache (test isolation). */
63020
+ function resetGoogleWebfontSessionCache() {
63021
+ resolvedFamilies.clear();
63022
+ }
63023
+ /**
63024
+ * The query fragments for the candidate families the catalogue knows,
63025
+ * requested under their canonical spelling. Unknown families are dropped
63026
+ * without any network request.
63027
+ */
63028
+ function matchGoogleWebfontFragments(families) {
63029
+ const fragments = [];
63030
+ for (const family of families) {
63031
+ const canonical = findGoogleFontsFamily(family);
63032
+ if (canonical !== null) {
63033
+ resolvedFamilies.add(family);
63034
+ fragments.push(buildGoogleFontsFragment(canonical));
61081
63035
  }
61082
- return probe;
61083
- });
61084
- return Promise.all(probes).then((fragments) => fragments.filter((f) => f !== null));
63036
+ }
63037
+ return fragments;
61085
63038
  }
61086
63039
  /**
61087
63040
  * One-stop helper the bindings call from their reactive wiring: resolve the
61088
- * href for a loaded deck's slides + embedded fonts (`null` when no fetch is
61089
- * needed). Families available locally are used as-is and never requested;
61090
- * the rest are probed (session-cached), so repeated calls (every load /
61091
- * edit) only fetch families never seen before.
61092
- *
61093
- * The local-install check is skipped for families the session has already
61094
- * probed. Once the injected stylesheet has loaded, the webfont itself
61095
- * satisfies the canvas measurement, so re-checking would report the family as
61096
- * installed, drop it from the href, remove the very `<link>` that made it
61097
- * available, and then find it missing again on the next call: an oscillation
61098
- * that re-fetches the stylesheet on every edit. The cached probe result (a
61099
- * fragment or null) already answers the question for those families.
61100
- */
61101
- async function resolveGoogleWebfontHref(slides, embeddedFonts, doFetch, isLocallyInstalled = isFontFamilyInstalledLocally) {
63041
+ * href for a loaded deck's slides + embedded fonts (`null` when no stylesheet
63042
+ * is needed). Families available locally are used as-is; the rest are matched
63043
+ * against the bundled catalogue. The local-install check is skipped for
63044
+ * families the session already resolved (see `resolvedFamilies`).
63045
+ *
63046
+ * Async only so the bindings' `.then` wiring is the same whether resolution
63047
+ * is a lookup or, one day, something slower.
63048
+ */
63049
+ async function resolveGoogleWebfontHref(slides, embeddedFonts, isLocallyInstalled = isFontFamilyInstalledLocally) {
61102
63050
  const referenced = collectReferencedFontFamilies(slides);
61103
- const candidates = selectGoogleWebfontFamilies(referenced, embeddedFonts.map((font) => font.name), (family) => !probeCache.has(family) && isLocallyInstalled(family));
61104
- const fragments = await probeGoogleWebfontFragments(candidates, doFetch);
61105
- return buildGoogleFontsHref(fragments);
63051
+ const candidates = selectGoogleWebfontFamilies(referenced, embeddedFonts.map((font) => font.name), (family) => !resolvedFamilies.has(family) && isLocallyInstalled(family));
63052
+ return buildGoogleFontsHref(matchGoogleWebfontFragments(candidates));
61106
63053
  }
61107
63054
 
61108
63055
  /**
@@ -62745,7 +64692,7 @@ function buildBroadcastViewerUrl(roomId, serverUrl, location) {
62745
64692
  * query key Angular's Share dialog uses. Returns just the room id when no
62746
64693
  * `origin`/`pathname` are available (e.g. non-browser environments).
62747
64694
  */
62748
- function buildShareUrl$1(roomId, serverUrl, location) {
64695
+ function buildShareUrl(roomId, serverUrl, location) {
62749
64696
  return buildQueryLinkUrl(roomId, serverUrl, location, 'room');
62750
64697
  }
62751
64698
  /** Whether the runtime exposes a usable async clipboard write API. */
@@ -76323,7 +78270,7 @@ function getOleIconShapes(type) {
76323
78270
  * (the manager no-ops a re-register), so re-entering the owning slide does not
76324
78271
  * restart the track.
76325
78272
  */
76326
- function registerCrossSlideAudio$1(element, src) {
78273
+ function registerCrossSlideAudio(element, src) {
76327
78274
  if (element.playAcrossSlides !== true || element.mediaType !== 'audio' || !src) {
76328
78275
  return false;
76329
78276
  }
@@ -76579,9 +78526,13 @@ function scheduleAutoAdvanceChain$1(controller, ctx) {
76579
78526
  * only; no DOM dependencies, so it is unit-testable in isolation. Extracted
76580
78527
  * from four byte-identical copies (Svelte / Vanilla `editor/editor-geometry`).
76581
78528
  */
76582
- /** Arrow-key nudge step in element px (Shift multiplies to the large step). */
76583
- const NUDGE_STEP$1 = 1;
76584
- const NUDGE_STEP_LARGE = 10;
78529
+ /**
78530
+ * Arrow-key nudge step in element px (Shift multiplies to the large step).
78531
+ * Aliases of the keymap's `NUDGE_SMALL`/`NUDGE_LARGE`: the step is defined once
78532
+ * so the inspector's position boxes and the keyboard cannot disagree.
78533
+ */
78534
+ const NUDGE_STEP = NUDGE_SMALL;
78535
+ const NUDGE_STEP_LARGE = NUDGE_LARGE;
76585
78536
  const CORNER_HANDLES = new Set(['nw', 'ne', 'se', 'sw']);
76586
78537
  /** True for the four corner handles (the ones Shift aspect-locks). */
76587
78538
  function isCornerHandle(handle) {
@@ -76621,23 +78572,10 @@ function lockResizeAspect(resized, start, handle, minSize = MIN_ELEMENT_SIZE$1)
76621
78572
  }
76622
78573
  /**
76623
78574
  * Map an arrow key to a nudge delta in element px, or `null` for other keys.
76624
- * `large` (Shift held) uses the 10px step.
78575
+ * `large` (Shift held) uses the 10px step. Same function as the keymap's
78576
+ * `editorNudgeDelta`, kept under this name for the Svelte/Vanilla editors.
76625
78577
  */
76626
- function nudgeDelta(key, large) {
76627
- const step = large ? NUDGE_STEP_LARGE : NUDGE_STEP$1;
76628
- switch (key) {
76629
- case 'ArrowLeft':
76630
- return { dx: -step, dy: 0 };
76631
- case 'ArrowRight':
76632
- return { dx: step, dy: 0 };
76633
- case 'ArrowUp':
76634
- return { dx: 0, dy: -step };
76635
- case 'ArrowDown':
76636
- return { dx: 0, dy: step };
76637
- default:
76638
- return null;
76639
- }
76640
- }
78578
+ const nudgeDelta = editorNudgeDelta;
76641
78579
 
76642
78580
  /** Pixel offset applied to a duplicated element so the copy is visible. */
76643
78581
  const DUPLICATE_OFFSET_PX = 20;
@@ -76976,25 +78914,25 @@ const LINE_CAP_OPTIONS = [
76976
78914
  * @module render/arrange-extras
76977
78915
  */
76978
78916
  /** Outline thickness the renderer assumes when the shape declares none. */
76979
- const DEFAULT_STROKE_WIDTH$1 = 1;
78917
+ const DEFAULT_STROKE_WIDTH = 1;
76980
78918
  /** Grouping needs an editable deck and at least two selected elements. */
76981
- function canGroupSelection$1(canEdit, selectedCount) {
78919
+ function canGroupSelection(canEdit, selectedCount) {
76982
78920
  return canEdit && selectedCount >= 2;
76983
78921
  }
76984
78922
  /** Ungrouping needs an editable deck and a selection that IS a group. */
76985
- function canUngroupSelection$1(canEdit, element) {
78923
+ function canUngroupSelection(canEdit, element) {
76986
78924
  return canEdit && element?.type === 'group';
76987
78925
  }
76988
78926
  /** An outline width only exists on an element that carries shape properties. */
76989
- function canSetStrokeWidth$1(canEdit, element) {
78927
+ function canSetStrokeWidth(canEdit, element) {
76990
78928
  return canEdit && element !== null && hasShapeProperties(element);
76991
78929
  }
76992
78930
  /** The stroke width to show for a selection, defaulted for a shape without one. */
76993
- function strokeWidthOf$1(element) {
78931
+ function strokeWidthOf(element) {
76994
78932
  if (element === null || !hasShapeProperties(element)) {
76995
- return DEFAULT_STROKE_WIDTH$1;
78933
+ return DEFAULT_STROKE_WIDTH;
76996
78934
  }
76997
- return element.shapeStyle?.strokeWidth ?? DEFAULT_STROKE_WIDTH$1;
78935
+ return element.shapeStyle?.strokeWidth ?? DEFAULT_STROKE_WIDTH;
76998
78936
  }
76999
78937
 
77000
78938
  /**
@@ -82350,7 +84288,7 @@ function createLocalStorageBackend(namespace) {
82350
84288
  /** Try IndexedDB first; fall back to localStorage on any failure. */
82351
84289
  async function resolveBackend(dbName, namespace) {
82352
84290
  try {
82353
- const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-DXb-O2ta.mjs');
84291
+ const { openChatDb, createIdbBackend } = await import('./pptx-angular-viewer-chat-history-idb-ClFN-XPJ.mjs');
82354
84292
  const db = await openChatDb(dbName);
82355
84293
  return createIdbBackend(db);
82356
84294
  }
@@ -82458,12 +84396,12 @@ function toRenderableParts(message) {
82458
84396
  * skip the store round-trip entirely. `toRenderableParts` (a pure sibling
82459
84397
  * helper) flattens each message into text runs + tool parts.
82460
84398
  */
82461
- function isoOf$1(ms) {
84399
+ function isoOf(ms) {
82462
84400
  const n = Number.isFinite(ms) ? ms : 0;
82463
84401
  return new Date(n).toISOString();
82464
84402
  }
82465
84403
  /** Convert one stored chat into its detailed export form. */
82466
- function toLogChat$1(chat, detailed) {
84404
+ function toLogChat(chat, detailed) {
82467
84405
  const messages = chat.messages.map((message) => {
82468
84406
  const parts = toRenderableParts(message);
82469
84407
  const textRuns = [];
@@ -82494,27 +84432,27 @@ function toLogChat$1(chat, detailed) {
82494
84432
  deckId: chat.deckId,
82495
84433
  createdAt: chat.createdAt,
82496
84434
  updatedAt: chat.updatedAt,
82497
- createdAtIso: isoOf$1(chat.createdAt),
82498
- updatedAtIso: isoOf$1(chat.updatedAt),
84435
+ createdAtIso: isoOf(chat.createdAt),
84436
+ updatedAtIso: isoOf(chat.updatedAt),
82499
84437
  messageCount: chat.messages.length,
82500
84438
  messages,
82501
84439
  };
82502
84440
  }
82503
84441
  /** Build the detailed export document from already-loaded chats (pure). */
82504
- function buildChatLogExport$1(chats, options) {
84442
+ function buildChatLogExport(chats, options) {
82505
84443
  const detailed = options?.detailed ?? true;
82506
84444
  const now = options?.now ?? Date.now();
82507
84445
  return {
82508
84446
  format: 'pptx-ai-chat-log',
82509
84447
  version: 1,
82510
- exportedAt: isoOf$1(now),
84448
+ exportedAt: isoOf(now),
82511
84449
  detailed,
82512
84450
  chatCount: chats.length,
82513
- chats: chats.map((chat) => toLogChat$1(chat, detailed)),
84451
+ chats: chats.map((chat) => toLogChat(chat, detailed)),
82514
84452
  };
82515
84453
  }
82516
84454
  /** Render one tool call as a Markdown bullet (+ fenced JSON when `detailed`). */
82517
- function toolCallLine$1(call, detailed) {
84455
+ function toolCallLine(call, detailed) {
82518
84456
  const lines = [`- Tool \`${call.toolName}\` (${call.state})`];
82519
84457
  if (call.errorText) {
82520
84458
  lines.push(` - error: ${call.errorText}`);
@@ -82532,7 +84470,7 @@ function toolCallLine$1(call, detailed) {
82532
84470
  return lines.join('\n');
82533
84471
  }
82534
84472
  /** Render the same detailed export as a human-readable Markdown transcript. */
82535
- function buildChatLogMarkdown$1(doc) {
84473
+ function buildChatLogMarkdown(doc) {
82536
84474
  const out = [
82537
84475
  `# AI chat logs`,
82538
84476
  '',
@@ -82559,7 +84497,7 @@ function buildChatLogMarkdown$1(doc) {
82559
84497
  out.push('');
82560
84498
  }
82561
84499
  for (const call of message.toolCalls) {
82562
- out.push(toolCallLine$1(call, doc.detailed));
84500
+ out.push(toolCallLine(call, doc.detailed));
82563
84501
  out.push('');
82564
84502
  }
82565
84503
  }
@@ -82567,7 +84505,7 @@ function buildChatLogMarkdown$1(doc) {
82567
84505
  return out.join('\n');
82568
84506
  }
82569
84507
  /** Load every stored chat (newest first) in full detail from a store. */
82570
- async function collectStoredChats$1(store = createChatHistoryStore()) {
84508
+ async function collectStoredChats(store = createChatHistoryStore()) {
82571
84509
  const summaries = await store.listChats();
82572
84510
  const chats = [];
82573
84511
  for (const summary of summaries) {
@@ -82578,7 +84516,7 @@ async function collectStoredChats$1(store = createChatHistoryStore()) {
82578
84516
  }
82579
84517
  return chats;
82580
84518
  }
82581
- function timestampSlug$1(now) {
84519
+ function timestampSlug(now) {
82582
84520
  // YYYYMMDD-HHmmss in local time; stable, filesystem-safe.
82583
84521
  const d = new Date(now);
82584
84522
  const p = (n) => String(n).padStart(2, '0');
@@ -82598,11 +84536,11 @@ function exportAiChatLogs$1(chats, meta, save) {
82598
84536
  return 0;
82599
84537
  }
82600
84538
  const now = meta?.now ?? Date.now();
82601
- const doc = buildChatLogExport$1(chats, { detailed: meta?.detailed ?? true, now });
82602
- const slug = timestampSlug$1(now);
84539
+ const doc = buildChatLogExport(chats, { detailed: meta?.detailed ?? true, now });
84540
+ const slug = timestampSlug(now);
82603
84541
  const format = meta?.format ?? 'json';
82604
84542
  if (format === 'markdown') {
82605
- save(`pptx-ai-chats-${slug}.md`, buildChatLogMarkdown$1(doc), 'text/markdown');
84543
+ save(`pptx-ai-chats-${slug}.md`, buildChatLogMarkdown(doc), 'text/markdown');
82606
84544
  }
82607
84545
  else {
82608
84546
  save(`pptx-ai-chats-${slug}.json`, JSON.stringify(doc, null, 2), 'application/json');
@@ -82616,7 +84554,7 @@ function exportAiChatLogs$1(chats, meta, save) {
82616
84554
  * nothing is selected. Order and multiplicity are preserved (multi-select and
82617
84555
  * tables included) so callers can detect e.g. "exactly two tables".
82618
84556
  */
82619
- function computeFocusTargets$1(input) {
84557
+ function computeFocusTargets(input) {
82620
84558
  const { activeSlideIndex, selectedElementIds, selectedElementId } = input;
82621
84559
  const ids = selectedElementIds.length > 0
82622
84560
  ? [...selectedElementIds]
@@ -82629,7 +84567,7 @@ function computeFocusTargets$1(input) {
82629
84567
  return ids.map((elementId) => ({ kind: 'element', slideIndex: activeSlideIndex, elementId }));
82630
84568
  }
82631
84569
  /** Title-case an element type for display, e.g. `smartArt` -> `SmartArt`. */
82632
- function elementTypeLabel$1(type) {
84570
+ function elementTypeLabel(type) {
82633
84571
  if (type === 'smartArt') {
82634
84572
  return 'SmartArt';
82635
84573
  }
@@ -82644,7 +84582,7 @@ function elementTypeLabel$1(type) {
82644
84582
  * useful disambiguator, so `Shape 9` reads far better than the raw id. Falls
82645
84583
  * back to the last path segment when there is no trailing number.
82646
84584
  */
82647
- function shortElementId$1(id) {
84585
+ function shortElementId(id) {
82648
84586
  const trailingNumber = id.match(/(\d+)\s*$/u);
82649
84587
  if (trailingNumber) {
82650
84588
  return trailingNumber[1];
@@ -82657,16 +84595,16 @@ function shortElementId$1(id) {
82657
84595
  * element targets read `<Type> <n>` (a friendly short label, full id on hover),
82658
84596
  * or `<Type> (missing)` when the element is no longer on the slide.
82659
84597
  */
82660
- function focusTargetChips$1(targets, slides) {
84598
+ function focusTargetChips(targets, slides) {
82661
84599
  return targets.map((target, index) => {
82662
84600
  if (target.kind === 'slide') {
82663
84601
  const label = `Slide ${target.slideIndex + 1}`;
82664
84602
  return { key: `slide-${target.slideIndex}-${index}`, label, title: label };
82665
84603
  }
82666
84604
  const el = slides[target.slideIndex]?.elements.find((e) => e.id === target.elementId);
82667
- const typeLabel = el ? elementTypeLabel$1(el.type) : 'Element';
84605
+ const typeLabel = el ? elementTypeLabel(el.type) : 'Element';
82668
84606
  const label = el
82669
- ? `${typeLabel} ${shortElementId$1(target.elementId)}`
84607
+ ? `${typeLabel} ${shortElementId(target.elementId)}`
82670
84608
  : `${typeLabel} (missing)`;
82671
84609
  return {
82672
84610
  key: `el-${target.elementId}-${index}`,
@@ -82676,7 +84614,7 @@ function focusTargetChips$1(targets, slides) {
82676
84614
  });
82677
84615
  }
82678
84616
  /** Whether the focus is exactly two table elements (drives the merge action). */
82679
- function isTwoTableFocus$1(targets, slides) {
84617
+ function isTwoTableFocus(targets, slides) {
82680
84618
  if (targets.length !== 2 || targets.some((target) => target.kind !== 'element')) {
82681
84619
  return false;
82682
84620
  }
@@ -83702,89 +85640,6 @@ function aiToggleVisible(config) {
83702
85640
  return Boolean(config);
83703
85641
  }
83704
85642
 
83705
- /**
83706
- * Derive focused targets from the live selection: one `element` target per
83707
- * selected element on the active slide, or a single whole-`slide` target when
83708
- * nothing is selected. Order and multiplicity are preserved (multi-select and
83709
- * tables included) so callers can detect e.g. "exactly two tables".
83710
- */
83711
- function computeFocusTargets(input) {
83712
- const { activeSlideIndex, selectedElementIds, selectedElementId } = input;
83713
- const ids = selectedElementIds.length > 0
83714
- ? selectedElementIds
83715
- : selectedElementId
83716
- ? [selectedElementId]
83717
- : [];
83718
- if (ids.length === 0) {
83719
- return [{ kind: 'slide', slideIndex: activeSlideIndex }];
83720
- }
83721
- return ids.map((elementId) => ({ kind: 'element', slideIndex: activeSlideIndex, elementId }));
83722
- }
83723
- /** Title-case an element type for display, e.g. `smartArt` -> `SmartArt`. */
83724
- function elementTypeLabel(type) {
83725
- if (type === 'smartArt') {
83726
- return 'SmartArt';
83727
- }
83728
- if (type === 'ole') {
83729
- return 'OLE';
83730
- }
83731
- return type.charAt(0).toUpperCase() + type.slice(1);
83732
- }
83733
- /**
83734
- * A short, human handle for an element id. Element ids carry a source-path
83735
- * prefix (e.g. `ppt/slides/slide1.xml-shape-9`); the trailing number is the
83736
- * useful disambiguator, so `Shape 9` reads far better than the raw id. Falls
83737
- * back to the last path segment when there is no trailing number.
83738
- */
83739
- function shortElementId(id) {
83740
- const trailingNumber = id.match(/(\d+)\s*$/u);
83741
- if (trailingNumber) {
83742
- return trailingNumber[1];
83743
- }
83744
- const tail = id.replace(/^.*[/.-]/u, '');
83745
- return tail || id;
83746
- }
83747
- /**
83748
- * Build display chips for the given targets. Slide targets read `Slide N`;
83749
- * element targets read `<Type> <n>` (a friendly short label, full id on hover),
83750
- * or `<Type> (missing)` when the element is no longer on the slide.
83751
- */
83752
- function focusTargetChips(targets, slides) {
83753
- return targets.map((target, index) => {
83754
- if (target.kind === 'slide') {
83755
- const label = `Slide ${target.slideIndex + 1}`;
83756
- return { key: `slide-${target.slideIndex}-${index}`, label, title: label };
83757
- }
83758
- const el = slides[target.slideIndex]?.elements.find((e) => e.id === target.elementId);
83759
- const typeLabel = el ? elementTypeLabel(el.type) : 'Element';
83760
- const label = el
83761
- ? `${typeLabel} ${shortElementId(target.elementId)}`
83762
- : `${typeLabel} (missing)`;
83763
- return {
83764
- key: `el-${target.elementId}-${index}`,
83765
- label,
83766
- title: `${typeLabel}: ${target.elementId}`,
83767
- };
83768
- });
83769
- }
83770
- /** Whether the focus is exactly two table elements (drives the merge action). */
83771
- function isTwoTableFocus(targets, slides) {
83772
- if (targets.length !== 2 || targets.some((t) => t.kind !== 'element')) {
83773
- return false;
83774
- }
83775
- const [a, b] = targets;
83776
- if (a.slideIndex !== b.slideIndex) {
83777
- return false;
83778
- }
83779
- const slide = slides[a.slideIndex];
83780
- const elA = slide?.elements.find((e) => e.id === a.elementId);
83781
- const elB = slide?.elements.find((e) => e.id === b.elementId);
83782
- if (elA?.type !== 'table' || elB?.type !== 'table') {
83783
- return false;
83784
- }
83785
- return { slideIndex: a.slideIndex, elementIdA: a.elementId, elementIdB: b.elementId };
83786
- }
83787
-
83788
85643
  /**
83789
85644
  * AiPanelStore: owns the AI panel's "scope" (focused targets + a prefilled
83790
85645
  * composer directive) and the two on-canvas highlight sources, mirroring
@@ -87347,87 +89202,15 @@ class LoadContentService {
87347
89202
  // Non-critical: image will show as broken.
87348
89203
  }
87349
89204
  }));
87350
- const elementPatches = new Map();
87351
- for (const refEntry of imageRefs) {
87352
- const url = resolvedMap.get(refEntry.path);
87353
- if (!url) {
87354
- continue;
87355
- }
87356
- const id = refEntry.element.id;
87357
- const existing = elementPatches.get(id) ?? {};
87358
- existing[refEntry.field] = url;
87359
- elementPatches.set(id, existing);
87360
- }
87361
- if (elementPatches.size > 0) {
87362
- const patchElements = (elements) => {
87363
- let mutated = false;
87364
- const next = elements.map((el) => {
87365
- let updated = el;
87366
- const patch = elementPatches.get(el.id);
87367
- if (patch) {
87368
- updated = { ...el, ...patch };
87369
- }
87370
- if (updated.type === 'group' && updated.children?.length) {
87371
- const newChildren = patchElements(updated.children);
87372
- if (newChildren !== updated.children) {
87373
- updated = { ...updated, children: newChildren };
87374
- }
87375
- }
87376
- if (updated !== el) {
87377
- mutated = true;
87378
- }
87379
- return updated;
87380
- });
87381
- return mutated ? next : elements;
87382
- };
87383
- nextSlides = parsed.slides.map((s) => {
87384
- const newElements = patchElements(s.elements);
87385
- return newElements === s.elements ? s : { ...s, elements: newElements };
87386
- });
87387
- }
89205
+ nextSlides = parsed.slides.map((s) => {
89206
+ const newElements = applyImagePathPatches(s.elements, resolvedMap, imageRefs);
89207
+ return newElements === s.elements ? s : { ...s, elements: newElements };
89208
+ });
87388
89209
  }
87389
89210
  // ── Resolve table cell image-fill Blob URLs ──
87390
- const { paths: tableImagePaths, refs: tableImageRefs } = collectTableCellImagePaths(nextSlides);
87391
- if (tableImagePaths.size > 0) {
87392
- const resolvedTableMap = new Map();
87393
- await Promise.all(Array.from(tableImagePaths).map(async (path) => {
87394
- try {
87395
- const url = await newHandler.getImageData(path);
87396
- if (url) {
87397
- resolvedTableMap.set(path, url);
87398
- }
87399
- }
87400
- catch {
87401
- // Non-critical: the cell falls back to no image fill.
87402
- }
87403
- }));
87404
- if (resolvedTableMap.size > 0) {
87405
- nextSlides = nextSlides.map((s) => {
87406
- const newElements = applyTableCellImagePatches(s.elements, resolvedTableMap, tableImageRefs);
87407
- return newElements === s.elements ? s : { ...s, elements: newElements };
87408
- });
87409
- }
87410
- }
89211
+ nextSlides = await resolveTableCellImageUrls(nextSlides, (path) => newHandler.getImageData(path));
87411
89212
  // ── Resolve whole-table-STYLE image-fill Blob URLs ──
87412
- let nextTableStyleMap = parsed.tableStyleMap;
87413
- const { paths: tableStyleImagePaths, refs: tableStyleImageRefs } = collectTableStyleImagePaths(nextTableStyleMap);
87414
- if (tableStyleImagePaths.size > 0) {
87415
- const resolvedStyleMap = new Map();
87416
- await Promise.all(Array.from(tableStyleImagePaths).map(async (path) => {
87417
- try {
87418
- const url = await newHandler.getImageData(path);
87419
- if (url) {
87420
- resolvedStyleMap.set(path, url);
87421
- }
87422
- }
87423
- catch {
87424
- // Non-critical: the style section falls back to no image fill.
87425
- }
87426
- }));
87427
- if (resolvedStyleMap.size > 0 && nextTableStyleMap) {
87428
- nextTableStyleMap = applyTableStyleImagePatches(nextTableStyleMap, resolvedStyleMap, tableStyleImageRefs);
87429
- }
87430
- }
89213
+ const nextTableStyleMap = await resolveTableStyleImageUrls(parsed.tableStyleMap, (path) => newHandler.getImageData(path));
87431
89214
  // Commit reactive state.
87432
89215
  this.revokeBlobUrls(this.activeBlobUrls);
87433
89216
  this.activeBlobUrls = loadBlobUrls;
@@ -87615,8 +89398,6 @@ async function parseSignaturesFromBuffer(buffer) {
87615
89398
  * only wires them to Angular signals. Provide it at the component level:
87616
89399
  * `@Component({ providers: [EditorStateService] })`.
87617
89400
  */
87618
- /** Default nudge distance (px) for arrow-key moves. */
87619
- const NUDGE_STEP = 1;
87620
89401
  /** Offset (px) applied to a duplicated element so it is visible. */
87621
89402
  const DUPLICATE_OFFSET = 12;
87622
89403
  class EditorStateService {
@@ -87846,9 +89627,6 @@ class EditorStateService {
87846
89627
  }
87847
89628
  this.commit(this.t('pptx.undoAction.move'), slideIndex, (els) => ids.reduce((acc, id) => moveElementBy(acc, id, dx, dy), [...els]));
87848
89629
  }
87849
- nudgeSelected(slideIndex, dirX, dirY) {
87850
- this.moveSelectedBy(slideIndex, dirX * NUDGE_STEP, dirY * NUDGE_STEP);
87851
- }
87852
89630
  setPosition(slideIndex, id, x, y) {
87853
89631
  this.commit(this.t('pptx.undoAction.move'), slideIndex, (els) => setElementPosition(els, id, x, y));
87854
89632
  }
@@ -90383,7 +92161,8 @@ function initialsOf(name) {
90383
92161
  * by silently downloading its "cloud fonts"; a browser has no equivalent).
90384
92162
  * When a referenced family is served by the Google Fonts API, this service
90385
92163
  * injects a `<link rel="stylesheet">` so the text renders with the intended
90386
- * face anyway. Candidates are probed (session-cached) asynchronously, so each
92164
+ * face anyway. Candidates are resolved against the bundled Google Fonts
92165
+ * catalogue (no network round-trip) asynchronously, so each
90387
92166
  * `sync` call tags its result with a token: only the most recent call may
90388
92167
  * apply its outcome. The managed `<link>` element lives in a single element
90389
92168
  * keyed by {@link GOOGLE_WEBFONTS_LINK_ID} and is removed on destroy via
@@ -90402,7 +92181,7 @@ function hasDomSupport() {
90402
92181
  class GoogleWebfontsService {
90403
92182
  constructor() {
90404
92183
  this.linkEl = null;
90405
- /** Tags in-flight probes; only the newest `sync` may apply its result. */
92184
+ /** Tags in-flight resolutions; only the newest `sync` may apply its result. */
90406
92185
  this.syncToken = 0;
90407
92186
  inject(DestroyRef).onDestroy(() => {
90408
92187
  this.dispose();
@@ -90410,7 +92189,7 @@ class GoogleWebfontsService {
90410
92189
  }
90411
92190
  /**
90412
92191
  * Resolve which referenced families need a Google Fonts fetch for this
90413
- * deck and sync the managed `<link>` element once the probe settles.
92192
+ * deck and sync the managed `<link>` element once the resolution settles.
90414
92193
  * Pass empty slides / fonts (e.g. before a load) to remove it.
90415
92194
  */
90416
92195
  sync(slides, embeddedFonts) {
@@ -90437,7 +92216,7 @@ class GoogleWebfontsService {
90437
92216
  });
90438
92217
  }
90439
92218
  /**
90440
- * Remove the injected `<link>` element and invalidate in-flight probes.
92219
+ * Remove the injected `<link>` element and invalidate in-flight resolutions.
90441
92220
  * Called automatically on destroy; safe to call manually.
90442
92221
  */
90443
92222
  dispose() {
@@ -91469,29 +93248,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
91469
93248
  *
91470
93249
  * @module angular-viewer/smart-art-preview
91471
93250
  */
91472
- /** Element size the insert handler creates; previews render the same box. */
91473
- const PREVIEW_ELEMENT_WIDTH = 600;
91474
- const PREVIEW_ELEMENT_HEIGHT = 340;
91475
- const FALLBACK_ITEMS = ['1', '2', '3'];
91476
93251
  class SmartArtPreviewComponent {
91477
93252
  constructor() {
91478
93253
  /** The SmartArt layout to draw a thumbnail for. */
91479
93254
  this.layout = input.required(/* @ts-ignore */
91480
93255
  ...(ngDevMode ? [{ debugName: "layout" }] : /* istanbul ignore next */ []));
91481
93256
  /** The element this preset would insert, rendered at full size then scaled. */
91482
- this.previewElement = computed(() => {
91483
- const layout = this.layout();
91484
- const preset = PRESETS.find((p) => p.layout === layout);
91485
- return {
91486
- id: `smartart-preview-${layout}`,
91487
- type: 'smartArt',
91488
- x: 0,
91489
- y: 0,
91490
- width: PREVIEW_ELEMENT_WIDTH,
91491
- height: PREVIEW_ELEMENT_HEIGHT,
91492
- smartArtData: buildSmartArtPresetData(layout, preset?.defaultItems ?? FALLBACK_ITEMS),
91493
- };
91494
- }, /* @ts-ignore */
93257
+ this.previewElement = computed(() => buildSmartArtPreviewElement(this.layout()), /* @ts-ignore */
91495
93258
  ...(ngDevMode ? [{ debugName: "previewElement" }] : /* istanbul ignore next */ []));
91496
93259
  }
91497
93260
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: SmartArtPreviewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
@@ -95140,21 +96903,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
95140
96903
  *
95141
96904
  * @module viewer/duotone-filter
95142
96905
  */
95143
- /**
95144
- * Parse a 6-digit hex colour (`#RRGGBB` or `RRGGBB`) to normalised 0–1 RGB.
95145
- * Any channel that fails to parse produces `0`.
95146
- */
95147
- function hexToRgbUnit(hex) {
95148
- const clean = hex.replace('#', '');
95149
- const r = Number.parseInt(clean.substring(0, 2), 16) / 255;
95150
- const g = Number.parseInt(clean.substring(2, 4), 16) / 255;
95151
- const b = Number.parseInt(clean.substring(4, 6), 16) / 255;
95152
- return {
95153
- r: Number.isFinite(r) ? r : 0,
95154
- g: Number.isFinite(g) ? g : 0,
95155
- b: Number.isFinite(b) ? b : 0,
95156
- };
95157
- }
95158
96906
  // ── BT.709 grayscale matrix (matches React implementation) ────────────────────
95159
96907
  /**
95160
96908
  * BT.709 luminance weights as a 4×5 SVG `feColorMatrix` values string.
@@ -96350,15 +98098,10 @@ function getClrChangeParams(el) {
96350
98098
  }
96351
98099
 
96352
98100
  function getImageCropShapeClipPath(element) {
96353
- if (!isImageLikeElement(element) || !element.cropShape || element.cropShape === 'none') {
98101
+ if (!isImageLikeElement(element)) {
96354
98102
  return undefined;
96355
98103
  }
96356
- const shapeType = element.cropShape === 'roundedRect'
96357
- ? 'roundRect'
96358
- : element.cropShape === 'star'
96359
- ? 'star5'
96360
- : element.cropShape;
96361
- return getResolvedShapeClipPathFor(shapeType, element.width, element.height);
98104
+ return getCropShapeClipPath(element.cropShape, element.width, element.height);
96362
98105
  }
96363
98106
  /** Build the complete shared image-effect view consumed by Angular templates. */
96364
98107
  function buildAngularImageRenderView(element) {
@@ -96786,26 +98529,6 @@ function asMediaElement(el) {
96786
98529
  function resolveMediaSrc(el, mediaDataUrls) {
96787
98530
  return el.mediaData ?? (el.mediaPath ? mediaDataUrls.get(el.mediaPath) : undefined);
96788
98531
  }
96789
- /**
96790
- * Register a `playAcrossSlides` audio element with the shared persistent-audio
96791
- * manager, using the same resolved source, loop, volume and trim start the
96792
- * slide-local element would have used. PowerPoint keeps such background audio
96793
- * playing when the show advances, but the slide-local `<audio>` dies with its
96794
- * slide's DOM; the manager's hidden document-level element survives it.
96795
- *
96796
- * Returns true when the persistent element owns playback, in which case the
96797
- * slide-local media node must stay silent or the track doubles. Idempotent per
96798
- * element id (the manager no-ops a re-register), so re-entering the owning
96799
- * slide does not restart the track.
96800
- */
96801
- function registerCrossSlideAudio(element, src) {
96802
- if (element.playAcrossSlides !== true || element.mediaType !== 'audio' || !src) {
96803
- return false;
96804
- }
96805
- const playback = mediaPlaybackAttributes(element);
96806
- registerPersistentAudio(element.id, src, element.mediaMimeType, playback.loop, playback.volume, (element.trimStartMs ?? 0) / 1000);
96807
- return true;
96808
- }
96809
98532
  /**
96810
98533
  * Build a media-fragment URI component (`#t=start,end`) for trimmed media.
96811
98534
  * Times are stored in milliseconds; the fragment uses seconds. Mirrors React's
@@ -97231,15 +98954,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
97231
98954
  `, styles: [".pptx-ng-media-el{display:block;pointer-events:auto}.pptx-ng-media-video{width:100%;height:100%;object-fit:contain}.pptx-ng-media-audio{width:100%}.pptx-ng-media-inert{pointer-events:none}.pptx-ng-img{width:100%;height:100%;object-fit:contain;display:block}.pptx-ng-media-dim{opacity:.5}.pptx-ng-media-badge{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;font-size:10px;color:#fffc;filter:drop-shadow(0 1px 2px rgba(0,0,0,.5));pointer-events:none}.pptx-ng-media-badge svg{width:48px;height:48px}.pptx-ng-media-badge-missing{color:#fff9}.pptx-ng-media-badge-missing svg{width:32px;height:32px}.pptx-ng-media-placeholder{flex-direction:column;gap:4px;font-size:10px}.pptx-ng-media-placeholder svg{width:32px;height:32px}\n"] }]
97232
98955
  }], ctorParameters: () => [], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], marked: [{ type: i0.Input, args: [{ isSignal: true, alias: "marked", required: false }] }], exposeElementId: [{ type: i0.Input, args: [{ isSignal: true, alias: "exposeElementId", required: false }] }], presenting: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenting", required: false }] }], placeholderLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholderLabel", required: false }] }], mediaElRef: [{ type: i0.ViewChild, args: ['mediaEl', { isSignal: true }] }] } });
97233
98956
 
97234
- /**
97235
- * Pure helpers for `Model3DRendererComponent`.
97236
- *
97237
- * All functions are framework-agnostic (no Angular dependency) so they can be
97238
- * unit-tested without TestBed, following the same pattern as
97239
- * `connector-path.ts`.
97240
- */
97241
- /** Default MIME type for a GLB binary model when the element omits one. */
97242
- const DEFAULT_MODEL_MIME = 'model/gltf-binary';
97243
98957
  /**
97244
98958
  * Narrow `element` to `Model3DPptxElement` and derive the poster source.
97245
98959
  * Uses the type discriminant directly (`el.type === 'model3d'`) to avoid an
@@ -97259,34 +98973,19 @@ function buildModel3DContainerStyle(element, zIndex) {
97259
98973
  }
97260
98974
  /**
97261
98975
  * Derive an object (blob) URL for the GLTF/GLB loader from the element's
97262
- * base64 `modelData` data URL.
97263
- *
97264
- * Reuses the core `parseDataUrlToBytes` helper (no hand-rolled base64) and
97265
- * wraps the bytes in a `Blob` typed with `modelMimeType` (falling back to
97266
- * `model/gltf-binary`). Returns `undefined` when the element is not a model3d,
97267
- * has no `modelData`, or the data URL cannot be parsed: the caller then shows
97268
- * the poster fallback. The returned URL is owned by the caller, which must
97269
- * `URL.revokeObjectURL` it on teardown.
98976
+ * base64 `modelData` data URL. Delegates to shared's `modelDataToBlobUrl`
98977
+ * (reuses core's `parseDataUrlToBytes`, no hand-rolled base64); this wrapper
98978
+ * only narrows `element` to `Model3DPptxElement` first. Returns `undefined`
98979
+ * when the element is not a model3d, has no `modelData`, or the data URL
98980
+ * cannot be parsed: the caller then shows the poster fallback. The returned
98981
+ * URL is owned by the caller, which must `URL.revokeObjectURL` it on teardown.
97270
98982
  */
97271
98983
  function deriveModel3DBlobUrl(element) {
97272
98984
  if (element.type !== 'model3d') {
97273
98985
  return undefined;
97274
98986
  }
97275
98987
  const model = element;
97276
- if (!model.modelData) {
97277
- return undefined;
97278
- }
97279
- const parsed = parseDataUrlToBytes(model.modelData);
97280
- if (!parsed) {
97281
- return undefined;
97282
- }
97283
- // `parsed.bytes` is a `Uint8Array<ArrayBufferLike>`; the cast matches the
97284
- // existing Angular `Blob` construction convention (see `export.service.ts`),
97285
- // working around the lib.dom `BlobPart` / `SharedArrayBuffer` mismatch.
97286
- const blob = new Blob([parsed.bytes], {
97287
- type: model.modelMimeType ?? DEFAULT_MODEL_MIME,
97288
- });
97289
- return URL.createObjectURL(blob);
98988
+ return modelDataToBlobUrl(model.modelData, model.modelMimeType);
97290
98989
  }
97291
98990
 
97292
98991
  /**
@@ -97671,6 +99370,15 @@ class OleRendererComponent {
97671
99370
  /** Border + background style for the placeholder box. */
97672
99371
  this.placeholderStyle = computed(() => getPlaceholderStyle(this.oleType()), /* @ts-ignore */
97673
99372
  ...(ngDevMode ? [{ debugName: "placeholderStyle" }] : /* istanbul ignore next */ []));
99373
+ /**
99374
+ * Data-driven `rect`/`line`/`text` primitives for the placeholder icon,
99375
+ * shared with every other binding's OLE renderer so the icon glyphs
99376
+ * (Excel grid, Word lines, PDF box, Visio diagram, MathType `f(x)`,
99377
+ * generic linked-object) cannot drift apart. The template maps each
99378
+ * primitive onto its own SVG element.
99379
+ */
99380
+ this.iconShapes = computed(() => getOleIconShapes(this.oleType()), /* @ts-ignore */
99381
+ ...(ngDevMode ? [{ debugName: "iconShapes" }] : /* istanbul ignore next */ []));
97674
99382
  /**
97675
99383
  * Download / Open action model derived from the recovered embedded payload.
97676
99384
  * When the input is not an OLE element, every action is disabled.
@@ -97718,11 +99426,11 @@ class OleRendererComponent {
97718
99426
  }
97719
99427
  }
97720
99428
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: OleRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
97721
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: OleRendererComponent, isStandalone: true, selector: "pptx-ole-renderer", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"pptx-ng-ole\" role=\"img\" [attr.aria-label]=\"ariaLabel()\" [attr.title]=\"infoTitle()\">\n\t@if (previewSrc()) {\n\t\t<!-- Preview image with type-badge overlay -->\n\t\t<div class=\"pptx-ng-ole-preview\">\n\t\t\t<img\n\t\t\t\t[src]=\"previewSrc()\"\n\t\t\t\t[attr.alt]=\"ariaLabel()\"\n\t\t\t\tclass=\"pptx-ng-ole-img\"\n\t\t\t\tdraggable=\"false\"\n\t\t\t/>\n\t\t\t<svg class=\"pptx-ng-ole-badge\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n\t\t\t\t<rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"3\" [attr.fill]=\"typeColor()\" />\n\t\t\t\t<text\n\t\t\t\t\tx=\"12\"\n\t\t\t\t\ty=\"16\"\n\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\tfill=\"white\"\n\t\t\t\t\t[attr.font-size]=\"badgeLabel().length > 4 ? 6 : 10\"\n\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t>\n\t\t\t\t\t{{ badgeLabel() }}\n\t\t\t\t</text>\n\t\t\t</svg>\n\t\t</div>\n\t} @else {\n\t\t<!-- Type-specific placeholder box -->\n\t\t<div class=\"pptx-ng-ole-placeholder\" [ngStyle]=\"placeholderStyle()\">\n\t\t\t@switch (oleType()) {\n\t\t\t\t@case ('excel') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"3\"\n\t\t\t\t\t\t\ty=\"3\"\n\t\t\t\t\t\t\twidth=\"18\"\n\t\t\t\t\t\t\theight=\"18\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t\t<line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t\t<line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t\t<line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('word') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"4\"\n\t\t\t\t\t\t\ty=\"2\"\n\t\t\t\t\t\t\twidth=\"16\"\n\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"7\"\n\t\t\t\t\t\t\ty1=\"7\"\n\t\t\t\t\t\t\tx2=\"17\"\n\t\t\t\t\t\t\ty2=\"7\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"7\"\n\t\t\t\t\t\t\ty1=\"11\"\n\t\t\t\t\t\t\tx2=\"17\"\n\t\t\t\t\t\t\ty2=\"11\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"7\"\n\t\t\t\t\t\t\ty1=\"15\"\n\t\t\t\t\t\t\tx2=\"13\"\n\t\t\t\t\t\t\ty2=\"15\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('pdf') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"4\"\n\t\t\t\t\t\t\ty=\"2\"\n\t\t\t\t\t\t\twidth=\"16\"\n\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"12\"\n\t\t\t\t\t\t\ty=\"14\"\n\t\t\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\t\t\t[attr.fill]=\"typeColor()\"\n\t\t\t\t\t\t\tfont-size=\"7\"\n\t\t\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tPDF\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('visio') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"8\"\n\t\t\t\t\t\t\ty=\"2\"\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"5\"\n\t\t\t\t\t\t\trx=\"1\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"10\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<line x1=\"6\" y1=\"10\" x2=\"18\" y2=\"10\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<line x1=\"6\" y1=\"10\" x2=\"6\" y2=\"13\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<line x1=\"18\" y1=\"10\" x2=\"18\" y2=\"13\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\ty=\"13\"\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"5\"\n\t\t\t\t\t\t\trx=\"1\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"14\"\n\t\t\t\t\t\t\ty=\"13\"\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"5\"\n\t\t\t\t\t\t\trx=\"1\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('mathtype') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\ty=\"4\"\n\t\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\t\theight=\"16\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"12\"\n\t\t\t\t\t\t\ty=\"15\"\n\t\t\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\t\t\t[attr.fill]=\"typeColor()\"\n\t\t\t\t\t\t\tfont-size=\"9\"\n\t\t\t\t\t\t\tfont-style=\"italic\"\n\t\t\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tf(x)\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@default {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\ty=\"5\"\n\t\t\t\t\t\t\twidth=\"9\"\n\t\t\t\t\t\t\theight=\"7\"\n\t\t\t\t\t\t\trx=\"1.5\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"13\"\n\t\t\t\t\t\t\ty=\"12\"\n\t\t\t\t\t\t\twidth=\"9\"\n\t\t\t\t\t\t\theight=\"7\"\n\t\t\t\t\t\t\trx=\"1.5\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"11\"\n\t\t\t\t\t\t\ty1=\"8.5\"\n\t\t\t\t\t\t\tx2=\"13\"\n\t\t\t\t\t\t\ty2=\"15.5\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t}\n\t\t\t<span class=\"pptx-ng-ole-name\" [ngStyle]=\"{ color: typeColor() }\">{{ displayName() }}</span>\n\t\t\t@if (fileName()) {\n\t\t\t\t<span class=\"pptx-ng-ole-sublabel\">{{ typeLabel() }}</span>\n\t\t\t}\n\t\t</div>\n\t}\n\t@if (actions().canDownload) {\n\t\t<!--\n\t\t\tDownload / Open actions for the recovered embedded payload.\n\t\t\tPointer events are isolated so clicking an action never starts a\n\t\t\tselection/drag of the underlying element; the controls are\n\t\t\tkeyboard-focusable and only paint on hover / focus-within.\n\t\t-->\n\t\t<div\n\t\t\tclass=\"pptx-ng-ole-actions\"\n\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t(mousedown)=\"$event.stopPropagation()\"\n\t\t>\n\t\t\t<a\n\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t[href]=\"actions().downloadHref\"\n\t\t\t\t[attr.download]=\"actions().downloadFileName\"\n\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t'pptx.ole.downloadFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\"\n\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t>\n\t\t\t\t{{ 'pptx.ole.download' | translate }}\n\t\t\t</a>\n\t\t\t@if (actions().canOpen) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t'pptx.ole.openFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\t\"\n\t\t\t\t\t(click)=\"$event.stopPropagation(); openEmbedded()\"\n\t\t\t\t>\n\t\t\t\t\t{{ 'pptx.ole.open' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</div>\n\t}\n</div>\n", styles: [".pptx-ng-ole{position:relative;box-sizing:border-box;width:100%;height:100%}.pptx-ng-ole-preview{position:relative;width:100%;height:100%}.pptx-ng-ole-img{width:100%;height:100%;object-fit:contain;pointer-events:none;-webkit-user-select:none;user-select:none;display:block}.pptx-ng-ole-badge{position:absolute;bottom:4px;right:4px;z-index:10}.pptx-ng-ole-placeholder{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;box-sizing:border-box}.pptx-ng-ole-name{margin-top:8px;font-size:12px;font-weight:500;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-sublabel{margin-top:2px;font-size:10px;color:#00000073;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-actions{position:absolute;bottom:4px;left:4px;display:flex;gap:4px;z-index:11;opacity:0;transition:opacity .12s ease-in-out}.pptx-ng-ole:hover .pptx-ng-ole-actions,.pptx-ng-ole-actions:focus-within{opacity:1}.pptx-ng-ole-action{font-size:11px;line-height:1;padding:4px 8px;border-radius:4px;background-color:#000000b8;color:#fff;text-decoration:none;cursor:pointer;white-space:nowrap;pointer-events:auto}.pptx-ng-ole-action:hover{background-color:#000000d9}.pptx-ng-ole-action:focus-visible{outline:2px solid #fff;outline-offset:1px}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
99429
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: OleRendererComponent, isStandalone: true, selector: "pptx-ole-renderer", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<div class=\"pptx-ng-ole\" role=\"img\" [attr.aria-label]=\"ariaLabel()\" [attr.title]=\"infoTitle()\">\n\t@if (previewSrc()) {\n\t\t<!-- Preview image with type-badge overlay -->\n\t\t<div class=\"pptx-ng-ole-preview\">\n\t\t\t<img\n\t\t\t\t[src]=\"previewSrc()\"\n\t\t\t\t[attr.alt]=\"ariaLabel()\"\n\t\t\t\tclass=\"pptx-ng-ole-img\"\n\t\t\t\tdraggable=\"false\"\n\t\t\t/>\n\t\t\t<svg class=\"pptx-ng-ole-badge\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n\t\t\t\t<rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"3\" [attr.fill]=\"typeColor()\" />\n\t\t\t\t<text\n\t\t\t\t\tx=\"12\"\n\t\t\t\t\ty=\"16\"\n\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\tfill=\"white\"\n\t\t\t\t\t[attr.font-size]=\"badgeLabel().length > 4 ? 6 : 10\"\n\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t>\n\t\t\t\t\t{{ badgeLabel() }}\n\t\t\t\t</text>\n\t\t\t</svg>\n\t\t</div>\n\t} @else {\n\t\t<!-- Type-specific placeholder box -->\n\t\t<div class=\"pptx-ng-ole-placeholder\" [ngStyle]=\"placeholderStyle()\">\n\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t@for (shape of iconShapes(); track $index) {\n\t\t\t\t\t@switch (shape.tag) {\n\t\t\t\t\t\t@case ('rect') {\n\t\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\t\t[attr.x]=\"shape.attrs['x']\"\n\t\t\t\t\t\t\t\t[attr.y]=\"shape.attrs['y']\"\n\t\t\t\t\t\t\t\t[attr.width]=\"shape.attrs['width']\"\n\t\t\t\t\t\t\t\t[attr.height]=\"shape.attrs['height']\"\n\t\t\t\t\t\t\t\t[attr.rx]=\"shape.attrs['rx']\"\n\t\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\t\t[attr.stroke-width]=\"shape.attrs['stroke-width']\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@case ('line') {\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\t[attr.x1]=\"shape.attrs['x1']\"\n\t\t\t\t\t\t\t\t[attr.y1]=\"shape.attrs['y1']\"\n\t\t\t\t\t\t\t\t[attr.x2]=\"shape.attrs['x2']\"\n\t\t\t\t\t\t\t\t[attr.y2]=\"shape.attrs['y2']\"\n\t\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\t\t[attr.stroke-width]=\"shape.attrs['stroke-width']\"\n\t\t\t\t\t\t\t\t[attr.stroke-linecap]=\"shape.attrs['stroke-linecap']\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@case ('text') {\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t[attr.x]=\"shape.attrs['x']\"\n\t\t\t\t\t\t\t\t[attr.y]=\"shape.attrs['y']\"\n\t\t\t\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\t\t\t\t[attr.fill]=\"typeColor()\"\n\t\t\t\t\t\t\t\t[attr.font-size]=\"shape.attrs['font-size']\"\n\t\t\t\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t\t\t\t\t[attr.font-style]=\"shape.attrs['font-style']\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{{ shape.text }}\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t\t<span class=\"pptx-ng-ole-name\" [ngStyle]=\"{ color: typeColor() }\">{{ displayName() }}</span>\n\t\t\t@if (fileName()) {\n\t\t\t\t<span class=\"pptx-ng-ole-sublabel\">{{ typeLabel() }}</span>\n\t\t\t}\n\t\t</div>\n\t}\n\t@if (actions().canDownload) {\n\t\t<!--\n\t\t\tDownload / Open actions for the recovered embedded payload.\n\t\t\tPointer events are isolated so clicking an action never starts a\n\t\t\tselection/drag of the underlying element; the controls are\n\t\t\tkeyboard-focusable and only paint on hover / focus-within.\n\t\t-->\n\t\t<div\n\t\t\tclass=\"pptx-ng-ole-actions\"\n\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t(mousedown)=\"$event.stopPropagation()\"\n\t\t>\n\t\t\t<a\n\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t[href]=\"actions().downloadHref\"\n\t\t\t\t[attr.download]=\"actions().downloadFileName\"\n\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t'pptx.ole.downloadFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\"\n\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t>\n\t\t\t\t{{ 'pptx.ole.download' | translate }}\n\t\t\t</a>\n\t\t\t@if (actions().canOpen) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t'pptx.ole.openFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\t\"\n\t\t\t\t\t(click)=\"$event.stopPropagation(); openEmbedded()\"\n\t\t\t\t>\n\t\t\t\t\t{{ 'pptx.ole.open' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</div>\n\t}\n</div>\n", styles: [".pptx-ng-ole{position:relative;box-sizing:border-box;width:100%;height:100%}.pptx-ng-ole-preview{position:relative;width:100%;height:100%}.pptx-ng-ole-img{width:100%;height:100%;object-fit:contain;pointer-events:none;-webkit-user-select:none;user-select:none;display:block}.pptx-ng-ole-badge{position:absolute;bottom:4px;right:4px;z-index:10}.pptx-ng-ole-placeholder{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;box-sizing:border-box}.pptx-ng-ole-name{margin-top:8px;font-size:12px;font-weight:500;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-sublabel{margin-top:2px;font-size:10px;color:#00000073;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-actions{position:absolute;bottom:4px;left:4px;display:flex;gap:4px;z-index:11;opacity:0;transition:opacity .12s ease-in-out}.pptx-ng-ole:hover .pptx-ng-ole-actions,.pptx-ng-ole-actions:focus-within{opacity:1}.pptx-ng-ole-action{font-size:11px;line-height:1;padding:4px 8px;border-radius:4px;background-color:#000000b8;color:#fff;text-decoration:none;cursor:pointer;white-space:nowrap;pointer-events:auto}.pptx-ng-ole-action:hover{background-color:#000000d9}.pptx-ng-ole-action:focus-visible{outline:2px solid #fff;outline-offset:1px}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
97722
99430
  }
97723
99431
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: OleRendererComponent, decorators: [{
97724
99432
  type: Component,
97725
- args: [{ selector: 'pptx-ole-renderer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgStyle, TranslatePipe], template: "<div class=\"pptx-ng-ole\" role=\"img\" [attr.aria-label]=\"ariaLabel()\" [attr.title]=\"infoTitle()\">\n\t@if (previewSrc()) {\n\t\t<!-- Preview image with type-badge overlay -->\n\t\t<div class=\"pptx-ng-ole-preview\">\n\t\t\t<img\n\t\t\t\t[src]=\"previewSrc()\"\n\t\t\t\t[attr.alt]=\"ariaLabel()\"\n\t\t\t\tclass=\"pptx-ng-ole-img\"\n\t\t\t\tdraggable=\"false\"\n\t\t\t/>\n\t\t\t<svg class=\"pptx-ng-ole-badge\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n\t\t\t\t<rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"3\" [attr.fill]=\"typeColor()\" />\n\t\t\t\t<text\n\t\t\t\t\tx=\"12\"\n\t\t\t\t\ty=\"16\"\n\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\tfill=\"white\"\n\t\t\t\t\t[attr.font-size]=\"badgeLabel().length > 4 ? 6 : 10\"\n\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t>\n\t\t\t\t\t{{ badgeLabel() }}\n\t\t\t\t</text>\n\t\t\t</svg>\n\t\t</div>\n\t} @else {\n\t\t<!-- Type-specific placeholder box -->\n\t\t<div class=\"pptx-ng-ole-placeholder\" [ngStyle]=\"placeholderStyle()\">\n\t\t\t@switch (oleType()) {\n\t\t\t\t@case ('excel') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"3\"\n\t\t\t\t\t\t\ty=\"3\"\n\t\t\t\t\t\t\twidth=\"18\"\n\t\t\t\t\t\t\theight=\"18\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line x1=\"3\" y1=\"9\" x2=\"21\" y2=\"9\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t\t<line x1=\"3\" y1=\"15\" x2=\"21\" y2=\"15\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t\t<line x1=\"9\" y1=\"3\" x2=\"9\" y2=\"21\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t\t<line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" [attr.stroke]=\"typeColor()\" stroke-width=\"1\" />\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('word') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"4\"\n\t\t\t\t\t\t\ty=\"2\"\n\t\t\t\t\t\t\twidth=\"16\"\n\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"7\"\n\t\t\t\t\t\t\ty1=\"7\"\n\t\t\t\t\t\t\tx2=\"17\"\n\t\t\t\t\t\t\ty2=\"7\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"7\"\n\t\t\t\t\t\t\ty1=\"11\"\n\t\t\t\t\t\t\tx2=\"17\"\n\t\t\t\t\t\t\ty2=\"11\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"7\"\n\t\t\t\t\t\t\ty1=\"15\"\n\t\t\t\t\t\t\tx2=\"13\"\n\t\t\t\t\t\t\ty2=\"15\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('pdf') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"4\"\n\t\t\t\t\t\t\ty=\"2\"\n\t\t\t\t\t\t\twidth=\"16\"\n\t\t\t\t\t\t\theight=\"20\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"12\"\n\t\t\t\t\t\t\ty=\"14\"\n\t\t\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\t\t\t[attr.fill]=\"typeColor()\"\n\t\t\t\t\t\t\tfont-size=\"7\"\n\t\t\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tPDF\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('visio') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"8\"\n\t\t\t\t\t\t\ty=\"2\"\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"5\"\n\t\t\t\t\t\t\trx=\"1\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line x1=\"12\" y1=\"7\" x2=\"12\" y2=\"10\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<line x1=\"6\" y1=\"10\" x2=\"18\" y2=\"10\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<line x1=\"6\" y1=\"10\" x2=\"6\" y2=\"13\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<line x1=\"18\" y1=\"10\" x2=\"18\" y2=\"13\" [attr.stroke]=\"typeColor()\" stroke-width=\"1.5\" />\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\ty=\"13\"\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"5\"\n\t\t\t\t\t\t\trx=\"1\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"14\"\n\t\t\t\t\t\t\ty=\"13\"\n\t\t\t\t\t\t\twidth=\"8\"\n\t\t\t\t\t\t\theight=\"5\"\n\t\t\t\t\t\t\trx=\"1\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@case ('mathtype') {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\ty=\"4\"\n\t\t\t\t\t\t\twidth=\"20\"\n\t\t\t\t\t\t\theight=\"16\"\n\t\t\t\t\t\t\trx=\"2\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<text\n\t\t\t\t\t\t\tx=\"12\"\n\t\t\t\t\t\t\ty=\"15\"\n\t\t\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\t\t\t[attr.fill]=\"typeColor()\"\n\t\t\t\t\t\t\tfont-size=\"9\"\n\t\t\t\t\t\t\tfont-style=\"italic\"\n\t\t\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tf(x)\n\t\t\t\t\t\t</text>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t\t@default {\n\t\t\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"2\"\n\t\t\t\t\t\t\ty=\"5\"\n\t\t\t\t\t\t\twidth=\"9\"\n\t\t\t\t\t\t\theight=\"7\"\n\t\t\t\t\t\t\trx=\"1.5\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\tx=\"13\"\n\t\t\t\t\t\t\ty=\"12\"\n\t\t\t\t\t\t\twidth=\"9\"\n\t\t\t\t\t\t\theight=\"7\"\n\t\t\t\t\t\t\trx=\"1.5\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t\t<line\n\t\t\t\t\t\t\tx1=\"11\"\n\t\t\t\t\t\t\ty1=\"8.5\"\n\t\t\t\t\t\t\tx2=\"13\"\n\t\t\t\t\t\t\ty2=\"15.5\"\n\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\tstroke-width=\"1.5\"\n\t\t\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t</svg>\n\t\t\t\t}\n\t\t\t}\n\t\t\t<span class=\"pptx-ng-ole-name\" [ngStyle]=\"{ color: typeColor() }\">{{ displayName() }}</span>\n\t\t\t@if (fileName()) {\n\t\t\t\t<span class=\"pptx-ng-ole-sublabel\">{{ typeLabel() }}</span>\n\t\t\t}\n\t\t</div>\n\t}\n\t@if (actions().canDownload) {\n\t\t<!--\n\t\t\tDownload / Open actions for the recovered embedded payload.\n\t\t\tPointer events are isolated so clicking an action never starts a\n\t\t\tselection/drag of the underlying element; the controls are\n\t\t\tkeyboard-focusable and only paint on hover / focus-within.\n\t\t-->\n\t\t<div\n\t\t\tclass=\"pptx-ng-ole-actions\"\n\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t(mousedown)=\"$event.stopPropagation()\"\n\t\t>\n\t\t\t<a\n\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t[href]=\"actions().downloadHref\"\n\t\t\t\t[attr.download]=\"actions().downloadFileName\"\n\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t'pptx.ole.downloadFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\"\n\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t>\n\t\t\t\t{{ 'pptx.ole.download' | translate }}\n\t\t\t</a>\n\t\t\t@if (actions().canOpen) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t'pptx.ole.openFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\t\"\n\t\t\t\t\t(click)=\"$event.stopPropagation(); openEmbedded()\"\n\t\t\t\t>\n\t\t\t\t\t{{ 'pptx.ole.open' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</div>\n\t}\n</div>\n", styles: [".pptx-ng-ole{position:relative;box-sizing:border-box;width:100%;height:100%}.pptx-ng-ole-preview{position:relative;width:100%;height:100%}.pptx-ng-ole-img{width:100%;height:100%;object-fit:contain;pointer-events:none;-webkit-user-select:none;user-select:none;display:block}.pptx-ng-ole-badge{position:absolute;bottom:4px;right:4px;z-index:10}.pptx-ng-ole-placeholder{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;box-sizing:border-box}.pptx-ng-ole-name{margin-top:8px;font-size:12px;font-weight:500;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-sublabel{margin-top:2px;font-size:10px;color:#00000073;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-actions{position:absolute;bottom:4px;left:4px;display:flex;gap:4px;z-index:11;opacity:0;transition:opacity .12s ease-in-out}.pptx-ng-ole:hover .pptx-ng-ole-actions,.pptx-ng-ole-actions:focus-within{opacity:1}.pptx-ng-ole-action{font-size:11px;line-height:1;padding:4px 8px;border-radius:4px;background-color:#000000b8;color:#fff;text-decoration:none;cursor:pointer;white-space:nowrap;pointer-events:auto}.pptx-ng-ole-action:hover{background-color:#000000d9}.pptx-ng-ole-action:focus-visible{outline:2px solid #fff;outline-offset:1px}\n"] }]
99433
+ args: [{ selector: 'pptx-ole-renderer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgStyle, TranslatePipe], template: "<div class=\"pptx-ng-ole\" role=\"img\" [attr.aria-label]=\"ariaLabel()\" [attr.title]=\"infoTitle()\">\n\t@if (previewSrc()) {\n\t\t<!-- Preview image with type-badge overlay -->\n\t\t<div class=\"pptx-ng-ole-preview\">\n\t\t\t<img\n\t\t\t\t[src]=\"previewSrc()\"\n\t\t\t\t[attr.alt]=\"ariaLabel()\"\n\t\t\t\tclass=\"pptx-ng-ole-img\"\n\t\t\t\tdraggable=\"false\"\n\t\t\t/>\n\t\t\t<svg class=\"pptx-ng-ole-badge\" width=\"24\" height=\"24\" viewBox=\"0 0 24 24\">\n\t\t\t\t<rect x=\"2\" y=\"2\" width=\"20\" height=\"20\" rx=\"3\" [attr.fill]=\"typeColor()\" />\n\t\t\t\t<text\n\t\t\t\t\tx=\"12\"\n\t\t\t\t\ty=\"16\"\n\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\tfill=\"white\"\n\t\t\t\t\t[attr.font-size]=\"badgeLabel().length > 4 ? 6 : 10\"\n\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t>\n\t\t\t\t\t{{ badgeLabel() }}\n\t\t\t\t</text>\n\t\t\t</svg>\n\t\t</div>\n\t} @else {\n\t\t<!-- Type-specific placeholder box -->\n\t\t<div class=\"pptx-ng-ole-placeholder\" [ngStyle]=\"placeholderStyle()\">\n\t\t\t<svg width=\"36\" height=\"36\" viewBox=\"0 0 24 24\" fill=\"none\">\n\t\t\t\t@for (shape of iconShapes(); track $index) {\n\t\t\t\t\t@switch (shape.tag) {\n\t\t\t\t\t\t@case ('rect') {\n\t\t\t\t\t\t\t<rect\n\t\t\t\t\t\t\t\t[attr.x]=\"shape.attrs['x']\"\n\t\t\t\t\t\t\t\t[attr.y]=\"shape.attrs['y']\"\n\t\t\t\t\t\t\t\t[attr.width]=\"shape.attrs['width']\"\n\t\t\t\t\t\t\t\t[attr.height]=\"shape.attrs['height']\"\n\t\t\t\t\t\t\t\t[attr.rx]=\"shape.attrs['rx']\"\n\t\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\t\t[attr.stroke-width]=\"shape.attrs['stroke-width']\"\n\t\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@case ('line') {\n\t\t\t\t\t\t\t<line\n\t\t\t\t\t\t\t\t[attr.x1]=\"shape.attrs['x1']\"\n\t\t\t\t\t\t\t\t[attr.y1]=\"shape.attrs['y1']\"\n\t\t\t\t\t\t\t\t[attr.x2]=\"shape.attrs['x2']\"\n\t\t\t\t\t\t\t\t[attr.y2]=\"shape.attrs['y2']\"\n\t\t\t\t\t\t\t\t[attr.stroke]=\"typeColor()\"\n\t\t\t\t\t\t\t\t[attr.stroke-width]=\"shape.attrs['stroke-width']\"\n\t\t\t\t\t\t\t\t[attr.stroke-linecap]=\"shape.attrs['stroke-linecap']\"\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t}\n\t\t\t\t\t\t@case ('text') {\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t[attr.x]=\"shape.attrs['x']\"\n\t\t\t\t\t\t\t\t[attr.y]=\"shape.attrs['y']\"\n\t\t\t\t\t\t\t\ttext-anchor=\"middle\"\n\t\t\t\t\t\t\t\t[attr.fill]=\"typeColor()\"\n\t\t\t\t\t\t\t\t[attr.font-size]=\"shape.attrs['font-size']\"\n\t\t\t\t\t\t\t\tfont-weight=\"bold\"\n\t\t\t\t\t\t\t\t[attr.font-style]=\"shape.attrs['font-style']\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{{ shape.text }}\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t</svg>\n\t\t\t<span class=\"pptx-ng-ole-name\" [ngStyle]=\"{ color: typeColor() }\">{{ displayName() }}</span>\n\t\t\t@if (fileName()) {\n\t\t\t\t<span class=\"pptx-ng-ole-sublabel\">{{ typeLabel() }}</span>\n\t\t\t}\n\t\t</div>\n\t}\n\t@if (actions().canDownload) {\n\t\t<!--\n\t\t\tDownload / Open actions for the recovered embedded payload.\n\t\t\tPointer events are isolated so clicking an action never starts a\n\t\t\tselection/drag of the underlying element; the controls are\n\t\t\tkeyboard-focusable and only paint on hover / focus-within.\n\t\t-->\n\t\t<div\n\t\t\tclass=\"pptx-ng-ole-actions\"\n\t\t\t(pointerdown)=\"$event.stopPropagation()\"\n\t\t\t(mousedown)=\"$event.stopPropagation()\"\n\t\t>\n\t\t\t<a\n\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t[href]=\"actions().downloadHref\"\n\t\t\t\t[attr.download]=\"actions().downloadFileName\"\n\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t'pptx.ole.downloadFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\"\n\t\t\t\t(click)=\"$event.stopPropagation()\"\n\t\t\t>\n\t\t\t\t{{ 'pptx.ole.download' | translate }}\n\t\t\t</a>\n\t\t\t@if (actions().canOpen) {\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tclass=\"pptx-ng-ole-action\"\n\t\t\t\t\t[attr.aria-label]=\"\n\t\t\t\t\t\t'pptx.ole.openFileAria' | translate: { file: actions().downloadFileName }\n\t\t\t\t\t\"\n\t\t\t\t\t(click)=\"$event.stopPropagation(); openEmbedded()\"\n\t\t\t\t>\n\t\t\t\t\t{{ 'pptx.ole.open' | translate }}\n\t\t\t\t</button>\n\t\t\t}\n\t\t</div>\n\t}\n</div>\n", styles: [".pptx-ng-ole{position:relative;box-sizing:border-box;width:100%;height:100%}.pptx-ng-ole-preview{position:relative;width:100%;height:100%}.pptx-ng-ole-img{width:100%;height:100%;object-fit:contain;pointer-events:none;-webkit-user-select:none;user-select:none;display:block}.pptx-ng-ole-badge{position:absolute;bottom:4px;right:4px;z-index:10}.pptx-ng-ole-placeholder{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;box-sizing:border-box}.pptx-ng-ole-name{margin-top:8px;font-size:12px;font-weight:500;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-sublabel{margin-top:2px;font-size:10px;color:#00000073;max-width:90%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pptx-ng-ole-actions{position:absolute;bottom:4px;left:4px;display:flex;gap:4px;z-index:11;opacity:0;transition:opacity .12s ease-in-out}.pptx-ng-ole:hover .pptx-ng-ole-actions,.pptx-ng-ole-actions:focus-within{opacity:1}.pptx-ng-ole-action{font-size:11px;line-height:1;padding:4px 8px;border-radius:4px;background-color:#000000b8;color:#fff;text-decoration:none;cursor:pointer;white-space:nowrap;pointer-events:auto}.pptx-ng-ole-action:hover{background-color:#000000d9}.pptx-ng-ole-action:focus-visible{outline:2px solid #fff;outline-offset:1px}\n"] }]
97726
99434
  }], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }] } });
97727
99435
 
97728
99436
  /**
@@ -99538,6 +101246,29 @@ class ElementRendererComponent {
99538
101246
  ...(ngDevMode ? [{ debugName: "paragraphs" }] : /* istanbul ignore next */ []));
99539
101247
  this.hasText = computed(() => this.paragraphs().some((p) => p.runs.length > 0 || p.bulletMarker !== undefined || p.bulletPicture !== undefined), /* @ts-ignore */
99540
101248
  ...(ngDevMode ? [{ debugName: "hasText" }] : /* istanbul ignore next */ []));
101249
+ /**
101250
+ * An empty inherited placeholder's greyed-out hint ("Click to add title"),
101251
+ * or null when it should not be shown. `editable` is only ever set true on
101252
+ * the live editing canvas (Present Mode leaves it at its `false` default,
101253
+ * and the thumbnail rail passes it explicitly false), matching shared's
101254
+ * `'edit'`-only surface: PowerPoint never prints, presents or thumbnails
101255
+ * this authoring hint.
101256
+ */
101257
+ this.placeholderPrompt = computed(() => {
101258
+ const descriptor = placeholderPromptDescriptor(this.element(), this.editable() && !this.presenting() ? 'edit' : 'present');
101259
+ if (!descriptor) {
101260
+ return null;
101261
+ }
101262
+ return {
101263
+ text: descriptor.text,
101264
+ style: {
101265
+ opacity: descriptor.style['opacity'] ?? '0.5',
101266
+ color: descriptor.style['color'] ?? '#888888',
101267
+ 'pointer-events': descriptor.style['pointerEvents'] ?? 'none',
101268
+ },
101269
+ };
101270
+ }, /* @ts-ignore */
101271
+ ...(ngDevMode ? [{ debugName: "placeholderPrompt" }] : /* istanbul ignore next */ []));
99541
101272
  this.placeholderLabel = computed(() => {
99542
101273
  const map = {
99543
101274
  group: 'pptx.elementType.group',
@@ -99569,7 +101300,7 @@ class ElementRendererComponent {
99569
101300
  return { ...(span.style ?? {}), ...textBuildSpanStyle(span) };
99570
101301
  }
99571
101302
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ElementRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
99572
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ElementRendererComponent, isStandalone: true, selector: "pptx-element-renderer", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, obstacles: { classPropertyName: "obstacles", publicName: "obstacles", isSignal: true, isRequired: false, transformFunction: null }, canvasWidth: { classPropertyName: "canvasWidth", publicName: "canvasWidth", isSignal: true, isRequired: false, transformFunction: null }, canvasHeight: { classPropertyName: "canvasHeight", publicName: "canvasHeight", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, marked: { classPropertyName: "marked", publicName: "marked", isSignal: true, isRequired: false, transformFunction: null }, exposeElementId: { classPropertyName: "exposeElementId", publicName: "exposeElementId", isSignal: true, isRequired: false, transformFunction: null }, presenting: { classPropertyName: "presenting", publicName: "presenting", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, fieldContext: { classPropertyName: "fieldContext", publicName: "fieldContext", isSignal: true, isRequired: false, transformFunction: null }, slideElements: { classPropertyName: "slideElements", publicName: "slideElements", isSignal: true, isRequired: false, transformFunction: null }, editTemplateMode: { classPropertyName: "editTemplateMode", publicName: "editTemplateMode", isSignal: true, isRequired: false, transformFunction: null }, parentGroupFill: { classPropertyName: "parentGroupFill", publicName: "parentGroupFill", isSignal: true, isRequired: false, transformFunction: null }, editingElementId: { classPropertyName: "editingElementId", publicName: "editingElementId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellCommit: "cellCommit", tableChange: "tableChange" }, host: { classAttribute: "contents" }, ngImport: i0, template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'contentPart') {\n\t\t<!--\n\t\t\tReal PowerPoint ink. Same positioning contract as pptx-ink-renderer\n\t\t\tabove: the renderer's own root is absolutely positioned, so it takes\n\t\t\tthe neutral element marker as an input rather than being wrapped.\n\t\t-->\n\t\t<pptx-content-part-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t\t[editingElementId]=\"editingElementId()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<!-- Per-sub-path fill overlay: a multi-sub-path preset (`smileyFace`'s\n\t\t\t open eyes, `actionButtonBlank`'s darkened bevel well) or custom\n\t\t\t geometry whose sub-paths cannot share one CSS background-color. -->\n\t\t\t@if (subpathFill(); as sf) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-subpath-fill\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"subpathFillViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; width: 100%; height: 100%\"\n\t\t\t\t>\n\t\t\t\t\t@for (paint of sf.paints; track $index) {\n\t\t\t\t\t\t<path [attr.d]=\"paint.d\" [attr.fill]=\"paint.fill\" stroke=\"none\" />\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Mirrored reflection sibling (`a:reflection`): cross-browser, unlike\n\t\t\t the `-webkit-box-reflect` this replaced (Firefox never implemented\n\t\t\t that property, so reflections were invisible there entirely). -->\n\t\t\t@if (reflection(); as refl) {\n\t\t\t\t<div class=\"pptx-ng-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl.wrapperStyle\">\n\t\t\t\t\t@if (refl.imgSrc) {\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t[src]=\"refl.imgSrc\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tdraggable=\"false\"\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[ngStyle]=\"refl.imgFitStyle\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t} @else if (refl.fill) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[style.background-color]=\"refl.fill.backgroundColor\"\n\t\t\t\t\t\t\t[style.background-image]=\"refl.fill.backgroundImage\"\n\t\t\t\t\t\t\t[style.background-size]=\"refl.fill.backgroundSize\"\n\t\t\t\t\t\t\t[style.background-position]=\"refl.fill.backgroundPosition\"\n\t\t\t\t\t\t\t[style.background-repeat]=\"refl.fill.backgroundRepeat\"\n\t\t\t\t\t\t></div>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- While this element is open in the inline text editor, its live text\n\t\t\t is drawn by that overlay instead (see `isBeingInlineEdited`);\n\t\t\t rendering it here too produced a duplicate, offset \"text shadow\"\n\t\t\t (issue #182). -->\n\t\t\t@if (!isBeingInlineEdited()) {\n\t\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t\t<svg\n\t\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t}\n\t\t\t\t\t</svg>\n\t\t\t\t} @else if (hasText()) {\n\t\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t\t[ngStyle]=\"para.paragraphStyle ?? null\"\n\t\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t} @else if (run.reflection; as refl) {\n\t\t\t\t\t\t\t\t\t\t\t<!-- `a:reflection`: wrapped HERE, around the whole base\n\t\t\t\t\t\t\t\t\t\t run (`runBase`), rather than inside its href/ruby/plain\n\t\t\t\t\t\t\t\t\t\t branches - a `<ruby>` run's own `display: ruby` (which\n\t\t\t\t\t\t\t\t\t\t positions the annotation above its base text) would\n\t\t\t\t\t\t\t\t\t\t break if forced to `display: inline-block` to host the\n\t\t\t\t\t\t\t\t\t\t mirror. Cross-browser, unlike the `-webkit-box-reflect`\n\t\t\t\t\t\t\t\t\t\t this replaced (Firefox never implemented it). -->\n\t\t\t\t\t\t\t\t\t\t\t<span style=\"position: relative; display: inline-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"pptx-ng-text-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t><span [ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t><ng-container\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*ngTemplateOutlet=\"runContent; context: { run: run }\" /></span\n\t\t\t\t\t\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!--\n\tOne run's base element (hyperlink / ruby / plain span), reused via\n\t`ngTemplateOutlet` both directly and inside the `a:reflection` wrapper above,\n\tso the reflection case does not duplicate this three-way branch.\n-->\n<ng-template #runBase let-run=\"run\">\n\t@if (run.href) {\n\t\t<a\n\t\t\tclass=\"pptx-ng-link\"\n\t\t\t[href]=\"run.href\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t[ngStyle]=\"run.style\"\n\t\t\t(click)=\"onHyperlinkClick($event, run.href)\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></a>\n\t} @else if (run.rubyText) {\n\t\t<!-- `a:ruby`: the phonetic guide sits above its base\n\t\t text; the <rp> parentheses are the fallback for a\n\t\t browser without ruby support. -->\n\t\t<ruby [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\" /><rp>(</rp\n\t\t\t><rt [ngStyle]=\"run.rubyStyle\">{{ run.rubyText }}</rt\n\t\t\t><rp>)</rp></ruby\n\t\t>\n\t} @else {\n\t\t<span [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></span>\n\t}\n</ng-template>\n\n<!--\n\tA run's text content, honouring shared's per-script font split\n\t(`run.scriptRuns`) and measured tab-stop layout (`run.tabLines`) when\n\teither is present. Both descriptors come from `pptx-viewer-shared`'s\n\t`buildParagraphs` (the per-script split was React-only before this\n\ttemplate existed: CJK, Arabic, Hebrew and Thai text rendered in the wrong\n\ttypeface here; the tab layout was likewise React-only, so a TOC-style row\n\tlost its leader dots and right-aligned page number). Reused via\n\t`ngTemplateOutlet` for the run's span / anchor / ruby base text, so all\n\tthree carry the same content logic.\n-->\n<ng-template #runContent let-run=\"run\">\n\t@if (run.tabLines) {\n\t\t@for (line of run.tabLines; track $index) {\n\t\t\t<span style=\"display: inline-block; white-space: nowrap\">\n\t\t\t\t@for (piece of line.pieces; track $index) {\n\t\t\t\t\t@if (piece.leaderStyle) {\n\t\t\t\t\t\t<span aria-hidden=\"true\" [ngStyle]=\"piece.leaderStyle\">{{ piece.leaderText }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t\t}\n\t\t\t</span>\n\t\t\t@if (!$last) {\n\t\t\t\t<br />\n\t\t\t}\n\t\t}\n\t} @else if (run.scriptRuns) {\n\t\t<!--\n\t\t\tA bare interpolation as the sole content of an `@if`/`@else` block\n\t\t\tleaks a real leading + trailing whitespace text node: Angular does\n\t\t\tnot collapse that whitespace the way it collapses whitespace between\n\t\t\telement TAGS. Worse, oxfmt's Angular-template printer always breaks a\n\t\t\tblock's content onto its own indented line, even when the block was\n\t\t\twritten as a single line with the braces touching, so writing the\n\t\t\t`{{ x }}` compact ourselves does not survive the next `bun run fmt` /\n\t\t\tpre-commit `lint-staged` pass: it silently re-introduces the leak\n\t\t\t(this happened twice, see `20d4d177`, `18eebb6f`). `<ng-container>`\n\t\t\tdoes not render any DOM node of its own, so wrapping the\n\t\t\tinterpolation in one keeps the no-wrapper-element behaviour of\n\t\t\tReact's `<>{piece.text}</>` fragment while making the interpolation\n\t\t\ttag-adjacent, which both Angular AND oxfmt already treat as safely\n\t\t\tcollapsible (see the many `<span>{{ x }}</span>` one-liners in this\n\t\t\tfile). That was invisible while a paragraph was one run per script\n\t\t\t(two stray spaces at the run's own edges, trimmed visually by the\n\t\t\tbrowser but still present in `textContent`), but shared's per-word /\n\t\t\tper-gap metric split (`text-run-spacing.ts`, issue #149) re-emits\n\t\t\tevery WORD and inter-word GAP as its own sibling run, so the same\n\t\t\tone-space leak lands between every word: \"will choose\" rendered as\n\t\t\t\"will choose\" (five spaces: the word's own trailing leak, the\n\t\t\tgap run's real space plus its OWN two leaks, the next word's leading\n\t\t\tleak). The same leak also showed up one paragraph at a time:\n\t\t\t\"Project\" / \"Atlas\" as two separate paragraphs read back as\n\t\t\t\"ProjectAtlas\" instead of React's \"Project Atlas\", because the\n\t\t\tplain-run `@else` below had the same bug.\n\t\t-->\n\t\t@for (piece of run.scriptRuns; track $index) {\n\t\t\t@if (piece.style) {\n\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t} @else {\n\t\t\t\t<ng-container>{{ piece.text }}</ng-container>\n\t\t\t}\n\t\t}\n\t} @else {\n\t\t<ng-container>{{ run.text }}</ng-container>\n\t}\n</ng-template>\n", dependencies: [{ kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill", "editingElementId"], outputs: ["cellCommit", "tableChange"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ConnectorRendererComponent, selector: "pptx-connector-renderer", inputs: ["element", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "animationState"] }, { kind: "component", type: TableRendererComponent, selector: "pptx-table-renderer", inputs: ["element", "editable"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: ChartElementViewComponent, selector: "pptx-chart-element-view", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArtRendererComponent, selector: "pptx-smart-art-renderer", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArt3DRendererComponent, selector: "pptx-smart-art-3d-renderer", inputs: ["element", "zIndex", "canEdit", "markElement"] }, { kind: "component", type: InkRendererComponent, selector: "pptx-ink-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "replay", "markElement", "exposeElementId"] }, { kind: "component", type: ContentPartRendererComponent, selector: "pptx-content-part-renderer", inputs: ["element", "zIndex", "replay", "markElement", "exposeElementId"] }, { kind: "component", type: MediaRendererComponent, selector: "pptx-media-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked", "exposeElementId", "presenting", "placeholderLabel"] }, { kind: "component", type: OleRendererComponent, selector: "pptx-ole-renderer", inputs: ["element"] }, { kind: "component", type: Model3DRendererComponent, selector: "pptx-model3d-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "interactive", "markElement", "exposeElementId"] }, { kind: "component", type: ZoomRendererComponent, selector: "pptx-zoom-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "markElement"] }, { kind: "component", type: EquationRendererComponent, selector: "pptx-equation-renderer", inputs: ["equationXml", "equationNumber"] }, { kind: "component", type: ImageRendererComponent, selector: "pptx-image-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked", "exposeElementId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
101303
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: ElementRendererComponent, isStandalone: true, selector: "pptx-element-renderer", inputs: { element: { classPropertyName: "element", publicName: "element", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, zIndex: { classPropertyName: "zIndex", publicName: "zIndex", isSignal: true, isRequired: false, transformFunction: null }, obstacles: { classPropertyName: "obstacles", publicName: "obstacles", isSignal: true, isRequired: false, transformFunction: null }, canvasWidth: { classPropertyName: "canvasWidth", publicName: "canvasWidth", isSignal: true, isRequired: false, transformFunction: null }, canvasHeight: { classPropertyName: "canvasHeight", publicName: "canvasHeight", isSignal: true, isRequired: false, transformFunction: null }, interactive: { classPropertyName: "interactive", publicName: "interactive", isSignal: true, isRequired: false, transformFunction: null }, marked: { classPropertyName: "marked", publicName: "marked", isSignal: true, isRequired: false, transformFunction: null }, exposeElementId: { classPropertyName: "exposeElementId", publicName: "exposeElementId", isSignal: true, isRequired: false, transformFunction: null }, presenting: { classPropertyName: "presenting", publicName: "presenting", isSignal: true, isRequired: false, transformFunction: null }, editable: { classPropertyName: "editable", publicName: "editable", isSignal: true, isRequired: false, transformFunction: null }, fieldContext: { classPropertyName: "fieldContext", publicName: "fieldContext", isSignal: true, isRequired: false, transformFunction: null }, slideElements: { classPropertyName: "slideElements", publicName: "slideElements", isSignal: true, isRequired: false, transformFunction: null }, editTemplateMode: { classPropertyName: "editTemplateMode", publicName: "editTemplateMode", isSignal: true, isRequired: false, transformFunction: null }, parentGroupFill: { classPropertyName: "parentGroupFill", publicName: "parentGroupFill", isSignal: true, isRequired: false, transformFunction: null }, editingElementId: { classPropertyName: "editingElementId", publicName: "editingElementId", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { cellCommit: "cellCommit", tableChange: "tableChange" }, host: { classAttribute: "contents" }, ngImport: i0, template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'contentPart') {\n\t\t<!--\n\t\t\tReal PowerPoint ink. Same positioning contract as pptx-ink-renderer\n\t\t\tabove: the renderer's own root is absolutely positioned, so it takes\n\t\t\tthe neutral element marker as an input rather than being wrapped.\n\t\t-->\n\t\t<pptx-content-part-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t\t[editingElementId]=\"editingElementId()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<!-- Per-sub-path fill overlay: a multi-sub-path preset (`smileyFace`'s\n\t\t\t open eyes, `actionButtonBlank`'s darkened bevel well) or custom\n\t\t\t geometry whose sub-paths cannot share one CSS background-color. -->\n\t\t\t@if (subpathFill(); as sf) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-subpath-fill\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"subpathFillViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; width: 100%; height: 100%\"\n\t\t\t\t>\n\t\t\t\t\t@for (paint of sf.paints; track $index) {\n\t\t\t\t\t\t<path [attr.d]=\"paint.d\" [attr.fill]=\"paint.fill\" stroke=\"none\" />\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Mirrored reflection sibling (`a:reflection`): cross-browser, unlike\n\t\t\t the `-webkit-box-reflect` this replaced (Firefox never implemented\n\t\t\t that property, so reflections were invisible there entirely). -->\n\t\t\t@if (reflection(); as refl) {\n\t\t\t\t<div class=\"pptx-ng-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl.wrapperStyle\">\n\t\t\t\t\t@if (refl.imgSrc) {\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t[src]=\"refl.imgSrc\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tdraggable=\"false\"\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[ngStyle]=\"refl.imgFitStyle\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t} @else if (refl.fill) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[style.background-color]=\"refl.fill.backgroundColor\"\n\t\t\t\t\t\t\t[style.background-image]=\"refl.fill.backgroundImage\"\n\t\t\t\t\t\t\t[style.background-size]=\"refl.fill.backgroundSize\"\n\t\t\t\t\t\t\t[style.background-position]=\"refl.fill.backgroundPosition\"\n\t\t\t\t\t\t\t[style.background-repeat]=\"refl.fill.backgroundRepeat\"\n\t\t\t\t\t\t></div>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- While this element is open in the inline text editor, its live text\n\t\t\t is drawn by that overlay instead (see `isBeingInlineEdited`);\n\t\t\t rendering it here too produced a duplicate, offset \"text shadow\"\n\t\t\t (issue #182). -->\n\t\t\t@if (!isBeingInlineEdited()) {\n\t\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t\t<svg\n\t\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t}\n\t\t\t\t\t</svg>\n\t\t\t\t} @else if (placeholderPrompt(); as prompt) {\n\t\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"prompt.style\">{{ prompt.text }}</div>\n\t\t\t\t} @else if (hasText()) {\n\t\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t\t[ngStyle]=\"para.paragraphStyle ?? null\"\n\t\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t} @else if (run.reflection; as refl) {\n\t\t\t\t\t\t\t\t\t\t\t<!-- `a:reflection`: wrapped HERE, around the whole base\n\t\t\t\t\t\t\t\t\t\t run (`runBase`), rather than inside its href/ruby/plain\n\t\t\t\t\t\t\t\t\t\t branches - a `<ruby>` run's own `display: ruby` (which\n\t\t\t\t\t\t\t\t\t\t positions the annotation above its base text) would\n\t\t\t\t\t\t\t\t\t\t break if forced to `display: inline-block` to host the\n\t\t\t\t\t\t\t\t\t\t mirror. Cross-browser, unlike the `-webkit-box-reflect`\n\t\t\t\t\t\t\t\t\t\t this replaced (Firefox never implemented it). -->\n\t\t\t\t\t\t\t\t\t\t\t<span style=\"position: relative; display: inline-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"pptx-ng-text-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t><span [ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t><ng-container\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*ngTemplateOutlet=\"runContent; context: { run: run }\" /></span\n\t\t\t\t\t\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!--\n\tOne run's base element (hyperlink / ruby / plain span), reused via\n\t`ngTemplateOutlet` both directly and inside the `a:reflection` wrapper above,\n\tso the reflection case does not duplicate this three-way branch.\n-->\n<ng-template #runBase let-run=\"run\">\n\t@if (run.href) {\n\t\t<a\n\t\t\tclass=\"pptx-ng-link\"\n\t\t\t[href]=\"run.href\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t[ngStyle]=\"run.style\"\n\t\t\t(click)=\"onHyperlinkClick($event, run.href)\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></a>\n\t} @else if (run.rubyText) {\n\t\t<!-- `a:ruby`: the phonetic guide sits above its base\n\t\t text; the <rp> parentheses are the fallback for a\n\t\t browser without ruby support. -->\n\t\t<ruby [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\" /><rp>(</rp\n\t\t\t><rt [ngStyle]=\"run.rubyStyle\">{{ run.rubyText }}</rt\n\t\t\t><rp>)</rp></ruby\n\t\t>\n\t} @else {\n\t\t<span [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></span>\n\t}\n</ng-template>\n\n<!--\n\tA run's text content, honouring shared's per-script font split\n\t(`run.scriptRuns`) and measured tab-stop layout (`run.tabLines`) when\n\teither is present. Both descriptors come from `pptx-viewer-shared`'s\n\t`buildParagraphs` (the per-script split was React-only before this\n\ttemplate existed: CJK, Arabic, Hebrew and Thai text rendered in the wrong\n\ttypeface here; the tab layout was likewise React-only, so a TOC-style row\n\tlost its leader dots and right-aligned page number). Reused via\n\t`ngTemplateOutlet` for the run's span / anchor / ruby base text, so all\n\tthree carry the same content logic.\n-->\n<ng-template #runContent let-run=\"run\">\n\t@if (run.tabLines) {\n\t\t@for (line of run.tabLines; track $index) {\n\t\t\t<span style=\"display: inline-block; white-space: nowrap\">\n\t\t\t\t@for (piece of line.pieces; track $index) {\n\t\t\t\t\t@if (piece.leaderStyle) {\n\t\t\t\t\t\t<span aria-hidden=\"true\" [ngStyle]=\"piece.leaderStyle\">{{ piece.leaderText }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t\t}\n\t\t\t</span>\n\t\t\t@if (!$last) {\n\t\t\t\t<br />\n\t\t\t}\n\t\t}\n\t} @else if (run.scriptRuns) {\n\t\t<!--\n\t\t\tA bare interpolation as the sole content of an `@if`/`@else` block\n\t\t\tleaks a real leading + trailing whitespace text node: Angular does\n\t\t\tnot collapse that whitespace the way it collapses whitespace between\n\t\t\telement TAGS. Worse, oxfmt's Angular-template printer always breaks a\n\t\t\tblock's content onto its own indented line, even when the block was\n\t\t\twritten as a single line with the braces touching, so writing the\n\t\t\t`{{ x }}` compact ourselves does not survive the next `bun run fmt` /\n\t\t\tpre-commit `lint-staged` pass: it silently re-introduces the leak\n\t\t\t(this happened twice, see `20d4d177`, `18eebb6f`). `<ng-container>`\n\t\t\tdoes not render any DOM node of its own, so wrapping the\n\t\t\tinterpolation in one keeps the no-wrapper-element behaviour of\n\t\t\tReact's `<>{piece.text}</>` fragment while making the interpolation\n\t\t\ttag-adjacent, which both Angular AND oxfmt already treat as safely\n\t\t\tcollapsible (see the many `<span>{{ x }}</span>` one-liners in this\n\t\t\tfile). That was invisible while a paragraph was one run per script\n\t\t\t(two stray spaces at the run's own edges, trimmed visually by the\n\t\t\tbrowser but still present in `textContent`), but shared's per-word /\n\t\t\tper-gap metric split (`text-run-spacing.ts`, issue #149) re-emits\n\t\t\tevery WORD and inter-word GAP as its own sibling run, so the same\n\t\t\tone-space leak lands between every word: \"will choose\" rendered as\n\t\t\t\"will choose\" (five spaces: the word's own trailing leak, the\n\t\t\tgap run's real space plus its OWN two leaks, the next word's leading\n\t\t\tleak). The same leak also showed up one paragraph at a time:\n\t\t\t\"Project\" / \"Atlas\" as two separate paragraphs read back as\n\t\t\t\"ProjectAtlas\" instead of React's \"Project Atlas\", because the\n\t\t\tplain-run `@else` below had the same bug.\n\t\t-->\n\t\t@for (piece of run.scriptRuns; track $index) {\n\t\t\t@if (piece.style) {\n\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t} @else {\n\t\t\t\t<ng-container>{{ piece.text }}</ng-container>\n\t\t\t}\n\t\t}\n\t} @else {\n\t\t<ng-container>{{ run.text }}</ng-container>\n\t}\n</ng-template>\n", dependencies: [{ kind: "component", type: ElementRendererComponent, selector: "pptx-element-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "presenting", "editable", "fieldContext", "slideElements", "editTemplateMode", "parentGroupFill", "editingElementId"], outputs: ["cellCommit", "tableChange"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ConnectorRendererComponent, selector: "pptx-connector-renderer", inputs: ["element", "zIndex", "obstacles", "canvasWidth", "canvasHeight", "interactive", "marked", "exposeElementId", "animationState"] }, { kind: "component", type: TableRendererComponent, selector: "pptx-table-renderer", inputs: ["element", "editable"], outputs: ["cellCommit", "tableChange"] }, { kind: "component", type: ChartElementViewComponent, selector: "pptx-chart-element-view", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArtRendererComponent, selector: "pptx-smart-art-renderer", inputs: ["element", "editable", "animationState"] }, { kind: "component", type: SmartArt3DRendererComponent, selector: "pptx-smart-art-3d-renderer", inputs: ["element", "zIndex", "canEdit", "markElement"] }, { kind: "component", type: InkRendererComponent, selector: "pptx-ink-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "replay", "markElement", "exposeElementId"] }, { kind: "component", type: ContentPartRendererComponent, selector: "pptx-content-part-renderer", inputs: ["element", "zIndex", "replay", "markElement", "exposeElementId"] }, { kind: "component", type: MediaRendererComponent, selector: "pptx-media-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked", "exposeElementId", "presenting", "placeholderLabel"] }, { kind: "component", type: OleRendererComponent, selector: "pptx-ole-renderer", inputs: ["element"] }, { kind: "component", type: Model3DRendererComponent, selector: "pptx-model3d-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "interactive", "markElement", "exposeElementId"] }, { kind: "component", type: ZoomRendererComponent, selector: "pptx-zoom-renderer", inputs: ["element", "zIndex", "mediaDataUrls", "markElement"] }, { kind: "component", type: EquationRendererComponent, selector: "pptx-equation-renderer", inputs: ["equationXml", "equationNumber"] }, { kind: "component", type: ImageRendererComponent, selector: "pptx-image-renderer", inputs: ["element", "mediaDataUrls", "zIndex", "interactive", "marked", "exposeElementId"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
99573
101304
  }
99574
101305
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: ElementRendererComponent, decorators: [{
99575
101306
  type: Component,
@@ -99589,7 +101320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
99589
101320
  ZoomRendererComponent,
99590
101321
  EquationRendererComponent,
99591
101322
  ImageRendererComponent,
99592
- ], template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'contentPart') {\n\t\t<!--\n\t\t\tReal PowerPoint ink. Same positioning contract as pptx-ink-renderer\n\t\t\tabove: the renderer's own root is absolutely positioned, so it takes\n\t\t\tthe neutral element marker as an input rather than being wrapped.\n\t\t-->\n\t\t<pptx-content-part-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t\t[editingElementId]=\"editingElementId()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<!-- Per-sub-path fill overlay: a multi-sub-path preset (`smileyFace`'s\n\t\t\t open eyes, `actionButtonBlank`'s darkened bevel well) or custom\n\t\t\t geometry whose sub-paths cannot share one CSS background-color. -->\n\t\t\t@if (subpathFill(); as sf) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-subpath-fill\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"subpathFillViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; width: 100%; height: 100%\"\n\t\t\t\t>\n\t\t\t\t\t@for (paint of sf.paints; track $index) {\n\t\t\t\t\t\t<path [attr.d]=\"paint.d\" [attr.fill]=\"paint.fill\" stroke=\"none\" />\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Mirrored reflection sibling (`a:reflection`): cross-browser, unlike\n\t\t\t the `-webkit-box-reflect` this replaced (Firefox never implemented\n\t\t\t that property, so reflections were invisible there entirely). -->\n\t\t\t@if (reflection(); as refl) {\n\t\t\t\t<div class=\"pptx-ng-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl.wrapperStyle\">\n\t\t\t\t\t@if (refl.imgSrc) {\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t[src]=\"refl.imgSrc\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tdraggable=\"false\"\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[ngStyle]=\"refl.imgFitStyle\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t} @else if (refl.fill) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[style.background-color]=\"refl.fill.backgroundColor\"\n\t\t\t\t\t\t\t[style.background-image]=\"refl.fill.backgroundImage\"\n\t\t\t\t\t\t\t[style.background-size]=\"refl.fill.backgroundSize\"\n\t\t\t\t\t\t\t[style.background-position]=\"refl.fill.backgroundPosition\"\n\t\t\t\t\t\t\t[style.background-repeat]=\"refl.fill.backgroundRepeat\"\n\t\t\t\t\t\t></div>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- While this element is open in the inline text editor, its live text\n\t\t\t is drawn by that overlay instead (see `isBeingInlineEdited`);\n\t\t\t rendering it here too produced a duplicate, offset \"text shadow\"\n\t\t\t (issue #182). -->\n\t\t\t@if (!isBeingInlineEdited()) {\n\t\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t\t<svg\n\t\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t}\n\t\t\t\t\t</svg>\n\t\t\t\t} @else if (hasText()) {\n\t\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t\t[ngStyle]=\"para.paragraphStyle ?? null\"\n\t\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t} @else if (run.reflection; as refl) {\n\t\t\t\t\t\t\t\t\t\t\t<!-- `a:reflection`: wrapped HERE, around the whole base\n\t\t\t\t\t\t\t\t\t\t run (`runBase`), rather than inside its href/ruby/plain\n\t\t\t\t\t\t\t\t\t\t branches - a `<ruby>` run's own `display: ruby` (which\n\t\t\t\t\t\t\t\t\t\t positions the annotation above its base text) would\n\t\t\t\t\t\t\t\t\t\t break if forced to `display: inline-block` to host the\n\t\t\t\t\t\t\t\t\t\t mirror. Cross-browser, unlike the `-webkit-box-reflect`\n\t\t\t\t\t\t\t\t\t\t this replaced (Firefox never implemented it). -->\n\t\t\t\t\t\t\t\t\t\t\t<span style=\"position: relative; display: inline-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"pptx-ng-text-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t><span [ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t><ng-container\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*ngTemplateOutlet=\"runContent; context: { run: run }\" /></span\n\t\t\t\t\t\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!--\n\tOne run's base element (hyperlink / ruby / plain span), reused via\n\t`ngTemplateOutlet` both directly and inside the `a:reflection` wrapper above,\n\tso the reflection case does not duplicate this three-way branch.\n-->\n<ng-template #runBase let-run=\"run\">\n\t@if (run.href) {\n\t\t<a\n\t\t\tclass=\"pptx-ng-link\"\n\t\t\t[href]=\"run.href\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t[ngStyle]=\"run.style\"\n\t\t\t(click)=\"onHyperlinkClick($event, run.href)\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></a>\n\t} @else if (run.rubyText) {\n\t\t<!-- `a:ruby`: the phonetic guide sits above its base\n\t\t text; the <rp> parentheses are the fallback for a\n\t\t browser without ruby support. -->\n\t\t<ruby [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\" /><rp>(</rp\n\t\t\t><rt [ngStyle]=\"run.rubyStyle\">{{ run.rubyText }}</rt\n\t\t\t><rp>)</rp></ruby\n\t\t>\n\t} @else {\n\t\t<span [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></span>\n\t}\n</ng-template>\n\n<!--\n\tA run's text content, honouring shared's per-script font split\n\t(`run.scriptRuns`) and measured tab-stop layout (`run.tabLines`) when\n\teither is present. Both descriptors come from `pptx-viewer-shared`'s\n\t`buildParagraphs` (the per-script split was React-only before this\n\ttemplate existed: CJK, Arabic, Hebrew and Thai text rendered in the wrong\n\ttypeface here; the tab layout was likewise React-only, so a TOC-style row\n\tlost its leader dots and right-aligned page number). Reused via\n\t`ngTemplateOutlet` for the run's span / anchor / ruby base text, so all\n\tthree carry the same content logic.\n-->\n<ng-template #runContent let-run=\"run\">\n\t@if (run.tabLines) {\n\t\t@for (line of run.tabLines; track $index) {\n\t\t\t<span style=\"display: inline-block; white-space: nowrap\">\n\t\t\t\t@for (piece of line.pieces; track $index) {\n\t\t\t\t\t@if (piece.leaderStyle) {\n\t\t\t\t\t\t<span aria-hidden=\"true\" [ngStyle]=\"piece.leaderStyle\">{{ piece.leaderText }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t\t}\n\t\t\t</span>\n\t\t\t@if (!$last) {\n\t\t\t\t<br />\n\t\t\t}\n\t\t}\n\t} @else if (run.scriptRuns) {\n\t\t<!--\n\t\t\tA bare interpolation as the sole content of an `@if`/`@else` block\n\t\t\tleaks a real leading + trailing whitespace text node: Angular does\n\t\t\tnot collapse that whitespace the way it collapses whitespace between\n\t\t\telement TAGS. Worse, oxfmt's Angular-template printer always breaks a\n\t\t\tblock's content onto its own indented line, even when the block was\n\t\t\twritten as a single line with the braces touching, so writing the\n\t\t\t`{{ x }}` compact ourselves does not survive the next `bun run fmt` /\n\t\t\tpre-commit `lint-staged` pass: it silently re-introduces the leak\n\t\t\t(this happened twice, see `20d4d177`, `18eebb6f`). `<ng-container>`\n\t\t\tdoes not render any DOM node of its own, so wrapping the\n\t\t\tinterpolation in one keeps the no-wrapper-element behaviour of\n\t\t\tReact's `<>{piece.text}</>` fragment while making the interpolation\n\t\t\ttag-adjacent, which both Angular AND oxfmt already treat as safely\n\t\t\tcollapsible (see the many `<span>{{ x }}</span>` one-liners in this\n\t\t\tfile). That was invisible while a paragraph was one run per script\n\t\t\t(two stray spaces at the run's own edges, trimmed visually by the\n\t\t\tbrowser but still present in `textContent`), but shared's per-word /\n\t\t\tper-gap metric split (`text-run-spacing.ts`, issue #149) re-emits\n\t\t\tevery WORD and inter-word GAP as its own sibling run, so the same\n\t\t\tone-space leak lands between every word: \"will choose\" rendered as\n\t\t\t\"will choose\" (five spaces: the word's own trailing leak, the\n\t\t\tgap run's real space plus its OWN two leaks, the next word's leading\n\t\t\tleak). The same leak also showed up one paragraph at a time:\n\t\t\t\"Project\" / \"Atlas\" as two separate paragraphs read back as\n\t\t\t\"ProjectAtlas\" instead of React's \"Project Atlas\", because the\n\t\t\tplain-run `@else` below had the same bug.\n\t\t-->\n\t\t@for (piece of run.scriptRuns; track $index) {\n\t\t\t@if (piece.style) {\n\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t} @else {\n\t\t\t\t<ng-container>{{ piece.text }}</ng-container>\n\t\t\t}\n\t\t}\n\t} @else {\n\t\t<ng-container>{{ run.text }}</ng-container>\n\t}\n</ng-template>\n" }]
101323
+ ], template: "@switch (true) {\n\t@case (isHidden()) {\n\t\t<!--\n\t\t\tHidden via the Selection Pane: draw nothing, exactly as PowerPoint\n\t\t\tdoes. This is the FIRST case on purpose - @switch takes the first\n\t\t\tmatch, so one empty branch suppresses every element type at once\n\t\t\twithout wrapping (and re-indenting) the whole template. The host\n\t\t\tcarries \\`display: contents\\`, so an empty component collapses.\n\t\t\tRendering nothing (rather than an invisible box) is what keeps the\n\t\t\telement out of hit-testing, the tab order and the export raster; it\n\t\t\tstays listed in and selectable from the Selection Pane, which reads\n\t\t\tthe slide model rather than the DOM.\n\t\t-->\n\t}\n\t@case (element().type === 'connector') {\n\t\t<pptx-connector-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[obstacles]=\"obstacles()\"\n\t\t\t[canvasWidth]=\"canvasWidth()\"\n\t\t\t[canvasHeight]=\"canvasHeight()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[animationState]=\"animationState()\"\n\t\t/>\n\t}\n\t@case (element().type === 'ink') {\n\t\t<!--\n\t\t\tThis renderer (and zoom / model3d / 3D SmartArt below) positions its\n\t\t\town root box, so it takes the neutral element marker\n\t\t\t(data-pptx-element) as an input instead of being wrapped in a marked\n\t\t\tbox the way chart / table / OLE are: an outer positioned box would\n\t\t\toffset it twice.\n\t\t-->\n\t\t<pptx-ink-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'contentPart') {\n\t\t<!--\n\t\t\tReal PowerPoint ink. Same positioning contract as pptx-ink-renderer\n\t\t\tabove: the renderer's own root is absolutely positioned, so it takes\n\t\t\tthe neutral element marker as an input rather than being wrapped.\n\t\t-->\n\t\t<pptx-content-part-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[replay]=\"presenting()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'zoom') {\n\t\t<pptx-zoom-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'model3d') {\n\t\t<pptx-model3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt' && smartArt3D()) {\n\t\t<pptx-smart-art-3d-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[canEdit]=\"interactive() && editable()\"\n\t\t\t[markElement]=\"elementMarked()\"\n\t\t/>\n\t}\n\t@case (element().type === 'smartArt') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-smartart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-smart-art-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'ole') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-ole\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-ole-renderer [element]=\"element()\" />\n\t\t</div>\n\t}\n\t@case (element().type === 'chart') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-chart\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-chart-element-view\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t[animationState]=\"animationState()\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'table') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-table\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<pptx-table-renderer\n\t\t\t\t[element]=\"element()\"\n\t\t\t\t[editable]=\"interactive() && editable()\"\n\t\t\t\t(cellCommit)=\"cellCommit.emit({ id: element().id, commit: $event })\"\n\t\t\t\t(tableChange)=\"tableChange.emit($event)\"\n\t\t\t/>\n\t\t</div>\n\t}\n\t@case (element().type === 'group') {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-group\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t@for (child of children(); track child.id) {\n\t\t\t\t<pptx-element-renderer\n\t\t\t\t\t[element]=\"child\"\n\t\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t\t[zIndex]=\"$index\"\n\t\t\t\t\t[interactive]=\"interactive()\"\n\t\t\t\t\t[marked]=\"marked()\"\n\t\t\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t\t\t[presenting]=\"presenting()\"\n\t\t\t\t\t[fieldContext]=\"fieldContext()\"\n\t\t\t\t\t[slideElements]=\"slideElements()\"\n\t\t\t\t\t[parentGroupFill]=\"childParentGroupFill()\"\n\t\t\t\t\t[editingElementId]=\"editingElementId()\"\n\t\t\t\t/>\n\t\t\t}\n\t\t</div>\n\t}\n\t@case (isImageLike()) {\n\t\t<pptx-image-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t/>\n\t}\n\t@case (element().type === 'media') {\n\t\t<pptx-media-renderer\n\t\t\t[element]=\"element()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zIndex]=\"zIndex()\"\n\t\t\t[interactive]=\"interactive()\"\n\t\t\t[marked]=\"elementMarked()\"\n\t\t\t[exposeElementId]=\"exposeElementId()\"\n\t\t\t[presenting]=\"presenting()\"\n\t\t\t[placeholderLabel]=\"placeholderLabel()\"\n\t\t/>\n\t}\n\t@case (isShapeLike()) {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-shape\"\n\t\t\t[ngStyle]=\"shapeContainerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<!-- Per-sub-path fill overlay: a multi-sub-path preset (`smileyFace`'s\n\t\t\t open eyes, `actionButtonBlank`'s darkened bevel well) or custom\n\t\t\t geometry whose sub-paths cannot share one CSS background-color. -->\n\t\t\t@if (subpathFill(); as sf) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-subpath-fill\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"subpathFillViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; width: 100%; height: 100%\"\n\t\t\t\t>\n\t\t\t\t\t@for (paint of sf.paints; track $index) {\n\t\t\t\t\t\t<path [attr.d]=\"paint.d\" [attr.fill]=\"paint.fill\" stroke=\"none\" />\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t@if (fillOverlay(); as ov) {\n\t\t\t\t<div\n\t\t\t\t\tclass=\"pptx-ng-fill-overlay\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\tstyle=\"position: absolute; inset: 0; pointer-events: none\"\n\t\t\t\t\t[style.background]=\"ov.color\"\n\t\t\t\t\t[style.mix-blend-mode]=\"ov.blendMode\"\n\t\t\t\t></div>\n\t\t\t}\n\t\t\t<!-- Mirrored reflection sibling (`a:reflection`): cross-browser, unlike\n\t\t\t the `-webkit-box-reflect` this replaced (Firefox never implemented\n\t\t\t that property, so reflections were invisible there entirely). -->\n\t\t\t@if (reflection(); as refl) {\n\t\t\t\t<div class=\"pptx-ng-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl.wrapperStyle\">\n\t\t\t\t\t@if (refl.imgSrc) {\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t[src]=\"refl.imgSrc\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tdraggable=\"false\"\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[ngStyle]=\"refl.imgFitStyle\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t} @else if (refl.fill) {\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tstyle=\"width: 100%; height: 100%\"\n\t\t\t\t\t\t\t[style.background-color]=\"refl.fill.backgroundColor\"\n\t\t\t\t\t\t\t[style.background-image]=\"refl.fill.backgroundImage\"\n\t\t\t\t\t\t\t[style.background-size]=\"refl.fill.backgroundSize\"\n\t\t\t\t\t\t\t[style.background-position]=\"refl.fill.backgroundPosition\"\n\t\t\t\t\t\t\t[style.background-repeat]=\"refl.fill.backgroundRepeat\"\n\t\t\t\t\t\t></div>\n\t\t\t\t\t}\n\t\t\t\t</div>\n\t\t\t}\n\t\t\t<!-- Hollow frame hit target: an unfilled, textless shape is hit-tested\n\t\t\t on its outline only, so its interior lets clicks through. -->\n\t\t\t@if (hollowHit(); as hit) {\n\t\t\t\t<svg\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\t[attr.d]=\"hit.d\"\n\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\tstroke=\"transparent\"\n\t\t\t\t\t\t[attr.stroke-width]=\"hit.strokeWidth\"\n\t\t\t\t\t\tstyle=\"pointer-events: stroke\"\n\t\t\t\t\t/>\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- Stroked outline: a CSS border takes one flat colour, and cannot\n\t\t\t outline an open preset (`line`, `arc`) at all. -->\n\t\t\t@if (gradientOutline(); as go) {\n\t\t\t\t<svg\n\t\t\t\t\tclass=\"pptx-ng-gradient-outline\"\n\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t[attr.viewBox]=\"outlineViewBox()\"\n\t\t\t\t\tpreserveAspectRatio=\"none\"\n\t\t\t\t\tstyle=\"\n\t\t\t\t\t\tposition: absolute;\n\t\t\t\t\t\tinset: 0;\n\t\t\t\t\t\twidth: 100%;\n\t\t\t\t\t\theight: 100%;\n\t\t\t\t\t\toverflow: visible;\n\t\t\t\t\t\tpointer-events: none;\n\t\t\t\t\t\"\n\t\t\t\t>\n\t\t\t\t\t@if (go.paint; as paint) {\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@if (paint.kind === 'pattern') {\n\t\t\t\t\t\t\t\t<pattern\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\tpatternUnits=\"userSpaceOnUse\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<image\n\t\t\t\t\t\t\t\t\t\t[attr.href]=\"paint.href\"\n\t\t\t\t\t\t\t\t\t\t[attr.width]=\"paint.width\"\n\t\t\t\t\t\t\t\t\t\t[attr.height]=\"paint.height\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</pattern>\n\t\t\t\t\t\t\t} @else if (paint.kind === 'radial') {\n\t\t\t\t\t\t\t\t<radialGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.cx]=\"paint.cx\"\n\t\t\t\t\t\t\t\t\t[attr.cy]=\"paint.cy\"\n\t\t\t\t\t\t\t\t\t[attr.r]=\"paint.r\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</radialGradient>\n\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t<linearGradient\n\t\t\t\t\t\t\t\t\t[attr.id]=\"paint.id\"\n\t\t\t\t\t\t\t\t\t[attr.x1]=\"paint.x1\"\n\t\t\t\t\t\t\t\t\t[attr.y1]=\"paint.y1\"\n\t\t\t\t\t\t\t\t\t[attr.x2]=\"paint.x2\"\n\t\t\t\t\t\t\t\t\t[attr.y2]=\"paint.y2\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (stop of paint.stops; track $index) {\n\t\t\t\t\t\t\t\t\t\t<stop\n\t\t\t\t\t\t\t\t\t\t\t[attr.offset]=\"stop.offset\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-color]=\"stop.color\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.stop-opacity]=\"stop.opacity\"\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</linearGradient>\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t}\n\t\t\t\t\t@for (strand of go.strands; track $index) {\n\t\t\t\t\t\t<path\n\t\t\t\t\t\t\t[attr.d]=\"go.d\"\n\t\t\t\t\t\t\tfill=\"none\"\n\t\t\t\t\t\t\t[attr.stroke]=\"go.stroke\"\n\t\t\t\t\t\t\t[attr.stroke-width]=\"strand.strokeWidth\"\n\t\t\t\t\t\t\t[attr.stroke-dasharray]=\"go.dashArray\"\n\t\t\t\t\t\t\t[attr.stroke-linecap]=\"go.lineCap\"\n\t\t\t\t\t\t\t[attr.stroke-linejoin]=\"go.lineJoin\"\n\t\t\t\t\t\t\t[style.transform]=\"\n\t\t\t\t\t\t\t\tstrand.offset !== 0 ? 'translate(0, ' + strand.offset + 'px)' : null\n\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t/>\n\t\t\t\t\t}\n\t\t\t\t</svg>\n\t\t\t}\n\t\t\t<!-- While this element is open in the inline text editor, its live text\n\t\t\t is drawn by that overlay instead (see `isBeingInlineEdited`);\n\t\t\t rendering it here too produced a duplicate, offset \"text shadow\"\n\t\t\t (issue #182). -->\n\t\t\t@if (!isBeingInlineEdited()) {\n\t\t\t\t@if (pathWarp(); as warp) {\n\t\t\t\t\t<svg\n\t\t\t\t\t\t[attr.width]=\"warp.width\"\n\t\t\t\t\t\t[attr.height]=\"warp.height\"\n\t\t\t\t\t\t[attr.viewBox]=\"'0 0 ' + warp.width + ' ' + warp.height\"\n\t\t\t\t\t\tstyle=\"position: absolute; inset: 0; overflow: visible; pointer-events: none\"\n\t\t\t\t\t\taria-hidden=\"true\"\n\t\t\t\t\t>\n\t\t\t\t\t\t<defs>\n\t\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t\t<path [attr.id]=\"line.pathId\" [attr.d]=\"line.d\" fill=\"none\" />\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t</defs>\n\t\t\t\t\t\t@for (line of warp.pathLines; track line.pathId) {\n\t\t\t\t\t\t\t<text\n\t\t\t\t\t\t\t\t[attr.font-size]=\"warp.baseFontSize\"\n\t\t\t\t\t\t\t\t[attr.font-family]=\"warp.baseFontFamily\"\n\t\t\t\t\t\t\t\t[attr.fill]=\"warp.baseColor\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<textPath\n\t\t\t\t\t\t\t\t\t[attr.href]=\"'#' + line.pathId\"\n\t\t\t\t\t\t\t\t\t[attr.startOffset]=\"warp.startOffset\"\n\t\t\t\t\t\t\t\t\t[attr.text-anchor]=\"warp.textAnchor\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t@for (seg of line.segments; track $index) {\n\t\t\t\t\t\t\t\t\t\t<tspan\n\t\t\t\t\t\t\t\t\t\t\t[attr.fill]=\"seg.style?.color ?? warp.baseColor\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-weight]=\"seg.style?.bold ? 700 : 400\"\n\t\t\t\t\t\t\t\t\t\t\t[attr.font-style]=\"seg.style?.italic ? 'italic' : 'normal'\"\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{{ seg.text }}\n\t\t\t\t\t\t\t\t\t\t</tspan>\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t</textPath>\n\t\t\t\t\t\t\t</text>\n\t\t\t\t\t\t}\n\t\t\t\t\t</svg>\n\t\t\t\t} @else if (placeholderPrompt(); as prompt) {\n\t\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"prompt.style\">{{ prompt.text }}</div>\n\t\t\t\t} @else if (hasText()) {\n\t\t\t\t\t<div class=\"pptx-ng-text\" [ngStyle]=\"warpedTextStyle()\">\n\t\t\t\t\t\t@for (para of paragraphs(); track $index) {\n\t\t\t\t\t\t\t<p\n\t\t\t\t\t\t\t\tclass=\"pptx-ng-para\"\n\t\t\t\t\t\t\t\t[ngStyle]=\"para.paragraphStyle ?? null\"\n\t\t\t\t\t\t\t\t[style.padding-left.px]=\"para.indentPx\"\n\t\t\t\t\t\t\t\t[style.text-indent.px]=\"para.textIndentPx ?? null\"\n\t\t\t\t\t\t\t\t[style.line-height]=\"para.lineHeight ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-top.px]=\"para.spaceBeforePx ?? null\"\n\t\t\t\t\t\t\t\t[style.margin-bottom.px]=\"para.spaceAfterPx ?? null\"\n\t\t\t\t\t\t\t\t[style.font-size.px]=\"para.strutFontSizePx ?? null\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t@if (para.bulletPicture?.src) {\n\t\t\t\t\t\t\t\t\t<img\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet-image\"\n\t\t\t\t\t\t\t\t\t\t[src]=\"para.bulletPicture.src\"\n\t\t\t\t\t\t\t\t\t\t[alt]=\"para.bulletPicture.accessibleLabel\"\n\t\t\t\t\t\t\t\t\t\t[style.width.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\t[style.height.px]=\"para.bulletPicture.sizePx\"\n\t\t\t\t\t\t\t\t\t\tstyle=\"\n\t\t\t\t\t\t\t\t\t\t\tdisplay: inline-block;\n\t\t\t\t\t\t\t\t\t\t\tvertical-align: middle;\n\t\t\t\t\t\t\t\t\t\t\tmargin-inline-end: 4px;\n\t\t\t\t\t\t\t\t\t\t\tobject-fit: contain;\n\t\t\t\t\t\t\t\t\t\t\"\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t} @else if (para.bulletMarker) {\n\t\t\t\t\t\t\t\t\t<span\n\t\t\t\t\t\t\t\t\t\tclass=\"pptx-ng-bullet\"\n\t\t\t\t\t\t\t\t\t\t[ngStyle]=\"para.bulletStyle\"\n\t\t\t\t\t\t\t\t\t\t[attr.aria-label]=\"para.bulletPicture?.accessibleLabel ?? null\"\n\t\t\t\t\t\t\t\t\t\t>{{ para.bulletMarker }}</span\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (textBuildSpecs()[$index]; as spec) {\n\t\t\t\t\t\t\t\t\t<!-- Staged text build: render the split pieces so each one\n\t\t\t\t\t\t\t\t carries its own sub-animation. -->\n\t\t\t\t\t\t\t\t\t@if (spec.granularity === 'paragraph') {\n\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"spec.animId\" [ngStyle]=\"buildSpanStyle(spec)\">{{\n\t\t\t\t\t\t\t\t\t\t\tparagraphText(para)\n\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t@for (span of spec.spans ?? []; track $index) {\n\t\t\t\t\t\t\t\t\t\t\t<span [attr.data-anim-id]=\"span.animId\" [ngStyle]=\"buildSpanStyle(span)\">{{\n\t\t\t\t\t\t\t\t\t\t\t\tspan.text\n\t\t\t\t\t\t\t\t\t\t\t}}</span>\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t@for (run of para.runs; track $index) {\n\t\t\t\t\t\t\t\t\t\t@if (run.equationXml) {\n\t\t\t\t\t\t\t\t\t\t\t<pptx-equation-renderer\n\t\t\t\t\t\t\t\t\t\t\t\t[equationXml]=\"run.equationXml\"\n\t\t\t\t\t\t\t\t\t\t\t\t[equationNumber]=\"run.equationNumber\"\n\t\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t} @else if (\n\t\t\t\t\t\t\t\t\t\t\trun.text ===\n\t\t\t\t\t\t\t\t\t\t\t'\n'\n\t\t\t\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t} @else if (run.reflection; as refl) {\n\t\t\t\t\t\t\t\t\t\t\t<!-- `a:reflection`: wrapped HERE, around the whole base\n\t\t\t\t\t\t\t\t\t\t run (`runBase`), rather than inside its href/ruby/plain\n\t\t\t\t\t\t\t\t\t\t branches - a `<ruby>` run's own `display: ruby` (which\n\t\t\t\t\t\t\t\t\t\t positions the annotation above its base text) would\n\t\t\t\t\t\t\t\t\t\t break if forced to `display: inline-block` to host the\n\t\t\t\t\t\t\t\t\t\t mirror. Cross-browser, unlike the `-webkit-box-reflect`\n\t\t\t\t\t\t\t\t\t\t this replaced (Firefox never implemented it). -->\n\t\t\t\t\t\t\t\t\t\t\t<span style=\"position: relative; display: inline-block\">\n\t\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t\t\t<span class=\"pptx-ng-text-reflection\" aria-hidden=\"true\" [ngStyle]=\"refl\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t><span [ngStyle]=\"run.style\"\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t><ng-container\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*ngTemplateOutlet=\"runContent; context: { run: run }\" /></span\n\t\t\t\t\t\t\t\t\t\t\t\t></span>\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t} @else {\n\t\t\t\t\t\t\t\t\t\t\t<ng-container *ngTemplateOutlet=\"runBase; context: { run: run }\" />\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t@if (para.isEmpty) {\n\t\t\t\t\t\t\t\t\t<!-- An authored blank line has no runs, so without this the\n\t\t\t\t\t\t\t\t <p> collapses to zero height and the gap a deck puts\n\t\t\t\t\t\t\t\t between a heading and its bullet list disappears. -->\n\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t</p>\n\t\t\t\t\t\t}\n\t\t\t\t\t</div>\n\t\t\t\t}\n\t\t\t}\n\t\t</div>\n\t}\n\t@default {\n\t\t<div\n\t\t\tclass=\"pptx-ng-element pptx-ng-unsupported\"\n\t\t\t[ngStyle]=\"containerStyle()\"\n\t\t\t[style.pointer-events]=\"rootPointerEvents()\"\n\t\t\t[attr.data-element-id]=\"elementIdAttr()\"\n\t\t\t[attr.data-pptx-element]=\"elementMarked() ? 'true' : null\"\n\t\t>\n\t\t\t<div class=\"pptx-ng-placeholder\">{{ placeholderLabel() }}</div>\n\t\t</div>\n\t}\n}\n\n<!-- Soft-edge feather <filter> def, referenced via filter: url(#soft-edge-<id>). -->\n@if (softEdgeFilter(); as sef) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter\n\t\t\t\t[attr.id]=\"sef.id\"\n\t\t\t\tx=\"-20%\"\n\t\t\t\ty=\"-20%\"\n\t\t\t\twidth=\"140%\"\n\t\t\t\theight=\"140%\"\n\t\t\t\tcolor-interpolation-filters=\"sRGB\"\n\t\t\t>\n\t\t\t\t<feGaussianBlur in=\"SourceAlpha\" [attr.stdDeviation]=\"sef.radius\" result=\"softEdgeAlpha\" />\n\t\t\t\t<feComposite in=\"SourceGraphic\" in2=\"softEdgeAlpha\" operator=\"in\" />\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!-- Duotone image-effect <filter> def, referenced via filter: url(#id). -->\n@if (duotoneFilter(); as df) {\n\t<svg\n\t\twidth=\"0\"\n\t\theight=\"0\"\n\t\taria-hidden=\"true\"\n\t\tstyle=\"position: absolute; width: 0; height: 0; overflow: hidden\"\n\t>\n\t\t<defs>\n\t\t\t<filter [attr.id]=\"df.id\" color-interpolation-filters=\"sRGB\">\n\t\t\t\t<feColorMatrix type=\"matrix\" [attr.values]=\"df.primitives[0].values\" />\n\t\t\t\t<feComponentTransfer>\n\t\t\t\t\t<feFuncR\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[0].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[0].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncG\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[1].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[1].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t\t<feFuncB\n\t\t\t\t\t\ttype=\"linear\"\n\t\t\t\t\t\t[attr.slope]=\"df.primitives[1].channels[2].slope\"\n\t\t\t\t\t\t[attr.intercept]=\"df.primitives[1].channels[2].intercept\"\n\t\t\t\t\t/>\n\t\t\t\t</feComponentTransfer>\n\t\t\t</filter>\n\t\t</defs>\n\t</svg>\n}\n\n<!--\n\tOne run's base element (hyperlink / ruby / plain span), reused via\n\t`ngTemplateOutlet` both directly and inside the `a:reflection` wrapper above,\n\tso the reflection case does not duplicate this three-way branch.\n-->\n<ng-template #runBase let-run=\"run\">\n\t@if (run.href) {\n\t\t<a\n\t\t\tclass=\"pptx-ng-link\"\n\t\t\t[href]=\"run.href\"\n\t\t\ttarget=\"_blank\"\n\t\t\trel=\"noopener noreferrer\"\n\t\t\t[attr.title]=\"run.tooltip ?? null\"\n\t\t\t[ngStyle]=\"run.style\"\n\t\t\t(click)=\"onHyperlinkClick($event, run.href)\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></a>\n\t} @else if (run.rubyText) {\n\t\t<!-- `a:ruby`: the phonetic guide sits above its base\n\t\t text; the <rp> parentheses are the fallback for a\n\t\t browser without ruby support. -->\n\t\t<ruby [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\" /><rp>(</rp\n\t\t\t><rt [ngStyle]=\"run.rubyStyle\">{{ run.rubyText }}</rt\n\t\t\t><rp>)</rp></ruby\n\t\t>\n\t} @else {\n\t\t<span [ngStyle]=\"run.style\"\n\t\t\t><ng-container *ngTemplateOutlet=\"runContent; context: { run: run }\"\n\t\t/></span>\n\t}\n</ng-template>\n\n<!--\n\tA run's text content, honouring shared's per-script font split\n\t(`run.scriptRuns`) and measured tab-stop layout (`run.tabLines`) when\n\teither is present. Both descriptors come from `pptx-viewer-shared`'s\n\t`buildParagraphs` (the per-script split was React-only before this\n\ttemplate existed: CJK, Arabic, Hebrew and Thai text rendered in the wrong\n\ttypeface here; the tab layout was likewise React-only, so a TOC-style row\n\tlost its leader dots and right-aligned page number). Reused via\n\t`ngTemplateOutlet` for the run's span / anchor / ruby base text, so all\n\tthree carry the same content logic.\n-->\n<ng-template #runContent let-run=\"run\">\n\t@if (run.tabLines) {\n\t\t@for (line of run.tabLines; track $index) {\n\t\t\t<span style=\"display: inline-block; white-space: nowrap\">\n\t\t\t\t@for (piece of line.pieces; track $index) {\n\t\t\t\t\t@if (piece.leaderStyle) {\n\t\t\t\t\t\t<span aria-hidden=\"true\" [ngStyle]=\"piece.leaderStyle\">{{ piece.leaderText }}</span>\n\t\t\t\t\t}\n\t\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t\t}\n\t\t\t</span>\n\t\t\t@if (!$last) {\n\t\t\t\t<br />\n\t\t\t}\n\t\t}\n\t} @else if (run.scriptRuns) {\n\t\t<!--\n\t\t\tA bare interpolation as the sole content of an `@if`/`@else` block\n\t\t\tleaks a real leading + trailing whitespace text node: Angular does\n\t\t\tnot collapse that whitespace the way it collapses whitespace between\n\t\t\telement TAGS. Worse, oxfmt's Angular-template printer always breaks a\n\t\t\tblock's content onto its own indented line, even when the block was\n\t\t\twritten as a single line with the braces touching, so writing the\n\t\t\t`{{ x }}` compact ourselves does not survive the next `bun run fmt` /\n\t\t\tpre-commit `lint-staged` pass: it silently re-introduces the leak\n\t\t\t(this happened twice, see `20d4d177`, `18eebb6f`). `<ng-container>`\n\t\t\tdoes not render any DOM node of its own, so wrapping the\n\t\t\tinterpolation in one keeps the no-wrapper-element behaviour of\n\t\t\tReact's `<>{piece.text}</>` fragment while making the interpolation\n\t\t\ttag-adjacent, which both Angular AND oxfmt already treat as safely\n\t\t\tcollapsible (see the many `<span>{{ x }}</span>` one-liners in this\n\t\t\tfile). That was invisible while a paragraph was one run per script\n\t\t\t(two stray spaces at the run's own edges, trimmed visually by the\n\t\t\tbrowser but still present in `textContent`), but shared's per-word /\n\t\t\tper-gap metric split (`text-run-spacing.ts`, issue #149) re-emits\n\t\t\tevery WORD and inter-word GAP as its own sibling run, so the same\n\t\t\tone-space leak lands between every word: \"will choose\" rendered as\n\t\t\t\"will choose\" (five spaces: the word's own trailing leak, the\n\t\t\tgap run's real space plus its OWN two leaks, the next word's leading\n\t\t\tleak). The same leak also showed up one paragraph at a time:\n\t\t\t\"Project\" / \"Atlas\" as two separate paragraphs read back as\n\t\t\t\"ProjectAtlas\" instead of React's \"Project Atlas\", because the\n\t\t\tplain-run `@else` below had the same bug.\n\t\t-->\n\t\t@for (piece of run.scriptRuns; track $index) {\n\t\t\t@if (piece.style) {\n\t\t\t\t<span [ngStyle]=\"piece.style\">{{ piece.text }}</span>\n\t\t\t} @else {\n\t\t\t\t<ng-container>{{ piece.text }}</ng-container>\n\t\t\t}\n\t\t}\n\t} @else {\n\t\t<ng-container>{{ run.text }}</ng-container>\n\t}\n</ng-template>\n" }]
99593
101324
  }], propDecorators: { element: [{ type: i0.Input, args: [{ isSignal: true, alias: "element", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], zIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "zIndex", required: false }] }], obstacles: [{ type: i0.Input, args: [{ isSignal: true, alias: "obstacles", required: false }] }], canvasWidth: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasWidth", required: false }] }], canvasHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasHeight", required: false }] }], interactive: [{ type: i0.Input, args: [{ isSignal: true, alias: "interactive", required: false }] }], marked: [{ type: i0.Input, args: [{ isSignal: true, alias: "marked", required: false }] }], exposeElementId: [{ type: i0.Input, args: [{ isSignal: true, alias: "exposeElementId", required: false }] }], presenting: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenting", required: false }] }], editable: [{ type: i0.Input, args: [{ isSignal: true, alias: "editable", required: false }] }], fieldContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "fieldContext", required: false }] }], slideElements: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideElements", required: false }] }], editTemplateMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "editTemplateMode", required: false }] }], parentGroupFill: [{ type: i0.Input, args: [{ isSignal: true, alias: "parentGroupFill", required: false }] }], editingElementId: [{ type: i0.Input, args: [{ isSignal: true, alias: "editingElementId", required: false }] }], cellCommit: [{ type: i0.Output, args: ["cellCommit"] }], tableChange: [{ type: i0.Output, args: ["tableChange"] }] } });
99594
101325
 
99595
101326
  /**
@@ -105515,12 +107246,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
105515
107246
  * share-helpers.ts: Share dialog helpers for the Angular viewer.
105516
107247
  *
105517
107248
  * The shared subset (ShareFormFields / ShareDefaults / seedShareFields /
105518
- * canStartShare) is re-exported from `pptx-viewer-shared` (`render/share-form`).
105519
- * Two helpers stay local because they diverge from the shared builders:
105520
- * - `buildCollaborationConfig` validates with `canStartShare` (non-blank room)
105521
- * and emits a config WITHOUT `role`/`sessionIntent`, unlike the shared
105522
- * `buildShareConfig` (which is `buildCreateCollaborationConfig`).
105523
- * - `buildShareUrl` is Angular-only (no other binding builds a share link).
107249
+ * canStartShare / buildShareUrl) is re-exported from `pptx-viewer-shared`
107250
+ * (`render/share-form`, `render/broadcast-helpers`). One helper stays local
107251
+ * because it diverges from the shared builders: `buildCollaborationConfig`
107252
+ * validates with `canStartShare` (non-blank room) and emits a config WITHOUT
107253
+ * `role`/`sessionIntent`, unlike the shared `buildShareConfig` (which is
107254
+ * `buildCreateCollaborationConfig`).
105524
107255
  *
105525
107256
  * No `any`; all regexes use the `/u` flag; no `String.prototype.replaceAll`,
105526
107257
  * no regex named-capture-groups (ng-packagr lib-target constraints).
@@ -105542,22 +107273,6 @@ function buildCollaborationConfig(fields) {
105542
107273
  transport: resolveTransportForServerUrl(serverUrl),
105543
107274
  };
105544
107275
  }
105545
- /**
105546
- * Build a shareable join URL for a session. Returns just the room id when no
105547
- * `origin`/`pathname` are available (e.g. non-browser environments).
105548
- */
105549
- function buildShareUrl(roomId, serverUrl, location) {
105550
- if (!location) {
105551
- return roomId;
105552
- }
105553
- const room = encodeURIComponent(roomId);
105554
- const trimmed = serverUrl.trim();
105555
- if (trimmed.length === 0) {
105556
- return `${location.origin}${location.pathname}?room=${room}&transport=webrtc`;
105557
- }
105558
- const server = encodeURIComponent(trimmed);
105559
- return `${location.origin}${location.pathname}?room=${room}&server=${server}`;
105560
- }
105561
107276
 
105562
107277
  /**
105563
107278
  * viewer-collaboration-session.service.ts: Viewer-scoped state + logic for the
@@ -107251,11 +108966,11 @@ function clampIndex(index, count) {
107251
108966
  * slides. Kept as a named export because the overlay's tests and the navigator
107252
108967
  * read better in terms of "next visible slide" than raw index lists.
107253
108968
  */
107254
- function nextVisibleIndex(current, slides, activeShow) {
108969
+ function nextVisibleIndex(current, slides, activeShow, authoredRange) {
107255
108970
  if (slides.length === 0) {
107256
108971
  return 0;
107257
108972
  }
107258
- const order = resolveShowSlideIndexes(slides, activeShow);
108973
+ const order = resolveShowSlideIndexes(slides, activeShow, authoredRange);
107259
108974
  return nextShowSlideIndex(current, order, { loop: true }) ?? current;
107260
108975
  }
107261
108976
  /**
@@ -107263,11 +108978,11 @@ function nextVisibleIndex(current, slides, activeShow) {
107263
108978
  * Returns `current` when no earlier visible slide exists: PowerPoint never
107264
108979
  * wraps backward off the first slide.
107265
108980
  */
107266
- function prevVisibleIndex(current, slides, activeShow) {
108981
+ function prevVisibleIndex(current, slides, activeShow, authoredRange) {
107267
108982
  if (slides.length === 0) {
107268
108983
  return 0;
107269
108984
  }
107270
- const order = resolveShowSlideIndexes(slides, activeShow);
108985
+ const order = resolveShowSlideIndexes(slides, activeShow, authoredRange);
107271
108986
  return previousShowSlideIndex(current, order) ?? current;
107272
108987
  }
107273
108988
  /**
@@ -107290,16 +109005,16 @@ function fitZoom(canvasW, canvasH, vw, vh) {
107290
109005
  * the last slide ends the show. Callers use this to tell "there is a next
107291
109006
  * slide" from "we just wrapped".
107292
109007
  */
107293
- function hasVisibleSlideAfter(current, slides, activeShow) {
107294
- return hasShowSlideAfter(current, resolveShowSlideIndexes(slides, activeShow));
109008
+ function hasVisibleSlideAfter(current, slides, activeShow, authoredRange) {
109009
+ return hasShowSlideAfter(current, resolveShowSlideIndexes(slides, activeShow, authoredRange));
107295
109010
  }
107296
109011
  /** The show's first visible slide (Home), or 0 for an empty deck. */
107297
- function firstVisibleIndex(slides, activeShow) {
107298
- return firstShowSlideIndex(resolveShowSlideIndexes(slides, activeShow)) ?? 0;
109012
+ function firstVisibleIndex(slides, activeShow, authoredRange) {
109013
+ return firstShowSlideIndex(resolveShowSlideIndexes(slides, activeShow, authoredRange)) ?? 0;
107299
109014
  }
107300
109015
  /** The show's last visible slide (End), or 0 for an empty deck. */
107301
- function lastVisibleIndex(slides, activeShow) {
107302
- return lastShowSlideIndex(resolveShowSlideIndexes(slides, activeShow)) ?? 0;
109016
+ function lastVisibleIndex(slides, activeShow, authoredRange) {
109017
+ return lastShowSlideIndex(resolveShowSlideIndexes(slides, activeShow, authoredRange)) ?? 0;
107303
109018
  }
107304
109019
  /**
107305
109020
  * Style record centring the scaled slide stage in the viewport.
@@ -108218,8 +109933,11 @@ const POWER_POINT_VIEWER_PROVIDERS = [
108218
109933
  * packages/react/src/viewer/components/PresentationAnnotationOverlay.tsx
108219
109934
  * packages/react/src/viewer/hooks/usePresentationAnnotations.ts
108220
109935
  *
108221
- * No Angular dependencies; all functions are pure so they can be unit-tested
108222
- * without TestBed.
109936
+ * The stroke-path and cursor helpers live in `pptx-viewer-shared`
109937
+ * (`render/annotation-overlay.ts`, shared by React/Vue/Angular) and are
109938
+ * re-wrapped here with this file's own local point/tool types; everything
109939
+ * else (smoothing, eraser hit-testing, laser fade, stroke ids) is
109940
+ * Angular-only and stays pure so it can be unit-tested without TestBed.
108223
109941
  */
108224
109942
  // ---------------------------------------------------------------------------
108225
109943
  // Constants
@@ -108260,16 +109978,7 @@ function resetStrokeIdCounter() {
108260
109978
  * buildPathD([{x:0,y:0},{x:10,y:5}]) // "M 0 0 L 10 5"
108261
109979
  */
108262
109980
  function buildPathD(points) {
108263
- if (points.length === 0) {
108264
- return '';
108265
- }
108266
- const first = points[0];
108267
- let d = `M ${first.x} ${first.y}`;
108268
- for (let i = 1; i < points.length; i++) {
108269
- const pt = points[i];
108270
- d += ` L ${pt.x} ${pt.y}`;
108271
- }
108272
- return d;
109981
+ return buildStrokePathD(points);
108273
109982
  }
108274
109983
  // ---------------------------------------------------------------------------
108275
109984
  // Point smoothing
@@ -108358,18 +110067,7 @@ function laserDotOpacity(ratio) {
108358
110067
  * Return the CSS `cursor` value that matches `tool`.
108359
110068
  */
108360
110069
  function cursorForTool(tool) {
108361
- switch (tool) {
108362
- case 'laser':
108363
- return 'none';
108364
- case 'pen':
108365
- return 'crosshair';
108366
- case 'highlighter':
108367
- return 'crosshair';
108368
- case 'eraser':
108369
- return 'crosshair';
108370
- default:
108371
- return 'default';
108372
- }
110070
+ return cursorForTool$1(tool);
108373
110071
  }
108374
110072
 
108375
110073
  /**
@@ -108795,16 +110493,7 @@ class PresentationAnnotationOverlayComponent {
108795
110493
  // Template helpers
108796
110494
  // ------------------------------------------------------------------
108797
110495
  strokePath(points) {
108798
- if (points.length === 0) {
108799
- return '';
108800
- }
108801
- const first = points[0];
108802
- let d = `M ${first.x} ${first.y}`;
108803
- for (let i = 1; i < points.length; i++) {
108804
- const pt = points[i];
108805
- d += ` L ${pt.x} ${pt.y}`;
108806
- }
108807
- return d;
110496
+ return buildPathD(points);
108808
110497
  }
108809
110498
  laserDotStyle(x, y) {
108810
110499
  const z = this.zoom();
@@ -109696,27 +111385,31 @@ class PresentationShowNavigator {
109696
111385
  }
109697
111386
  const current = this.currentIndex();
109698
111387
  const activeShow = this.deps.activeCustomShow?.();
111388
+ const authoredRange = this.deps.authoredRange?.();
109699
111389
  let next;
109700
111390
  switch (direction) {
109701
111391
  case 'next':
109702
- next = nextVisibleIndex(current, slides, activeShow);
111392
+ next = nextVisibleIndex(current, slides, activeShow, authoredRange);
109703
111393
  break;
109704
111394
  case 'prev':
109705
- next = prevVisibleIndex(current, slides, activeShow);
111395
+ next = prevVisibleIndex(current, slides, activeShow, authoredRange);
109706
111396
  break;
109707
111397
  case 'first':
109708
111398
  // Home goes to the START OF THE SHOW, which is not slide 1 when the
109709
111399
  // author hid it. Clamped anyway so an empty order cannot produce -1.
109710
- next = clampIndex(firstVisibleIndex(slides, activeShow), count);
111400
+ next = clampIndex(firstVisibleIndex(slides, activeShow, authoredRange), count);
109711
111401
  break;
109712
111402
  case 'last':
109713
- next = clampIndex(lastVisibleIndex(slides, activeShow), count);
111403
+ next = clampIndex(lastVisibleIndex(slides, activeShow, authoredRange), count);
109714
111404
  break;
109715
111405
  }
109716
- if (direction === 'next' && !hasVisibleSlideAfter(current, slides, activeShow)) {
109717
- // Nothing further to advance to. `nextVisibleIndex` would wrap back to
109718
- // the first slide and loop for ever; PowerPoint only loops when "Loop
109719
- // continuously until Esc" is set, so end the show instead.
111406
+ // `nextVisibleIndex` always wraps back to the first slide (`loop: true`)
111407
+ // so `next` above is already the wrapped index; whether that wrap is
111408
+ // honoured or overridden into ending the show is "Loop continuously
111409
+ // until Esc" (Set Up Slide Show), matching PowerPoint's own default OFF.
111410
+ if (direction === 'next' &&
111411
+ !hasVisibleSlideAfter(current, slides, activeShow, authoredRange) &&
111412
+ this.deps.loopContinuously?.() !== true) {
109720
111413
  if (this.deps.endWithBlackSlide?.() === false) {
109721
111414
  // No black slide configured: PowerPoint ends the show outright rather
109722
111415
  // than sitting on the last slide ignoring every further advance.
@@ -111160,6 +112853,17 @@ class PresentationOverlayComponent {
111160
112853
  */
111161
112854
  this.activeCustomShow = input(null, /* @ts-ignore */
111162
112855
  ...(ngDevMode ? [{ debugName: "activeCustomShow" }] : /* istanbul ignore next */ []));
112856
+ /**
112857
+ * The `p:showPr/p:sldRg` slide-range restriction, when the deck is authored
112858
+ * to open into a range (`p:showPr/@showSlidesMode == 'range'`) rather than
112859
+ * the whole deck or a custom show. Applied the same way `activeCustomShow`
112860
+ * is: a filter on the navigable order, not a pre-filtered slide array.
112861
+ */
112862
+ this.authoredRange = input(null, /* @ts-ignore */
112863
+ ...(ngDevMode ? [{ debugName: "authoredRange" }] : /* istanbul ignore next */ []));
112864
+ /** Set Up Slide Show > "Loop continuously until 'Esc'". */
112865
+ this.loopContinuously = input(false, /* @ts-ignore */
112866
+ ...(ngDevMode ? [{ debugName: "loopContinuously" }] : /* istanbul ignore next */ []));
111163
112867
  this.showWithAnimation = input(undefined, /* @ts-ignore */
111164
112868
  ...(ngDevMode ? [{ debugName: "showWithAnimation" }] : /* istanbul ignore next */ []));
111165
112869
  /**
@@ -111233,6 +112937,7 @@ class PresentationOverlayComponent {
111233
112937
  this.navigator = new PresentationShowNavigator({
111234
112938
  slides: () => this.slides(),
111235
112939
  activeCustomShow: () => this.activeCustomShow(),
112940
+ authoredRange: () => this.authoredRange(),
111236
112941
  currentSlide: () => this.currentSlide(),
111237
112942
  showWithAnimation: () => this.showWithAnimation(),
111238
112943
  playback: this.playback,
@@ -111240,6 +112945,7 @@ class PresentationOverlayComponent {
111240
112945
  emitIndex: (index) => this.indexChange.emit(index),
111241
112946
  requestClose: () => this.emitClosed(),
111242
112947
  endWithBlackSlide: () => this.endWithBlackSlide(),
112948
+ loopContinuously: () => this.loopContinuously(),
111243
112949
  });
111244
112950
  /**
111245
112951
  * Keyboard / pointer rules for the running show. See
@@ -111674,7 +113380,7 @@ class PresentationOverlayComponent {
111674
113380
  this.closed.emit();
111675
113381
  }
111676
113382
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PresentationOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
111677
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: PresentationOverlayComponent, isStandalone: true, selector: "pptx-presentation-overlay", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, startIndex: { classPropertyName: "startIndex", publicName: "startIndex", isSignal: true, isRequired: false, transformFunction: null }, activeCustomShow: { classPropertyName: "activeCustomShow", publicName: "activeCustomShow", isSignal: true, isRequired: false, transformFunction: null }, showWithAnimation: { classPropertyName: "showWithAnimation", publicName: "showWithAnimation", isSignal: true, isRequired: false, transformFunction: null }, useTimings: { classPropertyName: "useTimings", publicName: "useTimings", isSignal: true, isRequired: false, transformFunction: null }, subtitlesVisible: { classPropertyName: "subtitlesVisible", publicName: "subtitlesVisible", isSignal: true, isRequired: false, transformFunction: null }, sessionEnded: { classPropertyName: "sessionEnded", publicName: "sessionEnded", isSignal: true, isRequired: false, transformFunction: null }, endWithBlackSlide: { classPropertyName: "endWithBlackSlide", publicName: "endWithBlackSlide", isSignal: true, isRequired: false, transformFunction: null }, presenterMode: { classPropertyName: "presenterMode", publicName: "presenterMode", isSignal: true, isRequired: false, transformFunction: null }, showMenuOnRightClick: { classPropertyName: "showMenuOnRightClick", publicName: "showMenuOnRightClick", isSignal: true, isRequired: false, transformFunction: null }, showPopupToolbar: { classPropertyName: "showPopupToolbar", publicName: "showPopupToolbar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { indexChange: "indexChange", closed: "closed", subtitlesChange: "subtitlesChange", presenterViewToggle: "presenterViewToggle", annotationsExit: "annotationsExit" }, host: { listeners: { "document:wheel": "onWheel($event)", "document:fullscreenchange": "onFullscreenChange()", "window:resize": "onWindowResize()", "document:keydown": "onKeyDown($event)" } }, providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], viewQueries: [{ propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "rootRef", first: true, predicate: ["root"], descendants: true, isSignal: true }, { propertyName: "toolbarRef", first: true, predicate: PresentationToolbarComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"onStageContextMenu($event)\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t#toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t[popupToolbarEnabled]=\"showPopupToolbar()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n\n\t<!--\n\t\tPowerPoint's \"See All Slides\" (Ctrl+S during a show). The same navigator\n\t\tthe presenter console uses, laid over the show itself: the shortcut exists\n\t\tso a presenter can reach a backup slide WITHOUT leaving the show, so it\n\t\tmust not be a door into presenter view.\n\t-->\n\t@if (allSlidesOpen()) {\n\t\t<pptx-presenter-slide-navigator\n\t\t\t[slides]=\"slides()\"\n\t\t\t[current]=\"currentIndex()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t(select)=\"onNavigatorSelect($event)\"\n\t\t\t(close)=\"allSlidesOpen.set(false)\"\n\t\t/>\n\t}\n\n\t<!-- Slide-show right-click menu. -->\n\t@if (contextMenuState(); as pos) {\n\t\t<pptx-presentation-context-menu\n\t\t\t[x]=\"pos.x\"\n\t\t\t[y]=\"pos.y\"\n\t\t\t(action)=\"onContextMenuAction($event)\"\n\t\t\t(closed)=\"contextMenuState.set(null)\"\n\t\t/>\n\t}\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none;overflow:hidden}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y;overflow:hidden}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "gridSpacing", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "exposeElementIds", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "transformEnd", "adjustUpdate", "connectorEndpointUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationTransitionOverlayComponent, selector: "pptx-presentation-transition-overlay", inputs: ["outgoingSlide", "canvasSize", "transition", "templateElements", "mediaDataUrls", "durationMs", "zoom", "incomingSlide"], outputs: ["complete"] }, { kind: "component", type: PresentationAnnotationOverlayComponent, selector: "pptx-presentation-annotation-overlay", inputs: ["canvasSize", "zoom"] }, { kind: "component", type: PresentationSubtitleBarComponent, selector: "pptx-presentation-subtitle-bar", inputs: ["visible"] }, { kind: "component", type: PresentationToolbarComponent, selector: "pptx-presentation-toolbar", inputs: ["currentSlideIndex", "totalSlides", "presentationStartTime", "presenterMode", "popupToolbarEnabled"], outputs: ["move", "endPresentation", "presenterViewToggle"] }, { kind: "component", type: PresentationContextMenuComponent, selector: "pptx-presentation-context-menu", inputs: ["x", "y"], outputs: ["closed", "action"] }, { kind: "component", type: PresenterSlideNavigatorComponent, selector: "pptx-presenter-slide-navigator", inputs: ["slides", "current", "canvasSize", "mediaDataUrls", "templateElements"], outputs: ["select", "close"] }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
113383
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: PresentationOverlayComponent, isStandalone: true, selector: "pptx-presentation-overlay", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: true, transformFunction: null }, canvasSize: { classPropertyName: "canvasSize", publicName: "canvasSize", isSignal: true, isRequired: true, transformFunction: null }, mediaDataUrls: { classPropertyName: "mediaDataUrls", publicName: "mediaDataUrls", isSignal: true, isRequired: false, transformFunction: null }, startIndex: { classPropertyName: "startIndex", publicName: "startIndex", isSignal: true, isRequired: false, transformFunction: null }, activeCustomShow: { classPropertyName: "activeCustomShow", publicName: "activeCustomShow", isSignal: true, isRequired: false, transformFunction: null }, authoredRange: { classPropertyName: "authoredRange", publicName: "authoredRange", isSignal: true, isRequired: false, transformFunction: null }, loopContinuously: { classPropertyName: "loopContinuously", publicName: "loopContinuously", isSignal: true, isRequired: false, transformFunction: null }, showWithAnimation: { classPropertyName: "showWithAnimation", publicName: "showWithAnimation", isSignal: true, isRequired: false, transformFunction: null }, useTimings: { classPropertyName: "useTimings", publicName: "useTimings", isSignal: true, isRequired: false, transformFunction: null }, subtitlesVisible: { classPropertyName: "subtitlesVisible", publicName: "subtitlesVisible", isSignal: true, isRequired: false, transformFunction: null }, sessionEnded: { classPropertyName: "sessionEnded", publicName: "sessionEnded", isSignal: true, isRequired: false, transformFunction: null }, endWithBlackSlide: { classPropertyName: "endWithBlackSlide", publicName: "endWithBlackSlide", isSignal: true, isRequired: false, transformFunction: null }, presenterMode: { classPropertyName: "presenterMode", publicName: "presenterMode", isSignal: true, isRequired: false, transformFunction: null }, showMenuOnRightClick: { classPropertyName: "showMenuOnRightClick", publicName: "showMenuOnRightClick", isSignal: true, isRequired: false, transformFunction: null }, showPopupToolbar: { classPropertyName: "showPopupToolbar", publicName: "showPopupToolbar", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { indexChange: "indexChange", closed: "closed", subtitlesChange: "subtitlesChange", presenterViewToggle: "presenterViewToggle", annotationsExit: "annotationsExit" }, host: { listeners: { "document:wheel": "onWheel($event)", "document:fullscreenchange": "onFullscreenChange()", "window:resize": "onWindowResize()", "document:keydown": "onKeyDown($event)" } }, providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], viewQueries: [{ propertyName: "stageRef", first: true, predicate: ["stage"], descendants: true, isSignal: true }, { propertyName: "rootRef", first: true, predicate: ["root"], descendants: true, isSignal: true }, { propertyName: "toolbarRef", first: true, predicate: PresentationToolbarComponent, descendants: true, isSignal: true }], ngImport: i0, template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"onStageContextMenu($event)\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t#toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t[popupToolbarEnabled]=\"showPopupToolbar()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n\n\t<!--\n\t\tPowerPoint's \"See All Slides\" (Ctrl+S during a show). The same navigator\n\t\tthe presenter console uses, laid over the show itself: the shortcut exists\n\t\tso a presenter can reach a backup slide WITHOUT leaving the show, so it\n\t\tmust not be a door into presenter view.\n\t-->\n\t@if (allSlidesOpen()) {\n\t\t<pptx-presenter-slide-navigator\n\t\t\t[slides]=\"slides()\"\n\t\t\t[current]=\"currentIndex()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t(select)=\"onNavigatorSelect($event)\"\n\t\t\t(close)=\"allSlidesOpen.set(false)\"\n\t\t/>\n\t}\n\n\t<!-- Slide-show right-click menu. -->\n\t@if (contextMenuState(); as pos) {\n\t\t<pptx-presentation-context-menu\n\t\t\t[x]=\"pos.x\"\n\t\t\t[y]=\"pos.y\"\n\t\t\t(action)=\"onContextMenuAction($event)\"\n\t\t\t(closed)=\"contextMenuState.set(null)\"\n\t\t/>\n\t}\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none;overflow:hidden}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y;overflow:hidden}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"], dependencies: [{ kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "gridSpacing", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "exposeElementIds", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "transformEnd", "adjustUpdate", "connectorEndpointUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationTransitionOverlayComponent, selector: "pptx-presentation-transition-overlay", inputs: ["outgoingSlide", "canvasSize", "transition", "templateElements", "mediaDataUrls", "durationMs", "zoom", "incomingSlide"], outputs: ["complete"] }, { kind: "component", type: PresentationAnnotationOverlayComponent, selector: "pptx-presentation-annotation-overlay", inputs: ["canvasSize", "zoom"] }, { kind: "component", type: PresentationSubtitleBarComponent, selector: "pptx-presentation-subtitle-bar", inputs: ["visible"] }, { kind: "component", type: PresentationToolbarComponent, selector: "pptx-presentation-toolbar", inputs: ["currentSlideIndex", "totalSlides", "presentationStartTime", "presenterMode", "popupToolbarEnabled"], outputs: ["move", "endPresentation", "presenterViewToggle"] }, { kind: "component", type: PresentationContextMenuComponent, selector: "pptx-presentation-context-menu", inputs: ["x", "y"], outputs: ["closed", "action"] }, { kind: "component", type: PresenterSlideNavigatorComponent, selector: "pptx-presenter-slide-navigator", inputs: ["slides", "current", "canvasSize", "mediaDataUrls", "templateElements"], outputs: ["select", "close"] }, { kind: "component", type: LucideX, selector: "svg[lucideX]" }, { kind: "component", type: LucideChevronLeft, selector: "svg[lucideChevronLeft]" }, { kind: "component", type: LucideChevronRight, selector: "svg[lucideChevronRight]" }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
111678
113384
  }
111679
113385
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: PresentationOverlayComponent, decorators: [{
111680
113386
  type: Component,
@@ -111692,7 +113398,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
111692
113398
  LucideChevronLeft,
111693
113399
  LucideChevronRight,
111694
113400
  ], providers: [AnimationPlaybackService, PresentationAnnotationsService, ZoomNavigationService], template: "<div #root class=\"pptx-ng-presentation-root\">\n\t<!--\n\t\tSlide counter, rendered first in DOM (before slide content) so a\n\t\tgeneric \"N / M\" text query resolves to it rather than to any slide-text\n\t\trun that happens to read like \"24 / 7\". Position is fixed, so DOM order\n\t\tdoes not affect its on-screen placement.\n\t-->\n\t<span class=\"pptx-ng-presentation-counter\" [ngStyle]=\"counterStyle\">\n\t\t{{ counterLabel() }}\n\t</span>\n\n\t<!-- Black \"End of slide show\" screen: the show has run past its last\n\t slide. It MUST be visible - while it is up the next input either\n\t goes nowhere (backward) or ends the show (forward), so a deck that\n\t kept painting the last slide looked stuck and swallowed advances. -->\n\t@if (endOfShow()) {\n\t\t<button\n\t\t\ttype=\"button\"\n\t\t\tclass=\"pptx-ng-presentation-end\"\n\t\t\tdata-pptx-end-of-show\n\t\t\t(click)=\"onEndScreenClick($event)\"\n\t\t>\n\t\t\t<span>{{ 'pptx.presentation.endOfSlideShow' | translate }}</span>\n\t\t</button>\n\t}\n\n\t<div\n\t\t#stage\n\t\tclass=\"pptx-ng-presentation-stage\"\n\t\t[ngStyle]=\"stageContainerStyle()\"\n\t\t(click)=\"onBodyClick($event)\"\n\t\t(mouseover)=\"onStageHover($event)\"\n\t\t(mouseout)=\"onStageHoverEnd($event)\"\n\t\t(contextmenu)=\"onStageContextMenu($event)\"\n\t>\n\t\t<pptx-slide-canvas\n\t\t\t[slide]=\"currentSlide()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t[zoom]=\"zoom()\"\n\t\t\t[autoFit]=\"false\"\n\t\t\t[interactive]=\"false\"\n\t\t\t[presenting]=\"true\"\n\t\t/>\n\n\t\t@if (activeTransition(); as t) {\n\t\t\t<pptx-presentation-transition-overlay\n\t\t\t\t[outgoingSlide]=\"t.outgoing\"\n\t\t\t\t[incomingSlide]=\"currentSlide()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[transition]=\"t.transition\"\n\t\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t\t(complete)=\"activeTransition.set(null)\"\n\t\t\t/>\n\t\t}\n\n\t\t<!-- Ink annotation overlay (pen/highlighter/eraser/laser). Ctrl+M\n\t\t hides the markup without discarding the strokes. The host carries\n\t\t the shared blackboard z-index so strokes stay visible ABOVE the\n\t\t blackout sheet while the screen is blanked (the stage no longer\n\t\t creates a stacking context, see stageContainerStyle). -->\n\t\t@if (inkMarkupVisible()) {\n\t\t\t<pptx-presentation-annotation-overlay\n\t\t\t\tdata-pptx-annotation-overlay\n\t\t\t\t[style.z-index]=\"annotationOverlayZ()\"\n\t\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t\t[zoom]=\"zoom()\"\n\t\t\t/>\n\t\t}\n\t</div>\n\t@if (presenterWindow.snapshot().blackout !== 'none') {\n\t\t<div\n\t\t\tclass=\"presenter-blank\"\n\t\t\tdata-pptx-blackout\n\t\t\t[style.background]=\"presenterWindow.snapshot().blackout\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().pointer?.tool === 'laser') {\n\t\t<div\n\t\t\tclass=\"presenter-laser\"\n\t\t\t[style.left.%]=\"(presenterWindow.snapshot().pointer?.x ?? 0.5) * 100\"\n\t\t\t[style.top.%]=\"(presenterWindow.snapshot().pointer?.y ?? 0.5) * 100\"\n\t\t></div>\n\t}\n\t@if (presenterWindow.snapshot().subtitlesVisible && presenterWindow.snapshot().caption) {\n\t\t<div class=\"presenter-caption\">{{ presenterWindow.snapshot().caption }}</div>\n\t}\n\n\t<!-- Live-caption (subtitle) bar. -->\n\t<pptx-presentation-subtitle-bar [visible]=\"subtitlesVisible()\" />\n\n\t<!--\n\t\tTouch-only chrome (close button, edge arrows, counter pill). The\n\t\tcomponent stylesheet hides all three unless the device has a coarse\n\t\tpointer, matching React's `PresentationTouchControls`: on a desktop they\n\t\tduplicate the toolbar above and put a SECOND slide counter on screen.\n\n\t\tRendered BEFORE the show toolbar, as React renders its touch controls,\n\t\tbecause both carry the same accessible names (\"Next Slide\", \"Previous\n\t\tSlide\", \"End Presentation\"). On a coarse pointer the toolbar's copies are\n\t\tstill in the DOM but inert (`pointer-events: none`), so whichever comes\n\t\tfirst is what a by-name lookup - a screen reader's, or a spec's `.first()`\n\t\t- resolves to. With the toolbar first, every such lookup landed on a\n\t\tbutton no user could press: it reported itself visible and enabled, and\n\t\tthe tap was swallowed by the overlay. Position is fixed on all of these,\n\t\tso moving them in the DOM does not move them on screen.\n\t-->\n\t<!-- Always-visible close button (top-right, safe-area aware). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-close\"\n\t\t[ngStyle]=\"closeButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'close')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'close')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.endPresentation' | translate\"\n\t>\n\t\t<svg lucideX class=\"h-5 w-5\"></svg>\n\t</button>\n\n\t<!-- Edge navigation buttons (vertically centred, touch-friendly). -->\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-prev\"\n\t\t[ngStyle]=\"prevButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'prev')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'prev')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.previousSlide' | translate\"\n\t>\n\t\t<svg lucideChevronLeft class=\"h-6 w-6\"></svg>\n\t</button>\n\t<button\n\t\ttype=\"button\"\n\t\tclass=\"pptx-ng-presentation-nav pptx-ng-presentation-next\"\n\t\t[ngStyle]=\"nextButtonStyle\"\n\t\t(click)=\"onChromeButton($event, 'next')\"\n\t\t(touchend)=\"onChromeButtonTouch($event, 'next')\"\n\t\t[attr.aria-label]=\"'pptx.presenter.nextSlide' | translate\"\n\t>\n\t\t<svg lucideChevronRight class=\"h-6 w-6\"></svg>\n\t</button>\n\n\t<!--\n\t\tThe show toolbar (bottom-centre, auto-hiding): navigation, counter,\n\t\telapsed time, annotation tools, presenter view and end-show, per\n\t\t`PRESENT_TOOLBAR_CONTROLS` in pptx-viewer-shared.\n\t-->\n\t<pptx-presentation-toolbar\n\t\t#toolbar\n\t\t[currentSlideIndex]=\"currentIndex()\"\n\t\t[totalSlides]=\"slides().length\"\n\t\t[presentationStartTime]=\"showStartedAt\"\n\t\t[presenterMode]=\"presenterMode()\"\n\t\t[popupToolbarEnabled]=\"showPopupToolbar()\"\n\t\t(move)=\"navigator.navigate($event === 1 ? 'next' : 'prev')\"\n\t\t(presenterViewToggle)=\"presenterViewToggle.emit()\"\n\t\t(endPresentation)=\"onToolbarEnd()\"\n\t/>\n\n\t<!--\n\t\tPowerPoint's \"See All Slides\" (Ctrl+S during a show). The same navigator\n\t\tthe presenter console uses, laid over the show itself: the shortcut exists\n\t\tso a presenter can reach a backup slide WITHOUT leaving the show, so it\n\t\tmust not be a door into presenter view.\n\t-->\n\t@if (allSlidesOpen()) {\n\t\t<pptx-presenter-slide-navigator\n\t\t\t[slides]=\"slides()\"\n\t\t\t[current]=\"currentIndex()\"\n\t\t\t[canvasSize]=\"canvasSize()\"\n\t\t\t[mediaDataUrls]=\"mediaDataUrls()\"\n\t\t\t(select)=\"onNavigatorSelect($event)\"\n\t\t\t(close)=\"allSlidesOpen.set(false)\"\n\t\t/>\n\t}\n\n\t<!-- Slide-show right-click menu. -->\n\t@if (contextMenuState(); as pos) {\n\t\t<pptx-presentation-context-menu\n\t\t\t[x]=\"pos.x\"\n\t\t\t[y]=\"pos.y\"\n\t\t\t(action)=\"onContextMenuAction($event)\"\n\t\t\t(closed)=\"contextMenuState.set(null)\"\n\t\t/>\n\t}\n</div>\n", styles: [":host{display:block;position:fixed;inset:0;z-index:10000;background:#000;cursor:pointer;-webkit-user-select:none;user-select:none;overflow:hidden}.pptx-ng-presentation-root{position:absolute;inset:0;touch-action:pan-y;overflow:hidden}.pptx-ng-presentation-close:hover,.pptx-ng-presentation-nav:hover{background:#000000bf}@media not all and (any-pointer:coarse){.pptx-ng-presentation-close,.pptx-ng-presentation-nav,.pptx-ng-presentation-counter{display:none!important}}.presenter-blank{position:absolute;inset:0;z-index:75;pointer-events:none}.pptx-ng-presentation-end{position:absolute;inset:0;z-index:90;display:flex;align-items:flex-start;border:0;padding:0;background:#000;text-align:left;cursor:default}.pptx-ng-presentation-end span{padding:.75rem 1rem;color:#ffffffb3;font-size:12px}.presenter-laser{position:absolute;z-index:76;width:20px;height:20px;transform:translate(-50%,-50%);border-radius:50%;background:#ef4444;box-shadow:0 0 20px 8px #ef444488;pointer-events:none}.presenter-caption{position:absolute;z-index:77;left:10%;right:10%;bottom:2rem;padding:.75rem 1.5rem;border-radius:.5rem;background:#000c;color:#fff;text-align:center;font-size:1.25rem;pointer-events:none}\n"] }]
111695
- }], ctorParameters: () => [], propDecorators: { slides: [{ type: i0.Input, args: [{ isSignal: true, alias: "slides", required: true }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], startIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "startIndex", required: false }] }], activeCustomShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeCustomShow", required: false }] }], showWithAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "showWithAnimation", required: false }] }], useTimings: [{ type: i0.Input, args: [{ isSignal: true, alias: "useTimings", required: false }] }], subtitlesVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitlesVisible", required: false }] }], sessionEnded: [{ type: i0.Input, args: [{ isSignal: true, alias: "sessionEnded", required: false }] }], endWithBlackSlide: [{ type: i0.Input, args: [{ isSignal: true, alias: "endWithBlackSlide", required: false }] }], presenterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenterMode", required: false }] }], showMenuOnRightClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMenuOnRightClick", required: false }] }], showPopupToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPopupToolbar", required: false }] }], indexChange: [{ type: i0.Output, args: ["indexChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], subtitlesChange: [{ type: i0.Output, args: ["subtitlesChange"] }], presenterViewToggle: [{ type: i0.Output, args: ["presenterViewToggle"] }], annotationsExit: [{ type: i0.Output, args: ["annotationsExit"] }], stageRef: [{ type: i0.ViewChild, args: ['stage', { isSignal: true }] }], rootRef: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }], toolbarRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => PresentationToolbarComponent), { isSignal: true }] }], onWheel: [{
113401
+ }], ctorParameters: () => [], propDecorators: { slides: [{ type: i0.Input, args: [{ isSignal: true, alias: "slides", required: true }] }], canvasSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "canvasSize", required: true }] }], mediaDataUrls: [{ type: i0.Input, args: [{ isSignal: true, alias: "mediaDataUrls", required: false }] }], startIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "startIndex", required: false }] }], activeCustomShow: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeCustomShow", required: false }] }], authoredRange: [{ type: i0.Input, args: [{ isSignal: true, alias: "authoredRange", required: false }] }], loopContinuously: [{ type: i0.Input, args: [{ isSignal: true, alias: "loopContinuously", required: false }] }], showWithAnimation: [{ type: i0.Input, args: [{ isSignal: true, alias: "showWithAnimation", required: false }] }], useTimings: [{ type: i0.Input, args: [{ isSignal: true, alias: "useTimings", required: false }] }], subtitlesVisible: [{ type: i0.Input, args: [{ isSignal: true, alias: "subtitlesVisible", required: false }] }], sessionEnded: [{ type: i0.Input, args: [{ isSignal: true, alias: "sessionEnded", required: false }] }], endWithBlackSlide: [{ type: i0.Input, args: [{ isSignal: true, alias: "endWithBlackSlide", required: false }] }], presenterMode: [{ type: i0.Input, args: [{ isSignal: true, alias: "presenterMode", required: false }] }], showMenuOnRightClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "showMenuOnRightClick", required: false }] }], showPopupToolbar: [{ type: i0.Input, args: [{ isSignal: true, alias: "showPopupToolbar", required: false }] }], indexChange: [{ type: i0.Output, args: ["indexChange"] }], closed: [{ type: i0.Output, args: ["closed"] }], subtitlesChange: [{ type: i0.Output, args: ["subtitlesChange"] }], presenterViewToggle: [{ type: i0.Output, args: ["presenterViewToggle"] }], annotationsExit: [{ type: i0.Output, args: ["annotationsExit"] }], stageRef: [{ type: i0.ViewChild, args: ['stage', { isSignal: true }] }], rootRef: [{ type: i0.ViewChild, args: ['root', { isSignal: true }] }], toolbarRef: [{ type: i0.ViewChild, args: [i0.forwardRef(() => PresentationToolbarComponent), { isSignal: true }] }], onWheel: [{
111696
113402
  type: HostListener,
111697
113403
  args: ['document:wheel', ['$event']]
111698
113404
  }], onFullscreenChange: [{
@@ -117194,27 +118900,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
117194
118900
  * inventory spec diffs controls by accessible name and every other binding
117195
118901
  * settled on the context-menu wording.
117196
118902
  */
117197
- /** Outline thickness the renderer assumes when the shape declares none. */
117198
- const DEFAULT_STROKE_WIDTH = 1;
117199
- /** Grouping needs an editable deck and at least two selected elements. */
117200
- function canGroupSelection(canEdit, selectedCount) {
117201
- return canEdit && selectedCount >= 2;
117202
- }
117203
- /** Ungrouping needs an editable deck and a selection that IS a group. */
117204
- function canUngroupSelection(canEdit, element) {
117205
- return canEdit && element?.type === 'group';
117206
- }
117207
- /** An outline width only exists on an element that carries shape properties. */
117208
- function canSetStrokeWidth(canEdit, element) {
117209
- return canEdit && element !== null && hasShapeProperties(element);
117210
- }
117211
- /** The stroke width to show for a selection, defaulted for a shape without one. */
117212
- function strokeWidthOf(element) {
117213
- if (element === null || !hasShapeProperties(element)) {
117214
- return DEFAULT_STROKE_WIDTH;
117215
- }
117216
- return element.shapeStyle?.strokeWidth ?? DEFAULT_STROKE_WIDTH;
117217
- }
117218
118903
  class RibbonShapeExtrasComponent {
117219
118904
  constructor() {
117220
118905
  this.editor = inject(EditorStateService);
@@ -118400,7 +120085,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
118400
120085
  }], propDecorators: { canEdit: [{ type: i0.Input, args: [{ isSignal: true, alias: "canEdit", required: false }] }], slideIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideIndex", required: false }] }], selectedElement: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedElement", required: false }] }] } });
118401
120086
 
118402
120087
  // Generated by scripts/inline-shared.mjs from package.json. Do not edit.
118403
- const PPTX_ANGULAR_VIEWER_VERSION = "3.2.3";
120088
+ const PPTX_ANGULAR_VIEWER_VERSION = "3.3.0";
118404
120089
 
118405
120090
  /**
118406
120091
  * account-page.component.ts: File > Account content.
@@ -118756,7 +120441,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
118756
120441
  * {@link RibbonComponent}'s `fontControls` ng-template so the Home and Text tabs
118757
120442
  * share one implementation. Behaviour and markup are unchanged.
118758
120443
  */
118759
- const FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 44, 54, 66, 80, 96];
120444
+ /**
120445
+ * The Home/Text tab's size dropdown + grow/shrink ladder. Sourced from shared
120446
+ * so it cannot drift from the other bindings' Font control group.
120447
+ */
120448
+ const FONT_SIZES = COMMON_FONT_SIZES;
118760
120449
  /** Font-colour swatches in the Home/Text colour popover (mirrors React/Vue). */
118761
120450
  const FONT_COLOR_PRESETS = [
118762
120451
  '#000000',
@@ -127280,6 +128969,17 @@ class ChartDisplayOptionsComponent {
127280
128969
  this.legendPositions = LEGEND_POSITION_OPTIONS;
127281
128970
  this.style = computed(() => this.element().chartData?.style ?? {}, /* @ts-ignore */
127282
128971
  ...(ngDevMode ? [{ debugName: "style" }] : /* istanbul ignore next */ []));
128972
+ /**
128973
+ * Read from the primary value axis's `majorGridlines`, matching what the
128974
+ * cartesian renderer actually draws; `style.hasGridlines` alone is a legacy
128975
+ * field the renderer never reads, so wiring the checkbox straight to it
128976
+ * silently did nothing (see `chart-gridlines-toggle.ts` in shared).
128977
+ */
128978
+ this.gridlinesShown = computed(() => {
128979
+ const chartData = this.element().chartData;
128980
+ return chartData ? chartGridlinesState(chartData) : false;
128981
+ }, /* @ts-ignore */
128982
+ ...(ngDevMode ? [{ debugName: "gridlinesShown" }] : /* istanbul ignore next */ []));
127283
128983
  }
127284
128984
  onToggleTitle(event) {
127285
128985
  this.elementChange.emit(patchChartStyle(this.element(), { hasTitle: boolFromEvent(event) }));
@@ -127295,7 +128995,11 @@ class ChartDisplayOptionsComponent {
127295
128995
  this.elementChange.emit(setLegend(this.element(), { position: value }));
127296
128996
  }
127297
128997
  onToggleGridlines(event) {
127298
- this.elementChange.emit(patchChartStyle(this.element(), { hasGridlines: boolFromEvent(event) }));
128998
+ const chartData = this.element().chartData;
128999
+ if (!chartData) {
129000
+ return;
129001
+ }
129002
+ this.elementChange.emit(patchChartData(this.element(), chartGridlinesPatch(chartData, boolFromEvent(event))));
127299
129003
  }
127300
129004
  onToggleDataLabels(event) {
127301
129005
  // Route through the dedicated op so content keys initialise consistently.
@@ -127349,7 +129053,7 @@ class ChartDisplayOptionsComponent {
127349
129053
  <input
127350
129054
  type="checkbox"
127351
129055
  [disabled]="!canEdit()"
127352
- [checked]="style().hasGridlines ?? false"
129056
+ [checked]="gridlinesShown()"
127353
129057
  (change)="onToggleGridlines($event)"
127354
129058
  />
127355
129059
  <span>{{ 'pptx.chart.showGridlines' | translate }}</span>
@@ -127417,7 +129121,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
127417
129121
  <input
127418
129122
  type="checkbox"
127419
129123
  [disabled]="!canEdit()"
127420
- [checked]="style().hasGridlines ?? false"
129124
+ [checked]="gridlinesShown()"
127421
129125
  (change)="onToggleGridlines($event)"
127422
129126
  />
127423
129127
  <span>{{ 'pptx.chart.showGridlines' | translate }}</span>
@@ -128800,6 +130504,17 @@ class EffectsPanelComponent {
128800
130504
  }
128801
130505
  this.emit(updateOuterShadowPatch(el, { [field]: val }));
128802
130506
  }
130507
+ /**
130508
+ * `a:outerShdw@rotWithShape`: whether the shadow rotates along with the
130509
+ * shape. PowerPoint defaults to `true` when the attribute is absent.
130510
+ */
130511
+ onOuterShadowRotateWithShapeToggle(event) {
130512
+ const checked = checkedFromEvent$1(event);
130513
+ if (checked === null) {
130514
+ return;
130515
+ }
130516
+ this.emit(updateOuterShadowPatch(this.element(), { rotateWithShape: checked }));
130517
+ }
128803
130518
  // ── Inner shadow ──────────────────────────────────────────────────────────
128804
130519
  onInnerShadowToggle(event) {
128805
130520
  const checked = checkedFromEvent$1(event);
@@ -128968,6 +130683,16 @@ class EffectsPanelComponent {
128968
130683
  [value]="state().outerShadow.distance"
128969
130684
  (change)="onOuterShadowField('distance', $event)"
128970
130685
  />
130686
+ <label class="pptx-ng-fx__toggle-row" for="fx-os-rotate-with-shape">
130687
+ <input
130688
+ id="fx-os-rotate-with-shape"
130689
+ type="checkbox"
130690
+ class="pptx-ng-fx__checkbox"
130691
+ [checked]="state().outerShadow.rotateWithShape"
130692
+ (change)="onOuterShadowRotateWithShapeToggle($event)"
130693
+ />
130694
+ <span>{{ 'pptx.effects.rotateWithShape' | translate }}</span>
130695
+ </label>
128971
130696
  </div>
128972
130697
  }
128973
130698
  </section>
@@ -129306,6 +131031,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
129306
131031
  [value]="state().outerShadow.distance"
129307
131032
  (change)="onOuterShadowField('distance', $event)"
129308
131033
  />
131034
+ <label class="pptx-ng-fx__toggle-row" for="fx-os-rotate-with-shape">
131035
+ <input
131036
+ id="fx-os-rotate-with-shape"
131037
+ type="checkbox"
131038
+ class="pptx-ng-fx__checkbox"
131039
+ [checked]="state().outerShadow.rotateWithShape"
131040
+ (change)="onOuterShadowRotateWithShapeToggle($event)"
131041
+ />
131042
+ <span>{{ 'pptx.effects.rotateWithShape' | translate }}</span>
131043
+ </label>
129309
131044
  </div>
129310
131045
  }
129311
131046
  </section>
@@ -143825,139 +145560,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
143825
145560
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }], properties: [{ type: i0.Input, args: [{ isSignal: true, alias: "properties", required: false }] }], customShows: [{ type: i0.Input, args: [{ isSignal: true, alias: "customShows", required: false }] }], slideCount: [{ type: i0.Input, args: [{ isSignal: true, alias: "slideCount", required: false }] }], save: [{ type: i0.Output, args: ["save"] }], close: [{ type: i0.Output, args: ["close"] }] } });
143826
145561
 
143827
145562
  /**
143828
- * Detailed AI chat-log export for technical / debugging use. Angular replica of
143829
- * React's `utils/ai-log-export.ts`; kept in-binding because the shared package
143830
- * is consumed read-only here (only the pure `createChatHistoryStore` +
143831
- * `toRenderableParts` helpers are reused from shared).
143832
- *
143833
- * The AI settings section lets technical users download the full transcript of
143834
- * every stored assistant chat, INCLUDING each tool call's name, input, state and
143835
- * output/error text (the detail the panel only surfaces in collapsed cards). The
143836
- * primary artifact is machine-readable JSON; a human-readable Markdown transcript
143837
- * is also offered.
145563
+ * Angular wiring for the shared AI chat-log export. The document-building
145564
+ * logic (`buildChatLogExport` / `buildChatLogMarkdown` / `collectStoredChats`)
145565
+ * is pure and DOM-free and lives in `pptx-viewer-shared`; this file only adds
145566
+ * the two pieces that are genuinely binding-shaped: reading from a default
145567
+ * store and triggering the actual browser download via `downloadBlob`.
143838
145568
  */
143839
- function isoOf(ms) {
143840
- const n = Number.isFinite(ms) ? ms : 0;
143841
- return new Date(n).toISOString();
143842
- }
143843
- /** Convert one stored chat into its detailed export form. */
143844
- function toLogChat(chat, detailed) {
143845
- const messages = chat.messages.map((message) => {
143846
- const parts = toRenderableParts(message);
143847
- const textRuns = [];
143848
- const toolCalls = [];
143849
- for (const part of parts) {
143850
- if (part.kind === 'text') {
143851
- textRuns.push(part.text);
143852
- continue;
143853
- }
143854
- toolCalls.push({
143855
- toolName: part.toolName,
143856
- toolCallId: part.toolCallId,
143857
- state: part.state,
143858
- input: detailed ? part.input : undefined,
143859
- output: detailed ? part.output : undefined,
143860
- errorText: part.errorText,
143861
- });
143862
- }
143863
- return { role: message.role, text: textRuns.join('\n\n'), toolCalls };
143864
- });
143865
- return {
143866
- id: chat.id,
143867
- title: chat.title,
143868
- deckId: chat.deckId,
143869
- createdAt: chat.createdAt,
143870
- updatedAt: chat.updatedAt,
143871
- createdAtIso: isoOf(chat.createdAt),
143872
- updatedAtIso: isoOf(chat.updatedAt),
143873
- messageCount: chat.messages.length,
143874
- messages,
143875
- };
143876
- }
143877
- /** Build the detailed export document from already-loaded chats (pure). */
143878
- function buildChatLogExport(chats, options) {
143879
- const detailed = options?.detailed ?? true;
143880
- const now = options?.now ?? Date.now();
143881
- return {
143882
- format: 'pptx-ai-chat-log',
143883
- version: 1,
143884
- exportedAt: isoOf(now),
143885
- detailed,
143886
- chatCount: chats.length,
143887
- chats: chats.map((chat) => toLogChat(chat, detailed)),
143888
- };
143889
- }
143890
- function toolCallLine(call, detailed) {
143891
- const lines = [`- Tool \`${call.toolName}\` (${call.state})`];
143892
- if (call.errorText) {
143893
- lines.push(` - error: ${call.errorText}`);
143894
- }
143895
- if (detailed) {
143896
- lines.push(' - input:');
143897
- lines.push(' ```json');
143898
- lines.push(JSON.stringify(call.input ?? null, null, 2));
143899
- lines.push(' ```');
143900
- lines.push(' - output:');
143901
- lines.push(' ```json');
143902
- lines.push(JSON.stringify(call.output ?? null, null, 2));
143903
- lines.push(' ```');
143904
- }
143905
- return lines.join('\n');
143906
- }
143907
- /** Render the same detailed export as a human-readable Markdown transcript. */
143908
- function buildChatLogMarkdown(doc) {
143909
- const out = [
143910
- `# AI chat logs`,
143911
- '',
143912
- `Exported: ${doc.exportedAt}`,
143913
- `Chats: ${doc.chatCount}`,
143914
- '',
143915
- ];
143916
- for (const chat of doc.chats) {
143917
- out.push(`## ${chat.title || chat.id}`);
143918
- out.push('');
143919
- out.push(`- id: ${chat.id}`);
143920
- if (chat.deckId) {
143921
- out.push(`- deck: ${chat.deckId}`);
143922
- }
143923
- out.push(`- created: ${chat.createdAtIso}`);
143924
- out.push(`- updated: ${chat.updatedAtIso}`);
143925
- out.push(`- messages: ${chat.messageCount}`);
143926
- out.push('');
143927
- for (const message of chat.messages) {
143928
- out.push(`### ${message.role}`);
143929
- out.push('');
143930
- if (message.text) {
143931
- out.push(message.text);
143932
- out.push('');
143933
- }
143934
- for (const call of message.toolCalls) {
143935
- out.push(toolCallLine(call, doc.detailed));
143936
- out.push('');
143937
- }
143938
- }
143939
- }
143940
- return out.join('\n');
143941
- }
143942
- /** Load every stored chat (newest first) in full detail from a store. */
143943
- async function collectStoredChats(store) {
143944
- const summaries = await store.listChats();
143945
- const chats = [];
143946
- for (const summary of summaries) {
143947
- const chat = await store.loadChat(summary.id);
143948
- if (chat) {
143949
- chats.push(chat);
143950
- }
143951
- }
143952
- return chats;
143953
- }
143954
- function timestampSlug(now) {
143955
- // YYYYMMDD-HHmmss in local time; stable, filesystem-safe.
143956
- const d = new Date(now);
143957
- const p = (n) => String(n).padStart(2, '0');
143958
- return (`${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}` +
143959
- `-${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}`);
143960
- }
143961
145569
  /**
143962
145570
  * Read all stored chats and trigger a browser download of the detailed log.
143963
145571
  *
@@ -143966,23 +145574,10 @@ function timestampSlug(now) {
143966
145574
  */
143967
145575
  async function exportAiChatLogs(options) {
143968
145576
  const store = options?.store ?? createChatHistoryStore();
143969
- const format = options?.format ?? 'json';
143970
- const now = options?.now ?? Date.now();
143971
145577
  const chats = await collectStoredChats(store);
143972
- if (chats.length === 0) {
143973
- return 0;
143974
- }
143975
- const doc = buildChatLogExport(chats, { detailed: options?.detailed ?? true, now });
143976
- const slug = timestampSlug(now);
143977
- if (format === 'markdown') {
143978
- const blob = new Blob([buildChatLogMarkdown(doc)], { type: 'text/markdown' });
143979
- downloadBlob(blob, `pptx-ai-chats-${slug}.md`);
143980
- }
143981
- else {
143982
- const blob = new Blob([JSON.stringify(doc, null, 2)], { type: 'application/json' });
143983
- downloadBlob(blob, `pptx-ai-chats-${slug}.json`);
143984
- }
143985
- return chats.length;
145578
+ return exportAiChatLogs$1(chats, options, (filename, content, mime) => {
145579
+ downloadBlob(new Blob([content], { type: mime }), filename);
145580
+ });
143986
145581
  }
143987
145582
 
143988
145583
  /**
@@ -146689,6 +148284,14 @@ class PowerPointViewerComponent {
146689
148284
  this.xport = inject(ViewerExportService);
146690
148285
  this.findReplace = inject(ViewerFindReplaceService);
146691
148286
  this.customShowsCtl = inject(ViewerCustomShowsService);
148287
+ /**
148288
+ * The `p:showPr/p:sldRg` slide-range restriction, when the deck is authored
148289
+ * to open into a range (`showSlidesMode === 'range'`) rather than the whole
148290
+ * deck or a custom show. Fed to the presentation overlay's navigator
148291
+ * alongside `activeCustomShow` so a running show honours it.
148292
+ */
148293
+ this.presentationAuthoredRange = computed(() => resolveAuthoredSlideRange(this.loader.presentationProperties(), this.loader.slides().length) ?? null, /* @ts-ignore */
148294
+ ...(ngDevMode ? [{ debugName: "presentationAuthoredRange" }] : /* istanbul ignore next */ []));
146692
148295
  this.session = inject(ViewerCollaborationSessionService);
146693
148296
  this.formatPainter = inject(ViewerFormatPainterService);
146694
148297
  this.keyboard = inject(ViewerKeyboardService);
@@ -148910,6 +150513,8 @@ class PowerPointViewerComponent {
148910
150513
  [mediaDataUrls]="loader.mediaDataUrls()"
148911
150514
  [startIndex]="customShowsCtl.presentationStartIndex()"
148912
150515
  [activeCustomShow]="customShowsCtl.activeCustomShow()"
150516
+ [authoredRange]="presentationAuthoredRange()"
150517
+ [loopContinuously]="loader.presentationProperties().loopContinuously ?? false"
148913
150518
  [showWithAnimation]="loader.presentationProperties().showWithAnimation"
148914
150519
  [useTimings]="loader.presentationProperties().advanceMode !== 'manual'"
148915
150520
  [subtitlesVisible]="presentationMode.subtitlesVisible()"
@@ -149238,7 +150843,7 @@ class PowerPointViewerComponent {
149238
150843
  />
149239
150844
  }
149240
150845
  </div>
149241
- `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "gridSpacing", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "exposeElementIds", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "transformEnd", "adjustUpdate", "connectorEndpointUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationOverlayComponent, selector: "pptx-presentation-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "startIndex", "activeCustomShow", "showWithAnimation", "useTimings", "subtitlesVisible", "sessionEnded", "endWithBlackSlide", "presenterMode", "showMenuOnRightClick", "showPopupToolbar"], outputs: ["indexChange", "closed", "subtitlesChange", "presenterViewToggle", "annotationsExit"] }, { kind: "component", type: PresenterViewComponent, selector: "pptx-presenter-view", inputs: ["slides", "currentSlideIndex", "activeCustomShow", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime", "isAudienceWindowOpen"], outputs: ["movePresentationSlide", "exit", "openAudienceWindow", "closeAudienceWindow", "navigateToSlide"] }, { kind: "component", type: MobilePresenterViewComponent, selector: "pptx-mobile-presenter-view", inputs: ["slides", "currentSlideIndex", "activeCustomShow", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime"], outputs: ["movePresentationSlide", "exit"] }, { kind: "component", type: SlideSorterOverlayComponent, selector: "pptx-slide-sorter-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeIndex", "canEdit"], outputs: ["select", "closed", "deleteSlide", "duplicateSlide", "toggleHiddenSlide"] }, { kind: "component", type: OutlineViewOverlayComponent, selector: "pptx-outline-view-overlay", inputs: ["slides", "canvasSize", "canEdit"], outputs: ["commit", "closed"] }, { kind: "component", type: ReadingViewOverlayComponent, selector: "pptx-reading-view-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeSlideIndex"], outputs: ["exit"] }, { kind: "component", type: SlideDefaultInspectorComponent, selector: "pptx-slide-default-inspector", inputs: ["slideIndex", "canEdit", "selectedElement", "comments"], outputs: ["commentAdd", "commentRemove", "commentResolve", "commentReply"] }, { kind: "component", type: FindBarComponent, selector: "pptx-find-bar", inputs: ["slides"], outputs: ["navigate", "closed"] }, { kind: "component", type: FindReplaceBarComponent, selector: "pptx-find-replace-bar", inputs: ["matchCount", "matchIndex"], outputs: ["find", "navigate", "replaceOne", "replaceAll", "close"] }, { kind: "component", type: SlidesPanelComponent, selector: "pptx-slides-panel", inputs: ["canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["select"] }, { kind: "component", type: StatusBarComponent, selector: "pptx-status-bar", inputs: ["slideIndex", "slideCount", "canEdit", "dirty", "autosaveStatus", "notesOpen", "zoomPercent", "sorterActive", "presenting", "hiddenActions"], outputs: ["toggleNotes", "normalView", "openSorter", "slideShow", "zoomIn", "zoomOut", "zoomReset"] }, { kind: "component", type: EditorContextMenuComponent, selector: "pptx-editor-context-menu", inputs: ["x", "y", "slideIndex", "showAiActions"], outputs: ["closed", "askAi", "fixAi", "editHyperlink", "addComment"] }, { kind: "component", type: ExportProgressModalComponent, selector: "pptx-export-progress-modal", inputs: ["open", "title", "progress", "statusMessage"], outputs: ["cancel"] }, { kind: "component", type: CommentMarkersOverlayComponent, selector: "pptx-comment-markers-overlay", inputs: ["comments", "canvasSize"], outputs: ["markerClick"] }, { kind: "component", type: CommentsPanelComponent, selector: "pptx-comments-panel", inputs: ["comments", "authorName"], outputs: ["add", "remove", "resolve", "reply"] }, { kind: "component", type: SignaturesPanelComponent, selector: "pptx-signatures-panel", inputs: ["signatures"] }, { kind: "component", type: AccessibilityPanelComponent, selector: "pptx-accessibility-panel", inputs: ["issues"], outputs: ["selectSlide"] }, { kind: "component", type: CollaborationCursorsComponent, selector: "pptx-collaboration-cursors", inputs: ["cursors", "zoom"] }, { kind: "component", type: RemoteSelectionOverlayComponent, selector: "pptx-remote-selection-overlay", inputs: ["presences", "elements", "activeSlideIndex", "zoom"] }, { kind: "component", type: MotionPathOverlayComponent, selector: "pptx-motion-path-overlay", inputs: ["element", "animations", "canvasSize", "canEdit"], outputs: ["pathChange"] }, { kind: "component", type: FollowModeBarComponent, selector: "pptx-follow-mode-bar", inputs: ["presences", "followedClientId"], outputs: ["follow"] }, { kind: "component", type: PropertiesDialogComponent, selector: "pptx-properties-dialog", inputs: ["open", "properties"], outputs: ["save", "close"] }, { kind: "component", type: HyperlinkDialogComponent, selector: "pptx-hyperlink-dialog", inputs: ["open", "element"], outputs: ["save", "close"] }, { kind: "component", type: PrintDialogComponent, selector: "pptx-print-dialog", inputs: ["slides", "activeSlideIndex", "defaultSlidesPerPage", "defaultFrameSlides", "defaultSettings"], outputs: ["print", "cancel"] }, { kind: "component", type: ShareDialogComponent, selector: "pptx-share-dialog", inputs: ["open", "defaults", "active", "connected", "userCount", "shareUrl", "p2p", "activeRoomId", "activeServerUrl", "users"], outputs: ["start", "stop", "close"] }, { kind: "component", type: BroadcastDialogComponent, selector: "pptx-broadcast-dialog", inputs: ["open", "defaults", "active", "connected", "viewerCount", "viewerUrl", "p2p"], outputs: ["start", "stop", "close"] }, { kind: "component", type: MobileBottomBarComponent, selector: "pptx-mobile-bottom-bar", inputs: ["slideCount", "commentCount", "activeSheet"], outputs: ["openSlides", "insert", "openFormat", "openComments", "notes"] }, { kind: "component", type: MobileMenuSheetComponent, selector: "pptx-mobile-menu-sheet", inputs: ["open", "slideCount", "exporting", "showNotes", "canEdit", "hiddenActions"], outputs: ["closed", "openFind", "openSorter", "toggleNotes", "insertText", "present", "openFile", "savePptx", "exportPng", "exportPdf", "exportGif", "exportVideo", "print"] }, { kind: "component", type: MobileSlidesSheetComponent, selector: "pptx-mobile-slides-sheet", inputs: ["open", "slides", "canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["closed", "jumpToSlide"] }, { kind: "component", type: MobileToolbarComponent, selector: "pptx-mobile-toolbar", inputs: ["canUndo", "canRedo", "canPresent", "canEdit", "menuOpen", "aiEnabled", "aiPanelOpen", "hiddenActions"], outputs: ["toggleMenu", "toggleAiPanel", "undo", "redo", "share", "save", "present"] }, { kind: "component", type: MasterViewCanvasComponent, selector: "pptx-master-view-canvas", inputs: ["tab", "slideMasters", "activeMasterIndex", "activeLayoutIndex", "notesMaster", "handoutMaster", "canvasSize", "notesCanvasSize", "mediaDataUrls", "editable"], outputs: ["notesMasterChange", "handoutMasterChange", "slideMastersChange"] }, { kind: "component", type: MasterViewSidebarComponent, selector: "pptx-master-view-sidebar", inputs: ["tab", "slideMasters", "notesMaster", "handoutMaster", "activeMasterIndex", "activeLayoutIndex", "handoutSlidesPerPage", "editable"], outputs: ["tabChange", "selectMaster", "selectLayout", "slidesPerPageChange", "backgroundChange", "close"] }, { kind: "component", type: NotesPanelComponent, selector: "pptx-notes-panel", inputs: ["slide", "expanded", "notesStyle"], outputs: ["update", "notesToggle"] }, { kind: "component", type: QuickAccessStripComponent, selector: "pptx-quick-access-strip", inputs: ["quickAccess", "canUndo", "canRedo"], outputs: ["command"] }, { kind: "component", type: RibbonComponent, selector: "pptx-ribbon", inputs: ["slideIndex", "slideCount", "canEdit", "selectedElement", "zoomPercent", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "findOpen", "collabConnected", "connectedCount", "spellCheckEnabled", "showSubtitles", "hiddenActions", "aiEnabled", "aiPanelOpen", "accountAuth", "activeSlideHidden"], outputs: ["prev", "next", "zoomIn", "zoomOut", "zoomReset", "find", "present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "share", "broadcast", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "toggleSidebar", "toggleAiPanel", "signatures", "info", "print", "comments", "a11y", "shortcuts", "versionHistory", "passwordProtection", "fontEmbedding", "link", "openSorter", "openReadingView", "openOutlineView", "openMasterView", "toggleNotes", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "exportJson", "copySlideAsImage", "replace", "toggleInspector", "drawToolChange", "toggleThemeGallery", "editTheme", "openSlideSize", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSmartArtDialog", "openTemplateGallery", "openEquationDialog", "openSetUpSlideShow", "toggleHideSlide", "openCompare", "openPassword", "openFontEmbedding", "openVersionHistory", "openShortcuts", "openSettings"] }, { kind: "component", type: TitleBarComponent, selector: "pptx-title-bar", inputs: ["canEdit", "fileName", "isDirty", "autosaveStatus", "autosaveEnabled", "canUndo", "canRedo", "undoLabel", "redoLabel", "findReplaceOpen", "hiddenActions", "quickAccess"], outputs: ["toggleAutosave", "save", "undo", "redo", "quickCommand", "toggleFindReplace", "commandSearch"] }, { kind: "component", type: ThemeGalleryComponent, selector: "pptx-theme-gallery", inputs: ["open", "activeName", "theme", "startCustomizing"], outputs: ["applyTheme", "applyCustomTheme", "close"] }, { kind: "component", type: SelectionPaneComponent, selector: "pptx-selection-pane", inputs: ["elements", "selectedIds"], outputs: ["selectElement", "bringForward", "sendBackward", "toggleHidden", "renameElement"] }, { kind: "component", type: CustomShowsComponent, selector: "pptx-custom-shows", inputs: ["open", "slides", "customShows", "activeCustomShowId"], outputs: ["create", "remove", "update", "setActive", "close"] }, { kind: "component", type: InsertSmartArtDialogComponent, selector: "pptx-insert-smart-art-dialog", inputs: ["open"], outputs: ["close", "insert"] }, { kind: "component", type: SlideTemplateGalleryDialogComponent, selector: "pptx-slide-template-gallery-dialog", inputs: ["open", "scheme"], outputs: ["close", "insert"] }, { kind: "component", type: ViewerExtraDialogsComponent, selector: "pptx-viewer-extra-dialogs", inputs: ["activeSlideIndex", "selectedElementId", "filePath", "customShows", "themeKey", "availableThemes", "localeCode", "availableLocales", "aiExportVisible"], outputs: ["restoreContent", "themeKeySelect", "localeSelect"] }, { kind: "component", type: AutosaveRecoveryDialogComponent, selector: "pptx-autosave-recovery-dialog", inputs: ["prompt"], outputs: ["restore", "discard"] }, { kind: "component", type: RehearseTimingsComponent, selector: "pptx-rehearse-timings", inputs: ["summary", "paused", "slideStartedAt", "presentationStartedAt", "timings"], outputs: ["togglePause", "save", "discard"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [/* @ts-ignore */
150846
+ `, isInline: true, dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: SlideCanvasComponent, selector: "pptx-slide-canvas", inputs: ["slide", "canvasSize", "mediaDataUrls", "zoom", "editable", "showGrid", "showRulers", "rulerUnit", "showGuides", "snapToGrid", "gridSpacing", "snapToShape", "guideCommand", "spellCheck", "snapToGuides", "autoFit", "transparentBackground", "interactive", "exposeElementIds", "presenting", "selectedIds", "editingId", "editTemplateMode", "templateElements", "aiHighlights", "aiActive", "aiActiveSlideIndex", "aiChangeBatch", "aiPickMode", "drawTool", "drawColor", "drawWidth"], outputs: ["elementSelect", "backgroundClick", "transformStart", "transformUpdate", "transformEnd", "adjustUpdate", "connectorEndpointUpdate", "contextMenu", "textEditStart", "textCommit", "textInput", "textCancel", "textFormat", "rotateUpdate", "marqueeSelect", "inkStrokeComplete", "eraserHit", "cellCommit", "tableChange"] }, { kind: "component", type: PresentationOverlayComponent, selector: "pptx-presentation-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "startIndex", "activeCustomShow", "authoredRange", "loopContinuously", "showWithAnimation", "useTimings", "subtitlesVisible", "sessionEnded", "endWithBlackSlide", "presenterMode", "showMenuOnRightClick", "showPopupToolbar"], outputs: ["indexChange", "closed", "subtitlesChange", "presenterViewToggle", "annotationsExit"] }, { kind: "component", type: PresenterViewComponent, selector: "pptx-presenter-view", inputs: ["slides", "currentSlideIndex", "activeCustomShow", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime", "isAudienceWindowOpen"], outputs: ["movePresentationSlide", "exit", "openAudienceWindow", "closeAudienceWindow", "navigateToSlide"] }, { kind: "component", type: MobilePresenterViewComponent, selector: "pptx-mobile-presenter-view", inputs: ["slides", "currentSlideIndex", "activeCustomShow", "canvasSize", "templateElements", "mediaDataUrls", "presentationStartTime"], outputs: ["movePresentationSlide", "exit"] }, { kind: "component", type: SlideSorterOverlayComponent, selector: "pptx-slide-sorter-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeIndex", "canEdit"], outputs: ["select", "closed", "deleteSlide", "duplicateSlide", "toggleHiddenSlide"] }, { kind: "component", type: OutlineViewOverlayComponent, selector: "pptx-outline-view-overlay", inputs: ["slides", "canvasSize", "canEdit"], outputs: ["commit", "closed"] }, { kind: "component", type: ReadingViewOverlayComponent, selector: "pptx-reading-view-overlay", inputs: ["slides", "canvasSize", "mediaDataUrls", "activeSlideIndex"], outputs: ["exit"] }, { kind: "component", type: SlideDefaultInspectorComponent, selector: "pptx-slide-default-inspector", inputs: ["slideIndex", "canEdit", "selectedElement", "comments"], outputs: ["commentAdd", "commentRemove", "commentResolve", "commentReply"] }, { kind: "component", type: FindBarComponent, selector: "pptx-find-bar", inputs: ["slides"], outputs: ["navigate", "closed"] }, { kind: "component", type: FindReplaceBarComponent, selector: "pptx-find-replace-bar", inputs: ["matchCount", "matchIndex"], outputs: ["find", "navigate", "replaceOne", "replaceAll", "close"] }, { kind: "component", type: SlidesPanelComponent, selector: "pptx-slides-panel", inputs: ["canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["select"] }, { kind: "component", type: StatusBarComponent, selector: "pptx-status-bar", inputs: ["slideIndex", "slideCount", "canEdit", "dirty", "autosaveStatus", "notesOpen", "zoomPercent", "sorterActive", "presenting", "hiddenActions"], outputs: ["toggleNotes", "normalView", "openSorter", "slideShow", "zoomIn", "zoomOut", "zoomReset"] }, { kind: "component", type: EditorContextMenuComponent, selector: "pptx-editor-context-menu", inputs: ["x", "y", "slideIndex", "showAiActions"], outputs: ["closed", "askAi", "fixAi", "editHyperlink", "addComment"] }, { kind: "component", type: ExportProgressModalComponent, selector: "pptx-export-progress-modal", inputs: ["open", "title", "progress", "statusMessage"], outputs: ["cancel"] }, { kind: "component", type: CommentMarkersOverlayComponent, selector: "pptx-comment-markers-overlay", inputs: ["comments", "canvasSize"], outputs: ["markerClick"] }, { kind: "component", type: CommentsPanelComponent, selector: "pptx-comments-panel", inputs: ["comments", "authorName"], outputs: ["add", "remove", "resolve", "reply"] }, { kind: "component", type: SignaturesPanelComponent, selector: "pptx-signatures-panel", inputs: ["signatures"] }, { kind: "component", type: AccessibilityPanelComponent, selector: "pptx-accessibility-panel", inputs: ["issues"], outputs: ["selectSlide"] }, { kind: "component", type: CollaborationCursorsComponent, selector: "pptx-collaboration-cursors", inputs: ["cursors", "zoom"] }, { kind: "component", type: RemoteSelectionOverlayComponent, selector: "pptx-remote-selection-overlay", inputs: ["presences", "elements", "activeSlideIndex", "zoom"] }, { kind: "component", type: MotionPathOverlayComponent, selector: "pptx-motion-path-overlay", inputs: ["element", "animations", "canvasSize", "canEdit"], outputs: ["pathChange"] }, { kind: "component", type: FollowModeBarComponent, selector: "pptx-follow-mode-bar", inputs: ["presences", "followedClientId"], outputs: ["follow"] }, { kind: "component", type: PropertiesDialogComponent, selector: "pptx-properties-dialog", inputs: ["open", "properties"], outputs: ["save", "close"] }, { kind: "component", type: HyperlinkDialogComponent, selector: "pptx-hyperlink-dialog", inputs: ["open", "element"], outputs: ["save", "close"] }, { kind: "component", type: PrintDialogComponent, selector: "pptx-print-dialog", inputs: ["slides", "activeSlideIndex", "defaultSlidesPerPage", "defaultFrameSlides", "defaultSettings"], outputs: ["print", "cancel"] }, { kind: "component", type: ShareDialogComponent, selector: "pptx-share-dialog", inputs: ["open", "defaults", "active", "connected", "userCount", "shareUrl", "p2p", "activeRoomId", "activeServerUrl", "users"], outputs: ["start", "stop", "close"] }, { kind: "component", type: BroadcastDialogComponent, selector: "pptx-broadcast-dialog", inputs: ["open", "defaults", "active", "connected", "viewerCount", "viewerUrl", "p2p"], outputs: ["start", "stop", "close"] }, { kind: "component", type: MobileBottomBarComponent, selector: "pptx-mobile-bottom-bar", inputs: ["slideCount", "commentCount", "activeSheet"], outputs: ["openSlides", "insert", "openFormat", "openComments", "notes"] }, { kind: "component", type: MobileMenuSheetComponent, selector: "pptx-mobile-menu-sheet", inputs: ["open", "slideCount", "exporting", "showNotes", "canEdit", "hiddenActions"], outputs: ["closed", "openFind", "openSorter", "toggleNotes", "insertText", "present", "openFile", "savePptx", "exportPng", "exportPdf", "exportGif", "exportVideo", "print"] }, { kind: "component", type: MobileSlidesSheetComponent, selector: "pptx-mobile-slides-sheet", inputs: ["open", "slides", "canvasSize", "mediaDataUrls", "activeIndex"], outputs: ["closed", "jumpToSlide"] }, { kind: "component", type: MobileToolbarComponent, selector: "pptx-mobile-toolbar", inputs: ["canUndo", "canRedo", "canPresent", "canEdit", "menuOpen", "aiEnabled", "aiPanelOpen", "hiddenActions"], outputs: ["toggleMenu", "toggleAiPanel", "undo", "redo", "share", "save", "present"] }, { kind: "component", type: MasterViewCanvasComponent, selector: "pptx-master-view-canvas", inputs: ["tab", "slideMasters", "activeMasterIndex", "activeLayoutIndex", "notesMaster", "handoutMaster", "canvasSize", "notesCanvasSize", "mediaDataUrls", "editable"], outputs: ["notesMasterChange", "handoutMasterChange", "slideMastersChange"] }, { kind: "component", type: MasterViewSidebarComponent, selector: "pptx-master-view-sidebar", inputs: ["tab", "slideMasters", "notesMaster", "handoutMaster", "activeMasterIndex", "activeLayoutIndex", "handoutSlidesPerPage", "editable"], outputs: ["tabChange", "selectMaster", "selectLayout", "slidesPerPageChange", "backgroundChange", "close"] }, { kind: "component", type: NotesPanelComponent, selector: "pptx-notes-panel", inputs: ["slide", "expanded", "notesStyle"], outputs: ["update", "notesToggle"] }, { kind: "component", type: QuickAccessStripComponent, selector: "pptx-quick-access-strip", inputs: ["quickAccess", "canUndo", "canRedo"], outputs: ["command"] }, { kind: "component", type: RibbonComponent, selector: "pptx-ribbon", inputs: ["slideIndex", "slideCount", "canEdit", "selectedElement", "zoomPercent", "formatPainterActive", "canActivateFormatPainter", "exporting", "hasMacros", "showGrid", "showRulers", "showGuides", "snapToGrid", "snapToShape", "eyedropperActive", "themeGalleryOpen", "sidebarCollapsed", "inspectorOpen", "commentsOpen", "commentCount", "findOpen", "collabConnected", "connectedCount", "spellCheckEnabled", "showSubtitles", "hiddenActions", "aiEnabled", "aiPanelOpen", "accountAuth", "activeSlideHidden"], outputs: ["prev", "next", "zoomIn", "zoomOut", "zoomReset", "find", "present", "presenter", "record", "presentFromBeginning", "rehearseTimings", "toggleSubtitles", "openSubtitleSettings", "recordFromBeginning", "recordFromCurrent", "spellCheckChange", "share", "broadcast", "openFile", "openRecentFile", "createPresentation", "save", "savePpsx", "savePptm", "toggleSidebar", "toggleAiPanel", "signatures", "info", "print", "comments", "a11y", "shortcuts", "versionHistory", "passwordProtection", "fontEmbedding", "link", "openSorter", "openReadingView", "openOutlineView", "openMasterView", "toggleNotes", "toggleFormatPainter", "exportPng", "exportPdf", "exportGif", "exportVideo", "exportJson", "copySlideAsImage", "replace", "toggleInspector", "drawToolChange", "toggleThemeGallery", "editTheme", "openSlideSize", "toggleGrid", "toggleRulers", "toggleGuides", "toggleSelectionPane", "openCustomShows", "toggleSnapToGrid", "toggleSnapToShape", "addGuide", "zoomToFit", "toggleEyedropper", "openSmartArtDialog", "openTemplateGallery", "openEquationDialog", "openSetUpSlideShow", "toggleHideSlide", "openCompare", "openPassword", "openFontEmbedding", "openVersionHistory", "openShortcuts", "openSettings"] }, { kind: "component", type: TitleBarComponent, selector: "pptx-title-bar", inputs: ["canEdit", "fileName", "isDirty", "autosaveStatus", "autosaveEnabled", "canUndo", "canRedo", "undoLabel", "redoLabel", "findReplaceOpen", "hiddenActions", "quickAccess"], outputs: ["toggleAutosave", "save", "undo", "redo", "quickCommand", "toggleFindReplace", "commandSearch"] }, { kind: "component", type: ThemeGalleryComponent, selector: "pptx-theme-gallery", inputs: ["open", "activeName", "theme", "startCustomizing"], outputs: ["applyTheme", "applyCustomTheme", "close"] }, { kind: "component", type: SelectionPaneComponent, selector: "pptx-selection-pane", inputs: ["elements", "selectedIds"], outputs: ["selectElement", "bringForward", "sendBackward", "toggleHidden", "renameElement"] }, { kind: "component", type: CustomShowsComponent, selector: "pptx-custom-shows", inputs: ["open", "slides", "customShows", "activeCustomShowId"], outputs: ["create", "remove", "update", "setActive", "close"] }, { kind: "component", type: InsertSmartArtDialogComponent, selector: "pptx-insert-smart-art-dialog", inputs: ["open"], outputs: ["close", "insert"] }, { kind: "component", type: SlideTemplateGalleryDialogComponent, selector: "pptx-slide-template-gallery-dialog", inputs: ["open", "scheme"], outputs: ["close", "insert"] }, { kind: "component", type: ViewerExtraDialogsComponent, selector: "pptx-viewer-extra-dialogs", inputs: ["activeSlideIndex", "selectedElementId", "filePath", "customShows", "themeKey", "availableThemes", "localeCode", "availableLocales", "aiExportVisible"], outputs: ["restoreContent", "themeKeySelect", "localeSelect"] }, { kind: "component", type: AutosaveRecoveryDialogComponent, selector: "pptx-autosave-recovery-dialog", inputs: ["prompt"], outputs: ["restore", "discard"] }, { kind: "component", type: RehearseTimingsComponent, selector: "pptx-rehearse-timings", inputs: ["summary", "paused", "slideStartedAt", "presentationStartedAt", "timings"], outputs: ["togglePause", "save", "discard"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, deferBlockDependencies: [() => [/* @ts-ignore */
149242
150847
  Promise.resolve().then(function () { return aiChatPanel_component; }).then(m => m.AiChatPanelComponent)]] }); }
149243
150848
  }
149244
150849
  i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.3", ngImport: i0, type: PowerPointViewerComponent, resolveDeferredDeps: () => [/* @ts-ignore */
@@ -149895,6 +151500,8 @@ i0.ɵɵngDeclareClassMetadataAsync({ minVersion: "18.0.0", version: "22.1.3", ng
149895
151500
  [mediaDataUrls]="loader.mediaDataUrls()"
149896
151501
  [startIndex]="customShowsCtl.presentationStartIndex()"
149897
151502
  [activeCustomShow]="customShowsCtl.activeCustomShow()"
151503
+ [authoredRange]="presentationAuthoredRange()"
151504
+ [loopContinuously]="loader.presentationProperties().loopContinuously ?? false"
149898
151505
  [showWithAnimation]="loader.presentationProperties().showWithAnimation"
149899
151506
  [useTimings]="loader.presentationProperties().advanceMode !== 'manual'"
149900
151507
  [subtitlesVisible]="presentationMode.subtitlesVisible()"
@@ -150569,11 +152176,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.3", ngImpor
150569
152176
  * exactly two tables. Reads/writes the shared {@link AiPanelStore}; emits the
150570
152177
  * merge directive up to the conversation so it routes through the chat send.
150571
152178
  */
150572
- /** Build the directive that fires `merge_tables` without a confirmation round-trip. */
150573
- function mergeDirective(slideIndex, elementIdA, elementIdB) {
150574
- return (`Merge the two selected tables (elementIdA=${elementIdA}, elementIdB=${elementIdB}) ` +
150575
- `on slide ${slideIndex + 1} using merge_tables; stage it now, do not ask me to confirm.`);
150576
- }
150577
152179
  class AiFocusBarComponent {
150578
152180
  constructor() {
150579
152181
  /** Live deck, for resolving element chip labels + the two-table detection. */
@@ -150588,7 +152190,7 @@ class AiFocusBarComponent {
150588
152190
  ...(ngDevMode ? [{ debugName: "twoTables" }] : /* istanbul ignore next */ []));
150589
152191
  }
150590
152192
  onMerge(tt) {
150591
- this.sendDirective.emit(mergeDirective(tt.slideIndex, tt.elementIdA, tt.elementIdB));
152193
+ this.sendDirective.emit(mergeTablesDirective(tt.slideIndex, tt.elementIdA, tt.elementIdB));
150592
152194
  }
150593
152195
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.3", ngImport: i0, type: AiFocusBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
150594
152196
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.3", type: AiFocusBarComponent, isStandalone: true, selector: "pptx-ai-focus-bar", inputs: { slides: { classPropertyName: "slides", publicName: "slides", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { sendDirective: "sendDirective" }, ngImport: i0, template: `
@@ -152528,5 +154130,5 @@ function cn(...values) {
152528
154130
  * Generated bundle index. Do not edit.
152529
154131
  */
152530
154132
 
152531
- export { ColorChangedImageComponent as $, AFTER_ANIMATION_VALUES as A, AnimationPanelComponent as B, AnimationPlaybackService as C, AutosaveRecoveryDialogComponent as D, AutosaveService as E, BroadcastDialogComponent as F, CHART_EDITOR_STYLES as G, CURSOR_PALETTE as H, CanvasFitService as I, ChartAxisOptionsComponent as J, ChartAxisStyleOptionsComponent as K, ChartComboTypeOptionsComponent as L, ChartDataEditorComponent as M, ChartDataLabelOptionsComponent as N, ChartDatapointMarkerOptionsComponent as O, ChartDatapointOptionsComponent as P, ChartDisplayOptionsComponent as Q, ChartElementViewComponent as R, ChartErrorBarOptionsComponent as S, ChartMarkerOptionsComponent as T, ChartPartSelectionService as U, ChartPrimitivesComponent as V, ChartRendererComponent as W, ChartTrendlineOptionsComponent as X, ChartTypeSelectorComponent as Y, CollaborationCursorsComponent as Z, CollaborationService as _, ALIGN_OPTIONS as a, InspectorPanelComponent as a$, CommentMarkersOverlayComponent as a0, CommentsPanelComponent as a1, CommentsService as a2, ComparePanelComponent as a3, ConnectorRendererComponent as a4, ConnectorTextOverlayComponent as a5, CustomShowsComponent as a6, DEFAULT_BOUNDS as a7, DEFAULT_BROADCAST_SERVER_URL as a8, DEFAULT_CANVAS_HEIGHT as a9, ElementRendererComponent as aA, EmbeddedFontsService as aB, EncryptedFileDialogComponent as aC, EquationEditorDialogComponent as aD, EquationRendererComponent as aE, EquationTemplateGalleryComponent as aF, ExportProgressModalComponent as aG, ExportService as aH, FieldContextService as aI, FindBarComponent as aJ, FindReplaceBarComponent as aK, FollowModeBarComponent as aL, FontEmbeddingListComponent as aM, FontEmbeddingPanelComponent as aN, GALLERY_THEME_PRESETS as aO, GOOGLE_WEBFONTS_LINK_ID as aP, GRIDLINE_COLOR$1 as aQ, GoogleWebfontsService as aR, GradientPickerComponent as aS, HANDOUT_OPTIONS as aT, HeaderFooterDialogComponent as aU, HyperlinkDialogComponent as aV, ImagePropertiesPanelComponent as aW, InkDrawingService as aX, InkRendererComponent as aY, InsertSmartArtDialogComponent as aZ, InspectorPaneHeaderComponent as a_, DEFAULT_CANVAS_WIDTH as aa, DEFAULT_COLOR_SCHEME as ab, DEFAULT_FILL_COLOR$1 as ac, DEFAULT_LAYOUT as ad, DEFAULT_PALETTE$1 as ae, DEFAULT_PATTERN_FILL_PRESET as af, DEFAULT_PRINT_SETTINGS as ag, DEFAULT_SLIDE_BACKGROUND as ah, DEFAULT_STROKE_COLOR as ai, DEFAULT_STYLE as aj, DEFAULT_TABLE_ROW_HEIGHT as ak, DEFAULT_TEXT_COLOR$2 as al, DEFAULT_VIEWER_PROFILE as am, DIRECTIONAL_PRESETS as an, DIRECTION_OPTIONS as ao, DocumentPropertiesCardComponent as ap, EMBEDDED_FONTS_STYLE_ID as aq, EMPHASIS_PRESETS as ar, ENTRANCE_PRESETS as as, TEMPLATES as at, EXIT_PRESETS as au, EditorContextMenuComponent as av, EditorHistory as aw, EditorStateService as ax, EditorToolbarComponent as ay, EffectsPanelComponent as az, ANIMATION_PRESET_CATEGORIES as b, RibbonComponent as b$, IsMobileService as b0, KeepAnnotationsDialogComponent as b1, LOCALE_CATALOG as b2, LONG_PRESS_DURATION_MS as b3, LONG_PRESS_MOVE_TOLERANCE_PX as b4, LoadContentService as b5, LocalPresencePublisher as b6, MAX_ZOOM_SCALE as b7, MIN_ZOOM_SCALE as b8, MOTION_PATH_COLUMNS as b9, PasswordStrengthMeterComponent as bA, PowerPointViewerComponent as bB, PresentToolbarAutoHide as bC, PresentationAnnotationOverlayComponent as bD, PresentationAnnotationsService as bE, PresentationOverlayComponent as bF, PresentationPropertiesPanelComponent as bG, PresentationSettingsCardComponent as bH, PresentationSubtitleBarComponent as bI, PresentationToolbarComponent as bJ, PresentationTransitionOverlayComponent as bK, PresenterViewComponent as bL, PresenterWindowService as bM, PrintDialogComponent as bN, PrintService as bO, PrintSettingsPanelComponent as bP, PropertiesDialogComponent as bQ, REPEAT_MODE_OPTIONS as bR, RESIZE_HANDLES as bS, RULER_FONT_SIZE as bT, RULER_THICKNESS as bU, ReadingViewOverlayComponent as bV, RemoteSelectionOverlayComponent as bW, RibbonAnimationGalleryComponent as bX, RibbonAnimationsSectionComponent as bY, RibbonArrangeSectionComponent as bZ, RibbonColorPopoverComponent as b_, MediaPreviewComponent as ba, MediaPropertiesPanelComponent as bb, MediaRendererComponent as bc, MediaTrimTimelineComponent as bd, MobileBottomBarComponent as be, MobileMenuSheetComponent as bf, MobilePresenterViewComponent as bg, MobileSheetComponent as bh, MobileSlidesSheetComponent as bi, MobileToolbarComponent as bj, ModalDialogComponent as bk, Model3DRendererComponent as bl, NotesHandoutCardComponent as bm, NotesPanelComponent as bn, NotesToolbarComponent as bo, OleRendererComponent as bp, OutlineViewOverlayComponent as bq, POWER_POINT_VIEWER_PROVIDERS as br, PPTX_OPEN_ACCEPT as bs, PRESENTATION_OPEN_EXTENSIONS as bt, PRESENTER_CHANNEL_NAME as bu, PRESENTER_MSG_ORIGIN as bv, PRESENTER_TIMER_SEGMENT_MS as bw, PX_PER_CM as bx, PX_PER_INCH as by, PasswordProtectionDialogComponent as bz, AUDIENCE_HASH as c, TEXT_3D_TOP_BEVEL_KEYS as c$, RibbonDesignSectionComponent as c0, RibbonDrawSectionComponent as c1, RibbonDrawingGroupComponent as c2, RibbonEditingSectionComponent as c3, RibbonFileSectionComponent as c4, RibbonFontControlsComponent as c5, RibbonHomeSectionComponent as c6, RibbonHyperlinkButtonComponent as c7, RibbonInsertFieldsComponent as c8, RibbonInsertSectionComponent as c9, SettingsLanguageTabComponent as cA, ShareDialogComponent as cB, ShortcutPanelComponent as cC, ShowOptionsFieldsetComponent as cD, ShowSlidesFieldsetComponent as cE, SignatureStrippedDialogComponent as cF, SignaturesPanelComponent as cG, SignaturesService as cH, SlideBackgroundCardComponent as cI, SlideCanvasComponent as cJ, SlideDefaultInspectorComponent as cK, SlideDiffChangesComponent as cL, SlideDiffRowComponent as cM, SlideDiffThumbnailsComponent as cN, SlideSizeCardComponent as cO, SlideSorterOverlayComponent as cP, SlideThemeOverridePanelComponent as cQ, SlideTransitionCardComponent as cR, SlidesPanelComponent as cS, SmartArt3DRendererComponent as cT, SmartArt3DService as cU, SmartArtPreviewComponent as cV, SmartArtPropertiesComponent as cW, SmartArtRendererComponent as cX, StatusBarComponent as cY, TABLE_STRUCTURE_TOGGLES as cZ, TEXT_3D_BOTTOM_BEVEL_KEYS as c_, RibbonMotionPathGalleryComponent as ca, RibbonParagraphControlsComponent as cb, RibbonPrimaryRowComponent as cc, RibbonReviewSectionComponent as cd, RibbonShapeExtrasComponent as ce, RibbonSlideshowSectionComponent as cf, RibbonTransitionsSectionComponent as cg, RibbonViewSectionComponent as ch, RulerGuidesService as ci, SEQUENCE_OPTIONS as cj, SEVERITY_GROUPS as ck, SEVERITY_LABELS as cl, SHORTCUT_REFERENCE_ITEMS as cm, SLIDE_TRANSITION_KEYFRAMES as cn, DEFAULT_PALETTE as co, PALETTES$1 as cp, SMART_ART_COLOR_SCHEMES as cq, SMART_ART_STYLE_OPTIONS as cr, SUB_ITEM_LABEL as cs, SVG_WARP_PRESETS as ct, SWIPE_MAX_VERTICAL_PX as cu, SWIPE_THRESHOLD_PX as cv, SelectionPaneComponent as cw, SetUpSlideShowDialogComponent as cx, SettingsAppearanceTabComponent as cy, SettingsDialogComponent as cz, AUDIENCE_NONCE_KEY as d, animationPresetLabelKey as d$, TEXT_DIRECTION_OPTIONS$1 as d0, THEME_CATALOG as d1, TIMING_CURVE_OPTIONS as d2, TRIGGER_OPTIONS as d3, TYPE_LABELS as d4, TableCellAdvancedFillComponent as d5, TableCellFormattingComponent as d6, TableDataEditorComponent as d7, TablePropertiesComponent as d8, TableRendererComponent as d9, ViewerFileIOService as dA, ViewerFindReplaceService as dB, ViewerFormatPainterService as dC, ViewerInspectorPanelService as dD, ViewerKeyboardService as dE, ViewerMobileSheetService as dF, ViewerPresentationModeService as dG, ViewerThemeGalleryService as dH, ViewerTouchGesturesService as dI, ViewerZoomService as dJ, WEBM_MIME_CANDIDATES as dK, WriteBackScheduler as dL, ZERO_LINE_COLOR as dM, ZoomNavigationService as dN, ZoomRendererComponent as dO, ZoomTargetService as dP, addCategory as dQ, addCommentToList as dR, addGradientStopPatch as dS, addItem as dT, addSeries as dU, addSubItem as dV, advanceStep as dW, affordanceElements as dX, aiToggleVisible as dY, alignPatch as dZ, animationFor as d_, TableResizeOverlayComponent as da, TableSelectionService as db, TagsCardComponent as dc, Text3DBevelSectionComponent as dd, Text3DPanelComponent as de, TextAdvancedPanelComponent as df, ThemeEditorFieldsComponent as dg, ThemeGalleryComponent as dh, ThemeSelectorCardComponent as di, TitleBarComponent as dj, TitleBarSearchComponent as dk, TransitionDirectionPickerComponent as dl, TransitionPreviewComponent as dm, VALIGN_OPTIONS as dn, VIEWER_THEME as dp, VersionHistoryPanelComponent as dq, ViewerCanvasEditingService as dr, ViewerCollabCursorService as ds, ViewerCollaborationSessionService as dt, ViewerCompareService as du, ViewerCustomShowsService as dv, ViewerDialogsService as dw, ViewerDocumentPropertiesService as dx, ViewerExportService as dy, ViewerExtraDialogsComponent as dz, AVATAR_COLOR_SWATCHES as e, buildTreemapViewModel as e$, annotationMapToInkInserts as e0, applyAcceptedDiff as e1, applyAnimationPreset as e2, applyFindReplacements as e3, applyFormatToElement as e4, applyMove as e5, applyResize as e6, asMediaElement as e7, assignUserColor as e8, attachShowVisibilityPause as e9, buildEquationSegment as eA, buildFallbackViewModel as eB, buildFontFaceRule as eC, buildGradientFillCss as eD, buildGridlinesAndLabels as eE, buildHyperlinkPatch as eF, buildInkContainerStyle as eG, buildInkStrokes as eH, buildLegend as eI, buildMarkTooltip as eJ, buildModel3DContainerStyle as eK, buildModel3DViewModel as eL, buildOleActionModel as eM, buildOleInfoRows as eN, buildPatternFillCss as eO, buildPieViewModel as eP, buildPrintHtmlDocument as eQ, buildPropertiesPatch as eR, buildRadarViewModel as eS, buildRegionMapViewModel as eT, buildSaveSlides as eU, buildShareUrl as eV, buildSmartArtInsertElement as eW, buildSmartArtNodes as eX, buildStockViewModel as eY, buildSurfaceViewModel as eZ, buildTableViewModel as e_, attachTouchGestures as ea, axisTickValues as eb, beginNodeEdit as ec, bevelSizePatch as ed, boolFromEvent as ee, bringForward as ef, bringToFront as eg, buildBarActions as eh, buildBroadcastConfig as ei, buildBroadcastViewerUrl as ej, buildCategoryLabels as ek, buildCellParagraphs as el, buildChartViewModel as em, buildChatLogExport as en, buildChatLogMarkdown as eo, buildChromeStyle as ep, buildClearHyperlinkPatch as eq, buildClickGroups as er, buildColStyles as es, buildCollaborationConfig as et, buildComboViewModel as eu, buildCssGradientFromShapeStyle as ev, buildDuotoneFilter as ew, buildDuotoneFilterId as ex, buildEmbeddedFontStyles as ey, buildEquationElement as ez, AXIS_LABEL_COLOR as f, computeRotateHandleBox as f$, buildTrimFragment as f0, buildWaterfallViewModel as f1, buildZeroLine as f2, buildZoomContainerStyle as f3, buildZoomViewModel as f4, bulletIndentPx as f5, canAddTopLevelNode as f6, canGroupSelection as f7, canRemoveTopLevelNode as f8, canSetStrokeWidth as f9, collectUsedFontFamilies as fA, columnWidthStyle as fB, commitNodeText as fC, computeAlign as fD, computeAxisTitlePrimitives as fE, computeBarRects as fF, computeBubbleRadius as fG, computeCornerHandle as fH, computeDistribute as fI, computeDrawingViewBox as fJ, computeErrorBarPrimitives as fK, computeFocusTargets as fL, computeGridSpacingPx as fM, computeHandleBoxes as fN, computeHandoutLayout as fO, computeIsMobile as fP, computeIsTablet as fQ, computeLinePoints as fR, computeLinearRegression as fS, computePageCount as fT, computePieLayout as fU, computePieSlicePath as fV, computePieSlices as fW, computePlotLayout as fX, computeRSquared as fY, computeRadarPoints as fZ, computeResizeHandleBoxes as f_, canStartBroadcast as fa, canStartShare as fb, canUngroupSelection as fc, canUseClipboard as fd, captionDisplayText as fe, cellRunStyle as ff, cellStyleToStyleMap as fg, cellTdStyle as fh, changeCountLabel as fi, changeIcon as fj, characterSpacingPatch as fk, chartPreserveAspectRatio as fl, checkFontAvailable as fm, clampCursorPosition as fn, clampGifDimensions as fo, clampIndex as fp, clampNotesFontSize as fq, clampScale as fr, clampStep as fs, clearAllLocalViewerData as ft, clearAudienceContent as fu, cn as fv, collectAccessibilityIssues as fw, collectElementText as fx, collectSlideText as fy, collectStoredChats as fz, AccessibilityPanelComponent as g, formatAxisValue as g$, computeScatterDots as g0, computeScatterXDomain as g1, computeSelectionBoxes as g2, computeSingleSelected as g3, computeSlideIndices as g4, computeSnap as g5, computeStackedBarRects as g6, computeStackedValueRange as g7, computeTrendlinePrimitives as g8, computeValueRange as g9, disableSoftEdgePatch as gA, duplicateElementById as gB, durationOf as gC, effectsStateOf as gD, enableGlowPatch as gE, enableInnerShadowPatch as gF, enableOuterShadowPatch as gG, enableReflectionPatch as gH, enableSoftEdgePatch as gI, encodeGif as gJ, endShowMediaCleanup as gK, estimatePageCount as gL, exitPresentationFullscreen as gM, exportAiChatLogs as gN, extractPathPoints as gO, eyedropperAvailable as gP, fillColorOf$1 as gQ, findInSlides as gR, findOwningSlideIndex as gS, findSlideIndexByElementId as gT, firstVisibleIndex as gU, fitPolynomial as gV, fitZoom as gW, focusTargetChips as gX, fontMimeForFormat as gY, fontSizeOf as gZ, forgetSessionDeck as g_, convertOmmlToMathMl as ga, copyFormatFromElement as gb, countAccessibilityIssues as gc, countAnnotationStrokes as gd, createAngularAiBridge as ge, createCustomShow as gf, createSwipeDismissDrag as gg, createWebrtcBundle as gh, createWebsocketBundle as gi, cssObjectToStyleMap as gj, currentColorScheme as gk, currentLayout as gl, currentStyle as gm, defaultCssVars as gn, defaultRadius as go, defaultThemeColors as gp, deleteElementsByIds as gq, deleteVersion as gr, demoteNode as gs, deriveModel3DBlobUrl as gt, derivePresenceList as gu, describeSmartArtBounds as gv, disableGlowPatch as gw, disableInnerShadowPatch as gx, disableOuterShadowPatch as gy, disableReflectionPatch as gz, AccessibilityService as h, isElementInteractive as h$, formatBytes as h0, formatCursorLabel as h1, formatElapsed as h2, formatFileSize as h3, formatPropertyDate as h4, formatTime as h5, fpsToFrameIntervalMs as h6, generateBroadcastRoomId as h7, generateCommentId as h8, generateCustomShowId as h9, getTextBlockStyle as hA, getTextWarp as hB, getTouchDistance as hC, getWarpCategory as hD, getWarpPath as hE, gradientStateFromStyle as hF, gradientStateOf as hG, gradientStatePatch as hH, gridColumns as hI, groupIssuesBySeverity as hJ, hasAnimation as hK, hasCopyableFormat as hL, hasExistingLink as hM, hasExitedFullscreen as hN, hasGradientFill as hO, hasPressureVariation as hP, hasVisibleSlideAfter as hQ, headerLabel as hR, imageDimensions as hS, inkViewBox as hT, insertTableElementColumn as hU, insertTableElementRow as hV, interpolateWidth as hW, isAudienceTab as hX, isBold as hY, isBrowserOpenableMime as hZ, isChildNode as h_, generatePressureCircles as ha, generateTicks as hb, getClrChangeParams as hc, getContainerStyle as hd, getDuotoneFilterDef as he, getEffectSoundState as hf, getImageSrc as hg, getLocalStorageUsageSummary as hh, getOleAriaLabel as hi, getOleBadgeLabel as hj, getOleDisplayName as hk, getOleDownloadFileName as hl, getOleTypeColor as hm, getOleTypeLabel as hn, getPasswordStrength as ho, getPatternSvg as hp, getPlaceholderStyle as hq, getVersions as hr, getResolvedShapeClipPath as hs, getResolvedShapeClipPathFor as ht, getSessionTabId as hu, getShapeFillStrokeStyle as hv, getSlideBackgroundStyle as hw, getSlideTransitionAnimations as hx, getSmartArtNodeBounds as hy, getSpeechRecognitionCtor as hz, AccountPageComponent as i, paletteColor as i$, isInjectableUrl as i0, isItalic as i1, isLegacyBinaryPresentation as i2, isPpactionUrl as i3, isPresenterMessage as i4, isSigned as i5, isSupportedPresentationFile as i6, isTextElement as i7, isTwoTableFocus as i8, isUnderline as i9, msToFrameDelayCs as iA, narrowToCircle as iB, narrowToPolygon as iC, narrowToRect as iD, newChartElement as iE, newEquationElement as iF, newPresetShapeElement as iG, newShapeElement as iH, newSmartArtElement as iI, newTableElement as iJ, newTextElement as iK, nextVisibleIndex as iL, nodeBold as iM, nodeEditBox as iN, nodeFillColor as iO, nodeFontColor as iP, nodeIdFromKey as iQ, nodeItalic as iR, nodeStyle as iS, normalizeFontFormat as iT, normalizeSlidesPerPage as iU, normalizeValue as iV, numFromEvent as iW, ommlToMathml as iX, ooxmlDashToCssBorderStyle as iY, openNativeEyeDropper as iZ, overallStatus as i_, isUrlSafe as ia, isValidRoomId as ib, isViewportBackgroundPressTarget as ic, isZoomActivationKey as id, issueTrackKey as ie, issueTypeLabel as ig, keyToLabel as ih, lastVisibleIndex as ii, latexToMathml as ij, layoutConnectorPaints as ik, layoutNodeLabels as il, linePointsToSvgString as im, lineSpacingPatch as io, loadAudienceContent as ip, loadSessionDeck as iq, mediaFallbackFor as ir, mediaSurfaceFor as is, mergeCaptionResults as it, mergeDown as iu, mergeRight as iv, mergeSelection as iw, moveElementBy as ix, moveNodeDown as iy, moveNodeUp as iz, ActionSettingsPanelComponent as j, restoreSessionDeck as j$, parseAudienceNonce as j0, parseNodeTextarea as j1, partitionSlides as j2, patchChartData as j3, patchChartStyle as j4, patchTableData as j5, patchTextStyle as j6, patternPresetOptions as j7, pendingElementStyles as j8, pickColorByClickFallback as j9, removeElementAnimation as jA, removeGradientStopPatch as jB, removeNode as jC, removeTableElementRow as jD, removeSeries as jE, renderToCanvas as jF, reorderAnimationDown as jG, reorderAnimationUp as jH, replaceInSlides as jI, replaceMatch as jJ, requestPresentationFullscreen as jK, resizeElement as jL, resolveCaptionTracks as jM, resolveChartKind as jN, resolveFontVariant as jO, resolveHyperlinkHref as jP, resolveInteractiveElementId as jQ, resolveMediaSrc as jR, resolveOleType as jS, resolveParagraphBullet as jT, resolvePresenterNotes as jU, resolveProfileInitial as jV, resolveRegionCode as jW, resolveSlideAutoAdvanceMs as jX, resolvePalette as jY, resolveThemeCatalogEntry as jZ, resolveTransitionDuration as j_, pickFile as ja, pickSupportedMimeType as jb, planGifFrames as jc, planVideoSegments as jd, pointsToSvgPathD as je, presenceToCursors as jf, presentationBaseName as jg, presentationStageStyle as jh, presenterTimerProgress as ji, presetByLayout as jj, presetsForCategory as jk, pressuresToWidths as jl, prevVisibleIndex as jm, projectDrawingShapes as jn, promoteNode as jo, provideViewerTheme as jp, radarAngle as jq, radarRingPoints as jr, readAsDataUrl as js, recordWebm as jt, registerCrossSlideAudio as ju, rememberSessionDeck as jv, removeAnimation as jw, removeCategory as jx, removeTableElementColumn as jy, removeCommentFromList as jz, AdvancedChartEditorComponent as k, setTitle as k$, revealedElementStyles as k0, routeOrthogonalConnector as k1, rowStyle as k2, rulerDragToGuidePosition as k3, rulerHighlight as k4, rulerStripTicks as k5, sampleColorFromSlide as k6, sanitizeColor as k7, sanitizeSlideIndex as k8, sanitizeUserName as k9, setDataLabels as kA, setDataPointExplosion as kB, setDataPointFill as kC, setDataPointLabel as kD, setDataPointMarker as kE, setDelay as kF, setDirection as kG, setDuration as kH, setEffectSound as kI, setElementPosition as kJ, setGridlineStyle as kK, setLayout as kL, setLegend as kM, setNodeStyle as kN, setNodeText as kO, setRepeatCount as kP, setRepeatMode as kQ, setSequence as kR, setSeriesChartType as kS, setSeriesColor as kT, setSeriesErrorBars as kU, setSeriesMarker as kV, setSeriesName as kW, setSeriesTrendline as kX, setSeriesValue as kY, setStyle as kZ, setTimingCurve as k_, saveViewerProfile as ka, savedPresentationFileName as kb, scanAvailableFonts as kc, searchSlides as kd, seedBroadcastFields as ke, seedHyperlinkDraft as kf, seedPropertiesDraft as kg, seedShareFields as kh, segmentFrameCount as ki, selectValue$2 as kj, sendBackward as kk, sendToBack as kl, sequentialColorScale as km, serializeWriteBack as kn, seriesColor as ko, setAfterAnimation as kp, setAfterAnimationColor as kq, setAnimationEmphasis as kr, setAnimationEntrance as ks, setAnimationExit as kt, setAxis as ku, setAxisLogScale as kv, setAxisTitleStyle as kw, setCategoryLabel as kx, setCellText as ky, setColorScheme as kz, AiChangeOverlayComponent as l, waypointsToPathD as l$, setTrigger as l0, setTriggerShapeId as l1, shapeStylePatch$1 as l2, sheetAfterNavigate as l3, shouldBlockClickAdvance as l4, shouldUseSvgWarp as l5, showDirectionPicker as l6, showsTemplateAffordance as l7, signatureCountLabel as l8, signatureKey as l9, themeStyle as lA, themeToCssVars as lB, thumbnailHeight as lC, thumbnailZoom as lD, toggleCommentResolvedInList as lE, toggleNodeBold as lF, toggleNodeItalic as lG, toggleSheet as lH, topLevelNodeCount as lI, transformSelectedTextCase as lJ, translationsEn as lK, updateElementById as lL, updateGlowPatch as lM, updateGradientStopPatch as lN, updateInnerShadowPatch as lO, updateOuterShadowPatch as lP, updateReflectionPatch as lQ, vAlignPatch as lR, validatePassword as lS, validatePrintSettings as lT, validateRoomId as lU, valueToY as lV, vermilionDarkColors as lW, vermilionDarkTheme as lX, vermilionLightColors as lY, vermilionLightTheme as lZ, vermilionRadius as l_, signatureTimestamp as la, signerName as lb, statusLabel as lc, slideNumberOf as ld, slidesWithReappliedLayout as le, smartArtNodes as lf, paletteColour as lg, snapToGridStep as lh, splitCursorCell as li, splitMergedCell as lj, statusKind as lk, statusLabel$1 as ll, storeAudienceContent as lm, stringFromEvent$5 as ln, strokeColorOf as lo, strokeToInkElement as lp, strokeWidthOf as lq, styleShadowFilter as lr, surfaceColor as ls, textAdvancedPatch as lt, textAdvancedStateFromStyle as lu, textAdvancedStateOf as lv, textColorOf as lw, textDirectionPatch as lx, textStyleOf as ly, textStylePatch as lz, AiChatPanelComponent as m, withManualLayouts as m0, worstStatus as m1, zoomTargetSlideIndex as m2, AiChatService as n, AiComposerComponent as o, AiFocusBarComponent as p, AiFocusHighlightOverlayComponent as q, AiHistoryMenuComponent as r, AiHistoryService as s, toChatSummary as t, AiMessageListComponent as u, AiPanelStore as v, AiProposalCardComponent as w, AiSettingsSectionComponent as x, AiToolCallCardComponent as y, AnimationAuthorPanelComponent as z };
152532
- //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-D47r9ihQ.mjs.map
154133
+ export { ColorChangedImageComponent as $, AFTER_ANIMATION_VALUES as A, AnimationPanelComponent as B, AnimationPlaybackService as C, AutosaveRecoveryDialogComponent as D, AutosaveService as E, BroadcastDialogComponent as F, CHART_EDITOR_STYLES as G, CURSOR_PALETTE as H, CanvasFitService as I, ChartAxisOptionsComponent as J, ChartAxisStyleOptionsComponent as K, ChartComboTypeOptionsComponent as L, ChartDataEditorComponent as M, ChartDataLabelOptionsComponent as N, ChartDatapointMarkerOptionsComponent as O, ChartDatapointOptionsComponent as P, ChartDisplayOptionsComponent as Q, ChartElementViewComponent as R, ChartErrorBarOptionsComponent as S, ChartMarkerOptionsComponent as T, ChartPartSelectionService as U, ChartPrimitivesComponent as V, ChartRendererComponent as W, ChartTrendlineOptionsComponent as X, ChartTypeSelectorComponent as Y, CollaborationCursorsComponent as Z, CollaborationService as _, ALIGN_OPTIONS as a, InspectorPanelComponent as a$, CommentMarkersOverlayComponent as a0, CommentsPanelComponent as a1, CommentsService as a2, ComparePanelComponent as a3, ConnectorRendererComponent as a4, ConnectorTextOverlayComponent as a5, CustomShowsComponent as a6, DEFAULT_BOUNDS as a7, DEFAULT_BROADCAST_SERVER_URL as a8, DEFAULT_CANVAS_HEIGHT as a9, ElementRendererComponent as aA, EmbeddedFontsService as aB, EncryptedFileDialogComponent as aC, EquationEditorDialogComponent as aD, EquationRendererComponent as aE, EquationTemplateGalleryComponent as aF, ExportProgressModalComponent as aG, ExportService as aH, FieldContextService as aI, FindBarComponent as aJ, FindReplaceBarComponent as aK, FollowModeBarComponent as aL, FontEmbeddingListComponent as aM, FontEmbeddingPanelComponent as aN, GALLERY_THEME_PRESETS as aO, GOOGLE_WEBFONTS_LINK_ID as aP, GRIDLINE_COLOR$1 as aQ, GoogleWebfontsService as aR, GradientPickerComponent as aS, HANDOUT_OPTIONS as aT, HeaderFooterDialogComponent as aU, HyperlinkDialogComponent as aV, ImagePropertiesPanelComponent as aW, InkDrawingService as aX, InkRendererComponent as aY, InsertSmartArtDialogComponent as aZ, InspectorPaneHeaderComponent as a_, DEFAULT_CANVAS_WIDTH as aa, DEFAULT_COLOR_SCHEME as ab, DEFAULT_FILL_COLOR$1 as ac, DEFAULT_LAYOUT as ad, DEFAULT_PALETTE$1 as ae, DEFAULT_PATTERN_FILL_PRESET as af, DEFAULT_PRINT_SETTINGS as ag, DEFAULT_SLIDE_BACKGROUND as ah, DEFAULT_STROKE_COLOR as ai, DEFAULT_STYLE as aj, DEFAULT_TABLE_ROW_HEIGHT as ak, DEFAULT_TEXT_COLOR$2 as al, DEFAULT_VIEWER_PROFILE as am, DIRECTIONAL_PRESETS as an, DIRECTION_OPTIONS as ao, DocumentPropertiesCardComponent as ap, EMBEDDED_FONTS_STYLE_ID as aq, EMPHASIS_PRESETS as ar, ENTRANCE_PRESETS as as, TEMPLATES as at, EXIT_PRESETS as au, EditorContextMenuComponent as av, EditorHistory as aw, EditorStateService as ax, EditorToolbarComponent as ay, EffectsPanelComponent as az, ANIMATION_PRESET_CATEGORIES as b, RibbonComponent as b$, IsMobileService as b0, KeepAnnotationsDialogComponent as b1, LOCALE_CATALOG as b2, LONG_PRESS_DURATION_MS as b3, LONG_PRESS_MOVE_TOLERANCE_PX as b4, LoadContentService as b5, LocalPresencePublisher as b6, MAX_ZOOM_SCALE as b7, MIN_ZOOM_SCALE as b8, MOTION_PATH_COLUMNS as b9, PasswordStrengthMeterComponent as bA, PowerPointViewerComponent as bB, PresentToolbarAutoHide as bC, PresentationAnnotationOverlayComponent as bD, PresentationAnnotationsService as bE, PresentationOverlayComponent as bF, PresentationPropertiesPanelComponent as bG, PresentationSettingsCardComponent as bH, PresentationSubtitleBarComponent as bI, PresentationToolbarComponent as bJ, PresentationTransitionOverlayComponent as bK, PresenterViewComponent as bL, PresenterWindowService as bM, PrintDialogComponent as bN, PrintService as bO, PrintSettingsPanelComponent as bP, PropertiesDialogComponent as bQ, REPEAT_MODE_OPTIONS as bR, RESIZE_HANDLES as bS, RULER_FONT_SIZE as bT, RULER_THICKNESS as bU, ReadingViewOverlayComponent as bV, RemoteSelectionOverlayComponent as bW, RibbonAnimationGalleryComponent as bX, RibbonAnimationsSectionComponent as bY, RibbonArrangeSectionComponent as bZ, RibbonColorPopoverComponent as b_, MediaPreviewComponent as ba, MediaPropertiesPanelComponent as bb, MediaRendererComponent as bc, MediaTrimTimelineComponent as bd, MobileBottomBarComponent as be, MobileMenuSheetComponent as bf, MobilePresenterViewComponent as bg, MobileSheetComponent as bh, MobileSlidesSheetComponent as bi, MobileToolbarComponent as bj, ModalDialogComponent as bk, Model3DRendererComponent as bl, NotesHandoutCardComponent as bm, NotesPanelComponent as bn, NotesToolbarComponent as bo, OleRendererComponent as bp, OutlineViewOverlayComponent as bq, POWER_POINT_VIEWER_PROVIDERS as br, PPTX_OPEN_ACCEPT as bs, PRESENTATION_OPEN_EXTENSIONS as bt, PRESENTER_CHANNEL_NAME as bu, PRESENTER_MSG_ORIGIN as bv, PRESENTER_TIMER_SEGMENT_MS as bw, PX_PER_CM as bx, PX_PER_INCH as by, PasswordProtectionDialogComponent as bz, AUDIENCE_HASH as c, TEXT_3D_TOP_BEVEL_KEYS as c$, RibbonDesignSectionComponent as c0, RibbonDrawSectionComponent as c1, RibbonDrawingGroupComponent as c2, RibbonEditingSectionComponent as c3, RibbonFileSectionComponent as c4, RibbonFontControlsComponent as c5, RibbonHomeSectionComponent as c6, RibbonHyperlinkButtonComponent as c7, RibbonInsertFieldsComponent as c8, RibbonInsertSectionComponent as c9, SettingsLanguageTabComponent as cA, ShareDialogComponent as cB, ShortcutPanelComponent as cC, ShowOptionsFieldsetComponent as cD, ShowSlidesFieldsetComponent as cE, SignatureStrippedDialogComponent as cF, SignaturesPanelComponent as cG, SignaturesService as cH, SlideBackgroundCardComponent as cI, SlideCanvasComponent as cJ, SlideDefaultInspectorComponent as cK, SlideDiffChangesComponent as cL, SlideDiffRowComponent as cM, SlideDiffThumbnailsComponent as cN, SlideSizeCardComponent as cO, SlideSorterOverlayComponent as cP, SlideThemeOverridePanelComponent as cQ, SlideTransitionCardComponent as cR, SlidesPanelComponent as cS, SmartArt3DRendererComponent as cT, SmartArt3DService as cU, SmartArtPreviewComponent as cV, SmartArtPropertiesComponent as cW, SmartArtRendererComponent as cX, StatusBarComponent as cY, TABLE_STRUCTURE_TOGGLES as cZ, TEXT_3D_BOTTOM_BEVEL_KEYS as c_, RibbonMotionPathGalleryComponent as ca, RibbonParagraphControlsComponent as cb, RibbonPrimaryRowComponent as cc, RibbonReviewSectionComponent as cd, RibbonShapeExtrasComponent as ce, RibbonSlideshowSectionComponent as cf, RibbonTransitionsSectionComponent as cg, RibbonViewSectionComponent as ch, RulerGuidesService as ci, SEQUENCE_OPTIONS as cj, SEVERITY_GROUPS as ck, SEVERITY_LABELS as cl, SHORTCUT_REFERENCE_ITEMS as cm, SLIDE_TRANSITION_KEYFRAMES as cn, DEFAULT_PALETTE as co, PALETTES$1 as cp, SMART_ART_COLOR_SCHEMES as cq, SMART_ART_STYLE_OPTIONS as cr, SUB_ITEM_LABEL as cs, SVG_WARP_PRESETS as ct, SWIPE_MAX_VERTICAL_PX as cu, SWIPE_THRESHOLD_PX as cv, SelectionPaneComponent as cw, SetUpSlideShowDialogComponent as cx, SettingsAppearanceTabComponent as cy, SettingsDialogComponent as cz, AUDIENCE_NONCE_KEY as d, animationPresetLabelKey as d$, TEXT_DIRECTION_OPTIONS$1 as d0, THEME_CATALOG as d1, TIMING_CURVE_OPTIONS as d2, TRIGGER_OPTIONS as d3, TYPE_LABELS as d4, TableCellAdvancedFillComponent as d5, TableCellFormattingComponent as d6, TableDataEditorComponent as d7, TablePropertiesComponent as d8, TableRendererComponent as d9, ViewerFileIOService as dA, ViewerFindReplaceService as dB, ViewerFormatPainterService as dC, ViewerInspectorPanelService as dD, ViewerKeyboardService as dE, ViewerMobileSheetService as dF, ViewerPresentationModeService as dG, ViewerThemeGalleryService as dH, ViewerTouchGesturesService as dI, ViewerZoomService as dJ, WEBM_MIME_CANDIDATES as dK, WriteBackScheduler as dL, ZERO_LINE_COLOR as dM, ZoomNavigationService as dN, ZoomRendererComponent as dO, ZoomTargetService as dP, addCategory as dQ, addCommentToList as dR, addGradientStopPatch as dS, addItem as dT, addSeries as dU, addSubItem as dV, advanceStep as dW, affordanceElements as dX, aiToggleVisible as dY, alignPatch as dZ, animationFor as d_, TableResizeOverlayComponent as da, TableSelectionService as db, TagsCardComponent as dc, Text3DBevelSectionComponent as dd, Text3DPanelComponent as de, TextAdvancedPanelComponent as df, ThemeEditorFieldsComponent as dg, ThemeGalleryComponent as dh, ThemeSelectorCardComponent as di, TitleBarComponent as dj, TitleBarSearchComponent as dk, TransitionDirectionPickerComponent as dl, TransitionPreviewComponent as dm, VALIGN_OPTIONS as dn, VIEWER_THEME as dp, VersionHistoryPanelComponent as dq, ViewerCanvasEditingService as dr, ViewerCollabCursorService as ds, ViewerCollaborationSessionService as dt, ViewerCompareService as du, ViewerCustomShowsService as dv, ViewerDialogsService as dw, ViewerDocumentPropertiesService as dx, ViewerExportService as dy, ViewerExtraDialogsComponent as dz, AVATAR_COLOR_SWATCHES as e, buildTreemapViewModel as e$, annotationMapToInkInserts as e0, applyAcceptedDiff as e1, applyAnimationPreset as e2, applyFindReplacements as e3, applyFormatToElement as e4, applyMove as e5, applyResize as e6, asMediaElement as e7, assignUserColor as e8, attachShowVisibilityPause as e9, buildEquationSegment as eA, buildFallbackViewModel as eB, buildFontFaceRule as eC, buildGradientFillCss as eD, buildGridlinesAndLabels as eE, buildHyperlinkPatch as eF, buildInkContainerStyle as eG, buildInkStrokes as eH, buildLegend as eI, buildMarkTooltip as eJ, buildModel3DContainerStyle as eK, buildModel3DViewModel as eL, buildOleActionModel as eM, buildOleInfoRows as eN, buildPatternFillCss as eO, buildPieViewModel as eP, buildPrintHtmlDocument as eQ, buildPropertiesPatch as eR, buildRadarViewModel as eS, buildRegionMapViewModel as eT, buildSaveSlides as eU, buildShareUrl as eV, buildSmartArtInsertElement as eW, buildSmartArtNodes as eX, buildStockViewModel as eY, buildSurfaceViewModel as eZ, buildTableViewModel as e_, attachTouchGestures as ea, axisTickValues as eb, beginNodeEdit as ec, bevelSizePatch as ed, boolFromEvent as ee, bringForward as ef, bringToFront as eg, buildBarActions as eh, buildBroadcastConfig as ei, buildBroadcastViewerUrl as ej, buildCategoryLabels as ek, buildCellParagraphs as el, buildChartViewModel as em, buildChatLogExport as en, buildChatLogMarkdown as eo, buildChromeStyle as ep, buildClearHyperlinkPatch as eq, buildClickGroups as er, buildColStyles as es, buildCollaborationConfig as et, buildComboViewModel as eu, buildCssGradientFromShapeStyle as ev, buildDuotoneFilter as ew, buildDuotoneFilterId as ex, buildEmbeddedFontStyles as ey, buildEquationElement as ez, AXIS_LABEL_COLOR as f, computeRotateHandleBox as f$, buildTrimFragment as f0, buildWaterfallViewModel as f1, buildZeroLine as f2, buildZoomContainerStyle as f3, buildZoomViewModel as f4, bulletIndentPx as f5, canAddTopLevelNode as f6, canGroupSelection as f7, canRemoveTopLevelNode as f8, canSetStrokeWidth as f9, collectUsedFontFamilies as fA, columnWidthStyle as fB, commitNodeText as fC, computeAlign as fD, computeAxisTitlePrimitives as fE, computeBarRects as fF, computeBubbleRadius as fG, computeCornerHandle as fH, computeDistribute as fI, computeDrawingViewBox as fJ, computeErrorBarPrimitives as fK, computeFocusTargets as fL, computeGridSpacingPx as fM, computeHandleBoxes as fN, computeHandoutLayout as fO, computeIsMobile as fP, computeIsTablet as fQ, computeLinePoints as fR, computeLinearRegression as fS, computePageCount as fT, computePieLayout as fU, computePieSlicePath as fV, computePieSlices as fW, computePlotLayout as fX, computeRSquared as fY, computeRadarPoints as fZ, computeResizeHandleBoxes as f_, canStartBroadcast as fa, canStartShare as fb, canUngroupSelection as fc, canUseClipboard as fd, captionDisplayText as fe, cellRunStyle as ff, cellStyleToStyleMap as fg, cellTdStyle as fh, changeCountLabel as fi, changeIcon as fj, characterSpacingPatch as fk, chartPreserveAspectRatio as fl, checkFontAvailable as fm, clampCursorPosition as fn, clampGifDimensions as fo, clampIndex as fp, clampNotesFontSize as fq, clampScale as fr, clampStep as fs, clearAllLocalViewerData as ft, clearAudienceContent as fu, cn as fv, collectAccessibilityIssues as fw, collectElementText as fx, collectSlideText as fy, collectStoredChats as fz, AccessibilityPanelComponent as g, formatAxisValue as g$, computeScatterDots as g0, computeScatterXDomain as g1, computeSelectionBoxes as g2, computeSingleSelected as g3, computeSlideIndices as g4, computeSnap as g5, computeStackedBarRects as g6, computeStackedValueRange as g7, computeTrendlinePrimitives as g8, computeValueRange as g9, disableSoftEdgePatch as gA, duplicateElementById as gB, durationOf as gC, effectsStateOf as gD, enableGlowPatch as gE, enableInnerShadowPatch as gF, enableOuterShadowPatch as gG, enableReflectionPatch as gH, enableSoftEdgePatch as gI, encodeGif as gJ, endShowMediaCleanup as gK, estimatePageCount as gL, exitPresentationFullscreen as gM, exportAiChatLogs as gN, extractPathPoints as gO, eyedropperAvailable as gP, fillColorOf$1 as gQ, findInSlides as gR, findOwningSlideIndex as gS, findSlideIndexByElementId as gT, firstVisibleIndex as gU, fitPolynomial as gV, fitZoom as gW, focusTargetChips as gX, fontMimeForFormat as gY, fontSizeOf as gZ, forgetSessionDeck as g_, convertOmmlToMathMl as ga, copyFormatFromElement as gb, countAccessibilityIssues as gc, countAnnotationStrokes as gd, createAngularAiBridge as ge, createCustomShow as gf, createSwipeDismissDrag as gg, createWebrtcBundle as gh, createWebsocketBundle as gi, cssObjectToStyleMap as gj, currentColorScheme as gk, currentLayout as gl, currentStyle as gm, defaultCssVars as gn, defaultRadius as go, defaultThemeColors as gp, deleteElementsByIds as gq, deleteVersion as gr, demoteNode as gs, deriveModel3DBlobUrl as gt, derivePresenceList as gu, describeSmartArtBounds as gv, disableGlowPatch as gw, disableInnerShadowPatch as gx, disableOuterShadowPatch as gy, disableReflectionPatch as gz, AccessibilityService as h, isElementInteractive as h$, formatBytes as h0, formatCursorLabel as h1, formatElapsed as h2, formatFileSize as h3, formatPropertyDate as h4, formatTime as h5, fpsToFrameIntervalMs as h6, generateBroadcastRoomId as h7, generateCommentId as h8, generateCustomShowId as h9, getTextBlockStyle as hA, getTextWarp as hB, getTouchDistance as hC, getWarpCategory as hD, getWarpPath as hE, gradientStateFromStyle as hF, gradientStateOf as hG, gradientStatePatch as hH, gridColumns as hI, groupIssuesBySeverity as hJ, hasAnimation as hK, hasCopyableFormat as hL, hasExistingLink as hM, hasExitedFullscreen as hN, hasGradientFill as hO, hasPressureVariation as hP, hasVisibleSlideAfter as hQ, headerLabel as hR, imageDimensions as hS, inkViewBox as hT, insertTableElementColumn as hU, insertTableElementRow as hV, interpolateWidth as hW, isAudienceTab as hX, isBold as hY, isBrowserOpenableMime as hZ, isChildNode as h_, generatePressureCircles as ha, generateTicks as hb, getClrChangeParams as hc, getContainerStyle as hd, getDuotoneFilterDef as he, getEffectSoundState as hf, getImageSrc as hg, getLocalStorageUsageSummary as hh, getOleAriaLabel as hi, getOleBadgeLabel as hj, getOleDisplayName as hk, getOleDownloadFileName as hl, getOleTypeColor as hm, getOleTypeLabel as hn, getPasswordStrength as ho, getPatternSvg as hp, getPlaceholderStyle as hq, getVersions as hr, getResolvedShapeClipPath as hs, getResolvedShapeClipPathFor as ht, getSessionTabId as hu, getShapeFillStrokeStyle as hv, getSlideBackgroundStyle as hw, getSlideTransitionAnimations as hx, getSmartArtNodeBounds as hy, getSpeechRecognitionCtor as hz, AccountPageComponent as i, overallStatus as i$, isInjectableUrl as i0, isItalic as i1, isLegacyBinaryPresentation as i2, isPpactionUrl as i3, isPresenterMessage as i4, isSigned as i5, isSupportedPresentationFile as i6, isTextElement as i7, isTwoTableFocus as i8, isUnderline as i9, moveNodeUp as iA, msToFrameDelayCs as iB, narrowToCircle as iC, narrowToPolygon as iD, narrowToRect as iE, newChartElement as iF, newEquationElement as iG, newPresetShapeElement as iH, newShapeElement as iI, newSmartArtElement as iJ, newTableElement as iK, newTextElement as iL, nextVisibleIndex as iM, nodeBold as iN, nodeEditBox as iO, nodeFillColor as iP, nodeFontColor as iQ, nodeIdFromKey as iR, nodeItalic as iS, nodeStyle as iT, normalizeFontFormat as iU, normalizeSlidesPerPage as iV, normalizeValue as iW, numFromEvent as iX, ommlToMathml as iY, ooxmlDashToCssBorderStyle as iZ, openNativeEyeDropper as i_, isUrlSafe as ia, isValidRoomId as ib, isViewportBackgroundPressTarget as ic, isZoomActivationKey as id, issueTrackKey as ie, issueTypeLabel as ig, keyToLabel as ih, lastVisibleIndex as ii, latexToMathml as ij, layoutConnectorPaints as ik, layoutNodeLabels as il, linePointsToSvgString as im, lineSpacingPatch as io, loadAudienceContent as ip, loadSessionDeck as iq, mediaFallbackFor as ir, mediaSurfaceFor as is, mergeCaptionResults as it, mergeDown as iu, mergeRight as iv, mergeSelection as iw, mergeTablesDirective as ix, moveElementBy as iy, moveNodeDown as iz, ActionSettingsPanelComponent as j, resolveTransitionDuration as j$, paletteColor as j0, parseAudienceNonce as j1, parseNodeTextarea as j2, partitionSlides as j3, patchChartData as j4, patchChartStyle as j5, patchTableData as j6, patchTextStyle as j7, patternPresetOptions as j8, pendingElementStyles as j9, removeCommentFromList as jA, removeElementAnimation as jB, removeGradientStopPatch as jC, removeNode as jD, removeTableElementRow as jE, removeSeries as jF, renderToCanvas as jG, reorderAnimationDown as jH, reorderAnimationUp as jI, replaceInSlides as jJ, replaceMatch as jK, requestPresentationFullscreen as jL, resizeElement as jM, resolveCaptionTracks as jN, resolveChartKind as jO, resolveFontVariant as jP, resolveHyperlinkHref as jQ, resolveInteractiveElementId as jR, resolveMediaSrc as jS, resolveOleType as jT, resolveParagraphBullet as jU, resolvePresenterNotes as jV, resolveProfileInitial as jW, resolveRegionCode as jX, resolveSlideAutoAdvanceMs as jY, resolvePalette as jZ, resolveThemeCatalogEntry as j_, pickColorByClickFallback as ja, pickFile as jb, pickSupportedMimeType as jc, planGifFrames as jd, planVideoSegments as je, pointsToSvgPathD as jf, presenceToCursors as jg, presentationBaseName as jh, presentationStageStyle as ji, presenterTimerProgress as jj, presetByLayout as jk, presetsForCategory as jl, pressuresToWidths as jm, prevVisibleIndex as jn, projectDrawingShapes as jo, promoteNode as jp, provideViewerTheme as jq, radarAngle as jr, radarRingPoints as js, readAsDataUrl as jt, recordWebm as ju, registerCrossSlideAudio as jv, rememberSessionDeck as jw, removeAnimation as jx, removeCategory as jy, removeTableElementColumn as jz, AdvancedChartEditorComponent as k, setTimingCurve as k$, restoreSessionDeck as k0, revealedElementStyles as k1, routeOrthogonalConnector as k2, rowStyle as k3, rulerDragToGuidePosition as k4, rulerHighlight as k5, rulerStripTicks as k6, sampleColorFromSlide as k7, sanitizeColor as k8, sanitizeSlideIndex as k9, setColorScheme as kA, setDataLabels as kB, setDataPointExplosion as kC, setDataPointFill as kD, setDataPointLabel as kE, setDataPointMarker as kF, setDelay as kG, setDirection as kH, setDuration as kI, setEffectSound as kJ, setElementPosition as kK, setGridlineStyle as kL, setLayout as kM, setLegend as kN, setNodeStyle as kO, setNodeText as kP, setRepeatCount as kQ, setRepeatMode as kR, setSequence as kS, setSeriesChartType as kT, setSeriesColor as kU, setSeriesErrorBars as kV, setSeriesMarker as kW, setSeriesName as kX, setSeriesTrendline as kY, setSeriesValue as kZ, setStyle as k_, sanitizeUserName as ka, saveViewerProfile as kb, savedPresentationFileName as kc, scanAvailableFonts as kd, searchSlides as ke, seedBroadcastFields as kf, seedHyperlinkDraft as kg, seedPropertiesDraft as kh, seedShareFields as ki, segmentFrameCount as kj, selectValue$2 as kk, sendBackward as kl, sendToBack as km, sequentialColorScale as kn, serializeWriteBack as ko, seriesColor as kp, setAfterAnimation as kq, setAfterAnimationColor as kr, setAnimationEmphasis as ks, setAnimationEntrance as kt, setAnimationExit as ku, setAxis as kv, setAxisLogScale as kw, setAxisTitleStyle as kx, setCategoryLabel as ky, setCellText as kz, AiChangeOverlayComponent as l, vermilionRadius as l$, setTitle as l0, setTrigger as l1, setTriggerShapeId as l2, shapeStylePatch$1 as l3, sheetAfterNavigate as l4, shouldBlockClickAdvance as l5, shouldUseSvgWarp as l6, showDirectionPicker as l7, showsTemplateAffordance as l8, signatureCountLabel as l9, textStylePatch as lA, themeStyle as lB, themeToCssVars as lC, thumbnailHeight as lD, thumbnailZoom as lE, toggleCommentResolvedInList as lF, toggleNodeBold as lG, toggleNodeItalic as lH, toggleSheet as lI, topLevelNodeCount as lJ, transformSelectedTextCase as lK, translationsEn as lL, updateElementById as lM, updateGlowPatch as lN, updateGradientStopPatch as lO, updateInnerShadowPatch as lP, updateOuterShadowPatch as lQ, updateReflectionPatch as lR, vAlignPatch as lS, validatePassword as lT, validatePrintSettings as lU, validateRoomId as lV, valueToY as lW, vermilionDarkColors as lX, vermilionDarkTheme as lY, vermilionLightColors as lZ, vermilionLightTheme as l_, signatureKey as la, signatureTimestamp as lb, signerName as lc, statusLabel as ld, slideNumberOf as le, slidesWithReappliedLayout as lf, smartArtNodes as lg, paletteColour as lh, snapToGridStep as li, splitCursorCell as lj, splitMergedCell as lk, statusKind as ll, statusLabel$1 as lm, storeAudienceContent as ln, stringFromEvent$5 as lo, strokeColorOf as lp, strokeToInkElement as lq, strokeWidthOf as lr, styleShadowFilter as ls, surfaceColor as lt, textAdvancedPatch as lu, textAdvancedStateFromStyle as lv, textAdvancedStateOf as lw, textColorOf as lx, textDirectionPatch as ly, textStyleOf as lz, AiChatPanelComponent as m, waypointsToPathD as m0, withManualLayouts as m1, worstStatus as m2, zoomTargetSlideIndex as m3, AiChatService as n, AiComposerComponent as o, AiFocusBarComponent as p, AiFocusHighlightOverlayComponent as q, AiHistoryMenuComponent as r, AiHistoryService as s, toChatSummary as t, AiMessageListComponent as u, AiPanelStore as v, AiProposalCardComponent as w, AiSettingsSectionComponent as x, AiToolCallCardComponent as y, AnimationAuthorPanelComponent as z };
154134
+ //# sourceMappingURL=pptx-angular-viewer-pptx-angular-viewer-D9KH43PW.mjs.map