@cola1900/dsh-ppt 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  从 [dataelement/dsh-desktop](https://github.com/dataelement/dsh-desktop) 提取的独立 **DSH / DeepSeek Harness 插件**。一个包包含 PPT 按钮、模板选择、PPTD 编写与校验、预览和可编辑 PPTX 导出,无需 Electron 或原 Desktop 仓库。
4
4
 
5
5
  - 16 套模板、192 个版式,保留英文/中文 PPTD 示例和本地预览图。
6
- - 仅在会话启用 PPT 模式时自动注入创作指引。
6
+ - 提供原生 DSH **PPT 预设**;只有选择该预设时才注入 PPT 创作指引。
7
7
  - 保留原有文件授权、路径限制、写入哈希检查、版本记录和导出校验。
8
8
  - 提供 `dsh-pptd` 命令行和 `@cola1900/dsh-ppt/pptd` JavaScript API。
9
9
 
@@ -11,44 +11,36 @@
11
11
 
12
12
  需要 Node.js `^22.19.0 || >=24.0.0`,以及提供标准会话输入框插槽的 DSH Web / DSH Desktop。提取基线使用 DSH `0.1.5-rc.2`。
13
13
 
14
- 从公共 npm 安装到目标 DSH profile:
14
+ [公共 npm 包](https://www.npmjs.com/package/@cola1900/dsh-ppt) 直接安装到目标 DSH profile:
15
15
 
16
16
  ```sh
17
17
  dsh plugin --profile web add @cola1900/dsh-ppt
18
18
  ```
19
19
 
20
- 也可以从本仓库构建本地安装包:
20
+ 把 `web` 替换为实际 profile,然后重启该 profile。新会话顶部的原生预设选择器会出现 **PPT**;选择后,输入框下方显示模板面板,在首次发送前选择模板,再描述需求。首次发送后预设和模板固定,新会话可以重新选择。插件首次启动会把内置 preset 写入 `$DSH_HOME/.agent-presets/ppt`,无需手动复制或配置。
21
21
 
22
- ```sh
23
- cd /path/to/dsh-ppt
24
- npm ci
25
- npm run check
26
- npm pack
27
- ```
28
-
29
- 将生成的包加入目标 DSH profile:
30
-
31
- ```sh
32
- dsh plugin --profile web add /absolute/path/to/dsh-ppt/cola1900-dsh-ppt-0.1.2.tgz
33
- ```
34
-
35
- 把 `web` 替换为实际 profile,然后重启该 profile。新会话输入框上方启用 **PPT**,选择模板并描述需求。按钮、选中模板缩略图和可滚动模板列表使用官方 `conversation.input.dock` 插槽,无需 Desktop 的输入框补丁。
22
+ 界面只使用官方 `conversation.input.dock` 插槽,只设置插件自身样式,不修改原 DSH。模板名称继续在卡片内显示省略号,输入框底部不再显示 `PPT · 模板名` 控件。
36
23
 
37
24
  如果目标 Desktop 已内置 `dsh-ppt-composer`,先在目标 profile 的插件配置中停用原 PPT bundle,再加载本包。不要同时启用两套 PPT bundle,否则会重复注册工具、路由和输入框按钮。本包已经合并 composer,无需再安装 `dsh-ppt-composer`。
38
25
 
39
26
  ## 命令行
40
27
 
28
+ 使用独立命令行时,从 npm 全局安装:
29
+
41
30
  ```sh
42
- node lib/bin.js --help
43
- node lib/bin.js check skills/dsh-ppt/references/business/dsh-blue-professional/source --json
44
- node lib/bin.js render skills/dsh-ppt/references/business/dsh-blue-professional/source -o /tmp/example.pptx --json
31
+ npm install -g @cola1900/dsh-ppt
32
+ dsh-pptd --help
33
+ dsh-pptd check /path/to/deck --json
34
+ dsh-pptd render /path/to/deck -o /path/to/output.pptx --json
45
35
  ```
46
36
 
37
+ 把 `/path/to/deck` 替换为包含 `deck.pptd` 的 PPTD 项目目录。
38
+
47
39
  英文示例目录为 `source/`,中文为 `source-zh/`;预览语言不限制最终文稿语言。导出的文字、图形、表格与图表保留原生可编辑对象。机器上的字体会影响实际显示效果,插件不分发字体文件。
48
40
 
49
41
  ## 开发
50
42
 
51
- `lib/` 是上游维护的 JavaScript 运行时代码;`src/client.js` 是输入框客户端的构建输入。完整原始 TypeScript 源码不在上游提取基线中,本项目没有把声明文件冒充实现源码。
43
+ `lib/` 是上游维护的 JavaScript 运行时代码;`src/client.js` 是输入框客户端的构建输入。`presets/ppt/` 是随插件安装的原生 Agent Preset 定义,首次启动会同步到 DSH 的用户 preset 根目录。完整原始 TypeScript 源码不在上游提取基线中,本项目没有把声明文件冒充实现源码。
52
44
 
53
45
  `skills/dsh-ppt/references/` 保存模板元数据、设计说明、双语源文件和预览。修改元数据或预览后执行 `npm run build`,生成模板目录、预览白名单和客户端预览映射。构建使用已随包保存的预览,不依赖网络或原桌面工程。修改版式后可用 `dsh-pptd screenshot` 重新生成图片,再更新对应的 JPG 预览。
54
46
 
package/UPSTREAM.md CHANGED
@@ -8,7 +8,9 @@
8
8
  - 模板:`packages/ppt-runtime/templates/`
9
9
  - 模板许可证与来源资料:`packages/ppt-runtime/upstream/`
10
10
 
11
- 独立化改动:合并核心和 composer 为单个 `dsh-ppt` 包;客户端模块标识统一为 `dsh-ppt`;将 Desktop 专有输入框插槽替换为官方 `conversation.input.dock`,按钮、选中缩略图和模板列表在输入框上方显示;移除指向缺失文件的 `client-standard` 导出,并使用匹配实际客户端的类型声明;将构建改为读取包内模板、生成目录和预览白名单;移除未使用的 TypeScript、Zod 运行依赖;增加独立安装、打包说明及运行验证。
11
+ 独立化改动:合并核心和 composer 为单个 `dsh-ppt` 包;客户端模块标识统一为 `dsh-ppt`;改用 DSH 原生 Agent Preset,随包提供 `presets/ppt/` 并在首次启动时同步到用户 preset 根目录;模板面板只在 PPT 预设的空白会话中通过官方 `conversation.input.dock` 插槽显示,首次发送后固定预设和模板;移除输入框底部 `PPT · 模板名` 控件;移除常驻的选中缩略图;移除指向缺失文件的 `client-standard` 导出,并使用匹配实际客户端的类型声明;将构建改为读取包内模板、生成目录和预览白名单;移除未使用的 TypeScript、Zod 运行依赖;增加独立安装、打包说明及运行验证。
12
+
13
+ 输入框布局只通过插件自身 CSS 和标准会话插槽实现,不修改原 DSH 源码或宿主元素样式。
12
14
 
13
15
  公共 npm 包名为 `@cola1900/dsh-ppt`,插件加载入口、浏览器模块标识和 invariant 归属同步使用该包名。
14
16
 
package/cordis.patch.yml CHANGED
@@ -6,3 +6,4 @@
6
6
  name: '@cola1900/dsh-ppt'
7
7
  config:
8
8
  root: !!js dshHomePath('kimi-ppt')
9
+ presetRoot: !!js dshHomePath('.agent-presets')
package/lib/client.js CHANGED
@@ -5,7 +5,6 @@ window.__ModuleLoader__.load({
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
- let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
8
  let react_jsx_runtime = require("react/jsx-runtime");
10
9
  //#region ../office-ppt/src/protocol.ts
11
10
  /**
@@ -24,25 +23,30 @@ window.__ModuleLoader__.load({
24
23
  const CURATED_TEMPLATE_PREVIEWS = {"dsh-course-workshop":["/dsh-ppt/previews/fed8b4d0d8ce5e7141bb50ae43c39d8cf9618a7c3f77e59477a395892fa57079.jpg","/dsh-ppt/previews/a40ee3f4e99b200fd2c5f284ff2ccaeba277833ef619f8f3dd86aa7a78cc045f.jpg","/dsh-ppt/previews/2a4eb9bf9b551687cc757593cadd44a4d0459564f757c270efd9eb8668b394bc.jpg","/dsh-ppt/previews/69c0ef5e960884089112845a05aa04c57ece1b01f68f488f397bc1603c8865ca.jpg","/dsh-ppt/previews/0ce54cf57bfcc1b3f980a3f33f1f970d24f8125dc520f2a656518f6f2cda4912.jpg","/dsh-ppt/previews/2518d599c39a113284b62c1bae03efeabf3429d5aca60280c7c33c032a4a2e89.jpg","/dsh-ppt/previews/db0c5105dc50f53b6e30fbd92f52cf60d64222264507809135147f4d3e7fff5b.jpg","/dsh-ppt/previews/554da5c3ee239b39e8df86145eb435d1a805f8185b47ce4299a2051fabd104ad.jpg","/dsh-ppt/previews/627eb4cac49c395a367435275089b2d99dd0638db3e9061237e210c879f0f07e.jpg","/dsh-ppt/previews/a3d256926ee527eaebf89bded5f355fa0eef1dafb68d22d5fca97ea3d6ca2f1b.jpg","/dsh-ppt/previews/62f8078de80f96d9745f0c5b0d8ef3f74a8fde3fd8ba0f76febba90c12d50645.jpg","/dsh-ppt/previews/0e1580e8d9157a6592acfedb05464a4373f641569eda84c878592b44dddd9078.jpg"],"dsh-monochrome":["/dsh-ppt/previews/f701eb4f55ec79e820038e174fcfaa88eed1682b224fd6be8b5892dcc64dea7a.jpg","/dsh-ppt/previews/97cfebc5a7385e914322d39107870ffb6388d9e03d6408369da15082c150ea81.jpg","/dsh-ppt/previews/ee9202fe024ea1523e7ee09954f60945aa57cabbe8c2d1b9b749a0a635f2caef.jpg","/dsh-ppt/previews/e8df029190881a5a1cd7ba18cfd0f1420f65d2e3a41714b43e905cccb6d6aaad.jpg","/dsh-ppt/previews/30794acd02cbb33965769f6739f067860761473b950471724925ba91d97bec81.jpg","/dsh-ppt/previews/0de450d11bbdb1fad6554a83bc8828c14db34356dd56ee8f06ab9ed0503950e6.jpg","/dsh-ppt/previews/50db53c9f4cc986e74903321ed353294ca14cbd2060439b14ef35090313dde92.jpg","/dsh-ppt/previews/a16a39f25123bcab08f3e22b19094af9297dad307ad9fc91d871801b231c4330.jpg","/dsh-ppt/previews/18f94a4936eda3fcba8debd98322c785c99fc66feba4adec45670dd4797b8a74.jpg","/dsh-ppt/previews/d1be235428f34261d37f52cd1242f8260be61c7043b771b5318873d036403231.jpg","/dsh-ppt/previews/294fec3556f51125c64501b4474add0cfee1131fa41cf7688837a056e122ae0b.jpg","/dsh-ppt/previews/03e37701d44a7a82e654fbced88afac4948d7251429345715c42a1ecf34661fa.jpg"],"dsh-blue-professional":["/dsh-ppt/previews/868a103a21ffb7c05c3db006c2d3abdef714691572350af1173bc984bbb28ecb.jpg","/dsh-ppt/previews/cf37a24dec383c4595c057d7f044b9967583346829192ba38aff4decb25169ad.jpg","/dsh-ppt/previews/3f97a46d061b4dc47cb7da91435a743d621cdbc600d933145709e52e02f2e4a9.jpg","/dsh-ppt/previews/1f638ffdce60a794385a51c924d867ec17923b6cf32ae8019e7292aefe684e6c.jpg","/dsh-ppt/previews/986aaeafe96124e80d0a42c7038b40f83921a6eb0db76fd5aad4cb3e32c1c240.jpg","/dsh-ppt/previews/512ac2faea75296d7e5003d517f4aec0937e5b88fdb7db877d562d7f02c4efb6.jpg","/dsh-ppt/previews/58dd6121abec93c7237665cf79ea6dc6562d198ae9cadbdf61aa4f446339e8b4.jpg","/dsh-ppt/previews/0374e1174b59555c71a8efdf5e8aa3ca3f44c71db9d5b8045588edaaf08ad0cb.jpg","/dsh-ppt/previews/0ecb8745f9a5ef9f361f8517792cc0ec66c68ae2582eed5cbb867e3c8baf7742.jpg","/dsh-ppt/previews/882aaa1e1995cdf4b330d17338bf617bdeeccc1f25ff9969ef3735cfae0a75fd.jpg","/dsh-ppt/previews/539b0126fbe687906503faf6a2b5c28ef6dc496293eb1541857ce4536837a58f.jpg","/dsh-ppt/previews/5eac7a7dd81a6597c98c87965f8a828c5f278de06d86064acbc62dd45de3da7a.jpg"],"dsh-neo-grid-bold":["/dsh-ppt/previews/42ecc9887ef7a3b8f397183f3c048efa8b2d2b35345419ea630b28df266f3790.jpg","/dsh-ppt/previews/381d43c1b1b70b994a31b4ee25d7d7f628a9426e70007a64cf01c55fce31ec8f.jpg","/dsh-ppt/previews/64e83c7d45ce86de423df9a342bed9be3245717912d4d07b6068bd924fb4c9c0.jpg","/dsh-ppt/previews/793eef0fe660522245e0dbca446c68f91162baeef63ae27e59cf5a7d30c55475.jpg","/dsh-ppt/previews/d734547a151865d1b73b7d71fbfe08fcaddf7ff7094c669ba463c3cea2965b8e.jpg","/dsh-ppt/previews/f67ef0d4e370e1c60519bb78b16a11788aed134b2e4bff4fda2ed4e5f6bfdc1f.jpg","/dsh-ppt/previews/766b33eb3d390fff007cfc0e6e5d96bc8dbd2809cb761214a20fc85a0eb54409.jpg","/dsh-ppt/previews/571836e3e8b781f7a9b0530eb7e9419b399aeda72b74eff899d1d429e7ee837e.jpg","/dsh-ppt/previews/0e9b9303517f3e07d9e7aa39a243a70b0d9bedc5dff374ce69e94f7a4260c34f.jpg","/dsh-ppt/previews/a03ac86b654acc78b1beee5d92f4655cbf7bfd801555d08e8b28ae4877aa6a75.jpg","/dsh-ppt/previews/2ffa678ab3033ec8ee480a9f606e2868f3b06f0382659945c5f533412dc81bf2.jpg","/dsh-ppt/previews/7436471b575a5ace540f4b36ef1fdb2c5073454e08ecbb6575ea832b80632b43.jpg"],"dsh-consulting-curated-swiss-signal-grid":["/dsh-ppt/previews/a9fc261ff602e85ae5bcf1f3f6618d7f53a27ca8fb1250e83e6cbbc5622f05a2.jpg","/dsh-ppt/previews/9245aaaf9fc11d16a981230ec9227e6e0d7e5a8f3aa92864e303ea2ed933cc5f.jpg","/dsh-ppt/previews/ac4a30b4d8c195f78efffe1797ef78051a88cb2c2ad78eed61c062150dc3ea10.jpg","/dsh-ppt/previews/4e27f5f5b82c4f90313d54f602ac2c3b45aa35be4a82550d0160aa43e534a6a6.jpg","/dsh-ppt/previews/f62bf7b4b3c352cd13863390cfcb74ce15ea2b89a00b5883bb77474fe0ad7e46.jpg","/dsh-ppt/previews/669df5cecd9218a4a06ebfb5d081bdfdca8e7dec162d9b79b4f863962de4d1c5.jpg","/dsh-ppt/previews/703cb1cc235aa26255fa1f3dd3278957de95fa90137dea2e145592b71f30000b.jpg","/dsh-ppt/previews/dc6cb0333176a2a61febec9fed2e1abfe8cc9a3efbb7bc401fbfebc2c7653b68.jpg","/dsh-ppt/previews/d6475a405923849dae440d8b501a88f684a6270c791db3bb78de63237b4ea36d.jpg","/dsh-ppt/previews/62ccc3f3a2c60aa5eba128236e569413d4709de7bba24666301c9cc0adaae76f.jpg","/dsh-ppt/previews/8d6611a9ae8d8fe1c92b6405ca0f30f3d880416434c6397d3f57870263301131.jpg","/dsh-ppt/previews/fa2a74cc83300bcd1a1d140377bca9c46fa14d9d50eb781e14747ec7fcc84060.jpg"],"dsh-cartesian":["/dsh-ppt/previews/a808b79b56240cde4657fb0856015e8dd418ddd2e49b01e14bd9e1d3e146adaa.jpg","/dsh-ppt/previews/35eeaa5b18c169f708e4e42f2492cfb2dbcce1ef86b06599c29e04d30b9d22f5.jpg","/dsh-ppt/previews/77c4ca59b44ec96cd8382f2f3a48caafacaf3b393851000ebb6a84284eec4839.jpg","/dsh-ppt/previews/63e069e69471434522a848003e7ae4f36fa809d5c9062a01879f62b1d5c8ab2d.jpg","/dsh-ppt/previews/d93a7be1dce350a30aa26811da9b1fc7938bc7414c7dc441907e04e8ba79ca3f.jpg","/dsh-ppt/previews/f65d93506cde15156428878f13e6f85b095ceb8ed9df7537bfb7e79c9780fd58.jpg","/dsh-ppt/previews/e6f759a647188fbfb7dee5999b89b084dd3f8fa830e287f82fdee079a296d96f.jpg","/dsh-ppt/previews/816c48af2d9158b382f0a4c0797fe820c76d3b6c7ce1c49ac55e0ef4e9e9fe46.jpg","/dsh-ppt/previews/1824c45afa9c4d983a8d6eb38e726ff51592372579cbe504f79cfc6f254ec5e3.jpg","/dsh-ppt/previews/316da6a75dd2e861047832c64fd0356ca953c17d4e66107033b268ce9cd5295c.jpg","/dsh-ppt/previews/175c2d14ba109530173b6d276aad52de9ea587b6e370a29f084f092d8e6ca553.jpg","/dsh-ppt/previews/b180ffeca1c203030a8596e7c4975a4ebd6eebfe82cf4f7253e03a3e399735f6.jpg"],"dsh-signal":["/dsh-ppt/previews/e1ebc7996873e192a6a8e91b12e4da56756d98e0124baae6a5c78e17b1a63ff1.jpg","/dsh-ppt/previews/dfcb693665809f399d6626f31963efa24347dc654b49a986538f494d7b28bf31.jpg","/dsh-ppt/previews/28fea0e9c858a03fbe101148ca23ab910ee4cdee87ba6a31b232f922853952cb.jpg","/dsh-ppt/previews/eb7ba941e62a2a067f0938b62d4b11cb57d21710acbc516274080526a61a96a9.jpg","/dsh-ppt/previews/fc75d303af4d57715883610b1cc3530e1081c3b5d80bf9e29fcffeda7fb1cdb5.jpg","/dsh-ppt/previews/badf1cdc20c1ee9988bee10c99618e1c8beb5fa651aeb2cf574157bd38409850.jpg","/dsh-ppt/previews/339e5c7dfcd5af524580084155d9a977caa621136c270b28973928db8bcfbbfe.jpg","/dsh-ppt/previews/c98c474084e88f4d0d14d182b07a947bf21572c11621fe4f47f7a273009ed5af.jpg","/dsh-ppt/previews/96cadd291ad03d6a8e3d63ccce017093bb000614f868903429eb8f2beb2ce8e5.jpg","/dsh-ppt/previews/18ad51348ccb5ac5855d6008ab0f665e40459872aeaee38ca5931350e9c9f717.jpg","/dsh-ppt/previews/3578a587665afe90b3ddffd479e00b4c034f57febf3200baf2b7d6dea0acce54.jpg","/dsh-ppt/previews/8a11a88decd2d2434295c55f92fe311aaa5ce9c2a051bab306277374efd22db8.jpg"],"dsh-editorial-notebook":["/dsh-ppt/previews/64c6b0467a02358eab0e7c682b219ec10917e7457d8e65ab2734460e26ff006b.jpg","/dsh-ppt/previews/8abd112497cecf164b9d8d3b7f88978196013a6e8a68690740dbd8b50a8e3ef2.jpg","/dsh-ppt/previews/8cc740d20f1b5a0f3c5c5012b5991f6130414cd43eb8ecf72dbcd6908f29db5f.jpg","/dsh-ppt/previews/4dcd361d0086a690c660471202d4528fc6da72b051f30d19ba943dbb64e2e4db.jpg","/dsh-ppt/previews/68b87b7fe732344dc48deaeb9e85fa1a83f0d6f53965e2a20d83f876575eb0b3.jpg","/dsh-ppt/previews/5fafb45386a94acc94db14cc9e27d0ee7aff817b67b6f1e9966b29d3c7a1b752.jpg","/dsh-ppt/previews/b61d3f7e8330ed99137d5ca9a076715e07943b8c82a5f43901ce1b378083d3de.jpg","/dsh-ppt/previews/9ffb8c8b96c09b5ad8e52c71a3bac3def79593239140afa086a1d514c14e5d8d.jpg","/dsh-ppt/previews/7c05dd18fccacc12f1b914ef5f191e77538033127833410ce718ecb168e68044.jpg","/dsh-ppt/previews/11e802de58f2d6f22f799f1856818d845bb5a8a868a8df4505496ed213e905e4.jpg","/dsh-ppt/previews/0faedcf0681b4822510cdf63fffcb48e78aaff7857a1d25a55876c7956c34bbe.jpg","/dsh-ppt/previews/f1cfc6d9a19542ef9010ad2c97d11900f789c06e2710c29d7c95edea98992dd8.jpg"],"dsh-soft-editorial":["/dsh-ppt/previews/f4984470ee6aceef2064ec65c546cdd73f0c267bc814eaa3b101fa797fb0018f.jpg","/dsh-ppt/previews/ef510f7616c701d8e2991baca9bb29b5611d8d01eac5ee5f86b329f820123132.jpg","/dsh-ppt/previews/e059dd44269991e8b8e5cdff183862865061d68804fa09a259d842df4dfb663f.jpg","/dsh-ppt/previews/ffad10e507032c1279878f6197cf1a5901efb6d9ad052dea8a728ef9a170dd25.jpg","/dsh-ppt/previews/0900fb3baf783507567b5013348fc56dd43da13e8914ae3317ddf7d5739a3305.jpg","/dsh-ppt/previews/ea9558c4e2571ea9cb8e539f212403afa70981f30c01f2321513bba298aee76e.jpg","/dsh-ppt/previews/379f5b94697dce71b9bd7740356592efc6b292c5f98641dd787858ba6c690065.jpg","/dsh-ppt/previews/ba75e21f18de64ba003a9bec7a7096573cdae7a480e1a4365c1523c62e704830.jpg","/dsh-ppt/previews/3e0076a4d166477be2caf00e60c7a40c450312942cf94c4a2d65a43e5ac52d52.jpg","/dsh-ppt/previews/e14476fbd7eeab933e02fbc62b233a8e786bd32782ccb5cc19bb86a1708382ab.jpg","/dsh-ppt/previews/dc367d2c7697c9be87d95c9bc0a19b6e3f2f132cf5aa8fa464f7cf0afdd21b36.jpg","/dsh-ppt/previews/35ae039f1983df07f51660763edc82e4f1d3991d0ada37da64b432d588f88e42.jpg"],"dsh-broadside":["/dsh-ppt/previews/2e6f686dbec5cf41db6fc8063ef99e9716f9ca2daac92fa4b56745acb45587e7.jpg","/dsh-ppt/previews/002981cea2eb73a2991d31837777ed5348f69f64d298d4c8899c37fe8f0b7e82.jpg","/dsh-ppt/previews/34740261b665bf3708f535282f75cbb13259ac35d5177f2ba8ab09a564320d6e.jpg","/dsh-ppt/previews/3d5d55feabdac78b8e643e2a307b4c2cee27ecdccc40a4eb4a1741eec51d6ec4.jpg","/dsh-ppt/previews/2f607fb64a97a231905d4dd890a72953d44b04de6544e527fd5ff4aee8c75054.jpg","/dsh-ppt/previews/06b07ac6e9fab55730e0fbc0446fec13b397c005ce3cbc10275ec03896072b27.jpg","/dsh-ppt/previews/71015f8d090f21d0bfa0d74d06aba0105841c541b616b03192a64d6de2574c9c.jpg","/dsh-ppt/previews/1560e2ac3107c75dfa8f6c5a5e2766c0a0f2293a8bcde09261b0b7088d591109.jpg","/dsh-ppt/previews/6e61aa23ef8612fc9168bd2556e010feb0107618299d278e9a7781d6534d44a7.jpg","/dsh-ppt/previews/c66bb94f312ba993dc11ad251a0f63432c9ab7ea636f7a36eedeb16ea078309b.jpg","/dsh-ppt/previews/1c67b711fca88d2eedbe27bb332f083db7e620a8557aee3f365c19d744630bfa.jpg","/dsh-ppt/previews/ee1f448518443a10bf5683ef6240a1be6316fdd7348b7b1e1d818a8db8ee74f1.jpg"],"dsh-playful":["/dsh-ppt/previews/4edbea30c657a3b51a41969d9c7a817bf89bd99c32dff9917309da2ccd3f7f98.jpg","/dsh-ppt/previews/9eba580032113732acbb0cebc938b70ae39306d7df6c133aee2b41167b9bb308.jpg","/dsh-ppt/previews/2ad9bc36631dbce46ffab1f97edf10abc4c29f460c4334fe36e1424f86dda821.jpg","/dsh-ppt/previews/d9228f9b8e2f28876bbab72e53c4faf29395b390dcfe2c6472462c59074e5677.jpg","/dsh-ppt/previews/7599ebd17fa1666fc013d5922cf53247cefd41b0d7cf6ae02c65b15922e470b5.jpg","/dsh-ppt/previews/6f532cc31579c0bd4477bdbd647bd06b462cc6ae20c55eabdc7fe500d3f54ab2.jpg","/dsh-ppt/previews/3450dcf2261d97738861144de943d1bc39c5deb3dbb53e030c466f22c09cc75d.jpg","/dsh-ppt/previews/c10e9f7d4779fe1ec3a141cda7c6c851bace7191c1499680d185acc22ada7aa8.jpg","/dsh-ppt/previews/5bece461636792f9ac7b727f3d6e454944fd478cb0b8c196c51d594f52efa4fc.jpg","/dsh-ppt/previews/4ed05f3281426a89e08b1bfdcb770202570057e7223348fb041bda7dcfae79b7.jpg","/dsh-ppt/previews/b16c23a7ce96b32af0506a8e9af131637dd6cfb65272a775cee5d2327b1d7dc1.jpg","/dsh-ppt/previews/c44af6131cbf2f3340e30d4129166bf71f5366e0124bbdfb14892db8e0e6708d.jpg"],"dsh-sakura-chroma":["/dsh-ppt/previews/37e9b8f2cfb6f41e914a39afa83a75d803ee0f737c4c6a1359db430bcf62e892.jpg","/dsh-ppt/previews/e70e30b7b5eedb9946f6db1a4d4c8d8cf1dc5b62403bf7a6f8655a28d1023134.jpg","/dsh-ppt/previews/25183092c8159e828f5ab83b5340866309048e14983440192c376eb59ef4f4da.jpg","/dsh-ppt/previews/40c18cd52ab8a1308fea24e8d58259c94df366c822515a9942613ba6ef227ef8.jpg","/dsh-ppt/previews/ff657f6c773c9efda3f23d20d23a5a30551ef5a96735e6cc415ab1df91a5e901.jpg","/dsh-ppt/previews/7258ee425f3d22df91d5e8aa8e114281e0da9a008044173d5cac1676b3fdfa59.jpg","/dsh-ppt/previews/147cf72d365991d061c7e4c313e467c6162d62cf8860a8410973caab1e11aef2.jpg","/dsh-ppt/previews/ac468754eb618d5b26edb83c16fb87b0c84e19f2f2fd4f346ef19121afd1ab6f.jpg","/dsh-ppt/previews/19fd60f4e64e18be514fd32009b3ab71f1e83c10ee6d559a56b8790c95f6b734.jpg","/dsh-ppt/previews/768c0f362a9c5cae7821401173c491777833aabedc9566c51c1308380cf6e047.jpg","/dsh-ppt/previews/dc835bd049d7ad76f8cd24cb1cefae1240b1cb5ab11ba65829bd96bb18497021.jpg","/dsh-ppt/previews/c2d760b629fe3337fcdfc889538a67b36f161a4194d641943dd77e58c68e7abf.jpg"],"dsh-work-curated-modular-logistics-system":["/dsh-ppt/previews/352a8b8ecb36f7afaea2cb217d2e2a0f7fd5d046a34e0b627dd305dc4b274b0d.jpg","/dsh-ppt/previews/f07ce2e140c1073ccf41ce94a9432757a04ee6c944ad960349662d3b8aaa2dec.jpg","/dsh-ppt/previews/d044d9db6f2ae8f200bf049da71d3e9b64212da65747849102434b9397836a08.jpg","/dsh-ppt/previews/d0150b3bdd9baa1900d42c0c421296bca8c2727c28b962b359fd5cbfbc2382d9.jpg","/dsh-ppt/previews/b8f83ef6cc86a54e9df9bd6ebafd0e7f454c5dba6b43654d39cdb37658b1a63c.jpg","/dsh-ppt/previews/2040f8a2f887840ac51cf703f458f321814b7614e86b566118a88e76ce8ed4ac.jpg","/dsh-ppt/previews/2524d20ed733c8061cc163106d9f90b8bb208f4386877c9b12c18b19d8baafda.jpg","/dsh-ppt/previews/3a1387a8ab99c7c0542fea7c46d42eef32d1d4252605ff0db939d991588c3581.jpg","/dsh-ppt/previews/ea6ee0677a90f2960fdf6a30e6db66822b605bb4dc6e1699045ff5099e7595b0.jpg","/dsh-ppt/previews/6fbbbb664e18ebbb5898772348001c55b71f8a62310976655dca0cf37fbcdc0a.jpg","/dsh-ppt/previews/d3bddd9040ebd84c4641894d693b6436d4b3b080dfaf603176230599bf377025.jpg","/dsh-ppt/previews/dc6bba255470230eda70eb93cf161e290e79af81476a5acba7abf660ab0c97e8.jpg"],"dsh-work-curated-nordic-operating-report":["/dsh-ppt/previews/50edbc49b9e3003012bb87de8f93ab9b2b4784fa8494f4844dbd2f61e6a086b1.jpg","/dsh-ppt/previews/9effb8added62e9b8fc6982e652b7f32639f6aede8dc9a858913c2ee1a60235a.jpg","/dsh-ppt/previews/33e2639b91ae4dbe6ac1d2c963eb46d1eea4df85f30b712b73895012d1a3c6c0.jpg","/dsh-ppt/previews/4d970687799e035c9dd0df109fe65e76ea1b96c0d8d481299ff435d30a65ce26.jpg","/dsh-ppt/previews/57b3457cea8f332669b56fd01bc571d5f380a530750ba02aab7b8ef9614fd1a7.jpg","/dsh-ppt/previews/5152fd5bf15f0a27a55ae25723dde7dfb60fef7b6226dcb6c5b4cdeea6bd5ecf.jpg","/dsh-ppt/previews/9883a506d8163b0ade962f9502253b28a6d7b2551d3447869b0dcaaf30c15e8b.jpg","/dsh-ppt/previews/d3d3e7142733b18fdeb394da10e0328fa48ccc79d6d14848372610bd2d262175.jpg","/dsh-ppt/previews/2955b1fc98891bad55c2bfe0fa8d8a6ef90cc7c177a4ac0180fe9f117ca15b0e.jpg","/dsh-ppt/previews/2e1273cc2309932480aed2ffd181c827ab3f97740fee83419fc69d50ceb29aea.jpg","/dsh-ppt/previews/707c85ed84f668a51aef02c85e42acaa5db0daad623269c5dd64bb3e3f1b966f.jpg","/dsh-ppt/previews/ea1168214e3e137254c2ad219d3c96bcb74f67fe7bd344522a70f1765a4e6d93.jpg"],"dsh-editorial-forest":["/dsh-ppt/previews/602a146d4db9a3242c6e1c4a7bcb3baa3f2937d5e17570c460337a341766b30f.jpg","/dsh-ppt/previews/8d202fef8051dd0f30080ee02cc38bf8730a5e037739c9c3ebf2dee1203d9496.jpg","/dsh-ppt/previews/39968132d85c7e8c9b1dc8e0f553611d30b5db73145c35a875447427eaf22021.jpg","/dsh-ppt/previews/00554d6b491822b40fab87850226c5c6670c1a6a327c851c524d69219b5e06d9.jpg","/dsh-ppt/previews/d3bdcd19a6ed4f5835ee67c71df1f49e1191a29104e20268053dfa9348b46809.jpg","/dsh-ppt/previews/2bbfb7ff47a5b35011b1a2f633be4562110feae54f6f820d7cc73db6df1d9f32.jpg","/dsh-ppt/previews/0124f90ac4eab99d17a39be24e2721ca35ec8e4fd0b9c6c2f70d2ecc7bae476c.jpg","/dsh-ppt/previews/dfbab1e3ed4fc25ca4afe2e725ecf3d6b097da989bbf3016a0b243bc14db82ba.jpg","/dsh-ppt/previews/c9cdb76b6942517a687e40d8b29f70d5969c9d5bb3bc76a7b58c801f48e8dab0.jpg","/dsh-ppt/previews/446f8e7e066f9bb7d0210f0f61505df331460daf4e4249e5eb25b82c5fb3456a.jpg","/dsh-ppt/previews/acf81e5537f27c54fac23bd9b9d261074665df67afcf9f5391a45985a650a4bc.jpg","/dsh-ppt/previews/89998775d68eabfdb3bb88cfbd87b1fedf079bf9a85bd3d376df203d12fe4ce3.jpg"],"dsh-engineering-blueprint":["/dsh-ppt/previews/2d8d805401ca0dcc6866d1b218d46d3bdff9e1c05bca61a765b4f253bb2ba6fe.jpg","/dsh-ppt/previews/867b26c167cb7f3c64577d98792adcb95939a81d92aecb0e544f75707e6df61d.jpg","/dsh-ppt/previews/78f04acc8a457498e7d0e4b1dbfcda7d17aebf4c10d077771cc7c3431182a502.jpg","/dsh-ppt/previews/ddc9b69fc37b39f9300de821caa29903311aee88ed19e1c5538fd838c43bb7e1.jpg","/dsh-ppt/previews/c1967350c716cc02046f505e44bc821a39a935861676fa0c5e75c29fa34e5e18.jpg","/dsh-ppt/previews/22dd5793de7503f64e6589d57d4ca6cdf4753af78884f8ceca601a99857cc70a.jpg","/dsh-ppt/previews/0f03f78cca8ba49eb0b5dbc6b0a49da8cf24903a5246c1d51651afb4bb4f74ed.jpg","/dsh-ppt/previews/f4fb319f70eec1e32442190b5b15dee075c2ebb73aac0a056bd2e4aba4d73276.jpg","/dsh-ppt/previews/e839ee55067602e77dc21ae57d64e058611e33bd78a86dad8fcb9f0328b8bf57.jpg","/dsh-ppt/previews/7c670c63661ed054cbef90220700e54b1df470bed797e8c500c9341d7413b0f6.jpg","/dsh-ppt/previews/96d7d35e03ed2f1bd921a0524641d9ca0b71206e8247f8f137215ca25b55e554.jpg","/dsh-ppt/previews/aec3d2a73212cdfa6a1f50bd65f169891feb8e99048828348ebc75df70aa600c.jpg"]};
25
24
  //#endregion
26
25
  //#region \0dsh-css:ppt-composer.css.mjs
27
- const css = "._2S_x-q_modeRoot{box-sizing:border-box;width:100%;padding:0 var(--dsh-composer-side-clearance);position:relative}._2S_x-q_modeRow{flex-wrap:wrap;justify-content:flex-start;align-items:center;gap:8px;min-height:32px;display:flex}._2S_x-q_modeChip{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:999px;align-items:center;gap:6px;padding:7px 13px;font-size:12px;line-height:16px;display:inline-flex}._2S_x-q_modeChip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._2S_x-q_modeChip[data-selected=true]{border-color:color-mix(in srgb, var(--dsw-alias-state-business-primary) 55%, transparent);background:color-mix(in srgb, var(--dsw-alias-state-business-primary) 12%, transparent);color:var(--dsw-alias-state-business-primary)}._2S_x-q_templatePanel{box-sizing:border-box;z-index:2;width:100%;max-width:calc(var(--dsh-composer-card-max-width) + 32px);height:var(--office-ppt-template-panel-height,calc(100dvh - 178px));max-height:var(--office-ppt-template-panel-height,calc(100dvh - 178px));background:0 0;flex-direction:column;margin-top:8px;display:flex;position:absolute;top:100%;left:50%;overflow:hidden;transform:translate(-50%)}._2S_x-q_modeRoot[data-placement=fixed]{height:0;overflow:visible}._2S_x-q_modeRoot[data-placement=fixed] ._2S_x-q_templatePanel{max-height:none;top:0}._2S_x-q_modeRoot[data-placement=fixed] ._2S_x-q_templateViewport{overscroll-behavior:contain;flex:auto;padding-bottom:12px;overflow-y:auto}._2S_x-q_templateToolbar{z-index:2;background:0 0;flex:none;justify-content:space-between;align-items:center;gap:12px;min-height:38px;display:flex;position:relative}._2S_x-q_templateViewport{box-sizing:border-box;overscroll-behavior:contain;scrollbar-width:none;min-height:0;padding-bottom:12px;overflow-y:auto}._2S_x-q_templateViewport::-webkit-scrollbar{display:none}._2S_x-q_categoryTabs{scrollbar-width:none;gap:4px;min-width:0;display:flex;overflow-x:auto}._2S_x-q_categoryTabs::-webkit-scrollbar{display:none}._2S_x-q_categoryTabs button{color:var(--dsw-alias-label-caption);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:999px;flex:none;padding:5px 10px;font-size:11px;line-height:16px}._2S_x-q_categoryTabs button:hover{color:var(--dsw-alias-label-primary)}._2S_x-q_categoryTabs button[data-selected=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._2S_x-q_templateGrid{background:0 0;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 14px;display:grid}._2S_x-q_templateCard{min-width:0;min-height:0;position:relative}._2S_x-q_templateSelect{width:100%;min-width:0;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;outline:0;flex-direction:column;padding:0;display:flex}._2S_x-q_previewViewport,._2S_x-q_selectionPreview{container-type:inline-size}._2S_x-q_previewViewport{aspect-ratio:16/9;border:2px solid #0000;border-radius:9px;width:100%;transition:border-color .12s,transform .12s;display:block;position:relative;overflow:hidden}._2S_x-q_previewViewport:after{content:\"\";position:absolute;inset:0;z-index:2;border-radius:7px;box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-label-primary) 25%, transparent);pointer-events:none}._2S_x-q_previewViewport>._2S_x-q_preview{aspect-ratio:auto;width:100%;height:100%;animation:.18s _2S_x-q_previewReveal}@keyframes _2S_x-q_previewReveal{0%{opacity:.72}to{opacity:1}}._2S_x-q_templateCard:hover ._2S_x-q_previewViewport{transform:translateY(-1px)}._2S_x-q_templateSelect:active ._2S_x-q_previewViewport{transform:scale(.985)}._2S_x-q_templateCard[data-selected=true] ._2S_x-q_previewViewport{border-color:var(--dsw-alias-state-business-primary)}._2S_x-q_templateSelect:focus-visible ._2S_x-q_previewViewport{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}._2S_x-q_templateName{text-align:center;text-overflow:ellipsis;white-space:nowrap;padding-top:5px;font-size:12px;line-height:16px;overflow:hidden}._2S_x-q_templateCard[data-selected=true] ._2S_x-q_templateName{color:var(--dsw-alias-label-primary)}._2S_x-q_panelState{min-height:160px;color:var(--dsw-alias-label-tertiary);place-items:center;gap:10px;font-size:12px;display:grid}._2S_x-q_templateError{border:1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 40%, transparent);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);color:var(--dsw-alias-state-error-primary);border-radius:8px;margin-bottom:8px;padding:7px 10px;font-size:11px;line-height:16px}._2S_x-q_retryButton{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:999px;padding:6px 12px}._2S_x-q_retryButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._2S_x-q_selection{align-items:flex-start;display:flex}._2S_x-q_selectionPreview{aspect-ratio:16/9;transform-origin:50%;flex:none;width:clamp(76px,10vw,92px);transition:transform .2s cubic-bezier(.34,1.56,.64,1);display:block;position:relative;transform:rotate(-3deg)scale(1)}._2S_x-q_selectionFrame{border:2px solid var(--dsw-alias-state-business-primary);background:var(--dsw-alias-bg-base);border-radius:9px;width:100%;height:100%;display:block;overflow:hidden;box-shadow:0 4px 14px #0000002e}._2S_x-q_selectionRemove{z-index:2;color:#fff;opacity:0;pointer-events:none;cursor:pointer;background:#111111e0;border:1px solid #ffffff4d;border-radius:50%;place-items:center;width:20px;height:20px;padding:0;font:500 15px/1 ui-sans-serif,system-ui,sans-serif;transition:opacity .12s,transform .12s;display:grid;position:absolute;top:-8px;right:-8px;transform:rotate(3deg)scale(.88);box-shadow:0 3px 10px #00000047}._2S_x-q_selectionPreview:hover ._2S_x-q_selectionRemove,._2S_x-q_selectionPreview:focus-within ._2S_x-q_selectionRemove{opacity:1;pointer-events:auto;transform:rotate(3deg)scale(1)}._2S_x-q_selectionRemove:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}._2S_x-q_preview{box-sizing:border-box;aspect-ratio:16/9;background:var(--office-bg);color:var(--office-text);flex-direction:column;justify-content:center;padding:12% 10%;display:flex;position:relative;overflow:hidden}._2S_x-q_preview[data-source-preview=true]{background:#fff;padding:0}._2S_x-q_preview[data-source-preview=true]:before,._2S_x-q_preview[data-source-preview=true]:after{display:none}._2S_x-q_previewImage{object-fit:cover;width:100%;height:100%;display:block;position:absolute;inset:0}._2S_x-q_preview:before,._2S_x-q_preview:after{content:\"\";pointer-events:none;position:absolute}._2S_x-q_preview:before{border-left:1px solid color-mix(in srgb, var(--office-accent) 35%, transparent);background:color-mix(in srgb, var(--office-surface) 92%, transparent);width:34%;height:100%;top:0;right:0}._2S_x-q_preview:after{background:var(--office-accent);width:18%;height:clamp(1px,1.3cqi,3px);bottom:13%;right:8%}._2S_x-q_previewAccent{background:var(--office-accent);width:18%;height:clamp(1px,1.3cqi,3px);position:absolute;top:16%;left:10%}._2S_x-q_preview strong,._2S_x-q_preview small{z-index:1;text-overflow:ellipsis;white-space:nowrap;width:66%;display:block;position:relative;overflow:hidden}._2S_x-q_preview strong{margin-top:8%;font-size:clamp(4px,6cqi,14px);font-weight:650;line-height:1.12}._2S_x-q_preview small{color:var(--office-muted);margin-top:4px;font-size:clamp(3px,3.4cqi,8px)}._2S_x-q_preview[data-variant=blue-professional]:before{clip-path:polygon(25% 0,100% 0,100% 100%,0 100%);background:var(--office-surface);border:0;width:40%}._2S_x-q_preview[data-variant=blue-professional]:after{width:15%;height:2px;bottom:14%;right:8%}._2S_x-q_preview[data-variant=editorial-forest]{background:var(--office-surface);color:var(--office-accent);justify-content:flex-end;padding:10%;font-family:Georgia,Times New Roman,serif}._2S_x-q_preview[data-variant=editorial-forest]:before{aspect-ratio:1;border:1px solid var(--office-accent);background:0 0;border-radius:50%;width:16%;height:auto;top:11%;right:9%}._2S_x-q_preview[data-variant=editorial-forest]:after{background:var(--office-accent);width:80%;height:1px;bottom:10%;right:10%}._2S_x-q_preview[data-variant=editorial-forest] ._2S_x-q_previewAccent{background:var(--office-accent);width:26%;height:1px;top:13%}._2S_x-q_preview[data-variant=editorial-forest] strong,._2S_x-q_preview[data-variant=editorial-forest] small{width:78%}._2S_x-q_preview[data-variant=editorial-forest] strong{margin-bottom:11%;font-size:clamp(5px,7.4cqi,17px);font-weight:500}._2S_x-q_preview[data-variant=editorial-forest] small{color:var(--office-bg);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;position:absolute;top:16%;left:10%}._2S_x-q_preview[data-variant=signal]{background:var(--office-bg);color:var(--office-text);font-family:Georgia,Times New Roman,serif}._2S_x-q_preview[data-variant=signal]:before{background-image:linear-gradient(color-mix(in srgb, var(--office-secondary) 55%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--office-secondary) 55%, transparent) 1px, transparent 1px);opacity:.45;background-size:18% 31%;border:0;width:100%;height:100%;inset:0}._2S_x-q_preview[data-variant=signal]:after{background:var(--office-secondary);width:80%;height:1px;bottom:15%;left:10%;right:auto}._2S_x-q_preview[data-variant=signal] ._2S_x-q_previewAccent{background:var(--office-accent);width:14%;height:1px;top:18%}._2S_x-q_preview[data-variant=signal] strong{font-size:clamp(5px,6.8cqi,16px);font-weight:600}._2S_x-q_preview[data-variant=signal] small{color:var(--office-muted);letter-spacing:.08em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._2S_x-q_preview[data-variant=orange-data]{color:#111;background:#fff;justify-content:flex-start;padding:15% 8%;font-family:Arial,sans-serif}._2S_x-q_preview[data-variant=orange-data]:before{background:linear-gradient(90deg, var(--office-accent) 0 25%, var(--office-secondary) 25% 50%, #f19309 50% 75%, #f9c22b 75%) 0 21% / 100% 28% no-repeat, linear-gradient(#f2f2f2 0 0) 0 70% / 72% 24% no-repeat;border:0;border-top:clamp(1px,.9cqi,2px) solid #111;width:84%;height:45%;inset:8% 8% auto}._2S_x-q_preview[data-variant=orange-data]:after{background:#111;width:84%;height:11%;bottom:11%;right:8%}._2S_x-q_preview[data-variant=orange-data] ._2S_x-q_previewAccent{background:var(--office-accent);width:22%;height:clamp(1px,.9cqi,2px);top:8%;left:8%}._2S_x-q_preview[data-variant=orange-data] strong,._2S_x-q_preview[data-variant=orange-data] small{z-index:2;width:52%}._2S_x-q_preview[data-variant=orange-data] strong{margin-top:10%;font-size:clamp(4px,5.8cqi,13px)}._2S_x-q_preview[data-variant=orange-data] small{color:#5b626d;letter-spacing:.06em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._2S_x-q_preview[data-variant=custom]:before{background:linear-gradient(145deg, var(--office-surface), var(--office-secondary));width:40%}._2S_x-q_preview[data-page=\"1\"],._2S_x-q_preview[data-page=\"2\"]{background:color-mix(in srgb, var(--office-bg) 92%, var(--office-surface));color:var(--office-text);font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);justify-content:flex-start;padding:8% 8% 7%}._2S_x-q_preview[data-page=\"1\"]:before,._2S_x-q_preview[data-page=\"2\"]:before{background:linear-gradient(90deg, color-mix(in srgb, var(--office-accent) 13%, transparent) 1px, transparent 1px), linear-gradient(color-mix(in srgb, var(--office-accent) 13%, transparent) 1px, transparent 1px);clip-path:none;opacity:.48;background-size:20% 25%;border:0;width:100%;height:100%;inset:0}._2S_x-q_preview[data-page=\"1\"]:after,._2S_x-q_preview[data-page=\"2\"]:after{background:var(--office-accent);width:18%;height:2px;top:8%;bottom:auto;right:8%}._2S_x-q_preview[data-page=\"1\"] ._2S_x-q_previewAccent,._2S_x-q_preview[data-page=\"2\"] ._2S_x-q_previewAccent{background:color-mix(in srgb, var(--office-muted) 38%, transparent);width:84%;height:1px;top:auto;bottom:7%;left:8%}._2S_x-q_preview[data-page=\"1\"] strong,._2S_x-q_preview[data-page=\"2\"] strong{width:78%;margin-top:3%;font-size:clamp(4px,5.3cqi,12px);line-height:1.12}._2S_x-q_previewEyebrow{letter-spacing:.06em;width:74%!important;color:var(--office-muted)!important;margin:0!important;font:500 clamp(3px,2.7cqi,6px)/1.1 ui-monospace,SFMono-Regular,Menlo,monospace!important}._2S_x-q_previewKpis{z-index:1;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;width:100%;margin-top:auto;display:grid;position:relative}._2S_x-q_previewKpis>span{border:1px solid color-mix(in srgb, var(--office-accent) 18%, transparent);background:color-mix(in srgb, var(--office-surface) 88%, transparent);border-radius:3px;justify-content:space-between;align-items:baseline;min-width:0;padding:7% 8%;display:flex}._2S_x-q_previewKpis b{font-size:clamp(4px,4.8cqi,11px);font-weight:700}._2S_x-q_previewKpis i{color:var(--office-muted);font:clamp(2px,2.2cqi,5px)/1 ui-monospace,monospace}._2S_x-q_previewFooter,._2S_x-q_previewInsight{z-index:1;width:100%;color:var(--office-muted);text-overflow:ellipsis;white-space:nowrap;margin-top:4px;font-size:clamp(2px,2.3cqi,5px);line-height:1.15;display:block;position:relative;overflow:hidden}._2S_x-q_previewChart{z-index:1;border-bottom:1px solid color-mix(in srgb, var(--office-muted) 34%, transparent);align-items:flex-end;gap:7%;height:43%;margin-top:auto;padding:4% 5% 0;display:flex;position:relative}._2S_x-q_previewChart i{background:var(--office-accent);border-radius:2px 2px 0 0;width:11%}._2S_x-q_previewChart i:first-child{opacity:.52;height:28%}._2S_x-q_previewChart i:nth-child(2){opacity:.64;height:46%}._2S_x-q_previewChart i:nth-child(3){opacity:.76;height:41%}._2S_x-q_previewChart i:nth-child(4){opacity:.88;height:72%}._2S_x-q_previewChart i:nth-child(5){height:91%}@media (prefers-reduced-motion:reduce){._2S_x-q_previewViewport,._2S_x-q_selectionPreview{transition:none}._2S_x-q_previewViewport>._2S_x-q_preview{animation:none}}";
26
+ const css = "._2S_x-q_modeRoot{box-sizing:border-box;width:100%;padding:0 var(--dsh-composer-side-clearance);position:relative}._2S_x-q_modeRow{flex-wrap:wrap;justify-content:flex-start;align-items:center;gap:8px;min-height:32px;display:flex}._2S_x-q_modeChip{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:999px;align-items:center;gap:6px;padding:7px 13px;font-size:12px;line-height:16px;display:inline-flex}._2S_x-q_modeChip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._2S_x-q_modeChip[data-selected=true]{border-color:color-mix(in srgb, var(--dsw-alias-label-primary) 55%, transparent);background:color-mix(in srgb, var(--dsw-alias-label-primary) 12%, transparent);color:var(--dsw-alias-label-primary)}._2S_x-q_templatePanel{box-sizing:border-box;z-index:2;width:100%;max-width:calc(var(--dsh-composer-card-max-width) + 32px);height:var(--office-ppt-template-panel-height,calc(100dvh - 178px));max-height:var(--office-ppt-template-panel-height,calc(100dvh - 178px));background:0 0;flex-direction:column;margin-top:8px;display:flex;position:absolute;top:100%;left:50%;overflow:hidden;transform:translate(-50%)}._2S_x-q_modeRoot[data-placement=fixed]{height:0;overflow:visible}._2S_x-q_modeRoot[data-placement=fixed] ._2S_x-q_templatePanel{max-height:none;top:0}._2S_x-q_modeRoot[data-placement=fixed] ._2S_x-q_templateViewport{overscroll-behavior:contain;flex:auto;padding-bottom:12px;overflow-y:auto}._2S_x-q_templateToolbar{z-index:2;background:0 0;flex:none;justify-content:space-between;align-items:center;gap:12px;min-height:38px;display:flex;position:relative}._2S_x-q_templateViewport{box-sizing:border-box;overscroll-behavior:contain;scrollbar-width:none;min-height:0;padding-bottom:12px;overflow-y:auto}._2S_x-q_templateViewport::-webkit-scrollbar{display:none}._2S_x-q_categoryTabs{scrollbar-width:none;gap:4px;min-width:0;display:flex;overflow-x:auto}._2S_x-q_categoryTabs::-webkit-scrollbar{display:none}._2S_x-q_categoryTabs button{color:var(--dsw-alias-label-caption);font:inherit;cursor:pointer;background:0 0;border:0;border-radius:999px;flex:none;padding:5px 10px;font-size:11px;line-height:16px}._2S_x-q_categoryTabs button:hover{color:var(--dsw-alias-label-primary)}._2S_x-q_categoryTabs button[data-selected=true]{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._2S_x-q_templateGrid{background:0 0;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px 14px;display:grid}._2S_x-q_templateCard{min-width:0;min-height:0;position:relative}._2S_x-q_templateSelect{width:100%;min-width:0;color:var(--dsw-alias-label-tertiary);font:inherit;cursor:pointer;background:0 0;border:0;outline:0;flex-direction:column;padding:0;display:flex}._2S_x-q_previewViewport,._2S_x-q_selectionPreview{container-type:inline-size}._2S_x-q_previewViewport{aspect-ratio:16/9;border:2px solid #0000;border-radius:9px;width:100%;transition:border-color .12s,transform .12s;display:block;position:relative;overflow:hidden}._2S_x-q_previewViewport:after{content:\"\";position:absolute;inset:0;z-index:2;border-radius:7px;box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-label-primary) 25%, transparent);pointer-events:none}._2S_x-q_previewViewport>._2S_x-q_preview{aspect-ratio:auto;width:100%;height:100%;animation:.18s _2S_x-q_previewReveal}@keyframes _2S_x-q_previewReveal{0%{opacity:.72}to{opacity:1}}._2S_x-q_templateCard:hover ._2S_x-q_previewViewport{transform:translateY(-1px)}._2S_x-q_templateSelect:active ._2S_x-q_previewViewport{transform:scale(.985)}._2S_x-q_templateCard[data-selected=true] ._2S_x-q_previewViewport{border-color:var(--dsw-alias-label-primary)}._2S_x-q_templateSelect:focus-visible ._2S_x-q_previewViewport{outline:2px solid var(--dsw-alias-label-primary);outline-offset:2px}._2S_x-q_templateName{text-align:center;text-overflow:ellipsis;white-space:nowrap;padding-top:5px;font-size:12px;line-height:16px;overflow:hidden}._2S_x-q_templateCard[data-selected=true] ._2S_x-q_templateName{color:var(--dsw-alias-label-primary)}._2S_x-q_panelState{min-height:160px;color:var(--dsw-alias-label-tertiary);place-items:center;gap:10px;font-size:12px;display:grid}._2S_x-q_templateError{border:1px solid color-mix(in srgb, var(--dsw-alias-state-error-primary) 40%, transparent);background:color-mix(in srgb, var(--dsw-alias-state-error-primary) 10%, transparent);color:var(--dsw-alias-state-error-primary);border-radius:8px;margin-bottom:8px;padding:7px 10px;font-size:11px;line-height:16px}._2S_x-q_retryButton{border:1px solid var(--dsw-alias-border-l2-darkmode-thin);color:var(--dsw-alias-label-secondary);font:inherit;cursor:pointer;background:0 0;border-radius:999px;padding:6px 12px}._2S_x-q_retryButton:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}._2S_x-q_selection{align-items:flex-start;display:flex}._2S_x-q_selectionPreview{aspect-ratio:16/9;transform-origin:50%;flex:none;width:clamp(76px,10vw,92px);transition:transform .2s cubic-bezier(.34,1.56,.64,1);display:block;position:relative;transform:rotate(-3deg)scale(1)}._2S_x-q_selectionFrame{border:2px solid var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-base);border-radius:9px;width:100%;height:100%;display:block;overflow:hidden;box-shadow:0 4px 14px #0000002e}._2S_x-q_selectionRemove{z-index:2;color:#fff;opacity:0;pointer-events:none;cursor:pointer;background:#111111e0;border:1px solid #ffffff4d;border-radius:50%;place-items:center;width:20px;height:20px;padding:0;font:500 15px/1 ui-sans-serif,system-ui,sans-serif;transition:opacity .12s,transform .12s;display:grid;position:absolute;top:-8px;right:-8px;transform:rotate(3deg)scale(.88);box-shadow:0 3px 10px #00000047}._2S_x-q_selectionPreview:hover ._2S_x-q_selectionRemove,._2S_x-q_selectionPreview:focus-within ._2S_x-q_selectionRemove{opacity:1;pointer-events:auto;transform:rotate(3deg)scale(1)}._2S_x-q_selectionRemove:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:2px}._2S_x-q_preview{box-sizing:border-box;aspect-ratio:16/9;background:var(--office-bg);color:var(--office-text);flex-direction:column;justify-content:center;padding:12% 10%;display:flex;position:relative;overflow:hidden}._2S_x-q_preview[data-source-preview=true]{background:#fff;padding:0}._2S_x-q_preview[data-source-preview=true]:before,._2S_x-q_preview[data-source-preview=true]:after{display:none}._2S_x-q_previewImage{object-fit:cover;width:100%;height:100%;display:block;position:absolute;inset:0}._2S_x-q_preview:before,._2S_x-q_preview:after{content:\"\";pointer-events:none;position:absolute}._2S_x-q_preview:before{border-left:1px solid color-mix(in srgb, var(--office-accent) 35%, transparent);background:color-mix(in srgb, var(--office-surface) 92%, transparent);width:34%;height:100%;top:0;right:0}._2S_x-q_preview:after{background:var(--office-accent);width:18%;height:clamp(1px,1.3cqi,3px);bottom:13%;right:8%}._2S_x-q_previewAccent{background:var(--office-accent);width:18%;height:clamp(1px,1.3cqi,3px);position:absolute;top:16%;left:10%}._2S_x-q_preview strong,._2S_x-q_preview small{z-index:1;text-overflow:ellipsis;white-space:nowrap;width:66%;display:block;position:relative;overflow:hidden}._2S_x-q_preview strong{margin-top:8%;font-size:clamp(4px,6cqi,14px);font-weight:650;line-height:1.12}._2S_x-q_preview small{color:var(--office-muted);margin-top:4px;font-size:clamp(3px,3.4cqi,8px)}._2S_x-q_preview[data-variant=blue-professional]:before{clip-path:polygon(25% 0,100% 0,100% 100%,0 100%);background:var(--office-surface);border:0;width:40%}._2S_x-q_preview[data-variant=blue-professional]:after{width:15%;height:2px;bottom:14%;right:8%}._2S_x-q_preview[data-variant=editorial-forest]{background:var(--office-surface);color:var(--office-accent);justify-content:flex-end;padding:10%;font-family:Georgia,Times New Roman,serif}._2S_x-q_preview[data-variant=editorial-forest]:before{aspect-ratio:1;border:1px solid var(--office-accent);background:0 0;border-radius:50%;width:16%;height:auto;top:11%;right:9%}._2S_x-q_preview[data-variant=editorial-forest]:after{background:var(--office-accent);width:80%;height:1px;bottom:10%;right:10%}._2S_x-q_preview[data-variant=editorial-forest] ._2S_x-q_previewAccent{background:var(--office-accent);width:26%;height:1px;top:13%}._2S_x-q_preview[data-variant=editorial-forest] strong,._2S_x-q_preview[data-variant=editorial-forest] small{width:78%}._2S_x-q_preview[data-variant=editorial-forest] strong{margin-bottom:11%;font-size:clamp(5px,7.4cqi,17px);font-weight:500}._2S_x-q_preview[data-variant=editorial-forest] small{color:var(--office-bg);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;position:absolute;top:16%;left:10%}._2S_x-q_preview[data-variant=signal]{background:var(--office-bg);color:var(--office-text);font-family:Georgia,Times New Roman,serif}._2S_x-q_preview[data-variant=signal]:before{background-image:linear-gradient(color-mix(in srgb, var(--office-secondary) 55%, transparent) 1px, transparent 1px), linear-gradient(90deg, color-mix(in srgb, var(--office-secondary) 55%, transparent) 1px, transparent 1px);opacity:.45;background-size:18% 31%;border:0;width:100%;height:100%;inset:0}._2S_x-q_preview[data-variant=signal]:after{background:var(--office-secondary);width:80%;height:1px;bottom:15%;left:10%;right:auto}._2S_x-q_preview[data-variant=signal] ._2S_x-q_previewAccent{background:var(--office-accent);width:14%;height:1px;top:18%}._2S_x-q_preview[data-variant=signal] strong{font-size:clamp(5px,6.8cqi,16px);font-weight:600}._2S_x-q_preview[data-variant=signal] small{color:var(--office-muted);letter-spacing:.08em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._2S_x-q_preview[data-variant=orange-data]{color:#111;background:#fff;justify-content:flex-start;padding:15% 8%;font-family:Arial,sans-serif}._2S_x-q_preview[data-variant=orange-data]:before{background:linear-gradient(90deg, var(--office-accent) 0 25%, var(--office-secondary) 25% 50%, #f19309 50% 75%, #f9c22b 75%) 0 21% / 100% 28% no-repeat, linear-gradient(#f2f2f2 0 0) 0 70% / 72% 24% no-repeat;border:0;border-top:clamp(1px,.9cqi,2px) solid #111;width:84%;height:45%;inset:8% 8% auto}._2S_x-q_preview[data-variant=orange-data]:after{background:#111;width:84%;height:11%;bottom:11%;right:8%}._2S_x-q_preview[data-variant=orange-data] ._2S_x-q_previewAccent{background:var(--office-accent);width:22%;height:clamp(1px,.9cqi,2px);top:8%;left:8%}._2S_x-q_preview[data-variant=orange-data] strong,._2S_x-q_preview[data-variant=orange-data] small{z-index:2;width:52%}._2S_x-q_preview[data-variant=orange-data] strong{margin-top:10%;font-size:clamp(4px,5.8cqi,13px)}._2S_x-q_preview[data-variant=orange-data] small{color:#5b626d;letter-spacing:.06em;font-family:ui-monospace,SFMono-Regular,Menlo,monospace}._2S_x-q_preview[data-variant=custom]:before{background:linear-gradient(145deg, var(--office-surface), var(--office-secondary));width:40%}._2S_x-q_preview[data-page=\"1\"],._2S_x-q_preview[data-page=\"2\"]{background:color-mix(in srgb, var(--office-bg) 92%, var(--office-surface));color:var(--office-text);font-family:var(--font-sans,ui-sans-serif, system-ui, sans-serif);justify-content:flex-start;padding:8% 8% 7%}._2S_x-q_preview[data-page=\"1\"]:before,._2S_x-q_preview[data-page=\"2\"]:before{background:linear-gradient(90deg, color-mix(in srgb, var(--office-accent) 13%, transparent) 1px, transparent 1px), linear-gradient(color-mix(in srgb, var(--office-accent) 13%, transparent) 1px, transparent 1px);clip-path:none;opacity:.48;background-size:20% 25%;border:0;width:100%;height:100%;inset:0}._2S_x-q_preview[data-page=\"1\"]:after,._2S_x-q_preview[data-page=\"2\"]:after{background:var(--office-accent);width:18%;height:2px;top:8%;bottom:auto;right:8%}._2S_x-q_preview[data-page=\"1\"] ._2S_x-q_previewAccent,._2S_x-q_preview[data-page=\"2\"] ._2S_x-q_previewAccent{background:color-mix(in srgb, var(--office-muted) 38%, transparent);width:84%;height:1px;top:auto;bottom:7%;left:8%}._2S_x-q_preview[data-page=\"1\"] strong,._2S_x-q_preview[data-page=\"2\"] strong{width:78%;margin-top:3%;font-size:clamp(4px,5.3cqi,12px);line-height:1.12}._2S_x-q_previewEyebrow{letter-spacing:.06em;width:74%!important;color:var(--office-muted)!important;margin:0!important;font:500 clamp(3px,2.7cqi,6px)/1.1 ui-monospace,SFMono-Regular,Menlo,monospace!important}._2S_x-q_previewKpis{z-index:1;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;width:100%;margin-top:auto;display:grid;position:relative}._2S_x-q_previewKpis>span{border:1px solid color-mix(in srgb, var(--office-accent) 18%, transparent);background:color-mix(in srgb, var(--office-surface) 88%, transparent);border-radius:3px;justify-content:space-between;align-items:baseline;min-width:0;padding:7% 8%;display:flex}._2S_x-q_previewKpis b{font-size:clamp(4px,4.8cqi,11px);font-weight:700}._2S_x-q_previewKpis i{color:var(--office-muted);font:clamp(2px,2.2cqi,5px)/1 ui-monospace,monospace}._2S_x-q_previewFooter,._2S_x-q_previewInsight{z-index:1;width:100%;color:var(--office-muted);text-overflow:ellipsis;white-space:nowrap;margin-top:4px;font-size:clamp(2px,2.3cqi,5px);line-height:1.15;display:block;position:relative;overflow:hidden}._2S_x-q_previewChart{z-index:1;border-bottom:1px solid color-mix(in srgb, var(--office-muted) 34%, transparent);align-items:flex-end;gap:7%;height:43%;margin-top:auto;padding:4% 5% 0;display:flex;position:relative}._2S_x-q_previewChart i{background:var(--office-accent);border-radius:2px 2px 0 0;width:11%}._2S_x-q_previewChart i:first-child{opacity:.52;height:28%}._2S_x-q_previewChart i:nth-child(2){opacity:.64;height:46%}._2S_x-q_previewChart i:nth-child(3){opacity:.76;height:41%}._2S_x-q_previewChart i:nth-child(4){opacity:.88;height:72%}._2S_x-q_previewChart i:nth-child(5){height:91%}@media (prefers-reduced-motion:reduce){._2S_x-q_previewViewport,._2S_x-q_selectionPreview{transition:none}._2S_x-q_previewViewport>._2S_x-q_preview{animation:none}}";
28
27
  const tagId = "dsh-ppt/OfficePptHero.module.css";
29
28
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
30
29
  const tag = document.createElement("style");
31
30
  tag.dataset.plugin = "dsh-ppt";
32
31
  tag.dataset.pluginCss = tagId;
33
32
  tag.textContent = css + `
34
- button[data-desktop-ppt]{color:var(--dsw-alias-label-primary);transition:background-color .18s ease,color .18s ease,transform .18s ease}
35
- button[data-desktop-ppt] .desktop-ppt-icon{width:18px;height:18px;flex:none;transition:transform .18s ease}
36
- button[data-desktop-ppt][data-selected=true]{background:#262626!important;color:#fafafa!important;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--dsw-alias-label-primary) 30%,#262626)}
37
- button[data-desktop-ppt][data-selected=true] .desktop-ppt-icon{transform:translateY(-.5px)}
38
- button[data-desktop-ppt]:active:not(:disabled){transform:translateY(1px)}
39
- button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-primary)!important;outline-offset:2px}
40
- .dsh-ppt-composer{box-sizing:border-box;width:100%;padding:0 var(--dsh-composer-side-clearance,16px)}
41
- .dsh-ppt-controls{display:flex;align-items:center;gap:16px;min-height:44px;padding:8px 0}
42
- ._2S_x-q_modeRoot[data-placement=inline]{padding:0}
43
- ._2S_x-q_modeRoot[data-placement=inline] ._2S_x-q_templatePanel{position:relative;top:auto;left:auto;transform:none;width:100%;height:auto;max-height:min(42vh,360px);margin:0 0 8px}
44
- @media(max-width:600px){.dsh-ppt-composer ._2S_x-q_templateGrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
45
- @media(prefers-reduced-motion:reduce){button[data-desktop-ppt],button[data-desktop-ppt] .desktop-ppt-icon{transition:none}}
33
+ .dsh-ppt-panel{order:1;align-self:center;display:flex;flex-direction:column;flex-shrink:0;margin:0;padding:0;box-sizing:border-box;width:calc(100% - 2 * var(--dsh-composer-side-clearance,16px));max-height:400px;overflow:hidden;border:1px solid var(--dsw-alias-border-l2-darkmode-thin,#e4e6eb);border-radius:14px;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#20232a);box-shadow:0 12px 40px #0000001a,0 2px 8px #00000008;font:13px/1.5 var(--font-sans,system-ui,sans-serif)}
34
+ .dsh-ppt-panel-header{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px 8px;flex:none}
35
+ .dsh-ppt-panel-title{font-size:14px;font-weight:600;margin:0}
36
+ .dsh-ppt-panel ._2S_x-q_categoryTabs{padding:0 12px 10px;flex:none;border-bottom:1px solid var(--dsw-alias-border-l2-darkmode-thin,#eceef1)}
37
+ .dsh-ppt-panel ._2S_x-q_categoryTabs button{font-size:12px;padding:4px 9px}
38
+ .dsh-ppt-panel ._2S_x-q_categoryTabs button[data-selected=true]{color:var(--dsw-alias-label-primary,#20232a);background:var(--dsw-alias-interactive-bg-hover,#f3f4f6)}
39
+ .dsh-ppt-panel ._2S_x-q_templateViewport{padding:14px 16px;overflow-y:auto;scrollbar-width:thin;min-height:0;flex:1}
40
+ .dsh-ppt-panel ._2S_x-q_templateViewport::-webkit-scrollbar{display:block;width:5px}
41
+ .dsh-ppt-panel ._2S_x-q_templateViewport::-webkit-scrollbar-thumb{background:#c5c9d0;border-radius:3px}
42
+ .dsh-ppt-panel ._2S_x-q_templateGrid{gap:14px}
43
+ .dsh-ppt-panel ._2S_x-q_templateName{font-size:12px;text-align:left;padding:6px 2px 0;width:100%;box-sizing:border-box}
44
+ .dsh-ppt-panel ._2S_x-q_previewViewport{border-radius:8px}
45
+ .dsh-ppt-selected{position:absolute;top:8px;right:8px;z-index:3;display:grid;place-items:center;width:20px;height:20px;border-radius:50%;background:var(--dsw-alias-label-primary,#20232a);color:var(--dsw-alias-bg-base,#fff);font-size:12px;box-shadow:0 1px 4px #0002;pointer-events:none}
46
+ .dsh-ppt-panel button:focus-visible{outline:2px solid var(--dsw-alias-label-primary,#20232a);outline-offset:2px}
47
+ .dsh-ppt-panel button:disabled{cursor:wait;opacity:.55}
48
+ .dsh-ppt-panel-notice{margin:0 16px 8px;color:var(--dsw-alias-label-secondary,#626875);font-size:12px}
49
+ @media(max-width:600px){.dsh-ppt-panel ._2S_x-q_templateGrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
46
50
  `;
47
51
  document.head.appendChild(tag);
48
52
  }
@@ -89,25 +93,21 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
89
93
  "promotion",
90
94
  "academic", "editorial"
91
95
  ];
92
- const SELECTED_PREVIEW_ENTRY_TRANSFORM = "rotate(-3deg) scale(.92)";
93
- const SELECTED_PREVIEW_REST_TRANSFORM = "rotate(-3deg) scale(1)";
94
- const SELECTED_PREVIEW_DURATION_MS = 200;
95
96
  const TEMPLATE_LOAD_TIMEOUT_MS = 8e3;
96
97
  const FALLBACK_TEMPLATE_PREVIEW_PAGE_COUNT = 3;
97
98
  const TEMPLATE_PREVIEW_AUTOPLAY_START_MS = 420;
98
99
  const TEMPLATE_PREVIEW_AUTOPLAY_INTERVAL_MS = 900;
99
100
  const TEMPLATE_PREVIEW_WHEEL_LOCK_MS = 180;
100
- const TEMPLATE_DOCK_BOTTOM_PX = 12;
101
- const TEMPLATE_PANEL_MIN_HEIGHT_PX = 200;
102
101
  const EMPTY_STATE = {
103
102
  activeMode: null,
103
+ pickerOpen: false,
104
104
  loading: false,
105
105
  templates: [],
106
106
  selectedId: null,
107
107
  notice: false,
108
108
  error: ""
109
109
  };
110
- /** Session-keyed presentation state shared by the action tray and composer accessory. */
110
+ /** Session-keyed presentation state shared by the toolbar button and template panel. */
111
111
  var OfficePptHeroStore = class {
112
112
  constructor() {
113
113
  this.states = /* @__PURE__ */ new Map();
@@ -125,6 +125,9 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
125
125
  if (listeners.size === 0) this.listeners.delete(sessionId);
126
126
  };
127
127
  }
128
+ setPickerOpen(sessionId, pickerOpen) {
129
+ this.update(sessionId, current => ({ ...current, pickerOpen }));
130
+ }
128
131
  setMode(sessionId, activeMode) {
129
132
  this.update(sessionId, (current) => ({
130
133
  ...current,
@@ -277,7 +280,7 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
277
280
  }, page)
278
281
  });
279
282
  }
280
- function TemplateCard({ template, selected, choose }) {
283
+ function TemplateCard({ template, selected, choose, disabled }) {
281
284
  const [page, setPage] = (0, react.useState)(0);
282
285
  const [hovered, setHovered] = (0, react.useState)(false);
283
286
  const card = (0, react.useRef)(null);
@@ -355,10 +358,12 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
355
358
  className: OfficePptHero_module_css_default.templateSelect,
356
359
  "aria-label": template.name,
357
360
  "aria-pressed": selected,
361
+ disabled,
358
362
  onClick: () => {
359
363
  choose(template);
360
364
  },
361
365
  children: [
366
+ selected && react_jsx_runtime.jsx("span", { className: "dsh-ppt-selected", "aria-hidden": true, children: "✓" }),
362
367
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TemplatePreviewDeck, {
363
368
  template,
364
369
  page
@@ -390,95 +395,6 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
390
395
  });
391
396
  });
392
397
  }
393
- function deselectTemplate(client, mode, sessionId, activeMode) {
394
- mode.setLoading(sessionId, true);
395
- client.call("template/deselect").then(() => {
396
- return client.call("presentation/mode", { mode: activeMode });
397
- }).then(() => {
398
- mode.deselect(sessionId, activeMode);
399
- }).catch((reason) => {
400
- mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason));
401
- });
402
- }
403
- function selectPresentationMode(client, mode, sessionId, activeMode) {
404
- mode.setMode(sessionId, activeMode);
405
- client.call("presentation/mode", { mode: activeMode }).catch((reason) => {
406
- mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason));
407
- });
408
- }
409
- /** Compact selected-template thumbnail inside the resident input card. */
410
- function OfficePptInputAccessory({ client, mode, sessionId, t }) {
411
- const state = useMode(mode, sessionId);
412
- const selected = state.templates.find((template) => template.id === state.selectedId);
413
- const selectedId = state.activeMode !== null && selected !== void 0 ? selected.id : null;
414
- const preview = (0, react.useRef)(null);
415
- const frame = (0, react.useRef)(null);
416
- const settleTimer = (0, react.useRef)(null);
417
- const previousId = (0, react.useRef)(selectedId);
418
- (0, react.useLayoutEffect)(() => {
419
- if (selectedId === null) {
420
- if (frame.current !== null) window.cancelAnimationFrame(frame.current);
421
- if (settleTimer.current !== null) window.clearTimeout(settleTimer.current);
422
- frame.current = null;
423
- settleTimer.current = null;
424
- previousId.current = null;
425
- return;
426
- }
427
- if (previousId.current === selectedId || preview.current === null) return;
428
- previousId.current = selectedId;
429
- const element = preview.current;
430
- const from = frame.current !== null || settleTimer.current !== null ? window.getComputedStyle(element).transform : SELECTED_PREVIEW_ENTRY_TRANSFORM;
431
- if (frame.current !== null) window.cancelAnimationFrame(frame.current);
432
- if (settleTimer.current !== null) window.clearTimeout(settleTimer.current);
433
- frame.current = null;
434
- settleTimer.current = null;
435
- element.style.transition = "none";
436
- element.style.transform = from;
437
- if (reducedMotionPreferred()) {
438
- element.style.removeProperty("transition");
439
- element.style.removeProperty("transform");
440
- return;
441
- }
442
- element.getBoundingClientRect();
443
- const settle = () => {
444
- element.style.removeProperty("transition");
445
- element.style.transform = SELECTED_PREVIEW_REST_TRANSFORM;
446
- frame.current = null;
447
- settleTimer.current = window.setTimeout(() => {
448
- element.style.removeProperty("transform");
449
- settleTimer.current = null;
450
- }, SELECTED_PREVIEW_DURATION_MS);
451
- };
452
- if (typeof window.requestAnimationFrame === "function") frame.current = window.requestAnimationFrame(settle);
453
- else settle();
454
- }, [selectedId]);
455
- (0, react.useEffect)(() => () => {
456
- if (frame.current !== null) window.cancelAnimationFrame(frame.current);
457
- if (settleTimer.current !== null) window.clearTimeout(settleTimer.current);
458
- }, []);
459
- if (state.activeMode === null || selected === void 0) return null;
460
- const activeMode = state.activeMode;
461
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
462
- className: OfficePptHero_module_css_default.selection,
463
- "aria-label": `${t("composer.selectedTemplate")}: ${selected.name}`,
464
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
465
- ref: preview,
466
- className: OfficePptHero_module_css_default.selectionPreview,
467
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
468
- className: OfficePptHero_module_css_default.selectionFrame,
469
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TemplatePreview, { template: selected })
470
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
471
- type: "button",
472
- className: OfficePptHero_module_css_default.selectionRemove,
473
- "aria-label": t("composer.removeTemplate"),
474
- onClick: () => {
475
- deselectTemplate(client, mode, sessionId, activeMode);
476
- },
477
- children: "×"
478
- })]
479
- })
480
- });
481
- }
482
398
  /** Monochrome presentation screen used by both PPT mode controls. */
483
399
  function DesktopPptIcon() {
484
400
  return (0, react_jsx_runtime.jsxs)("svg", {
@@ -490,226 +406,64 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
490
406
  ]
491
407
  });
492
408
  }
493
- /** PPT option and template chooser shared by both Composer layouts. */
494
- function OfficePptChooser({ client, mode, sessionId, t, placement, loadTemplates = true }) {
409
+ /** Template picker shown only for the native PPT agent preset. */
410
+ function OfficePptChooser({ client, mode, sessionId, t }) {
495
411
  const state = useMode(mode, sessionId);
496
- const modeRootRef = (0, react.useRef)(null);
497
- const templatePanelRef = (0, react.useRef)(null);
498
- const templateViewportRef = (0, react.useRef)(null);
499
- const [category, setCategory] = (0, react.useState)("all");
500
- (0, react.useEffect)(() => {
501
- if (!loadTemplates || state.loading || state.templates.length > 0 || state.error !== "") return;
412
+ const [category, setCategory] = react.useState("all");
413
+
414
+ react.useEffect(() => {
415
+ if (mode.snapshot(sessionId).loading || state.templates.length > 0 || state.error !== "") return;
502
416
  mode.setLoading(sessionId, true);
503
- loadTemplateState(client, t("templates.loadTimeout")).then((next) => {
504
- const activeMode = mode.snapshot(sessionId).activeMode ?? (next.presentationMode === "ppt" ? "ppt" : null);
417
+ loadTemplateState(client, t("templates.loadTimeout")).then(next => {
505
418
  mode.setTemplates(sessionId, next.templates);
506
- if (activeMode === null) return;
507
- mode.setMode(sessionId, activeMode);
508
- const selected = next.templates.find((template) => template.id === next.selectedTemplateId && templateSupportsMode(template, "ppt"));
509
- if (selected === void 0) {
510
- mode.deselect(sessionId, activeMode);
511
- return;
512
- }
513
- mode.select(sessionId, selected, activeMode);
514
- mode.setNotice(sessionId, next.templateMigration?.reason === "template-retired");
515
- }).catch((reason) => {
516
- mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason));
517
- });
518
- }, [
519
- client,
520
- loadTemplates,
521
- mode,
522
- sessionId,
523
- state.error,
524
- state.loading,
525
- state.templates.length,
526
- t
527
- ]);
528
- const deselect = () => {
529
- deselectTemplate(client, mode, sessionId, state.activeMode ?? "ppt");
530
- };
531
- const select = (template, activeMode = state.activeMode ?? "ppt") => {
419
+ const template = next.templates.find(item => item.id === next.selectedTemplateId);
420
+ if (template) mode.select(sessionId, template, "ppt");
421
+ else mode.deselect(sessionId, "ppt");
422
+ mode.setNotice(sessionId, next.templateMigration?.reason === "template-retired");
423
+ }).catch(reason => mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason)));
424
+ }, [client, mode, sessionId, state.loading, state.templates.length, state.error, t]);
425
+
426
+ const choose = async template => {
427
+ if (state.loading || template.id === state.selectedId) return;
532
428
  mode.setLoading(sessionId, true);
533
- client.call("template/select", {
534
- templateId: template.id,
535
- mode: activeMode
536
- }).then(() => {
537
- mode.select(sessionId, template, activeMode);
538
- }).catch((reason) => {
429
+ try {
430
+ await client.call("template/select", { templateId: template.id, mode: "ppt" });
431
+ mode.select(sessionId, template, "ppt");
432
+ } catch (reason) {
539
433
  mode.setError(sessionId, reason instanceof Error ? reason.message : String(reason));
540
- });
541
- };
542
- const choose = (template) => {
543
- if (template.id === state.selectedId) {
544
- deselect();
545
- return;
546
434
  }
547
- select(template);
548
435
  };
549
- const togglePpt = () => {
550
- if (state.activeMode === "ppt") {
551
- selectPresentationMode(client, mode, sessionId, null);
552
- return;
553
- }
554
- const selected = state.templates.find((template) => template.id === state.selectedId && templateSupportsMode(template, "ppt"));
555
- if (selected === void 0) {
556
- if (state.selectedId !== null) {
557
- deselectTemplate(client, mode, sessionId, "ppt");
558
- return;
559
- }
560
- selectPresentationMode(client, mode, sessionId, "ppt");
561
- return;
562
- }
563
- select(selected, "ppt");
564
- };
565
- const modeTemplates = state.templates.filter((template) => templateSupportsMode(template, "ppt"));
566
- const templateCategories = ["all", ...new Set(modeTemplates.map(templateCategory))];
567
- const visibleTemplates = modeTemplates.filter((template) => category === "all" || templateCategory(template) === category);
568
- (0, react.useEffect)(() => {
569
- if (!templateCategories.includes(category)) setCategory("all");
570
- }, [category, templateCategories]);
571
- (0, react.useLayoutEffect)(() => {
572
- if (placement === "trigger" || placement === "inline") return;
573
- const root = modeRootRef.current;
574
- const panel = templatePanelRef.current;
575
- if (state.activeMode === null || root === null || panel === null) return;
576
- const scrollBody = root.closest("[data-conversation-scroll]");
577
- const composerCard = root.closest("[data-composer-seat]")?.querySelector("[data-composer-card]") ?? null;
578
- if (scrollBody === null || composerCard === null) return;
579
- const syncGeometry = () => {
580
- const scrollRect = scrollBody.getBoundingClientRect();
581
- const panelRect = panel.getBoundingClientRect();
582
- const availableHeight = Math.max(TEMPLATE_PANEL_MIN_HEIGHT_PX, Math.floor(scrollRect.bottom - panelRect.top - TEMPLATE_DOCK_BOTTOM_PX));
583
- root.style.setProperty("--office-ppt-template-panel-height", `${availableHeight}px`);
584
- };
585
- const resizeObserver = typeof ResizeObserver === "function" ? new ResizeObserver(syncGeometry) : null;
586
- resizeObserver?.observe(scrollBody);
587
- resizeObserver?.observe(composerCard);
588
- window.addEventListener("resize", syncGeometry);
589
- const frame = window.requestAnimationFrame(syncGeometry);
590
- return () => {
591
- window.cancelAnimationFrame(frame);
592
- resizeObserver?.disconnect();
593
- window.removeEventListener("resize", syncGeometry);
594
- root.style.removeProperty("--office-ppt-template-panel-height");
595
- };
596
- }, [placement, state.activeMode]);
597
- if (placement === "trigger") return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
598
- type: "button",
599
- className: OfficePptHero_module_css_default.modeChip,
600
- "data-selected": state.activeMode === "ppt" || void 0,
601
- "aria-expanded": state.activeMode === "ppt",
602
- "aria-pressed": state.activeMode === "ppt",
603
- "data-desktop-ppt": "",
604
- onClick: togglePpt,
605
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesktopPptIcon, {}), t("mode.label")]
606
- });
607
- if ((placement === "fixed" || placement === "inline") && state.activeMode === null) return null;
608
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
609
- ref: modeRootRef,
610
- className: OfficePptHero_module_css_default.modeRoot,
611
- "data-placement": placement,
612
- "aria-label": t("mode.region"),
613
- children: [placement === "overlay" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
614
- className: OfficePptHero_module_css_default.modeRow,
615
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
616
- type: "button",
617
- className: OfficePptHero_module_css_default.modeChip,
618
- "data-selected": state.activeMode === "ppt" || void 0,
619
- "aria-expanded": state.activeMode === "ppt",
620
- "aria-pressed": state.activeMode === "ppt",
621
- "data-desktop-ppt": "",
622
- onClick: togglePpt,
623
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesktopPptIcon, {}), t("mode.label")]
624
- })
625
- }), state.activeMode !== null && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
626
- ref: templatePanelRef,
627
- className: OfficePptHero_module_css_default.templatePanel,
628
- "data-office-ppt-template-panel": "",
629
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
630
- className: OfficePptHero_module_css_default.templateToolbar,
631
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
632
- className: OfficePptHero_module_css_default.categoryTabs,
633
- role: "tablist",
634
- "aria-label": t("templates.categories"),
635
- children: templateCategories.map((item) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
636
- type: "button",
637
- role: "tab",
638
- "aria-selected": category === item,
639
- "data-selected": category === item || void 0,
640
- onClick: () => {
641
- setCategory(item);
642
- },
643
- children: t(`templates.category.${item}`)
644
- }, item))
645
- })
646
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
647
- ref: templateViewportRef,
648
- className: OfficePptHero_module_css_default.templateViewport,
649
- "data-office-ppt-template-viewport": "",
650
- "data-native-wheel-owner": "",
651
- children: [state.error !== "" && state.templates.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
652
- className: OfficePptHero_module_css_default.templateError,
653
- role: "alert",
654
- children: state.error
655
- }), state.loading && state.templates.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
656
- className: OfficePptHero_module_css_default.panelState,
657
- children: t("status.loading")
658
- }) : state.error !== "" && state.templates.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
659
- className: OfficePptHero_module_css_default.panelState,
660
- role: "alert",
661
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: state.error }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
662
- type: "button",
663
- className: OfficePptHero_module_css_default.retryButton,
664
- onClick: () => {
665
- mode.setError(sessionId, "");
666
- },
667
- children: t("templates.retry")
668
- })]
669
- }) : visibleTemplates.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
670
- className: OfficePptHero_module_css_default.panelState,
671
- children: t("templates.empty")
672
- }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
673
- className: OfficePptHero_module_css_default.templateGrid,
674
- children: visibleTemplates.map((template) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TemplateCard, {
675
- template,
676
- selected: template.id === state.selectedId,
677
- choose
678
- }, template.id))
679
- })]
680
- })]
681
- })]
682
- });
436
+ const templates = state.templates.filter(template => templateSupportsMode(template, "ppt"));
437
+ const categories = ["all", ...new Set(templates.map(templateCategory))];
438
+ const visible = templates.filter(template => category === "all" || templateCategory(template) === category);
439
+ const h = react.createElement;
440
+ return h("section", {
441
+ "aria-label": t("templates.title"),
442
+ className: "dsh-ppt-panel", "data-office-ppt-template-panel": "", "data-placement": "bottom"
443
+ },
444
+ h("div", { className: "dsh-ppt-panel-header" },
445
+ h("h2", { className: "dsh-ppt-panel-title" }, t("templates.title"))),
446
+ state.notice && h("p", { className: "dsh-ppt-panel-notice", role: "status" }, t("templates.migrated")),
447
+ h("div", { className: OfficePptHero_module_css_default.categoryTabs, role: "group", "aria-label": t("templates.categories") },
448
+ categories.map(item => h("button", {
449
+ key: item, type: "button", "data-ppt-category": item, "aria-pressed": category === item,
450
+ "data-selected": category === item || undefined, onClick: () => setCategory(item)
451
+ }, t(`templates.category.${item}`)))),
452
+ h("div", { className: OfficePptHero_module_css_default.templateViewport, "data-office-ppt-template-viewport": "", "data-native-wheel-owner": "", "aria-busy": state.loading },
453
+ state.error && h("div", { className: OfficePptHero_module_css_default.templateError, role: "alert" }, state.error,
454
+ state.templates.length === 0 && h("button", { type: "button", className: OfficePptHero_module_css_default.retryButton, onClick: () => mode.setError(sessionId, "") }, t("templates.retry"))),
455
+ state.loading && templates.length === 0 ? h("div", { className: OfficePptHero_module_css_default.panelState }, t("status.loading")) :
456
+ h("div", { className: OfficePptHero_module_css_default.templateGrid }, visible.map(template => h(TemplateCard, {
457
+ key: template.id, template, selected: template.id === state.selectedId, choose, disabled: state.loading
458
+ })))));
683
459
  }
684
- /** Use the public input dock; no Desktop-only slots or host patches are required. */
685
460
  function OfficePptComposer(props) {
686
- if (!props.session.blank) return null;
687
- return (0, react_jsx_runtime.jsxs)("div", {
688
- className: "dsh-ppt-composer",
689
- children: [
690
- (0, react_jsx_runtime.jsxs)("div", {
691
- className: "dsh-ppt-controls",
692
- children: [
693
- (0, react_jsx_runtime.jsx)(OfficePptStandardModeAction, props),
694
- (0, react_jsx_runtime.jsx)(OfficePptInputAccessory, props)
695
- ]
696
- }),
697
- (0, react_jsx_runtime.jsx)(OfficePptChooser, { ...props, placement: "inline", loadTemplates: false })
698
- ]
699
- });
461
+ const session = props.useSession(current => ({ blank: current.blank, agentPreset: current.agentPreset }));
462
+ if (!session.blank || session.agentPreset !== "ppt") return null;
463
+ return react_jsx_runtime.jsx(OfficePptChooser, {
464
+ client: props.client, mode: props.mode, sessionId: props.sessionId, t: props.t
465
+ }, props.sessionId);
700
466
  }
701
- /** PPT mode control beside the blank-session agent preset. */
702
- function OfficePptStandardModeAction(props) {
703
- const state = useMode(props.mode, props.sessionId);
704
- return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [
705
- (0, react_jsx_runtime.jsx)(OfficePptChooser, { ...props, placement: "trigger" }),
706
- state.notice && state.activeMode !== null ? (0, react_jsx_runtime.jsx)("span", {
707
- role: "status", "data-ppt-template-migration": "",
708
- style: { fontSize: 11, color: "var(--dsw-alias-label-secondary)", maxWidth: 300 },
709
- children: props.t("templates.migrated")
710
- }) : null
711
- ] });
712
- }
713
467
  //#endregion
714
468
  //#region ../office-ppt/src/client/locales.ts
715
469
  /** Office PPT composer-mode dictionaries. */
@@ -719,6 +473,8 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
719
473
  const zh = {
720
474
  "mode.label": "PPT",
721
475
  "mode.region": "演示文稿模式",
476
+ "mode.exit": "退出 PPT 模式",
477
+ "templates.close": "收起模板选择",
722
478
  "composer.selectedTemplate": "已选模板",
723
479
  "composer.removeTemplate": "取消选择模板",
724
480
  "templates.title": "选择模板",
@@ -783,6 +539,8 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
783
539
  const en = {
784
540
  "mode.label": "PPT",
785
541
  "mode.region": "Presentation modes",
542
+ "mode.exit": "Exit PPT mode",
543
+ "templates.close": "Close template picker",
786
544
  "composer.selectedTemplate": "Selected template",
787
545
  "composer.removeTemplate": "Remove selected template",
788
546
  "templates.title": "Select template",
@@ -886,25 +644,22 @@ button[data-desktop-ppt]:focus-visible{outline:2px solid var(--dsw-alias-label-p
886
644
  mode
887
645
  });
888
646
  }
889
- /**
890
- * Register the PPT chooser on the cross-version standard Composer seats.
891
- * @param ctx - Browser context that owns the standard Composer slots.
892
- */
647
+ /** Register the template picker below the composer for the native PPT preset. */
893
648
  function applyStandard(ctx) {
894
649
  const injectHero = officePptHeroInjection(ctx);
895
- ctx.slots.inject("conversation.input.dock", () => ctx.slots.register({
896
- name: "conversation.input.dock",
897
- id: "dsh-ppt",
898
- order: 20,
899
- locale: NS,
900
- inject: injectHero
901
- }, OfficePptComposer));
650
+ const name = "conversation.input.dock";
651
+ ctx.slots.inject(name, () => ctx.slots.register({
652
+ name, id: "dsh-ppt", order: 20, locale: NS, inject: injectHero
653
+ }, props => react_jsx_runtime.jsx(OfficePptComposer, {
654
+ client: props.client, mode: props.mode, sessionId: props.sessionId,
655
+ useSession: props.useSession, t: props.t
656
+ }, props.sessionId)));
902
657
  }
903
658
  //#endregion
904
659
  //#region src/client/index.ts
905
660
  /** Required standard browser services. */
906
661
  const inject = standardInject;
907
- /** Mount the selected template in the reference rail and the chooser below the Composer card. */
662
+ /** Mount the native-PPT-preset template picker below the input card. */
908
663
  function apply(ctx) {
909
664
  applyStandard(ctx);
910
665
  }
package/lib/index.js CHANGED
@@ -11,7 +11,7 @@ import { definitions as DSH_PPT_TEMPLATE_DEFINITIONS, semantics as DSH_PPT_TEMPL
11
11
  import { i as renderPptdProject, n as loadPptdProject, o as recommendedTextCapacity, r as parsePptdProject, t as checkPptdProject } from "./pptd-2VqVzr_T.js";
12
12
  import z from "@deepseek-ai/schemastery";
13
13
  import { fileURLToPath } from "node:url";
14
- import { access, appendFile, link, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
14
+ import { access, appendFile, copyFile, link, lstat, mkdir, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
15
15
  import path from "node:path";
16
16
  import { BUNDLED_SKILL_RANK, renderSkillContent } from "@deepseek-ai/dsh-skill";
17
17
  import { createHash, randomUUID } from "node:crypto";
@@ -758,8 +758,7 @@ var PptService = class {
758
758
  state: {
759
759
  ...state,
760
760
  selectedTemplateId: template.id,
761
- templateMigration: undefined,
762
- presentationMode: "ppt"
761
+ templateMigration: undefined
763
762
  },
764
763
  value: template,
765
764
  summary: `已选择模板 ${template.name}`,
@@ -3143,6 +3142,20 @@ function pptComposerContext(state) {
3143
3142
  "workflow: direct local PPTD authoring with bounded pptd_* tools and final pptd_render conversion"
3144
3143
  ].join("\n");
3145
3144
  }
3145
+ /** Resolve the preset currently running this session, including blank-session switches. */
3146
+ function sessionAgentPreset(session) {
3147
+ if (session === void 0 || typeof session !== "object") return void 0;
3148
+ for (let index = (session.events?.length ?? 0) - 1; index >= 0; index -= 1) {
3149
+ const event = session.events[index];
3150
+ if (event?.type === "agent-preset/selected" && typeof event.data?.agentPreset === "string") return event.data.agentPreset;
3151
+ }
3152
+ return typeof session.header?.agentPreset === "string" ? session.header.agentPreset : void 0;
3153
+ }
3154
+ /** New sessions use the native preset; the state flag remains for old sessions. */
3155
+ function isPptSession(agent, state) {
3156
+ const preset = sessionAgentPreset(agent?.session);
3157
+ return preset === "ppt" || (preset === void 0 && state.presentationMode === "ppt");
3158
+ }
3146
3159
  function hasActiveSkill(agent) {
3147
3160
  return agent.session.deriveMessages().some((message) => {
3148
3161
  if (message.role !== "user") return false;
@@ -3207,7 +3220,7 @@ function registerPptTools(ctx, service) {
3207
3220
  });
3208
3221
  // Resolve the persisted composer state for this assembly, never a process-wide toggle.
3209
3222
  ctx.on("system-prompt/assemble", async (_assembly, { agent }, next) => {
3210
- const active = agent !== void 0 && (await service.state(agent.id)).presentationMode === "ppt";
3223
+ const active = agent !== void 0 && isPptSession(agent, await service.state(agent.id));
3211
3224
  const assembly = await next();
3212
3225
  return active ? assembly : {
3213
3226
  ...assembly,
@@ -3217,7 +3230,8 @@ function registerPptTools(ctx, service) {
3217
3230
  ctx.on("agent/pre-step", async ({ agent, step, signal }, next) => {
3218
3231
  const decision = await next();
3219
3232
  if (decision.kind === "reject" || signal.aborted) return decision;
3220
- const context = pptComposerContext(await service.state(agent.id));
3233
+ const state = await service.state(agent.id);
3234
+ const context = isPptSession(agent, state) ? pptComposerContext({ ...state, presentationMode: "ppt" }) : void 0;
3221
3235
  if (signal.aborted) return decision;
3222
3236
  if (context === void 0) {
3223
3237
  clearAutomaticPptContext(agent);
@@ -3604,6 +3618,7 @@ const Config = z.object({
3604
3618
  maxDecksPerSession: z.natural().min(1).default(50),
3605
3619
  maxActivities: z.natural().min(1).default(200),
3606
3620
  kimiPptSkillRoot: z.string(),
3621
+ presetRoot: z.string(),
3607
3622
  pptSkillRoot: z.string()
3608
3623
  });
3609
3624
  /** Compose storage, browser RPC, and bounded model tools. */
@@ -3663,8 +3678,29 @@ function registerPptRpcRoute(webCtx, channel, rpcHandler) {
3663
3678
  }), `dsh-ppt: ${channel} rpc route`);
3664
3679
  }
3665
3680
 
3681
+ /** Make the package preset visible to the native DSH roster on first install. */
3682
+ async function ensurePptPreset(root) {
3683
+ if (typeof root !== "string" || !path.isAbsolute(root)) return;
3684
+ const source = fileURLToPath(new URL("../presets/ppt/", import.meta.url));
3685
+ const target = path.join(root, "ppt");
3686
+ await mkdir(target, { recursive: true });
3687
+ for (const file of ["agent.cordis.yml", "preset.yml"]) {
3688
+ const destination = path.join(target, file);
3689
+ try {
3690
+ await access(destination);
3691
+ } catch {
3692
+ await copyFile(path.join(source, file), destination);
3693
+ }
3694
+ }
3695
+ }
3696
+
3666
3697
  async function apply(ctx, config) {
3667
3698
  const bundledPptSkillRoot = fileURLToPath(new URL("../skills/dsh-ppt", import.meta.url));
3699
+ try {
3700
+ await ensurePptPreset(config.presetRoot ?? path.join(path.dirname(config.root), ".agent-presets"));
3701
+ } catch (error) {
3702
+ ctx.logger.warn(`dsh-ppt: could not install native PPT preset: ${error instanceof Error ? error.message : String(error)}`);
3703
+ }
3668
3704
  registerPreviewAssets(ctx, previewFiles, path.join(bundledPptSkillRoot, "references"));
3669
3705
  registerPptSkill(ctx, config.pptSkillRoot ?? config.kimiPptSkillRoot ?? process.env.DSH_PPT_SKILL_ROOT ?? process.env.DSH_KIMI_PPT_SKILL_ROOT ?? bundledPptSkillRoot);
3670
3706
  const service = new PptService(new PptStore(config.root, {
@@ -3685,4 +3721,3 @@ async function apply(ctx, config) {
3685
3721
  }
3686
3722
  //#endregion
3687
3723
  export { Config, apply, inject, name };
3688
-
package/lib/preset.js ADDED
@@ -0,0 +1,4 @@
1
+ /** Native agent-preset marker for @cola1900/dsh-ppt. */
2
+ export const name = 'dsh-ppt-preset'
3
+ export const inject = []
4
+ export function apply() {}
@@ -1,6 +1,6 @@
1
- /** Browser entry for the public DSH input dock. */
1
+ /** Browser entry for the public DSH composer toolbar. */
2
2
  import type { Context } from '@deepseek-ai/cordis';
3
3
  /** Required standard browser services. */
4
4
  export declare const inject: string[];
5
- /** Mount the PPT controls, selected reference and template chooser above the input card. */
5
+ /** Mount the PPT toolbar button and the collapsible picker below the input card. */
6
6
  export declare function apply(ctx: Context): void;
@@ -15,6 +15,8 @@ export interface Config {
15
15
  maxDecksPerSession?: number;
16
16
  /** Maximum recent activity records retained in session state. */
17
17
  maxActivities?: number;
18
+ /** Absolute DSH agent-preset root used for the bundled PPT preset. */
19
+ presetRoot?: string;
18
20
  /** Absolute DSH PPT Skill override. The package-bundled Skill is the default. */
19
21
  pptSkillRoot?: string;
20
22
  }
@@ -22,4 +24,4 @@ export interface Config {
22
24
  export declare const Config: z<Config>;
23
25
  /** Compose storage, browser RPC, and bounded model tools. */
24
26
  export declare function apply(ctx: Context, config: Config): Promise<void>;
25
- export type { PptService } from './ppt-service.ts';
27
+ export type { PptService } from './ppt-service.ts';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cola1900/dsh-ppt",
3
3
  "description": "Standalone DSH plugin for PPT authoring, template selection, validation and editable PPTX export",
4
- "version": "0.1.2",
4
+ "version": "0.2.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/boe1900/dsh-ppt.git"
@@ -43,7 +43,8 @@
43
43
  "default": "./lib/pptd.js"
44
44
  },
45
45
  "./cordis.patch.yml": "./cordis.patch.yml",
46
- "./package.json": "./package.json"
46
+ "./package.json": "./package.json",
47
+ "./preset": "./lib/preset.js"
47
48
  },
48
49
  "dsh": {
49
50
  "bundle": {
@@ -93,6 +94,7 @@
93
94
  "files": [
94
95
  "lib",
95
96
  "skills",
97
+ "presets",
96
98
  "cordis.patch.yml",
97
99
  "LICENSE",
98
100
  "THIRD_PARTY_NOTICES.md",
@@ -0,0 +1,4 @@
1
+ # The PPT tools and prompt are supplied by the installed dsh-ppt bundle.
2
+ # This tiny entry makes the package's native PPT preset discoverable without
3
+ # mounting a second copy of the bundle's server and tool registrations.
4
+ - name: '@cola1900/dsh-ppt/preset'
@@ -0,0 +1,4 @@
1
+ name: PPT
2
+ # 固定 PPT 创作工具和提示词;首次发送前选择一个模板。
3
+ description: 使用 PPT 工作流,并在首次发送前选择模板。
4
+ order: 30
@@ -7,7 +7,7 @@ description: DSH 演示文稿:编写本地 PPTD 工程并输出可编辑 PPTX
7
7
 
8
8
  <!-- DSH-PPT-AUTHORING-20260907-V3 -->
9
9
 
10
- 本 Skill 仅由用户选中的 PPT 模式启用。
10
+ 本 Skill 仅由用户选中的 PPT 预设启用;预设一旦开始对话便保持不变。
11
11
 
12
12
  ## 工作过程
13
13