dsh-cmdk 0.0.0-stage → 0.3.2

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/client.js ADDED
@@ -0,0 +1,2263 @@
1
+ /**
2
+ * dsh-cmdk — client half: the ⌘K palette.
3
+ *
4
+ * One overlay (shell.overlay) plus a small sidebar footer button. Navigation,
5
+ * renaming, archiving, forking and theming all go through public Client
6
+ * services; only the things a browser cannot do (reveal a directory) come
7
+ * from the tiny Host route. Transcript export uses the native
8
+ * /api/session.markdown route.
9
+ */
10
+ window.__ModuleLoader__.load({
11
+ id: 'dsh-cmdk',
12
+ factory: (require) => {
13
+ var module = { exports: {} };
14
+ var exports = module.exports;
15
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
16
+ var react = require('react');
17
+ var h = react.createElement;
18
+ var useEffect = react.useEffect;
19
+ var useRef = react.useRef;
20
+ var useState = react.useState;
21
+
22
+ var API = '/cmdk';
23
+ var RECENT_KEY = 'dsh-cmdk/recent';
24
+ var MONO = 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace';
25
+ var IS_MAC = /Mac|iPhone|iPad|iPod/.test(String(navigator.platform || navigator.userAgent || ''));
26
+ var MOD_KEY = IS_MAC ? '⌘' : 'Ctrl';
27
+ var HOTKEY = MOD_KEY + 'K';
28
+
29
+ var C = {
30
+ text: 'var(--dsw-alias-label-primary)',
31
+ sub: 'var(--dsw-alias-label-secondary)',
32
+ line: 'var(--dsw-alias-border-l1)',
33
+ lineStrong: 'var(--dsw-alias-border-l2)',
34
+ layer: 'var(--dsw-alias-bg-layer-1)',
35
+ layerAlt: 'var(--dsw-alias-bg-layer-2)',
36
+ overlay: 'var(--dsw-alias-bg-overlay)',
37
+ base: 'var(--dsw-alias-bg-base)',
38
+ brand: 'var(--dsw-alias-brand-primary)',
39
+ err: 'var(--dsw-alias-state-error-primary)',
40
+ ok: 'var(--dsw-alias-state-success-primary)',
41
+ warn: 'var(--dsw-alias-state-warn-primary)',
42
+ };
43
+
44
+ var STRINGS = {
45
+ zh: {
46
+ placeholder: '搜索会话、工作区,或直接执行…',
47
+ emptyTitle: '没有匹配的结果',
48
+ emptyFor: '没有找到 “{q}”',
49
+ emptySub: '试试会话标题、工作区路径,或直接输入命令',
50
+ results: '项结果',
51
+ resultsLabel: '搜索结果',
52
+ palette: '命令面板',
53
+ clear: '清除',
54
+ hintSelect: '选择',
55
+ hintOpen: '打开',
56
+ hintActions: '更多',
57
+ hintRun: '执行',
58
+ hintBack: '返回',
59
+ hintClose: '关闭',
60
+ searching: '正在搜索…',
61
+ action: '动作',
62
+ session: '会话',
63
+ untitled: '无标题',
64
+ workspace: '工作区',
65
+ theme: '外观',
66
+ system: '系统',
67
+ recent: '最近使用',
68
+ footer: '搜索',
69
+ newSession: '新建会话',
70
+ newSessionHint: '在当前工作区开一个新会话',
71
+ switchWorkspace: '切换工作区',
72
+ themeLight: '外观:浅色',
73
+ themeDark: '外观:深色',
74
+ themeSystem: '外观:跟随系统',
75
+ fontBigger: '字号:放大',
76
+ fontSmaller: '字号:缩小',
77
+ fontReset: '字号:恢复默认',
78
+ langZh: '语言:中文',
79
+ langEn: 'Language: English',
80
+ openProfile: '打开 profile 目录',
81
+ openProfileHint: '在访达里定位当前 profile',
82
+ openSessions: '打开 sessions 目录',
83
+ openSessionsHint: '所有会话日志的存放位置',
84
+ plugin: '插件',
85
+ ext: '插件命令',
86
+ pluginOn: '已启用',
87
+ pluginOff: '已禁用',
88
+ enablePlugin: '启用插件',
89
+ disablePlugin: '禁用插件',
90
+ pluginDir: '打开插件目录',
91
+ restartHint: '重启后生效',
92
+ openLogs: '打开日志目录',
93
+ openLogsHint: '宿主运行日志',
94
+ reload: '刷新页面',
95
+ reloadHint: '重新加载客户端(插件更新后用)',
96
+ sessionOpen: '打开会话',
97
+ sessionOpenHint: '跳到这条会话',
98
+ rename: '重命名…',
99
+ renameHint: '改这条会话的标题',
100
+ archive: '归档会话',
101
+ archiveHint: '从侧栏移走(可在归档里找回)',
102
+ fork: 'Fork 到新会话',
103
+ forkHint: '从这条会话分叉出一条新的',
104
+ copyId: '复制会话 ID',
105
+ copyPath: '复制工作目录路径',
106
+ revealPath: '在访达打开工作目录',
107
+ exportMd: '导出为 Markdown…',
108
+ exportMdHint: '把整段对话存成 .md',
109
+ wsOpen: '打开工作区',
110
+ wsNew: '在工作区新建会话',
111
+ wsCopyPath: '复制工作区路径',
112
+ wsReveal: '在访达打开工作区',
113
+ renamePrompt: '输入新标题,回车确认',
114
+ cancelled: '已取消',
115
+ copied: '已复制',
116
+ done: '完成',
117
+ failed: '失败',
118
+ failedSep: ':',
119
+ fontNow: '字号',
120
+ },
121
+ en: {
122
+ footer: 'Search',
123
+ placeholder: 'Search sessions and workspaces, or run a command…',
124
+ emptyTitle: 'No matching results',
125
+ emptyFor: 'No results for “{q}”',
126
+ emptySub: 'Try a session title, a workspace path, or a command',
127
+ results: 'results',
128
+ resultsLabel: 'Search results',
129
+ palette: 'Command palette',
130
+ clear: 'Clear',
131
+ hintSelect: 'select',
132
+ hintOpen: 'open',
133
+ hintActions: 'more',
134
+ hintRun: 'run',
135
+ hintBack: 'back',
136
+ hintClose: 'close',
137
+ searching: 'Searching…',
138
+ action: 'Actions',
139
+ session: 'Sessions',
140
+ untitled: 'Untitled',
141
+ workspace: 'Workspaces',
142
+ theme: 'Appearance',
143
+ system: 'System',
144
+ recent: 'Recent',
145
+ newSession: 'New session',
146
+ newSessionHint: 'Start a fresh session in the current workspace',
147
+ switchWorkspace: 'Switch workspace',
148
+ themeLight: 'Appearance: light',
149
+ themeDark: 'Appearance: dark',
150
+ themeSystem: 'Appearance: follow system',
151
+ fontBigger: 'Font: larger',
152
+ fontSmaller: 'Font: smaller',
153
+ fontReset: 'Font: reset',
154
+ langZh: '语言:中文',
155
+ langEn: 'Language: English',
156
+ plugin: 'Plugins',
157
+ ext: 'Plugin commands',
158
+ pluginOn: 'enabled',
159
+ pluginOff: 'disabled',
160
+ enablePlugin: 'Enable plugin',
161
+ disablePlugin: 'Disable plugin',
162
+ pluginDir: 'Open plugin folder',
163
+ restartHint: 'takes effect after restart',
164
+ openProfile: 'Open profile folder',
165
+ openProfileHint: 'Reveal the running profile in Finder',
166
+ openSessions: 'Open sessions folder',
167
+ openSessionsHint: 'Where every session log lives',
168
+ openLogs: 'Open log folder',
169
+ openLogsHint: 'Host runtime logs',
170
+ reload: 'Reload page',
171
+ reloadHint: 'Reload the client after a plugin update',
172
+ sessionOpen: 'Open session',
173
+ sessionOpenHint: 'Jump to this session',
174
+ rename: 'Rename…',
175
+ renameHint: 'Change this session title',
176
+ archive: 'Archive session',
177
+ archiveHint: 'Move it out of the sidebar (recoverable)',
178
+ fork: 'Fork into a new session',
179
+ forkHint: 'Branch a new session from this one',
180
+ copyId: 'Copy session id',
181
+ copyPath: 'Copy working directory',
182
+ revealPath: 'Reveal working directory',
183
+ exportMd: 'Export as Markdown…',
184
+ exportMdHint: 'Save the whole conversation as .md',
185
+ wsOpen: 'Open workspace',
186
+ wsNew: 'New session in workspace',
187
+ wsCopyPath: 'Copy workspace path',
188
+ wsReveal: 'Reveal workspace',
189
+ renamePrompt: 'Type a new title, ↵ to confirm',
190
+ cancelled: 'Cancelled',
191
+ copied: 'Copied',
192
+ done: 'Done',
193
+ failed: 'Failed',
194
+ failedSep: ': ',
195
+ fontNow: 'Font size',
196
+ },
197
+ };
198
+
199
+ // ---------------------------------------------------------------------
200
+ // pinyin initials (one letter per code point, 0x4E00 ↔ index 0)
201
+ // ---------------------------------------------------------------------
202
+ var PINYIN_LO = 0x4e00;
203
+ var PINYIN_HI = 0x9fff;
204
+ var PINYIN = 'ydkqsxhwzssxjbymgcczqpssqbycdscdqldylybsgjgyqzjjfgcclzzbwdwzjljpfyynwjjtmyyzwzhflyppqhgccyyymjqyxxgjxhsdsjnjjsmhmlzrxyfsngsyzzqzggllyjlgyzss.cykyyhqwjssggyxyqyjtwkdjhychmyxjtlxjyqbyxdldwrrjjwysrldzjpcbzjjbrcfslbczstzfxxthtrqggbdlyccscymmrfcyqzpwwjjyfcrwfdfzqpyddwyxkyj.wjffxjpdftzyhhycyswccyqsclcxxwzcxnbgnnxbxlzsqcbsgpysyzdhmdzbqbzcwdzzyytzhbtsyyfzgntnxqywqykbphhlxgybfmj.bjhhgqtjcysxstkzglyckglysmzxy.lm.ldccxgzyrcxsdltjzcqkcnnjwhjczzcqljststbnxbtyxc.qxgkwjyflzqlyhjqspsfxlfpbyqxxxydcczylllsjxfhjxpjbcffy.byxbhczbjyclwlczggbtssmdtjcxpthyqtgjjscjfzkjzjqnlzwlslhdzbwjncjzyzsqnycqyrzcjjwybrtwpyftw.xcskdzctbxhyzcyyjxzcfbzzmjyxxcdcz.ttbzljwfcgszsxfyrlnyjmbdthjxsqjccsbxyytsyfbjdztgbcnclcyzzbs.cyzzscjcshzqydxlbpjllmqxtydzxsqjtzpxlcglqccwjbhctdjjsfxj.jjtlbgxsxjmyjjqpfz.syjncydjxkjcdjszcb.rtcclnjqmwnqnclllkbybzzsyhqcltwlccrshllzntyln.wyzyxczxxgdkdmtc.d.jtsyys.dqdfmsd.jlhrwnqlybglxhlgtgxbqjdzfyjsjyjcjmrnymgrcjczgjmzmgxmmryxkjnymsgmzjymklfxmbdtgfbhcjhkylpfmdxlqjjsmtqgzsjlqdldgjyc.lcmzcsdjllnxdjffffjczfmzffpfkhkgdpqxkt.cjdhhzdddrrcfqyjkqccwjdxhwjlyllzgcfcqdsmlzpbjjplsbcjggdckkd.zsqsckjgcgkdjtjllzycxklqscgjcltfpcqczgwbjdqsdjjbyjhsjddwgfsjgdkccctllpspkjgqjhzzljplgjgjjthjjyjzcjmlzlyqbgjwmljkxzdznjqsyzmljlljkywxmkjlhskjgbmclyymkxjqlbmclkmdxxkwyxwslmlpsjqjcqxyjfjtjdxmxxllcrqbsyjbgwywxggbcyxpjtgp.pfgdjgbhbnsfjyzjkjkhxqfgqzkfhygkhdgllsdjjxpqykybnqsxqnszswhbsxwhxwbzzxdmndjbsbkbbzklylxgwxjjw.qzmywsjqlcjxxjqwj.qxscw.tlzhlyyysdzpyqyzcptlshtzcfycyxyljsdcjj.gyslcllyyysglrqq.ldxzscccc.dycjysfsgbfrsszqsbxjpsjwsdrckgjlgdkzjzbdktcsyqpyhstcldjlhmxmcgxyzhjdctmhltxzxylym.hyjcltyfbqqjbfbdf.htksqhzywwcnxxcdwhhwgyjl.gmdqcwgfjhcsntwyd.lbygqqw.sjpwn.lrydzsztxyqpzgcwxhngpyxshmdqjgztdppbfyhzhhjyfdzwkgkzbldntsxhq..gzxylzmmzyjzgszxkhkhtx.xxgyly.psthxdwhzydpx.gkydxbhnhxkdfjnmyhylpmg.cslnzhkxxlbzzlbmlsfbhhgsgyyggbhscy.jtxwlxtzqcwzydqdqmmgdqllszhlsjzwfjhqswsc.lq.zynytlsxth.znkzzsdhlacxtwwcsgqqtddyzbcchyqzflxpslzygpzsznglydqcbdlxjtct.jdkywnsyzljhhdzcwnyyzy.mhychhhxhjkzwsxhdnxlyscqydpclyzwmypbkxyjlkzhtyh.xqsyshx.smchkdscrswjpwqsgzjlwwschs.hsqnhzs.gnd.qtb..lzzmsstdqjcjktscj.xplggxhhg.xzcxpdmmhldgtybysjmxhmrcplxjzckzxshflqxccdhx.zfchzccdytcjyxqhlxdhypjqxnlsyydz.zjnyxq.zysjy.yjkypdgxddxsppyzndlthrhxydpcjjhtcxmctlhbynyhmhzllhnxmylllmdcppxhmxdkycyrdltxjchhznxclcclylnzsxzjzzlnnllwhyqsnjhxynttdkyjpychhy.gkcttwlgqrlggtgtygyhpyhylqyqgcwyqkpyyyttttlhyhlltyttsplkyzwgywgpydqqzzdqxskcqnmjjzzbxyqmjrtfbbtkhzkbjdjjkdjjtlbwfzpbtkqtztgpdgntpjyf.lqmkgxbcclzfhzcllll.dpmxdjhlcclgyhdzfgyddgcyyfgydxkss.bdhykdkdkhn.xxybfbyyhxcqg.bfqyjjdmljcsjzllpchbsxgjyndybyqspqwjlzkcddt.ccbkzdyzypjzqsjnkktknjdjgy.pgtlfyqk.sdntcyhblgdzhbbydmjrygkzyh.yybcmcdtyfzjjhgcjplxhldwxjjkytcyksssmtwcttqzlzbszdtwzxgz.gyktywxlhlcpbcll.qmmzsslcmbjcszzkydczxgqjdsmcytzqqlwzqzxssbpkdfqmddzdsddtdmfhtdyzj.qjqkypbdjyyxtljhdrqxxxh.ydhrjlklytwhllrllrcxylbwsrszzsymkzzhhkyhxksmzsyzgcjfbzbsqlfcxxxnxkxwymsddyqwggqmmyhcdzttfgyyhgstttybykjdhkyjb.lhdypjqnfxfdqkzhqkzbyjtzbxhfdxbd.swh.w.jldyjsfhbldnndnqjtjnchxfjsrfwhzfmdrfjyhwzpdjkzyjymfcyznynxfbytfwfwygdbnzzzdnytxz.mmqbsq.hxfzmbmflzzsrsymjgsxwzjsprydjsjgxhjjgljjynzjjxhgjkymlp.yycsysgqzswhwlyrjlpxslcxmfsmwkcctnxnynpnjszhdz.ptxmwyw.yysywlxjqzqxzdcl...lmcpjpclwbxsqhfwrtffjtnqjhjqdxhwlbyccfjl.lkyyjldxhhycstdywncjtxywdrmdrqhwqcmfjdyzmhm.yxjwmyzqsxtlmrspwwch.jbxtgcypxyyrrclmp.mgkqjszyjrmyjsnxtplnb.ppypylxmyzkynldgyjzczhnlmzhh.nqmpgwqtzmxxmllhgdzxyhxkrxycjmffxyhjfsbssqlhxndyc.nnmtcjcyprrnytyqnyymbmsxndlylysljnlqyshqmllyzlzjjjkymzcsfbzxxmstbjgnxyzhlsnmcqscyznfzlxbrnnnylmnrtgzqys.tswryhyjzmzdhzgzdwybsscskxsyhytsxgcqgxzzbhyxjscrhmkkbsczjyjymkqhzjfnbhmqhysnjnzybknqmcjgqhwlsnzswxkhljhyybqcbfcdsxdldspfzfskjjzwzxsddxjs...gjscssmgclxxkywyllymwwwgydkzjgggtggsycknjwnjpcxbjjtqtjwdsspjxzxnzxwm.lptfsxtllxcljxjjljsxctnswxl.hhlyqrwhsycsqryby.ywj.jqfwqcqqcjqgx.ldbzzyjgkgxpltqyfxjltp.dkyqhpm.tlcpdhkxmtxybhbl.fxdl..gqdyms.whzmljtwyqxlyjzlj..yxbqqffnlyxrdsctgjgxyylkllxqkcctlhjlqmkkzgcyygllljdzgydhzwxpysjbzkdzgyzzhywyfqytyzszy.zklymhjjhtsmqwyzlkyywzcsrkqyqltdxwcdrjklwsqzwbdcqyncjsrszjlkcdcdtlzzz.cqqczddxyplxcbqjylzllljddzjgyjyjzyxnyyynxjxkxd.zwyrdljyyyrjlglldrxjcykywnqcclddnyyykyckczhjxcclgzqjgjwggcqqjysbzzxyjxjbxjfzbsbdsfnsfpzxhdwztdmpptblzzbzdmyypqjrsdzsqzsqxbdgcpzswdwcsqzgmdhzxmwwfybpdgphtmjthzsmmbgzmbzjcfzhfcbbzmqcfmbcmcjxlgpnjbbxgyhyyjgptzgzmqbqdcgybjxlwzkydpdymgcftpfxyztzxdzxtgkmtybbclbj.skytssqyymscxfj.glsllszbqjjj.klyldlycctsxmcwfgkkbqxlllljyxtyltyxytdpjhnhgnkbyqnfjyyzbyy.ss.ssgdyhfhwtcjbsdzjtfdmxhcnjzymqwsrxjdzjqpdqbbsdjggfbkjbxdgjhmgwjjjgdllthzhhyyyyyysxwtyyyccbdbpypzyccztjpzywcbdlfwzcwjdxxhyhlhwczxjtcclcdpxdjczczlyxjjsjbhfxwpywxzptdzzbdccjhjhmlxbqxxbylrddgjrrctttgqsczwmxfytmwzcwjwxjywcskybzqccttqnhxnkxxkhkfhtsw.ccjybcmpzzyjbnnzpbthhjdlscddytyfjpxyngfxbyqxcbhxcbsxtyzdmzysnxsxlhkmzxlthdhkghxjsshqyhhcjyxglhzxcsnh.kdtgqxqypkdh.qtykcnymyyypkqyytjxzlthhqtbyqhxbmyhsqckwwyllhcyylnn.qxqwmcfbdccmljggxdqktlxkgnqcdgzjwyjjlyhhqtttnwchhxcxwh.szjydjccdbqcdgdnyxzdhcqrxcbmztqcbxwgqwyybxhmbymykdy.cmqky.qyngyzslfykkqgyssqyshjgjcnxkzycxsbkyxhyylstycxqthysmgscpmmgcccccmtzt.smgqzjhkl.sqylswtmqsyqkdzljqqyplcycztcqqpbbqjzclpkhqcyyxxdtdddsjcxffllchqxmjlwcjcxtspycxndtjshjwxdqqjckxy.mylsjhml.lykxcyydm.mdqmlmcznnyybzkkyflmchcmlhxrcjjhsylnmtjggzgywjxsrxcwjgjqhqzdqjdzjjzkjkgdzqgjjyjylhzxxcdqhhh.stmhlfsbdjsyyshfyssczqlpbdrfrztzdkykgsctgkwdqzrkmsynbcrxqbjyf.xpzz.dzcjykbcjwhyjbqdzywnyszptdkzpfpb.ztklqyhbbzpnbptyzzybhnydcpjmmcycqmcjfzzdcmnlfpbplngqjtbtt.jzpzbbdnjkljqylnbzqhksjznggqsczkyxchpzsnbcgzkddzq.nzgjkdntlzldwjljzlywtxndjzjhxy.tncbgtzcsskmnjpjytsrwxcfjwjjtkhtzplbhsnjzsyjbwbzyzlstlsbjhdwwqpslmmfbjdw.jyzccjtbnnrzwqxcdslqgdsdpdzhjtqqpsqlyyjzlgyhszlctcbjtktyczjtqkbpjlgmjzdmcsgpynjzjjyyknhrpwszxmtncszzyxybyhyz.xywkcjtllckjjtjhgcxdxyqyczbywblwqcglzgjgqrqcczssbcrbcskydznljsqgxssjm.cnstztpbdlthzwhqwqtz.xnqczgw.skssbybstscsjccgbfsdqszlccglllzghzcthcnmjgyz.znmckcstjmmzckbjygqljyjppldxrgzyxccsnhshgdznlzhzjjcddcbcjflbfqbczzwpqdnhxljcthqwjgylnlszzpcjdscqqhjqkdxkpb.jy.msmjtzdxlcjyryynwjbngzzkmjxltbsllrtpylcsznxjhllhyllqqzqlxymrcwcxsljmczltzldwdjjllnzggqxppskygyggbfzpdkmwghcxmcgdxjmcjsdyc.bxjdlnbcddygskydjtxdjjyxms.q.zdzfslqxyjsjzylblxxwxqqzbjzlfbblylwdsljhxjyzjwtdjcyfqzqzzdcsxzzqlzcdzfchyspympqzmlpplffxjjnzzylsjyyqzfpfzksywjjjhrdjzzxtxxglghtdxcskyswmmtcwyb.zbjkshfhgcxmhfqhyxxyzftsjyzbxyxpzlchmzmbxhzzssyfdmncwd.b.zlxktcshhxkxjjzjsthygxsxyyhhhjwxkzxcsbzzwwhhcwtzzzpjxsnxqqjgzyz.wllcwxzfxgyxyhxmkyyswsqmnjn.ycyspmjkgwcqhyl.jjmzxhmmcnzhbhxclxtjpltxyjhdyylttxfszhyxxsjbjy.yrsmxyplckdlyhlxrlnllstyzyyqygyhhsccsmcctzcxhyqfpyyrpfflfqtntszllzmhwtcjqyzwtllmlmdwmbzssmzrbpdddlgjjbxccsrzqqygwcsxfwzlxccrbtdzmcyggdlqsgtjmwljmymmsyhfbjdgyxccpshxczcsbsjwjgjmpbw.ffyfnxhydxzylr.mzgzcyhsszdlljcsqfzxxkptxzgxjjgbmyyysnbdylbnlhbfzdcyfbmgqrrmsszxysgtznnydzzcdgbj.fjbdknzblcsscpsgzycjszlmlrzzbzzldlsllysxsqzqlyxzlsgkbrxbrbzcycxzjz..yfgklzlyyhgysgzlfjhgtgwkr..jyzkzqtsshjjxdzyz.yjlzyrzdqqhgjzxsszbtkjpbfrtjxllfqwjgslqtymblpzdxtz.gbdhzzrbgjhwnjtjxlhscfsmwlldqysjtxkzscfwjlbxftzlljzllqblcqmqqcgcdfpbbhzczjlpyygjdtgwdcfczqyyyqysrclqzfklzzzgffsqnwglhjycjjczlqzcyjbjzzbpdccmhjgxdqdgdlzqmfgpsytsdyfwwdjzjysxyycjcyhzwpbyhxrylybhkjksfxtzjmmchhlltnyymsxxyzpyjjycdyzwmtjjkqyrhllqxpsgtlwycljscbxjyzfnmlrgjjtyzbsyzmsjyjhgfzqmsyxrszcwtlrtqzsstkxgqggsptgcdnjsgcqcqhmxggztqydjkzdlbzsxjlhyqgggthqscpyhjhhgnygkggcmjdzllcclxqsftgzslllmlcskctbljzzszmmnytpzsxqhjcjyqxy.xzqzcpshkzzysxcdfgmwqrllqxrfztlysdctmjcsjjdhjnxtnrztzfqrhqgllgcxszzjdjlxcytsjtlnyxhszxcgjzyqpylfhdjsbpcczgjjjqzjqdybssllcmyttmqtbhjqnnygkynqyqmzgcjkpdcgmyzhqllsllclmh.lzgdylfzsljcqzlylzcj.shnyllqxgjxlyjyyyxnbcljsswcqqcjyllcldjyllzllbnylgqchxyyq.xccqkyjxxhyklksx.yqccqkkkkcsgyxxyqxygwtj.hthxpxxcsshcy.ychzzcbwqbbwjqcscszsslzylgd.sjzmmymcytsdsxxscjpqqsqylyfzychdjdzywcbtjsydjhcyddjlbdjjs.dzyqysqkxxdhhgqjy.hdyxwgmmm.jdybbbppbcmhcpljzsmtx.rxjmhqdstpjdcbssmsssthjtslmmtrcplzszmlqdsdmjmqpnqdxcfynnfsdqqyxhy.ykqyddlqyyysszbydslntfgtzqbzmchdhczcwfdxtmqqsphqwwxsrgjcwtjtzzqmgwjjrjhtqjbbgwzfxjhnqfxxqywyyhyscdydhhqmnmdmmcpbszppzzglmzf.llcfwhmmsjzttthlmyffytzzgzyskjjxqyjzqphmbzzlyghgfmshpcfzsnclpbqsnjszslxjfpmtyjygbxlldlxpzjypjyhhzcywhjylsj.xfsszywxkzjll.dtmlymqjpwxxhxsktqj.zrpxxzghmhwqpwqlyjjqjjzszcfhjlchhnxjlqwzjhbmzyxbdhhypylhlhlgfwlcfyytlhjjcjmscpxstkpnhjxsntyxxt.stjctlsslstdlllwwyhdhrjzsfgxssyczykwhtdhwjslhtzdqdjzxxqggyltzphcsqfzlnjtclzpfstpdynylgmjllycqhynsbchylhqyqtmzybbywrfqykjsyslzdyjmpxyyssrhzjnyqtqdfzbwwdwwrxcwhgyhxmkmyyyhmsmzhngc.pmlqqmtcwctmhmxjpjjhfxyyzsjzhtybmstsyjdtjjqytlhynbyqzlcxcnzwsmylkfjxlwgbypjytysylymzckttwlgsmzsylmpwlzwxwqzss.qsyxyrhssntsr.pccpwcmgdhhxzdzxfjhgzttsbjhgyglzysmyclllybtyxhbbzjkssdm.lhhycfygmqypjycqxjllljgclzgqlycjcct.tyxmtmshllwcgfxymzmklpszzzxhhjyslctyjcyhxsgyxzkxlzwpyjpdhjwpjpwsqqxlxxdhmrslzcyzwstcxkystzshbsccstplwsscjchjlcgchssphylhfhhxjsx.llnylmzdhzxylsxlwzyhcldy.hzcmddyspjtqjzlngjfsjshctsdszlblmssmnyymjqbjhrcwtyydchqlj.pzwbgqybkfcmjwlzllyylszydwhxpsbcmljpscgbhxlqhyrljxyswxhxzlldfhlslymjljyflyjycdrjlfsyzfsllcqyqfgjyhyszlylmstdjcyhbzllnwlxxygyyhbmgdhxxhhlzzjzxczzzcyqzfnjwpylcpkpykpmclqkdgxzggwqbdxzzkzfbxxlzxjtpjpttbytszzdwslchzhsltjxhqlhyxxxywzyswtmzkhlxzxzpyhgchkjfsyh.tjrlxfjxptztwhplyxfcrhxshxkjxxyhzjdxjwylhyhmjdbflkhtxcwhcfwjcfpqrxqxcyyyjygrpxgscsxngqchkzdxhflxxhjjbyzwtsxnncyjjymswzjqrmhxzwfqsylzjzgbhynshbgttcs.bhxxwxyhhxyxnsqyxmlywrgyqlxbbcljsylpsytjzyhyz.wlh.rjmksczjxxxyxchcytryxqjddsjfslyltsffyxlmtyjmzjyyyxltzcsxqzlhzxlwyxzhdnlrxhxjcdyhlbrlmbrll.xksllljlyxxlycrylcjcgqcmtlzllcyzzpzpcy.whjjfybdyyzs.pckzdqyqpbpcjpdcyzbdbbcyydycnnpjmtmlrmfmmgwygbsjgygsmdqqqztxmkqwgxllpjgzbqcdjjjfpkjkcxbljmswmdtqjxldlppbxcwkcqqbfqjcz.gzgmykbhyyhzykndkzmbpjyspxthlfpnyygxjdbkxnhhjhzjxstrstldxskzysybmxjlxyslbzyslhxjpfxbqnbylljqkygzmcyzzymccsldlhzgwfwyxzmwcxtynxjhbyymcysbmhysmydyshqyzchmjjmzc..hcbjbbhplxtylsxsdjgjdhkxxtxxnbhnmlngsltxmrhnlxqjxmzllyswqgdlbjhdcgjyqycmhwfwjybbbyjmjwjmdpwhxqldy.pdfxxbcgjspckrssyzjmslbzzjfljjjlgxzgyxyxlszqyxb.xyxhgcxbpldyhw.cdwwcjmbtxchxyqxllxflyxlljlssfwdpzsmyjclmswtczbchq.kcqbwlcgydblqppqzqfjqdjhymmcxtxdrmjwrhxcjzclqxdyynhyyhrslsrsywwzjymtltllgzqcjzy.bsckzcjyccqljsqx.lmzyyywlwdxzxqdllqshgpjfjljhj.bcqzdjgthhsstcyjlbswzlxzxrwgldlzrlzqtgsllllzlymxqgdzhgbdbhzpbrlw.xqbpfdw...thlypcbjcc.dmbzpbzz.cyqxld.mzblzwpdwyygdstthcsqsccrsssyslfybfntyjszdfndpthtzzmbblxlcmyffgtjjqwftmdpjwdnlbzcmmctgbdzlqlpyfhsymjylsdchdzjwjcctljcldtljjcpddpjdsszynndbjlggjzxsxnlycybjjqxcbylzcfzppgkcxzdzfztjjfjsjxzbnzyjqttyjwhtyczhymdjxttmpxsflzcdwslshxybzgtfmlcjt.cbbmgd.wycyzcdszcyhflyctygwhkjyylsjcxgywjcbhlcsnddbtzbsclyzczzssqdllmqyyhfllqllxfdyh.bxggnywyypllsdldllbjcyxjzmlhljdxyyqytdlllbbgbfdfbbqjzzmdpjhgclgmjjpg..hhbwcqx.xhhhzchxyphj.xhlphjpgpzjqcqzgjjzzgzdmqyybzzphyhybwh.zyjhykfgdpfqsdlzmljxjpg.lxzd.glmdgxmwzqytxdxxpfdmmssympfmdmmkxksyzyshdzkjsysmmzzzmsydnzzczxbmlstmddnmxckjmztyymzmzzmsshhdccj.mxxkljstgwlsqlyjzllsjssdbpmhnlyjczyhmxxhgzcjmdhxtkgrmxfwmckmwkdcksxqmmmfzzydkmsclcmpcgmwrpxqpzdsslcxkyxtmlgjy.hzjgzqmcsnxyhmmpmlkjxmhlmlgmxctkzmjjyszjsyszhsyjzjcd.jzybsdqjzgwzkgxfkdmsdjlfm.hkzqkjb.ypzyszcdwyjffmzjykttdzz.fmzlbnpplplpbpsz.lltylkckqzkg.nqlw.gxxydpxlhsxqhwqykxqclhyxxmlyccwlymqyskychlcjnszkpyzkcqzqljbdmdjhl.sqlbydwqlwdnbqcrydddtjybkbwszdxdtnpjdtctqdfxqqmgns.clstbhpwslctxxlpwydzklzygzcq.pllkccylbqmqczqcljslqzdjxldthpzqdljjxzqdjyzhkzljcyqdyjppyp..kjyrmpcbymcxkllzllfqpylllmbsglcysslrsysqtmxyxqqzbdzrysyztffmzzsmzqhzssccmlyxwtpzgxzjgzgsjsgkddhtqggzllbjdzlcbzhyxyzhzfywxyzymsdbzzyjgtsmtfxqyxjscdgslnmdlrytzlryylxqhtxsrtzcgyxbnqqzfhykmzjbzymkbpnlyzpblmcnqyzzzsjzhjctzhhyzzjrdyzhnfxglfxslkgjtctssyllgzrzbbjzzklpkbczyslxyxbjfpnjzzxcdwxzyjxzzdjjgggrsrjkmcmzjlsjywqshyhqjsxpjzzzlsnshrnypjtwchklbsrzlcxwjqxqkysjycztlqzybbybwzjqdwgyzcytjcjxckcwdkkzxsgkdzxwwyyjqyytcytdjlxwkczkklcclzcqqdzlqlcsfqchqhsfsmqzzllbjjzbsjhtsjdysjqjpdlzcdcwjkjzzlpycgmzwdjjbsjqzsyzyhhxcbbjydssddzncglqmbtsfcbfdzdlznfgfjgfsmpsjqlmblgqcyyxbqkdxjqsrfkztjdhczklbsdzcfytplljgjhtxzcsszzxstcygkgckgy.qxjplzbbbgtgyjdgczqszlbjlsjfzgkqqjcgyczbzqtldxrjxbsxxpzxhyzyclwdsjjhxmfczpfzhqhqmqgkylyhtycgfrzgnqxclpdlbzcsczqlljblhbdcypczppdymtzsgyhckcpzjgslclnscdsldzxbmsdlddfjmkdjdhslzxlszqpqpgjllybdszgqlbzlslkyyhzttncjyqtzzfszqztlljtyyllqllqyzqlbdzlslyyzymdfszsnhlxznczqzbbwskrfbcyzmthblgjpmczzcstlxshtzcyzlzblf.qhlxflcjlyljqcbzlzjghsstbrmhxzhjzclxfnbgxgtqjcztmsfzkjmssnxljkbhszxntnlzdntlmsjxgzjyjczxyhyhwrwwqnztnfjscpzshzjfyrdjsfscjzhjfzqzchzlxfxsbzqlzsgyftzdcszxzjbqmszkjrhxjzcgbjkhchgtjkjqglxbxfgdrtylxjxgdtsjxhjzjjcmzlcqsbtxhqgxttxhxftsdkfjhzyjfjxrzcdlllcqsqqzqwqxswqtwgwbzcgcllqzbclmqqtzgzxzxljfrmyzflxyszxxjkxrmjdcdmmyxbsqbhgcmwfwtgmxlzbyytgzyccdxyzxswgxyjyznbgpzjcqsyxcxrtfycgrhztxszzthcbfclsyxzljqmzlmplmxzjssflbysmyqhxjzxrxsqzzzsslyflczjrcrxhhzxqwdshxsjjhzcxjbdynsysxjbqlpxzqpymlxzkyxlxcjlcycrxzzlldlllsjyhzxgyjwkjrwyhcpsgnrzlfzwfzznsxgxflzsxzzzbfcsyjdbrjkrdhhgxjljjtgxjxxstjtjxlyxqfcsgswmsbctlqzzwlzzkxjmltmjyhsddbxgzhdlbmyjfrzfcgclyjbpmlysmsxlszjqqhjzfxgfqfqbpxzgyyqxgztcqwyltlgwwgwhllfsfgzjmgmgbgtjfsyzzgzyz.flsspmlbflcwbjzcljjmzlpjjlymqdmyyyfbgygqzglyzdxqyxrqqqhsxyyqqygjtyxfsfsllgnqcygycwfhcccfxbylypllzqxxxxxkqhhxshjdcfdsczjxcpzwhhhhh.pylh.lpq.fyhxdyllkmzqgggdd.srnndltzgchybpysqjjhclljt.lnjpzljlhymh.ydydsqycddhgzpndzclzywllznt.ytgxlhslpjjbdgwxpcdntjcklkclwkllc.sstknzdnqnttlyyzssysszzryljqkcgbhhcrxrzydgrgcwcgzhfffppjfzyn.krgywyqpqxxfkjtszzxswzddfbbqtbgtzfznpzfpzxzpjszbmqhkcyxyldkljnypkyghgdcjxx..hpnzgctzcmxcxmmjxnkszqnmnlwbwwxjjyhclstmcsqtjcxxtpcnpdtnnpglllzcjlspblplkcdtnjnlyyrscffjfqwdpgzdwmnzccl.d.xnssnyzr.styjwjyjdbcfxnmwttbqlwstszgybljpxglb.clgpcbjftmxzljylzxcltpnclcgxtfzjshcrxsfyszdkntlbyjcyjllstgqcbxnwzxbxklylhzlqzlnzcqwgzlgzjncjgcmnzzgjdzxtzjxycyycxxjyyxjjxsssjstssttppghtcsxwzdcsyfptfbchfbblzjclzzdbxgcxlqpxkfzflsyltywbmnjhskbmddbcysccldxycddqlyjjhmqllcsgljjsyfpyyccyltj.ntjjpwycmmgqyysqdhqmzhszxpftwwzqswqrfkjlxjqqyfbrxjhhfwjgzyq.cmyfrhcyybyqwlp.xcczstyrltsdmqlykmbbgmyyjprknnbbsxyxbhyzdjdnghpmfsgbwfzmfjmmbcmzzcjjlcnyxyqgmlrygqccyhzlwjgcjcggmcjjfyzzjhycfrrcmtzqzxhfqgdjxccj..qcrjthpljlszdjrbcqhjdzrhxlyxjsymhzydwldfryhbbydtssccwbxglpzmlzztqsscpjmmxjcsjytycghycjwsnsxlf.mwjnmkllswtxhyyygcmmcwjdqdjzglljwjnkhpzggflccsczmcbltbhbqjxqdjpdjqtghglfq.wbzyjjltstdhqhctcbchflqmpwdshyytqwcnztjtlbypbpdyyyxsqkxwyyflxxncwcxybm..lykkjmzzzbrxy.qjfljpfhhhytzzxrgqqmhspgdzjwbwpjhzjdyscqwzkthxsqlzyymysdzgrxckkhjlwpysyscsyzlrmlqsyljxbcxtlhdqzpcycykpppnsxfyzjjrc.mhszmsxlxglrwgcstlrsxbygbzgztcpldjlslylymdtmtcp.lcxpqjcjwtcyyzlblxbzlqmyljbghdslssdmxmbdczsxwh.mlczcpjmcnhjyjnsygchskqmzzqdllk.blwjqsfm.cdxjrrlyqchjmybyqlrh.tfjzfrfksryxfjdwdsxxlwsqjyslyxwjhsnlxyyxhbh.whhjcxwmyljcsqlkydttxbzsxfdxgxsjhhsxxybssxdpwncmrptjzcz.nygcxqfjxkjbdmljcmqqxl.xslyxxlylljdzbtymhbfsttqqwlh.gyblsc.lzxqlhtwrrqhlstmypyxjjxmqsjpnbryxyjllyqylthylqyfmhkljdmllhfzwkzhljmlhljkljstlqxylmbhhlnlsxqchxcfxxlhyhjjgbyzzkbxscqdjqdsxjzsyhzhhmgsxcsymxf.bcqwwrbpyyjqtyqcyjhqqzyhmwffhgzfrjfcdbxndqyzpcyhhjlfrzgppxzdbbgzqstlgdgylcqmgchhmfywlzyxkjlypqhsywmqqgqzmlzjnsqxjqsyjtcb.hsxfssfxzwfllbcyyjdytdthwzsfjmqqyjlmqsxlldttkhhybfpwdyysqqrnqwlgwd.bdwcyygcdlkjxtmxmyjsxhybrwfymwfrxyqmxysctzztfykmldhqdlwyqnlcryjtlpsxcxywlsbrrjwxhqybhtydnhhgmmywytzcsqmdssccd.lwztcpqpyjllqzyjswxwzzmmglmxclmxczmxmzsqtzppjqblpgxjzhfljjhycjsnxwcxsccdlxsyjdcqcxslqyclzxlzzxmxqrjmhrhzjphmfljlmlclqnldxzlllfypngjysxcqqdcmqjzzxhnpnxzm.kmxxykyqlxsxtxjxyhwdcwdzhqyybgybcyscfgfsjnzdyzzjzxrzrqjjymc.nhrjtldbpyzbstjhxxzypbdwfgzzrpymtngxzqbyxmbbfcckrjjjbj.grzgyclkhzdxkknsjkcljspgyyzlqqjybzssqlllkjfcbktylcccdblsppfylgydtzjyqggkqttfcxbdkdxxhybbfytyhbclpdytgdhryrnjsbtcsnyjqhklllzslydxxwbcjqsbxbfjzjcjdzfbxxbrml.zgcsnclbjdstblfrzdswsbxbcllxxlzdjzsjpylyxxyftfffbhjjjgbygjpmmmmsscljmtlyzjxswxtyl.dqpjmygqzjgdjlqjwjqllsdgjgygmscljjxdtygjqjqjcjzcjgdzdshqgsjggcjhqxsnjlzzbxhsgzxcxyljxyxyydfqqjhjfxdhctxjyrxysqtjxy.fyyssyxjxncyzxfxcsyszxyyschshxzzzgzzzgfjdldylnpzgyjyzyyqzpbxqbdztzczyxxyhhscxshcggqhjhgxwsztmzm.hyxg.btylzkkwytjzrcl.k.stdbcykqqs.yxcjxwwgsbhjszsdhcsjkqcxswxfctynydpzcczjqtzwjqdzzzqzljchlsbhpydxpsxshh.zdxfptjqyzzxhy.xncfzyyhxgnqmywxtzsjpkhhgymxmxqcxtsbcqsjyxhtyylybcqlmmszmjzjllc.gxz..jzyhjmchhcxzsxzdznl.yjjzjbhzwzzsqtzpsxztdsxjjjzny.zphhyysrnqdthzh.yjyjhdzxzlswclybzy.cwcycrylcxnhzydzydyjdfrjjhtrsqtxyxjrjh.jynx.lxsfsfjzghpzsxzszdzcqzbyyklsgsjhczshdgqgxyzgxchxzjwyqwgyhkss.qzzndzfkwyssdclzstsymcdhjxxyw.yxcz.ydmpxmdsxybsqmjmzjmtzqlpjyqzcgqhxjhhhxxhlhdldjqsldwbsxfzzyyschtytyjbh.cxhjkgjfxbhyzjfxbwhbdzfyzbc.pnpgnydmsxhkhhm.mlnbyjtmpxyjmcthjbzyfcgtyhwphftgzz.zsbz.gpbmdskftycmhbllhgpzjxzjgzjyxzsbbqsczzlzccstpgxmjsftcczjzdjxcybzlfcjsyzfgszlybcwzzbyzdzypswyjgxzbdsysxlgzbzfygczxbzhzftpbgzg.jbstgkdmfhyzzjhzllzzgjqzlsfdjsscbzgpdlfzfzszyzyzsygcxsntxchczxtzzljfzgqsqyxzjqccccdjcdxzjyqjccgxztdlgscxzsyjjqtcclqdqztqchqqjzt.zzzpbkkdjfcjfztybqyqttynlmbdktjcpqzjdzfpjsbnjlgyjdxjdzqkzgqkxclpzjtcjdqbxdjjjstcjnxbxcmslyjcqmtjqwwcjjnjnlllhjcwqtbzqyczczpzzdzyddcyzdzccjgtjfzdprntctjdcqtqndtjnplzbcllctdsxkjzqdpzlbznbtjdcxfczdbccjjltqjpldcgzdbbzjcqdcjwynllzlzccdwllxwzlxrsntqjccxkjlsgdfqtddglrl.jjtklymkqlldzytdyycygjwyxdxfrskstcd.nqmrkqzhhqkdld.zfkypbggpzr.bzzykyzsp.gjjglkqzzzslysywyzwfqznlzzlzhwcgkypqgnpgblplrrjyxcccgyhsfzfwbzywtgzxyljczwhxzjzblfflgskhyjz.yjhlpllllcygxdrz.lrhgklzzyhzlyqszzjzqljzflnbhgwlczcfjwspyxnlzlxgccpzbllcxbbbbxbbcbbcrnncccyrbbsyldcgqyyqxygmqzwtzydyjhyfwd.hzdjywlccntzyjjcd.dpzdztstqjhdymbjnyjzlxtsstphndjxxbyxqtzqddtjtdyztgwscszqflshlglbcjbhdlyzjyckwtydylbnydsdsycctyszyy.bg.xhqddwnygyclxtdcystqmygz.sccszzddlcclzrqxyy.ljsbymxshzt.mbbllyyllytdqyshymrqxkfkbfxnxsbychxbwjyhtqbpbsbwdzylkgzskyghqzjhhxjxgnljkzlyycdxlfwfghljgjybxblybxqpqgztzplncybxdjyqydymrb.sjyyhkxxstmxrczzywxyhybmcflyzhqyzmqxdbxbzwzmslpdmyckfmzklzcyjycclhxfzlydqzpzygyjyzmzxdzfyfyttqtchgspczmlccytzxjcytjmkslpzhysnwllytpzctzzcktxdhxxtqcypksmqccyy.zhtjpcylzlyjbjxtfnyljyynrxcylmmnxjsmybcsysslzylljjgyldzdpqbfzzblfndsqkczfhhhgqmrdsxycstxnqqjpyjbfcxdyqfbnx.jdgyqbsrcnfyyqpghyjdyzxgrhtkyl.qdzntsmgklbsgbpyszbytjzsstjcssxzbhbscsbzczptqfzmqflypybbjgszmxxdjmthyskkbjtxhjc.gbsmjyjzcxtmljyxrzzqscxxqptzxmkyxxxjcljprmyyg.dyskqls.dhrskqxzxztcghztlmlwxybwsycdbhjhcfcwzsxhytkzlxqshlyczjx.mplprcgltbzztlzjcyjgdtclglpllqpjmzp.pxyzl.ktkdnczzbnzctdqqzjyjgmctxltgcszlmlhbglkfbnwzhdxphlfmkydlgxdtwzfrj.jctzhydxykshwfzcqshktmqqhtchymjdjskhxzjzbzzxymp.jjmsdbxlsklyynwrtsqlscbpdbsgzwyhtlkssswhzzlyytnxjgmjszsxfwnls.ztxgxls.mmlbwldszyl.kqcqctmycfjbslxclzjclxxksbjqclhjphqplsxsckslnhpsfqqytxjjzlqldxzjjzdyydjnzptfcdskjfsljhylzqjzlbthydgdjfdby.zxdzhzjnhhqbyknxjjqczmlljzkspldsclbblxkl.lxjlbjycxjxgcnlcqplzlznjtzljgyzdzpltqcssfdmnycxgbtjdcznbgbqyqjwgkfhtnbyqzqgbkpbbyzmtjdytblsqmbsxtbnpdxkl.myycjynzdtldykzzxddxhqshdgmzsjycct.yrzlpwltlkxslzcgg.xclfxlkjrtlqj.qzncmbqdkkcxglczjzxjhptdjjmzqykqs.cqzdshh.dmlzfmmzbgntjnnlgbyjbrbtmlbyjdzxlcjlpldlpcqdhlhzlycblcxzcj.dqlmzmmsshmybhbskkbhrsxxjmxsdznzpxlbbr.gggfchgmsklltsjyycqlcskywy.hywhbhqywb.wykqldqftntkhqcgdqktgpkxhcpdhtwtmssyhbwcrwxhjmkmzngwtmlkfghkjyldyycxwhy.clqhkqhtdqhhffldxqwgzyyd.sbpkyrzpjfyyzjc.qdzzdl.ttbbfjllcxdlmjsdx.gygsjqxcfbxsszpdyzcxdnyxpfzydlyjccpltxlsxyzyrxcyysdylwwnds.hjsygyhgywk.xtjzd.xysrltdjss.xfn.jdxyzhlxlllzhzsjnyqyqqxyjghzgjcyjchzlycdshwsgczyjxcllnxzjjyyxnfsmwfpylcyll.bwddhwdxjmcxztzpmlqzhsfhzynztlldywlslxhymmylmbwwkyxy.dtxylldjpybpwfxjmmmllh.fdll.flbhhhbqqjtzjcqjjdjtffkmmmbythygdcqrddwrqjxnbysnmzdbyytbjhpybygtjx..hgqdqtmystqxkbtsbkjlxrb.qqhqmjjbdjwtgtbxpgbktlgqxjjjcdhxqdwjlwrfmqgwqhckryswgbtgygbwsdwdwrfhwytjjxxxjyzyslphyyp.yxhydqkxshxyx.skqhywbdddpplcjlhq..wxksyyhdyplfjthkjltcyyhhjttpltzzcdlthqkcxqyst..ywkyzyxxyysddjkllpwmcyhqgxyhcrmbxpllnqydqhxsxxwgdqbshyllpjjjthyjkyphthyykty.zy.nmdshlcrpqfbgfxzbsbtlgxsjbswyysksflxlpplbbblbsfxfyzbsjssylpbbffffsscjdstzsxtryjcyffsytyzbjtbctsbsdhrtjjbytcxyj.ygxcbn.bjdsysyhgsjzbxbytfzwg.nyhhthjh.tfwgcstbgxklstywmtmbyxjskzscdyjrcytwxzfhmymcxlznsdjtttxrycfyjsbsdy.rxhljxbbd.ynjghxgckgscymblxjmsznskgxfbnbbthfj..fxyxfpxmyfhdtzcxzzpxrsywzdlybbjtyqwqjpzypzjznjpzjlztfysbttslmptzrtdxqsj.hbzylzdhljsqmlhtxtj.cx.lzzspktlzkqqyfsygywpcpqfhqhytqxzkrsgtgsqczlptxcdyyzssqzslxlzm.cbcqbzyxhbsxlzdltcdjtylzjyytpzylltxjsjxhlbmytxcqrblzssfjzztnjydxmyjhlhpblcyxqjqqkzzscpzksw.lqsblcczjsxgwwwygy.tjbbctdkhqhkgtgpbkqyslbxbbckbmllxdzstbklggqkqlsbkkdfxrmdkbftpzfrtbbmf.rqgxkjpzsstlbzdpszqzsjthljqlzbpmsmmsxlqqnhknblrddnhxdhddjcyygyfqgzlgsygmjqgkhbpmxyxlytqwlwgcpbmjxcyzydrjbhtdjx..shtmjsbyplwhlzffnypmhxqhpltbqpfbcwjdbygpnxtbfzjgsddtjshx..wzzyllttybwjkgxghlfkxdjtmszsqynzggswqsphtlsskmclzxyszqzxncjdqgzdlfnykljcjllzlmzznhydsshthxzlzzbbhqzwwycrdhlyqqjb.yfsgxthsrxwqhwfslmssgztty.yqqwrsl.lhmjtqjsmxqbjjzjxzyzkxbyqxbjxshzssfglxmxzxfghkzszggylcls.rjxhslllmzx.lglxydjytlfbhbpnlyzfbbhptgjkw.tzhkjjxzxxglljlstgshjjyqlqzfkcgnndjsszfdbctwws.qfhqjbs.qtgypjlbxbmmywxgslzhglzgnyfljbyfdjfrgsfmbyzhqfbwjsyfyjjphzbyyzffw.dgrlmftmlbzgycqxcdjygzyyyytytydw.g.zyhxjlzythlrmgrjxzclhn.ljjthtbwjybjjbxjjtjt..khwslzplpsf.zpqqbdlqjjtyyqlyzkdksqjyyjzldqcgjjyzjsycmr.qtht.jmfctyhypkmhycwjdcfhyyxwshctxrljgjshccyyyjltkttytmxgtcjtz.yy.czlylbszywjytsjyhbyshfjlygjxxtmzyyltxxypclxyjzyzyypnhmymdyylblhlsyygqllnjjyms.ycbzgdlyxylcqyxtsz.gxhzglhwbljg.yxtwqm.kbpqcgyshh.gqcmwyywljyjhyyzlljjylhzyhmgsljljxcjjyclycjpcpzjzjmmylcjlnqljjjlxxjmlszljqlycmmhcfmmfpqqmfxlqmcffqmmmmhmznfhhjgtthhkhslnchhyqdxtmmqdcydyxyqmyqylddcyyyd.zdcymzydlzfffmmycqcwzzm.btbyctdmndzggdftypcgqyttssffwbdtzqssystwjjhjytsxxylbyqhwwhx.zxwznnqzjzjjqjccchyyxbzxccyjtllcqxknjycyycynzzqyy..wyczdcjycchyjlbtzkycqwlpgpyllgkdldlgkgqbgychjxy....z.w...z....s.....l.......sl..z....lgtm....gd......................tn..hbltdzl.tmmbj.lx';
205
+
206
+ function initialOf(code) {
207
+ if (code < PINYIN_LO || code > PINYIN_HI) return '';
208
+ var letter = PINYIN.charAt(code - PINYIN_LO);
209
+ return letter === '.' ? '' : letter;
210
+ }
211
+
212
+ /** Latin text is kept; CJK turns into the pinyin initial; everything else is dropped. */
213
+ function initials(text) {
214
+ var out = '';
215
+ var source = String(text || '');
216
+ for (var i = 0; i < source.length; i += 1) {
217
+ var code = source.charCodeAt(i);
218
+ if (code >= 48 && code <= 57) out += source.charAt(i);
219
+ else if (code >= 97 && code <= 122) out += source.charAt(i);
220
+ else if (code >= 65 && code <= 90) out += source.charAt(i).toLowerCase();
221
+ else out += initialOf(code);
222
+ }
223
+ return out;
224
+ }
225
+
226
+ // ---------------------------------------------------------------------
227
+ // shared open/closed store: the overlay and the footer button both drive it
228
+ // ---------------------------------------------------------------------
229
+ var store = {
230
+ open: false,
231
+ listeners: new Set(),
232
+ set(next) {
233
+ if (store.open === next) return;
234
+ store.open = next;
235
+ store.listeners.forEach((fn) => {
236
+ try {
237
+ fn(next);
238
+ } catch {
239
+ /* a broken listener must not break the palette */
240
+ }
241
+ });
242
+ },
243
+ toggle() {
244
+ store.set(!store.open);
245
+ },
246
+ };
247
+
248
+ var extCommands = [];
249
+ var extListeners = new Set();
250
+
251
+ function emitExt() {
252
+ extListeners.forEach((fn) => {
253
+ try {
254
+ fn();
255
+ } catch {
256
+ /* ignore */
257
+ }
258
+ });
259
+ }
260
+
261
+ /** A plugin can contribute a row: { id, title, sub?, group?, run(ctx) }. */
262
+ function registerCommand(command) {
263
+ if (!command || typeof command.id !== 'string' || !command.id) return false;
264
+ if (typeof command.title !== 'string' || !command.title) return false;
265
+ if (typeof command.run !== 'function') return false;
266
+ extCommands = extCommands.filter((entry) => entry.id !== command.id);
267
+ extCommands.push(command);
268
+ emitExt();
269
+ return true;
270
+ }
271
+
272
+ function unregisterCommand(id) {
273
+ var before = extCommands.length;
274
+ extCommands = extCommands.filter((entry) => entry.id !== id);
275
+ if (extCommands.length !== before) emitExt();
276
+ }
277
+
278
+ function useExtCommands() {
279
+ var [, bump] = useState(0);
280
+ useEffect(() => {
281
+ var listener = () => bump((value) => value + 1);
282
+ extListeners.add(listener);
283
+ return () => extListeners.delete(listener);
284
+ }, []);
285
+ return extCommands;
286
+ }
287
+
288
+ function useOpen() {
289
+ var [open, setOpen] = useState(store.open);
290
+ useEffect(() => {
291
+ var listener = (value) => setOpen(value);
292
+ store.listeners.add(listener);
293
+ setOpen(store.open);
294
+ return () => store.listeners.delete(listener);
295
+ }, []);
296
+ return open;
297
+ }
298
+
299
+ function activeLocale(ctx) {
300
+ try {
301
+ var snapshot = ctx.locale.getLocale();
302
+ return (snapshot && snapshot.active) || 'zh';
303
+ } catch {
304
+ return 'zh';
305
+ }
306
+ }
307
+
308
+ function useLang(ctx) {
309
+ var [locale, setLocale] = useState(() => activeLocale(ctx));
310
+ useEffect(() => {
311
+ if (!ctx.locale || typeof ctx.locale.subscribe !== 'function') return undefined;
312
+ return ctx.locale.subscribe(() => setLocale(activeLocale(ctx)));
313
+ }, []);
314
+ return /^zh/i.test(String(locale)) ? 'zh' : 'en';
315
+ }
316
+
317
+ function copy(lang) {
318
+ return STRINGS[lang] || STRINGS.zh;
319
+ }
320
+
321
+ function request(path, body) {
322
+ var init = body === undefined ? { headers: { Accept: 'application/json' } } : {
323
+ method: 'POST',
324
+ headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
325
+ body: JSON.stringify(body),
326
+ };
327
+ return fetch(path, init).then((response) =>
328
+ response.json().then(
329
+ (payload) => {
330
+ if (!response.ok || !payload || payload.ok !== true) {
331
+ var message = payload && payload.error ? payload.error : 'HTTP ' + response.status;
332
+ throw new Error(message);
333
+ }
334
+ return payload;
335
+ },
336
+ () => {
337
+ throw new Error('HTTP ' + response.status);
338
+ },
339
+ ),
340
+ );
341
+ }
342
+
343
+ function getJson(path) {
344
+ return request(path);
345
+ }
346
+
347
+ // ---------------------------------------------------------------------
348
+ // ranking
349
+ // ---------------------------------------------------------------------
350
+ function fuzzy(query, text) {
351
+ var needle = String(query || '').toLowerCase();
352
+ var hay = String(text || '').toLowerCase();
353
+ if (!needle) return 0.12;
354
+ if (!hay) return 0;
355
+ var direct = hay.indexOf(needle);
356
+ if (direct === 0) return 1;
357
+ if (direct > 0) return 0.86 - Math.min(direct, 40) * 0.004;
358
+ // pinyin initials: "cj" should reach 插件
359
+ var py = initials(hay);
360
+ if (py) {
361
+ var at = py.indexOf(needle);
362
+ if (at === 0) return 0.78;
363
+ if (at > 0) return 0.62 - Math.min(at, 30) * 0.004;
364
+ }
365
+ // subsequence, in order, on the raw text
366
+ var cursor = 0;
367
+ var hits = 0;
368
+ for (var i = 0; i < hay.length && cursor < needle.length; i += 1) {
369
+ if (hay.charAt(i) === needle.charAt(cursor)) {
370
+ cursor += 1;
371
+ hits += 1;
372
+ }
373
+ }
374
+ if (cursor === needle.length) return 0.4 + Math.min(hits, 12) * 0.01 - Math.min(hay.length, 200) * 0.0004;
375
+ return 0;
376
+ }
377
+
378
+ function scoreOf(query, item) {
379
+ var best = fuzzy(query, item.title);
380
+ if (item.sub) best = Math.max(best, fuzzy(query, item.sub) * 0.72);
381
+ if (item.keys) {
382
+ for (var i = 0; i < item.keys.length; i += 1) {
383
+ best = Math.max(best, fuzzy(query, item.keys[i]) * 0.9);
384
+ }
385
+ }
386
+ return best;
387
+ }
388
+
389
+ // ---------------------------------------------------------------------
390
+ // recency memory: a small weight on things the user already reached for
391
+ // ---------------------------------------------------------------------
392
+ function readRecent() {
393
+ try {
394
+ var raw = window.localStorage.getItem(RECENT_KEY);
395
+ var parsed = raw ? JSON.parse(raw) : null;
396
+ return parsed && typeof parsed === 'object' ? parsed : {};
397
+ } catch {
398
+ return {};
399
+ }
400
+ }
401
+
402
+ function bumpRecent(key) {
403
+ if (!key) return;
404
+ try {
405
+ var map = readRecent();
406
+ var entry = map[key] || { count: 0, at: 0 };
407
+ entry.count = Math.min((entry.count || 0) + 1, 40);
408
+ entry.at = Date.now();
409
+ map[key] = entry;
410
+ var keys = Object.keys(map);
411
+ if (keys.length > 60) {
412
+ keys
413
+ .sort((a, b) => (map[a].at || 0) - (map[b].at || 0))
414
+ .slice(0, keys.length - 60)
415
+ .forEach((old) => {
416
+ delete map[old];
417
+ });
418
+ }
419
+ window.localStorage.setItem(RECENT_KEY, JSON.stringify(map));
420
+ return map;
421
+ } catch {
422
+ return {};
423
+ }
424
+ }
425
+
426
+ /**
427
+ * Frecency: how often it was used, discounted by a one-week half-life.
428
+ * A brand-new action (count 1) beats something used twice a month ago.
429
+ */
430
+ function frecency(hit, now) {
431
+ if (!hit || (!hit.at && !hit.count)) return 0;
432
+ var count = Math.max(1, Math.min(hit.count || 1, 40));
433
+ var ageDays = Math.max(0, ((now || Date.now()) - (hit.at || 0)) / 86400000);
434
+ return count * Math.pow(0.5, ageDays / 7);
435
+ }
436
+
437
+ // ---------------------------------------------------------------------
438
+ // item helpers
439
+ // ---------------------------------------------------------------------
440
+ function item(key, group, title, sub, run, actions) {
441
+ return { key: key, group: group, title: title, sub: sub || '', run: run, actions: actions || null };
442
+ }
443
+
444
+ function copyText(text) {
445
+ if (!text) return Promise.reject(new Error('empty'));
446
+ if (navigator.clipboard && navigator.clipboard.writeText) return navigator.clipboard.writeText(text);
447
+ return Promise.reject(new Error('clipboard unavailable'));
448
+ }
449
+
450
+ function revealPath(path) {
451
+ return request(API + '/open-profile', { path: path }).then(() => null);
452
+ }
453
+
454
+ function shortPath(value) {
455
+ var text = typeof value === 'string' ? value.trim() : '';
456
+ if (!text) return '';
457
+ var home = /^\/Users\/[^/]+/;
458
+ if (home.test(text)) text = text.replace(home, '~');
459
+ var parts = text.split('/');
460
+ if (text.length > 38 && parts.length > 3) text = '…/' + parts.slice(-2).join('/');
461
+ return text;
462
+ }
463
+
464
+ function sessionItem(ctx, lang, entry) {
465
+ var t = copy(lang);
466
+ var id = entry.sessionId;
467
+ var title = entry.title || t.untitled;
468
+ var run = () => {
469
+ ctx.uiWorkspace.openSession(id);
470
+ return undefined;
471
+ };
472
+ var actions = () => sessionActions(ctx, lang, entry);
473
+ return item('session:' + id, 'session', title, entry.snippet || shortPath(entry.cwd), run, actions);
474
+ }
475
+
476
+ function renameOf(ctx, id, title) {
477
+ var ref = ctx.sessions.retain(id, { source: 'controllerOperation' });
478
+ var finish = () => {
479
+ try {
480
+ ref.release();
481
+ } catch {
482
+ /* already released */
483
+ }
484
+ };
485
+ return Promise.resolve(ref.ready).then(
486
+ (binding) =>
487
+ Promise.resolve(binding.session.rename(title)).then(
488
+ (result) => {
489
+ finish();
490
+ if (!result || result.ok === false) throw new Error('rename rejected');
491
+ try {
492
+ ctx.sessions.refreshProjections(id);
493
+ } catch {
494
+ /* projection refresh is best-effort */
495
+ }
496
+ return result.value;
497
+ },
498
+ (error) => {
499
+ finish();
500
+ throw error;
501
+ },
502
+ ),
503
+ (error) => {
504
+ finish();
505
+ throw error;
506
+ },
507
+ );
508
+ }
509
+
510
+ function sessionActions(ctx, lang, entry) {
511
+ var t = copy(lang);
512
+ var id = entry.sessionId;
513
+ var cwd = entry.cwd || '';
514
+ return [
515
+ item('action:open', 'action', t.sessionOpen, t.sessionOpenHint, () => {
516
+ ctx.uiWorkspace.openSession(id);
517
+ return undefined;
518
+ }),
519
+ item('action:rename', 'action', t.rename, t.renameHint, () => ({
520
+ input: {
521
+ kind: 'rename',
522
+ title: t.renamePrompt,
523
+ value: entry.title || '',
524
+ submit: (value) =>
525
+ renameOf(ctx, id, value.trim()).then(
526
+ () => ({ status: t.done }),
527
+ (error) => {
528
+ throw error;
529
+ },
530
+ ),
531
+ },
532
+ })),
533
+ item('action:fork', 'action', t.fork, t.forkHint, () =>
534
+ Promise.resolve(ctx.uiWorkspace.forkSession(id)).then((childId) => {
535
+ if (childId) ctx.uiWorkspace.openSession(childId);
536
+ return { status: t.done };
537
+ }),
538
+ ),
539
+ item('action:archive', 'action', t.archive, t.archiveHint, () =>
540
+ Promise.resolve(ctx.uiWorkspace.archiveSession(id, { stopActivity: true })).then(() => ({
541
+ status: t.done,
542
+ })),
543
+ ),
544
+ item('action:copy-id', 'action', t.copyId, id, () =>
545
+ copyText(id).then(() => ({ status: t.copied })),
546
+ ),
547
+ item('action:copy-cwd', 'action', t.copyPath, shortPath(cwd), () =>
548
+ copyText(cwd).then(() => ({ status: t.copied })),
549
+ ),
550
+ item('action:reveal', 'action', t.revealPath, shortPath(cwd), () =>
551
+ revealPath(cwd).then(() => ({ status: t.done })),
552
+ ),
553
+ item('action:export', 'action', t.exportMd, t.exportMdHint, () =>
554
+ fetch('/api/session.markdown?sessionId=' + encodeURIComponent(id), {
555
+ headers: { Accept: 'text/markdown' },
556
+ }).then((response) => {
557
+ if (!response.ok) throw new Error('HTTP ' + response.status);
558
+ return response.text();
559
+ }).then((markdown) => {
560
+ var fallback = entry.title || id || 'session';
561
+ var filename = String(fallback).replace(/[\\/:*?"<>|]+/g, '-').slice(0, 80) + '.md';
562
+ var blob = new Blob([markdown], { type: 'text/markdown;charset=utf-8' });
563
+ var url = URL.createObjectURL(blob);
564
+ var anchor = document.createElement('a');
565
+ anchor.href = url;
566
+ anchor.download = filename;
567
+ document.body.appendChild(anchor);
568
+ anchor.click();
569
+ anchor.remove();
570
+ setTimeout(() => URL.revokeObjectURL(url), 4000);
571
+ return { status: t.done };
572
+ }),
573
+ ),
574
+ ];
575
+ }
576
+
577
+ function workspaceActions(ctx, lang, workspace) {
578
+ var t = copy(lang);
579
+ var id = workspace.workspaceId;
580
+ var path = workspace.path || '';
581
+ return [
582
+ item('action:ws-open', 'action', t.wsOpen, shortPath(path), () =>
583
+ Promise.resolve(ctx.uiWorkspace.openWorkspace(id)).then(() => undefined),
584
+ ),
585
+ item('action:ws-new', 'action', t.wsNew, shortPath(path), () => {
586
+ ctx.uiWorkspace.startSession(id);
587
+ return undefined;
588
+ }),
589
+ item('action:ws-copy', 'action', t.wsCopyPath, shortPath(path), () =>
590
+ copyText(path).then(() => ({ status: t.copied })),
591
+ ),
592
+ item('action:ws-reveal', 'action', t.wsReveal, shortPath(path), () =>
593
+ revealPath(path).then(() => ({ status: t.done })),
594
+ ),
595
+ ];
596
+ }
597
+
598
+ function buildActions(ctx, lang) {
599
+ var t = copy(lang);
600
+ var list = [
601
+ item('cmd:new', 'action', t.newSession, t.newSessionHint, () => {
602
+ ctx.uiWorkspace.startSession();
603
+ return undefined;
604
+ }),
605
+ item('cmd:profile', 'action', t.openProfile, t.openProfileHint, () =>
606
+ request(API + '/open-profile', {}).then(() => ({ status: t.done })),
607
+ ),
608
+ item('cmd:sessions', 'action', t.openSessions, t.openSessionsHint, () =>
609
+ getJson(API + '/info').then((info) => revealPath(info.home + '/sessions')).then(() => ({
610
+ status: t.done,
611
+ })),
612
+ ),
613
+ item('cmd:logs', 'action', t.openLogs, t.openLogsHint, () =>
614
+ getJson(API + '/info').then((info) => revealPath(info.home + '/logs')).then(() => ({
615
+ status: t.done,
616
+ })),
617
+ ),
618
+ item('cmd:reload', 'action', t.reload, t.reloadHint, () => {
619
+ window.location.reload();
620
+ return undefined;
621
+ }),
622
+ ];
623
+ return list;
624
+ }
625
+
626
+ function buildThemes(ctx, lang) {
627
+ var t = copy(lang);
628
+ return ['light', 'dark', 'system'].map((id) =>
629
+ item(
630
+ 'theme:' + id,
631
+ 'theme',
632
+ id === 'light' ? t.themeLight : id === 'dark' ? t.themeDark : t.themeSystem,
633
+ '',
634
+ () => {
635
+ ctx.theme.setTheme(id);
636
+ return { status: t.done };
637
+ },
638
+ ),
639
+ );
640
+ }
641
+
642
+ function buildLanguages(ctx, lang) {
643
+ var t = copy(lang);
644
+ var locales = [];
645
+ try {
646
+ var snapshot = ctx.locale.getLocale();
647
+ locales = (snapshot && snapshot.locales) || [];
648
+ } catch {
649
+ locales = [];
650
+ }
651
+ var installed = [];
652
+ for (var i = 0; i < locales.length; i++) {
653
+ var raw = locales[i];
654
+ var id = raw && typeof raw === 'object' ? raw.id : raw;
655
+ var label = raw && typeof raw === 'object' ? raw.label || raw.id : raw;
656
+ if (!id || id === 'en' || id === 'zh') continue;
657
+ installed.push(
658
+ item('lang:' + id, 'system', label, id, () => {
659
+ ctx.locale.setLocale(id);
660
+ return { status: t.done };
661
+ }),
662
+ );
663
+ }
664
+ return installed.concat([
665
+ item('lang:zh', 'system', t.langZh, 'zh', () => {
666
+ ctx.locale.setLocale('zh');
667
+ return { status: t.done };
668
+ }),
669
+ item('lang:en', 'system', t.langEn, 'en', () => {
670
+ ctx.locale.setLocale('en');
671
+ return { status: t.done };
672
+ }),
673
+ ]);
674
+ }
675
+
676
+ function workspaceItem(ctx, lang, workspace) {
677
+ var path = workspace.path || '';
678
+ return item(
679
+ 'workspace:' + workspace.workspaceId,
680
+ 'workspace',
681
+ (workspace.title || path || '').trim(),
682
+ shortPath(path),
683
+ () => Promise.resolve(ctx.uiWorkspace.openWorkspace(workspace.workspaceId)).then(() => undefined),
684
+ () => workspaceActions(ctx, lang, workspace),
685
+ );
686
+ }
687
+
688
+ function pluginItem(ctx, lang, plugin, reload) {
689
+ var t = copy(lang);
690
+ var key = 'plugin:' + plugin.name;
691
+ var toggle = () => {
692
+ var next = !plugin.enabled;
693
+ return request(API + '/plugin', { name: plugin.name, enabled: next }).then((payload) => {
694
+ if (reload) reload();
695
+ var status = next ? t.pluginOn : t.pluginOff;
696
+ var suffix = payload && payload.application === 'restart-required' ? ' · ' + t.restartHint : '';
697
+ return { status: plugin.name + ' · ' + status + suffix };
698
+ });
699
+ };
700
+ var actions = () => [
701
+ item(key + ':toggle', 'action', plugin.enabled ? t.disablePlugin : t.enablePlugin, plugin.name, toggle, null),
702
+ item(key + ':dir', 'action', t.pluginDir, plugin.name, () => revealPath(plugin.dir), null),
703
+ ];
704
+ var sub = [plugin.version ? 'v' + plugin.version : '', plugin.enabled ? t.pluginOn : t.pluginOff]
705
+ .filter(Boolean)
706
+ .join(' · ');
707
+ var row = item(key, 'plugin', plugin.name, sub, toggle, actions);
708
+ row.dot = plugin.enabled ? C.ok : C.sub;
709
+ return row;
710
+ }
711
+
712
+ function extItem(ctx, lang, command) {
713
+ var key = 'ext:' + command.id;
714
+ return item(
715
+ key,
716
+ 'ext',
717
+ command.title,
718
+ command.sub || '',
719
+ () => {
720
+ var out = command.run(ctx);
721
+ if (out && typeof out.then === 'function') {
722
+ return out.then((value) => (value && value.status ? { status: value.status } : null));
723
+ }
724
+ return out && out.status ? { status: out.status } : null;
725
+ },
726
+ null,
727
+ );
728
+ }
729
+
730
+ // ---------------------------------------------------------------------
731
+ // root list
732
+ // ---------------------------------------------------------------------
733
+ var GROUP_ORDER = ['recent', 'session', 'plugin', 'action', 'workspace', 'theme', 'system', 'ext'];
734
+
735
+ function groupLabel(group, lang) {
736
+ var t = copy(lang);
737
+ if (group === 'session') return t.session;
738
+ if (group === 'workspace') return t.workspace;
739
+ if (group === 'action') return t.action;
740
+ if (group === 'theme') return t.theme;
741
+ if (group === 'system') return t.system;
742
+ if (group === 'plugin') return t.plugin;
743
+ if (group === 'ext') return t.ext;
744
+ return t.recent;
745
+ }
746
+
747
+ function buildRoot(ctx, lang, query, catalog, hits, workspaces, recent, plugins, ext, reloadPlugins) {
748
+ var items = [];
749
+ var text = query.trim();
750
+ var now = Date.now();
751
+ var seenSessions = new Set();
752
+ var sessionRows = [];
753
+ // Local-first: every catalogue row is fuzzy-matched in the browser, so
754
+ // keystrokes never wait for the Host. Content hits arrive separately.
755
+ var requested = text ? catalog : catalog.slice(0, 5);
756
+ requested.forEach(function (entry) {
757
+ var row = sessionItem(ctx, lang, entry);
758
+ if (text && scoreOf(query, row) <= 0) return;
759
+ seenSessions.add(entry.sessionId);
760
+ sessionRows.push(row);
761
+ });
762
+ if (text) {
763
+ (hits || []).forEach(function (entry) {
764
+ if (seenSessions.has(entry.sessionId)) return;
765
+ seenSessions.add(entry.sessionId);
766
+ var row = sessionItem(ctx, lang, entry);
767
+ row.force = true;
768
+ sessionRows.push(row);
769
+ });
770
+ }
771
+ sessionRows.forEach(function (row) {
772
+ items.push(row);
773
+ });
774
+ (plugins || []).slice(0, text ? plugins.length : 6).forEach((plugin) => items.push(pluginItem(ctx, lang, plugin, reloadPlugins)));
775
+ buildActions(ctx, lang).forEach((entry) => items.push(entry));
776
+ workspaces.forEach((workspace) => items.push(workspaceItem(ctx, lang, workspace)));
777
+ (ext || []).forEach((command) => items.push(extItem(ctx, lang, command)));
778
+ buildThemes(ctx, lang).forEach((entry) => items.push(entry));
779
+ buildLanguages(ctx, lang).forEach((entry) => items.push(entry));
780
+
781
+ if (!text) {
782
+ // a short "recent" band on top, then the natural groups
783
+ var ranked = items
784
+ .map((entry) => ({ entry: entry, hit: recent[entry.key] }))
785
+ .filter((row) => row.hit && (row.hit.at || row.hit.count))
786
+ .sort((a, b) => frecency(b.hit, now) - frecency(a.hit, now))
787
+ .slice(0, 4)
788
+ .map((row) => row.entry);
789
+ var seen = new Set(ranked.map((entry) => entry.key));
790
+ return ranked
791
+ .map((entry) => Object.assign({}, entry, { group: 'recent' }))
792
+ .concat(items.filter((entry) => !seen.has(entry.key)));
793
+ }
794
+
795
+ var scored = [];
796
+ items.forEach((entry) => {
797
+ var score = entry.force ? Math.max(scoreOf(query, entry), 0.95) : scoreOf(query, entry);
798
+ if (score <= 0) return;
799
+ var hit = recent[entry.key];
800
+ var bump = hit ? Math.min(frecency(hit, now), 8) * 0.015 : 0;
801
+ scored.push({ entry: entry, score: score + bump });
802
+ });
803
+ // keep every group contiguous: a group's place comes from its best hit, the
804
+ // rows inside keep their own order. Otherwise one group shows up twice.
805
+ var best = {};
806
+ scored.forEach((row) => {
807
+ var key = row.entry.group;
808
+ if (!(key in best) || row.score > best[key]) best[key] = row.score;
809
+ });
810
+ scored.sort((a, b) => {
811
+ var ga = a.entry.group;
812
+ var gb = b.entry.group;
813
+ if (ga !== gb) {
814
+ if (best[gb] !== best[ga]) return best[gb] - best[ga];
815
+ return GROUP_ORDER.indexOf(ga) - GROUP_ORDER.indexOf(gb);
816
+ }
817
+ return b.score - a.score;
818
+ });
819
+ return scored.map((row) => row.entry);
820
+ }
821
+
822
+ // ---------------------------------------------------------------------
823
+ // visual helpers
824
+ // ---------------------------------------------------------------------
825
+ function mix(color, percent, over) {
826
+ return 'color-mix(in srgb, ' + color + ' ' + percent + '%, ' + (over || 'transparent') + ')';
827
+ }
828
+
829
+ var ICONS = {
830
+ search: [
831
+ ['circle', { cx: 11, cy: 11, r: 7 }],
832
+ ['path', { d: 'm20 20-3.2-3.2' }],
833
+ ],
834
+ session: [['path', { d: 'M21 15a2 2 0 0 1-2 2H8l-5 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z' }]],
835
+ workspace: [['path', { d: 'M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' }]],
836
+ plugin: [
837
+ ['path', { d: 'M21 8v8a2 2 0 0 1-1 1.73l-7 4a2 2 0 0 1-2 0l-7-4A2 2 0 0 1 3 16V8a2 2 0 0 1 1-1.73l7-4a2 2 0 0 1 2 0l7 4A2 2 0 0 1 21 8z' }],
838
+ ['path', { d: 'm3.3 7 8.7 5 8.7-5' }],
839
+ ['path', { d: 'M12 22V12' }],
840
+ ],
841
+ action: [['path', { d: 'M13 2 4 14h7l-1 8 9-12h-7z' }]],
842
+ theme: [
843
+ ['circle', { cx: 12, cy: 12, r: 4 }],
844
+ ['path', { d: 'M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4' }],
845
+ ],
846
+ system: [
847
+ ['path', { d: 'M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3' }],
848
+ ['path', { d: 'M1 14h6M9 8h6M17 16h6' }],
849
+ ],
850
+ recent: [
851
+ ['circle', { cx: 12, cy: 12, r: 9 }],
852
+ ['path', { d: 'M12 7v5l3 2' }],
853
+ ],
854
+ ext: [['path', { d: 'M12 3l1.9 5.1L19 10l-5.1 1.9L12 17l-1.9-5.1L5 10l5.1-1.9z' }]],
855
+ more: [
856
+ ['circle', { cx: 5, cy: 12, r: 1.4 }],
857
+ ['circle', { cx: 12, cy: 12, r: 1.4 }],
858
+ ['circle', { cx: 19, cy: 12, r: 1.4 }],
859
+ ],
860
+ back: [['path', { d: 'm15 18-6-6 6-6' }]],
861
+ 'arrow-up-right': [['path', { d: 'M7 17 17 7M8 7h9v9' }]],
862
+ external: [['path', { d: 'M15 3h6v6M10 14 21 3M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6' }]],
863
+ pencil: [
864
+ ['path', { d: 'M12 20h9' }],
865
+ ['path', { d: 'M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4z' }],
866
+ ],
867
+ branch: [
868
+ ['circle', { cx: 6, cy: 6, r: 2.5 }],
869
+ ['circle', { cx: 6, cy: 18, r: 2.5 }],
870
+ ['circle', { cx: 18, cy: 6, r: 2.5 }],
871
+ ['path', { d: 'M6 8.5v7M18 8.5c0 3-2 4-5 4H8' }],
872
+ ],
873
+ archive: [
874
+ ['rect', { x: 3, y: 4, width: 18, height: 4, rx: 1 }],
875
+ ['path', { d: 'M5 8v11a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V8M10 12h4' }],
876
+ ],
877
+ copy: [
878
+ ['rect', { x: 9, y: 9, width: 11, height: 11, rx: 2 }],
879
+ ['path', { d: 'M5 15V5a2 2 0 0 1 2-2h10' }],
880
+ ],
881
+ folder: [['path', { d: 'M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z' }]],
882
+ download: [['path', { d: 'M12 3v12M7 10l5 5 5-5M5 21h14' }]],
883
+ power: [
884
+ ['path', { d: 'M12 3v9' }],
885
+ ['path', { d: 'M7 6.5a7 7 0 1 0 10 0' }],
886
+ ],
887
+ plus: [['path', { d: 'M12 5v14M5 12h14' }]],
888
+ refresh: [
889
+ ['path', { d: 'M20 11a8 8 0 1 0-2.3 5.7' }],
890
+ ['path', { d: 'M20 4v7h-7' }],
891
+ ],
892
+ globe: [
893
+ ['circle', { cx: 12, cy: 12, r: 9 }],
894
+ ['path', { d: 'M3 12h18M12 3c2.5 2.7 3.8 5.7 3.8 9S14.5 18.3 12 21c-2.5-2.7-3.8-5.7-3.8-9S9.5 5.7 12 3z' }],
895
+ ],
896
+ check: [['path', { d: 'm20 6-11 11-5-5' }]],
897
+ x: [['path', { d: 'M18 6 6 18M6 6l12 12' }]],
898
+ };
899
+
900
+ function Icon(props) {
901
+ var paint = ICONS[props.name] || ICONS.action;
902
+ var size = props.size || 16;
903
+ return h(
904
+ 'svg',
905
+ {
906
+ width: size,
907
+ height: size,
908
+ viewBox: '0 0 24 24',
909
+ fill: 'none',
910
+ stroke: 'currentColor',
911
+ strokeWidth: props.stroke || 1.7,
912
+ strokeLinecap: 'round',
913
+ strokeLinejoin: 'round',
914
+ 'aria-hidden': 'true',
915
+ style: { display: 'block', flex: '0 0 auto' },
916
+ },
917
+ paint.map(function (entry, position) {
918
+ return h(entry[0], Object.assign({ key: position }, entry[1]));
919
+ }),
920
+ );
921
+ }
922
+
923
+ function iconForGroup(group) {
924
+ if (group === 'recent') return 'recent';
925
+ if (group === 'session') return 'session';
926
+ if (group === 'workspace') return 'workspace';
927
+ if (group === 'plugin') return 'plugin';
928
+ if (group === 'theme') return 'theme';
929
+ if (group === 'system') return 'system';
930
+ if (group === 'ext') return 'ext';
931
+ return 'action';
932
+ }
933
+
934
+ function iconForEntry(entry) {
935
+ if (!entry) return 'action';
936
+ var key = String(entry.key || '');
937
+ if (/:toggle$/.test(key)) return 'power';
938
+ if (/:dir$/.test(key)) return 'folder';
939
+ if (key.indexOf('theme:') === 0) return 'theme';
940
+ if (key.indexOf('lang:') === 0) return 'globe';
941
+ if (key.indexOf('plugin:') === 0) return 'plugin';
942
+ if (key.indexOf('workspace:') === 0) return 'workspace';
943
+ if (key.indexOf('session:') === 0) return 'session';
944
+ if (key.indexOf('ext:') === 0) return 'ext';
945
+ if (key.indexOf('cmd:reload') === 0) return 'refresh';
946
+ if (key.indexOf('cmd:new') === 0) return 'plus';
947
+ if (key.indexOf('cmd:profile') === 0) return 'folder';
948
+ if (key.indexOf('cmd:sessions') === 0) return 'folder';
949
+ if (key.indexOf('cmd:logs') === 0) return 'folder';
950
+ if (key.indexOf('action:rename') === 0) return 'pencil';
951
+ if (key.indexOf('action:fork') === 0) return 'branch';
952
+ if (key.indexOf('action:archive') === 0) return 'archive';
953
+ if (key.indexOf('action:copy') === 0) return 'copy';
954
+ if (key.indexOf('action:ws-copy') === 0) return 'copy';
955
+ if (key.indexOf('action:reveal') === 0) return 'external';
956
+ if (key.indexOf('action:ws-reveal') === 0) return 'external';
957
+ if (key.indexOf('action:export') === 0) return 'download';
958
+ if (key.indexOf('action:ws-new') === 0) return 'plus';
959
+ if (key.indexOf('action:open') === 0) return 'arrow-up-right';
960
+ if (key.indexOf('action:ws-open') === 0) return 'arrow-up-right';
961
+ return iconForGroup(entry.group);
962
+ }
963
+
964
+ function Kbd(props) {
965
+ return h(
966
+ 'span',
967
+ {
968
+ style: {
969
+ display: 'inline-flex',
970
+ alignItems: 'center',
971
+ justifyContent: 'center',
972
+ minWidth: 20,
973
+ height: 20,
974
+ padding: '0 5px',
975
+ boxSizing: 'border-box',
976
+ flex: '0 0 auto',
977
+ fontFamily: MONO,
978
+ fontSize: 10.5,
979
+ fontWeight: 600,
980
+ lineHeight: 1,
981
+ color: C.sub,
982
+ background: mix(C.layerAlt, 72),
983
+ border: '1px solid ' + mix(C.lineStrong, 65),
984
+ borderBottomColor: mix(C.lineStrong, 88),
985
+ borderRadius: 5,
986
+ boxShadow: '0 1px 0 ' + mix(C.text, 5),
987
+ whiteSpace: 'nowrap',
988
+ },
989
+ },
990
+ props.children,
991
+ );
992
+ }
993
+
994
+ function IconTile(props) {
995
+ var active = props.active;
996
+ return h(
997
+ 'span',
998
+ {
999
+ style: {
1000
+ position: 'relative',
1001
+ flex: '0 0 auto',
1002
+ width: 30,
1003
+ height: 30,
1004
+ display: 'inline-flex',
1005
+ alignItems: 'center',
1006
+ justifyContent: 'center',
1007
+ borderRadius: 8,
1008
+ color: active ? C.brand : C.sub,
1009
+ background: active ? mix(C.brand, 13) : mix(C.layerAlt, 76),
1010
+ border: '1px solid ' + (active ? mix(C.brand, 24) : mix(C.line, 70)),
1011
+ transition: 'background 120ms ease, color 120ms ease, border-color 120ms ease',
1012
+ },
1013
+ },
1014
+ h(Icon, { name: props.name, size: 15 }),
1015
+ props.dot
1016
+ ? h('span', {
1017
+ style: {
1018
+ position: 'absolute',
1019
+ right: -1,
1020
+ bottom: -1,
1021
+ width: 7,
1022
+ height: 7,
1023
+ borderRadius: 4,
1024
+ background: props.dot,
1025
+ border: '2px solid ' + C.overlay,
1026
+ boxSizing: 'content-box',
1027
+ },
1028
+ })
1029
+ : null,
1030
+ );
1031
+ }
1032
+
1033
+ var SHIMMER =
1034
+ 'linear-gradient(90deg, ' +
1035
+ mix(C.layerAlt, 78) +
1036
+ ' 25%, ' +
1037
+ mix(C.lineStrong, 58) +
1038
+ ' 37%, ' +
1039
+ mix(C.layerAlt, 78) +
1040
+ ' 63%)';
1041
+
1042
+ var PANEL_CSS = [
1043
+ '@keyframes dsh-cmdk-in{from{opacity:0;transform:translateY(-10px) scale(.985)}to{opacity:1;transform:none}}',
1044
+ '@keyframes dsh-cmdk-fade{from{opacity:0}}',
1045
+ '@keyframes dsh-cmdk-shimmer{0%{background-position:-240px 0}100%{background-position:240px 0}}',
1046
+ '@keyframes dsh-cmdk-spin{to{transform:rotate(360deg)}}',
1047
+ '.dsh-cmdk-input::placeholder{color:' + C.sub + ';opacity:.72}',
1048
+ '.dsh-cmdk-back:hover,.dsh-cmdk-more:hover{background:' + mix(C.layerAlt, 82) + '!important;color:' + C.text + '!important}',
1049
+ '.dsh-cmdk-clear:hover{color:' + C.text + '!important}',
1050
+ '.dsh-cmdk-scroll{scrollbar-width:thin;scrollbar-color:' + mix(C.sub, 30) + ' transparent}',
1051
+ '.dsh-cmdk-scroll::-webkit-scrollbar{width:10px;height:10px}',
1052
+ '.dsh-cmdk-scroll::-webkit-scrollbar-track{background:transparent}',
1053
+ '.dsh-cmdk-scroll::-webkit-scrollbar-thumb{background:' + mix(C.sub, 26) + ';border-radius:999px;border:3px solid transparent;background-clip:content-box}',
1054
+ '.dsh-cmdk-scroll::-webkit-scrollbar-thumb:hover{background:' + mix(C.sub, 44) + ';border:3px solid transparent;background-clip:content-box}',
1055
+ '@media (prefers-reduced-motion:reduce){.dsh-cmdk-panel,.dsh-cmdk-scrim{animation:none!important}.dsh-cmdk-panel *{transition:none!important}.dsh-cmdk-shimmer{animation:none!important}}',
1056
+ ].join('');
1057
+
1058
+ function Hints(props) {
1059
+ return h(
1060
+ 'div',
1061
+ { style: { display: 'flex', alignItems: 'center', gap: 12, minWidth: 0, overflow: 'hidden' } },
1062
+ props.items.map(function (pair, position) {
1063
+ return h(
1064
+ 'span',
1065
+ {
1066
+ key: position,
1067
+ style: { display: 'inline-flex', alignItems: 'center', gap: 5, whiteSpace: 'nowrap' },
1068
+ },
1069
+ h(Kbd, null, pair[0]),
1070
+ pair[1],
1071
+ );
1072
+ }),
1073
+ );
1074
+ }
1075
+
1076
+ function Highlight(props) {
1077
+ var text = props.text == null ? '' : String(props.text);
1078
+ var query = String(props.query || '').trim();
1079
+ if (!query) return text;
1080
+ var lower = text.toLowerCase();
1081
+ var needle = query.toLowerCase();
1082
+ var at = lower.indexOf(needle);
1083
+ if (at < 0) return text;
1084
+ var parts = [];
1085
+ var from = 0;
1086
+ var guard = 0;
1087
+ while (at >= 0 && guard < 40) {
1088
+ if (at > from) parts.push(text.slice(from, at));
1089
+ parts.push(
1090
+ h(
1091
+ 'mark',
1092
+ {
1093
+ key: 'm' + parts.length,
1094
+ style: {
1095
+ backgroundColor: mix(C.brand, 22),
1096
+ boxShadow: 'inset 0 -1px 0 ' + mix(C.brand, 62),
1097
+ color: 'inherit',
1098
+ borderRadius: 3,
1099
+ padding: '0 1px',
1100
+ fontWeight: 600,
1101
+ },
1102
+ },
1103
+ text.slice(at, at + needle.length),
1104
+ ),
1105
+ );
1106
+ from = at + needle.length;
1107
+ at = lower.indexOf(needle, from);
1108
+ guard += 1;
1109
+ }
1110
+ if (from < text.length) parts.push(text.slice(from));
1111
+ return parts;
1112
+ }
1113
+
1114
+ function EmptyState(props) {
1115
+ var query = String(props.query || '').trim();
1116
+ if (query.length > 30) query = query.slice(0, 30) + '…';
1117
+ return h(
1118
+ 'div',
1119
+ {
1120
+ style: {
1121
+ display: 'flex',
1122
+ flexDirection: 'column',
1123
+ alignItems: 'center',
1124
+ textAlign: 'center',
1125
+ gap: 9,
1126
+ padding: '54px 24px 60px',
1127
+ },
1128
+ },
1129
+ h(
1130
+ 'span',
1131
+ {
1132
+ style: {
1133
+ width: 46,
1134
+ height: 46,
1135
+ borderRadius: 14,
1136
+ display: 'inline-flex',
1137
+ alignItems: 'center',
1138
+ justifyContent: 'center',
1139
+ background: mix(C.layerAlt, 80),
1140
+ border: '1px solid ' + mix(C.lineStrong, 55),
1141
+ color: C.sub,
1142
+ marginBottom: 2,
1143
+ },
1144
+ },
1145
+ h(Icon, { name: 'search', size: 20 }),
1146
+ ),
1147
+ h(
1148
+ 'div',
1149
+ {
1150
+ style: {
1151
+ fontSize: 13.5,
1152
+ fontWeight: 600,
1153
+ color: C.text,
1154
+ maxWidth: 380,
1155
+ lineHeight: 1.4,
1156
+ overflowWrap: 'anywhere',
1157
+ },
1158
+ },
1159
+ query ? props.t.emptyFor.replace('{q}', function () { return query; }) : props.t.emptyTitle,
1160
+ ),
1161
+ h(
1162
+ 'div',
1163
+ { style: { fontSize: 12, color: C.sub, maxWidth: 300, lineHeight: 1.55 } },
1164
+ props.t.emptySub,
1165
+ ),
1166
+ );
1167
+ }
1168
+
1169
+ function Skeleton() {
1170
+ return h(
1171
+ 'div',
1172
+ { style: { padding: '8px 2px' } },
1173
+ [0, 1, 2, 3].map(function (row) {
1174
+ var shimmer = {
1175
+ background: SHIMMER,
1176
+ backgroundSize: '400px 100%',
1177
+ animation: 'dsh-cmdk-shimmer 1.3s linear infinite',
1178
+ };
1179
+ return h(
1180
+ 'div',
1181
+ { key: row, style: { display: 'flex', alignItems: 'center', gap: 11, padding: '8px 10px' } },
1182
+ h('div', { style: Object.assign({ width: 30, height: 30, borderRadius: 8, flex: '0 0 auto' }, shimmer) }),
1183
+ h(
1184
+ 'div',
1185
+ { style: { flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 6 } },
1186
+ h(
1187
+ 'div',
1188
+ { style: Object.assign({ height: 10, width: 46 + ((row * 13) % 34) + '%', borderRadius: 4 }, shimmer) },
1189
+ ),
1190
+ h(
1191
+ 'div',
1192
+ {
1193
+ style: Object.assign(
1194
+ { height: 8, width: 28 + ((row * 9) % 26) + '%', borderRadius: 4, opacity: 0.7 },
1195
+ shimmer,
1196
+ ),
1197
+ },
1198
+ ),
1199
+ ),
1200
+ );
1201
+ }),
1202
+ );
1203
+ }
1204
+
1205
+ // ---------------------------------------------------------------------
1206
+ // the palette itself
1207
+ // ---------------------------------------------------------------------
1208
+ function Palette(props) {
1209
+ var ctx = props.ctx;
1210
+ var lang = useLang(ctx);
1211
+ var t = copy(lang);
1212
+ var open = useOpen();
1213
+ var [query, setQuery] = useState('');
1214
+ var [catalog, setCatalog] = useState({ items: [], hits: [], hitsFor: '', loading: true });
1215
+ var [index, setIndex] = useState(0);
1216
+ var [stack, setStack] = useState([]);
1217
+ var [input, setInput] = useState(null);
1218
+ var [status, setStatus] = useState(null);
1219
+ var [busy, setBusy] = useState(false);
1220
+ var [focused, setFocused] = useState(false);
1221
+ var [canFade, setCanFade] = useState(false);
1222
+ var inputRef = useRef(null);
1223
+ var listRef = useRef(null);
1224
+ var [workspaces, setWorkspaces] = useState([]);
1225
+ var [archived, setArchived] = useState({});
1226
+ var [recent, setRecent] = useState(() => readRecent());
1227
+ var [plugins, setPlugins] = useState([]);
1228
+ var ext = useExtCommands();
1229
+
1230
+ function reloadPlugins() {
1231
+ getJson(API + '/plugins')
1232
+ .then((payload) => setPlugins(Array.isArray(payload.items) ? payload.items : []))
1233
+ .catch(() => undefined);
1234
+ }
1235
+
1236
+ var panelRef = useRef(null);
1237
+ var handlerRef = useRef(null);
1238
+
1239
+ // After a mode change the text input unmounts, so focus falls back to the
1240
+ // body: pull it onto the panel and relay keys that escape our dialog.
1241
+ useEffect(() => {
1242
+ if (!open) return;
1243
+ var node = panelRef.current;
1244
+ if (node && document.activeElement !== node) {
1245
+ try {
1246
+ node.focus({ preventScroll: true });
1247
+ } catch (error) {
1248
+ node.focus();
1249
+ }
1250
+ }
1251
+ }, [open, stack.length, input]);
1252
+
1253
+ useEffect(() => {
1254
+ if (!open) return undefined;
1255
+ function relay(event) {
1256
+ var node = panelRef.current;
1257
+ var target = event.target;
1258
+ if (node && target && target.nodeType && node.contains(target)) return;
1259
+ if (handlerRef.current) handlerRef.current(event);
1260
+ }
1261
+ window.addEventListener('keydown', relay, true);
1262
+ return () => window.removeEventListener('keydown', relay, true);
1263
+ }, [open]);
1264
+
1265
+ handlerRef.current = onKeyDown;
1266
+
1267
+ // workspaces + archived ids come from the Host store mirror
1268
+ useEffect(() => {
1269
+ if (!open) return undefined;
1270
+ reloadPlugins();
1271
+ return undefined;
1272
+ }, [open]);
1273
+
1274
+ useEffect(() => {
1275
+ if (!open) return undefined;
1276
+ var alive = true;
1277
+ getJson(API + '/workspaces')
1278
+ .then((payload) => {
1279
+ if (!alive) return;
1280
+ setWorkspaces(Array.isArray(payload.items) ? payload.items : []);
1281
+ var map = {};
1282
+ (payload.archived || []).forEach((id) => {
1283
+ map[id] = true;
1284
+ });
1285
+ setArchived(map);
1286
+ })
1287
+ .catch(() => {
1288
+ /* the palette still works without the workspace list */
1289
+ });
1290
+ return () => {
1291
+ alive = false;
1292
+ };
1293
+ }, [open]);
1294
+
1295
+ // session catalogue comes from the Host: titles + content hits
1296
+ useEffect(() => {
1297
+ if (!open) return undefined;
1298
+ var alive = true;
1299
+ var text = query.trim();
1300
+ setStatus(null);
1301
+ var timer = setTimeout(
1302
+ () => {
1303
+ setCatalog((prev) => (prev.items.length ? prev : { items: [], hits: [], hitsFor: '', loading: true }));
1304
+ getJson(API + '/sessions?limit=24' + (text ? '&q=' + encodeURIComponent(text) : ''))
1305
+ .then((payload) => {
1306
+ if (!alive) return;
1307
+ var live = (payload.items || []).filter((entry) => !archived[entry.sessionId]);
1308
+ var liveHits = (payload.hits || []).filter((entry) => !archived[entry.sessionId]);
1309
+ setCatalog({ items: live, hits: liveHits, hitsFor: text, loading: false });
1310
+ })
1311
+ .catch(() => {
1312
+ if (!alive) return;
1313
+ setCatalog({ items: [], hits: [], hitsFor: text, loading: false });
1314
+ });
1315
+ },
1316
+ text ? 180 : 0,
1317
+ );
1318
+ return () => {
1319
+ alive = false;
1320
+ clearTimeout(timer);
1321
+ };
1322
+ }, [open, query]);
1323
+
1324
+ useEffect(() => {
1325
+ if (!open) {
1326
+ setQuery('');
1327
+ setIndex(0);
1328
+ setStack([]);
1329
+ setInput(null);
1330
+ setStatus(null);
1331
+ return;
1332
+ }
1333
+ setRecent(readRecent());
1334
+ var handle = setTimeout(() => {
1335
+ if (inputRef.current) {
1336
+ inputRef.current.focus({ preventScroll: true });
1337
+ inputRef.current.select && inputRef.current.select();
1338
+ }
1339
+ }, 30);
1340
+ return () => clearTimeout(handle);
1341
+ }, [open]);
1342
+
1343
+ useEffect(() => {
1344
+ if (!open) return undefined;
1345
+ var handle = setTimeout(() => {
1346
+ var node = inputRef.current;
1347
+ if (node && typeof node.focus === 'function') node.focus({ preventScroll: true });
1348
+ }, 20);
1349
+ return () => clearTimeout(handle);
1350
+ }, [open, stack.length, input]);
1351
+
1352
+ useEffect(() => {
1353
+ if (!status) return undefined;
1354
+ var handle = setTimeout(() => setStatus(null), 2200);
1355
+ return () => clearTimeout(handle);
1356
+ }, [status]);
1357
+
1358
+ var visible = [];
1359
+ for (var vi = 0; vi < catalog.items.length; vi += 1) {
1360
+ if (!archived[catalog.items[vi].sessionId]) visible.push(catalog.items[vi]);
1361
+ }
1362
+ var visibleHits = [];
1363
+ var freshHits = catalog.hitsFor === query.trim() ? catalog.hits : [];
1364
+ for (var hi = 0; hi < freshHits.length; hi += 1) {
1365
+ if (!archived[freshHits[hi].sessionId]) visibleHits.push(freshHits[hi]);
1366
+ }
1367
+ var root = buildRoot(ctx, lang, query, visible, visibleHits, workspaces, recent, plugins, ext, reloadPlugins);
1368
+ var current = stack.length ? stack[stack.length - 1] : null;
1369
+ var items = input ? [] : current ? current.items : root;
1370
+ var active = Math.min(index, Math.max(items.length - 1, 0));
1371
+
1372
+ function close() {
1373
+ setFocused(false);
1374
+ store.set(false);
1375
+ }
1376
+
1377
+ function goBack() {
1378
+ if (input) {
1379
+ setInput(null);
1380
+ return;
1381
+ }
1382
+ if (stack.length) {
1383
+ setStack((prev) => prev.slice(0, -1));
1384
+ setIndex(0);
1385
+ }
1386
+ }
1387
+
1388
+ function syncScrollFade() {
1389
+ var node = listRef.current;
1390
+ if (!node) return;
1391
+ setCanFade(node.scrollHeight - node.scrollTop - node.clientHeight > 4);
1392
+ }
1393
+
1394
+ // Keep the highlighted row inside the viewport when the keyboard moves it.
1395
+ useEffect(() => {
1396
+ if (!open) return;
1397
+ var node = listRef.current;
1398
+ if (!node) return;
1399
+ var option = node.querySelector('#dsh-cmdk-opt-' + active);
1400
+ if (option && typeof option.scrollIntoView === 'function') {
1401
+ option.scrollIntoView({ block: 'nearest', inline: 'nearest', behavior: 'instant' });
1402
+ }
1403
+ }, [open, active, stack.length, input, items.length]);
1404
+
1405
+ useEffect(() => {
1406
+ syncScrollFade();
1407
+ }, [open, items.length, query, stack.length, input, catalog.loading]);
1408
+
1409
+ function remember(key) {
1410
+ var next = bumpRecent(key);
1411
+ if (next) setRecent(next);
1412
+ }
1413
+
1414
+ function settle(result) {
1415
+ if (!result) {
1416
+ close();
1417
+ return;
1418
+ }
1419
+ if (result.input) {
1420
+ setInput({ title: result.input.title, value: result.input.value || '', submit: result.input.submit });
1421
+ setStatus(null);
1422
+ return;
1423
+ }
1424
+ if (result.status) {
1425
+ setStatus(result.status);
1426
+ // keep the palette open so the toast is visible, but leave action mode
1427
+ setStack([]);
1428
+ return;
1429
+ }
1430
+ close();
1431
+ }
1432
+
1433
+ function run(entry) {
1434
+ if (!entry || busy) return;
1435
+ remember(entry.key);
1436
+ var result;
1437
+ try {
1438
+ result = entry.run();
1439
+ } catch (error) {
1440
+ setStatus(t.failed + t.failedSep + String((error && error.message) || error));
1441
+ return;
1442
+ }
1443
+ if (result && typeof result.then === 'function') {
1444
+ setBusy(true);
1445
+ result.then(
1446
+ (value) => {
1447
+ setBusy(false);
1448
+ settle(value);
1449
+ },
1450
+ (error) => {
1451
+ setBusy(false);
1452
+ setStatus(t.failed + t.failedSep + String((error && error.message) || error));
1453
+ },
1454
+ );
1455
+ return;
1456
+ }
1457
+ settle(result);
1458
+ }
1459
+
1460
+ function openActions(entry) {
1461
+ if (!entry || !entry.actions) return false;
1462
+ setStack((prev) => prev.concat([{ title: entry.title, group: entry.group, items: entry.actions() }]));
1463
+ setIndex(0);
1464
+ return true;
1465
+ }
1466
+
1467
+ function submitInput() {
1468
+ if (!input) return;
1469
+ var value = String(input.value || '').trim();
1470
+ if (!value) {
1471
+ setStatus(t.cancelled);
1472
+ setInput(null);
1473
+ return;
1474
+ }
1475
+ var pending;
1476
+ try {
1477
+ pending = input.submit(value);
1478
+ } catch (error) {
1479
+ setStatus(t.failed + t.failedSep + String((error && error.message) || error));
1480
+ return;
1481
+ }
1482
+ setBusy(true);
1483
+ Promise.resolve(pending).then(
1484
+ (result) => {
1485
+ setBusy(false);
1486
+ setInput(null);
1487
+ settle(result || { status: t.done });
1488
+ },
1489
+ (error) => {
1490
+ setBusy(false);
1491
+ setStatus(t.failed + t.failedSep + String((error && error.message) || error));
1492
+ },
1493
+ );
1494
+ }
1495
+
1496
+ function onKeyDown(event) {
1497
+ if (event.isComposing || (event.nativeEvent && event.nativeEvent.isComposing) || event.keyCode === 229) {
1498
+ return;
1499
+ }
1500
+ if (event.key === 'Escape') {
1501
+ event.preventDefault();
1502
+ event.stopPropagation();
1503
+ if (input) {
1504
+ setInput(null);
1505
+ return;
1506
+ }
1507
+ if (stack.length) {
1508
+ setStack((prev) => prev.slice(0, -1));
1509
+ setIndex(0);
1510
+ return;
1511
+ }
1512
+ close();
1513
+ return;
1514
+ }
1515
+ if (input) {
1516
+ if (event.key === 'Enter') {
1517
+ event.preventDefault();
1518
+ submitInput();
1519
+ }
1520
+ return;
1521
+ }
1522
+ if (event.key === 'ArrowDown') {
1523
+ event.preventDefault();
1524
+ if (items.length) setIndex((active + 1) % items.length);
1525
+ return;
1526
+ }
1527
+ if (event.key === 'ArrowUp') {
1528
+ event.preventDefault();
1529
+ if (items.length) setIndex((active - 1 + items.length) % items.length);
1530
+ return;
1531
+ }
1532
+ if (event.key === 'ArrowRight' || event.key === 'Tab') {
1533
+ if (openActions(items[active])) {
1534
+ event.preventDefault();
1535
+ return;
1536
+ }
1537
+ if (event.key === 'Tab') event.preventDefault();
1538
+ return;
1539
+ }
1540
+ if (event.key === 'ArrowLeft' && stack.length) {
1541
+ event.preventDefault();
1542
+ setStack((prev) => prev.slice(0, -1));
1543
+ setIndex(0);
1544
+ return;
1545
+ }
1546
+ if (event.key === 'Enter') {
1547
+ event.preventDefault();
1548
+ run(items[active]);
1549
+ return;
1550
+ }
1551
+ if (event.key === 'Backspace' && !query && stack.length) {
1552
+ event.preventDefault();
1553
+ setStack((prev) => prev.slice(0, -1));
1554
+ setIndex(0);
1555
+ }
1556
+ }
1557
+
1558
+ if (!open) return null;
1559
+
1560
+ var sections = [];
1561
+ var lastGroup = null;
1562
+ var counts = {};
1563
+ items.forEach((entry) => {
1564
+ counts[entry.group] = (counts[entry.group] || 0) + 1;
1565
+ });
1566
+ items.forEach((entry, position) => {
1567
+ if (entry.group !== lastGroup) {
1568
+ lastGroup = entry.group;
1569
+ sections.push({
1570
+ key: 'group:' + entry.group + ':' + position,
1571
+ group: entry.group,
1572
+ rows: [],
1573
+ });
1574
+ }
1575
+ sections[sections.length - 1].rows.push(
1576
+ renderRow(
1577
+ entry,
1578
+ position === active,
1579
+ () => run(entry),
1580
+ () => openActions(entry),
1581
+ () => setIndex(position),
1582
+ position,
1583
+ t.hintActions,
1584
+ stack.length ? '' : query,
1585
+ ),
1586
+ );
1587
+ });
1588
+ var rows = sections.map(function (section) {
1589
+ return h(
1590
+ 'div',
1591
+ {
1592
+ key: section.key,
1593
+ role: 'group',
1594
+ 'aria-label': groupLabel(section.group, lang),
1595
+ },
1596
+ h(
1597
+ 'div',
1598
+ {
1599
+ style: {
1600
+ position: 'sticky',
1601
+ top: 0,
1602
+ zIndex: 1,
1603
+ display: 'flex',
1604
+ alignItems: 'center',
1605
+ justifyContent: 'space-between',
1606
+ gap: 8,
1607
+ padding: '11px 10px 5px',
1608
+ background: C.overlay,
1609
+ },
1610
+ },
1611
+ h(
1612
+ 'span',
1613
+ {
1614
+ style: {
1615
+ fontSize: 10.5,
1616
+ fontWeight: 700,
1617
+ letterSpacing: '.09em',
1618
+ textTransform: 'uppercase',
1619
+ color: C.sub,
1620
+ },
1621
+ },
1622
+ groupLabel(section.group, lang),
1623
+ ),
1624
+ h(
1625
+ 'span',
1626
+ {
1627
+ style: {
1628
+ fontSize: 10.5,
1629
+ fontVariantNumeric: 'tabular-nums',
1630
+ color: mix(C.sub, 72),
1631
+ },
1632
+ },
1633
+ counts[section.group],
1634
+ ),
1635
+ ),
1636
+ section.rows,
1637
+ );
1638
+ });
1639
+
1640
+ var headerStyle = {
1641
+ display: 'flex',
1642
+ alignItems: 'center',
1643
+ gap: 9,
1644
+ padding: '12px 14px',
1645
+ borderBottom: '1px solid ' + mix(C.lineStrong, 55),
1646
+ position: 'relative',
1647
+ zIndex: 2,
1648
+ background: mix(C.overlay, 70),
1649
+ };
1650
+ var fieldStyle = {
1651
+ flex: 1,
1652
+ minWidth: 0,
1653
+ display: 'flex',
1654
+ alignItems: 'center',
1655
+ gap: 9,
1656
+ height: 42,
1657
+ padding: '0 11px',
1658
+ boxSizing: 'border-box',
1659
+ borderRadius: 10,
1660
+ background: mix(C.base, 66),
1661
+ border: '1px solid ' + (focused ? mix(C.brand, 55) : mix(C.lineStrong, 62)),
1662
+ boxShadow: focused
1663
+ ? '0 0 0 3px ' + mix(C.brand, 14) + ', inset 0 1px 2px ' + mix(C.text, 5)
1664
+ : 'inset 0 1px 2px ' + mix(C.text, 4),
1665
+ transition: 'border-color 140ms ease, box-shadow 140ms ease',
1666
+ };
1667
+ var inputStyle = {
1668
+ flex: 1,
1669
+ minWidth: 0,
1670
+ width: '100%',
1671
+ height: '100%',
1672
+ padding: 0,
1673
+ border: 'none',
1674
+ outline: 'none',
1675
+ background: 'transparent',
1676
+ color: C.text,
1677
+ fontSize: 15,
1678
+ fontFamily: 'inherit',
1679
+ caretColor: C.brand,
1680
+ };
1681
+ var backButton = h(
1682
+ 'button',
1683
+ {
1684
+ type: 'button',
1685
+ className: 'dsh-cmdk-back',
1686
+ title: t.hintBack,
1687
+ 'aria-label': t.hintBack,
1688
+ onClick: goBack,
1689
+ style: {
1690
+ flex: '0 0 auto',
1691
+ width: 28,
1692
+ height: 28,
1693
+ display: 'inline-flex',
1694
+ alignItems: 'center',
1695
+ justifyContent: 'center',
1696
+ padding: 0,
1697
+ border: 'none',
1698
+ borderRadius: 8,
1699
+ background: 'transparent',
1700
+ color: C.sub,
1701
+ cursor: 'pointer',
1702
+ transition: 'background 120ms ease, color 120ms ease',
1703
+ },
1704
+ },
1705
+ h(Icon, { name: 'back', size: 16 }),
1706
+ );
1707
+
1708
+ var header;
1709
+ if (input) {
1710
+ header = h(
1711
+ 'div',
1712
+ { style: headerStyle },
1713
+ backButton,
1714
+ h(
1715
+ 'div',
1716
+ { style: fieldStyle },
1717
+ h(Icon, { name: 'pencil', size: 16 }),
1718
+ h('input', {
1719
+ ref: inputRef,
1720
+ value: input.value,
1721
+ placeholder: input.title,
1722
+ className: 'dsh-cmdk-input',
1723
+ onChange: (event) => setInput(Object.assign({}, input, { value: event.target.value })),
1724
+ onFocus: () => setFocused(true),
1725
+ onBlur: () => setFocused(false),
1726
+ style: inputStyle,
1727
+ 'aria-label': input.title,
1728
+ spellCheck: false,
1729
+ autoComplete: 'off',
1730
+ }),
1731
+ ),
1732
+ h(Kbd, null, '↵'),
1733
+ h(Kbd, null, 'esc'),
1734
+ );
1735
+ } else if (current) {
1736
+ header = h(
1737
+ 'div',
1738
+ { style: headerStyle },
1739
+ backButton,
1740
+ h(
1741
+ 'div',
1742
+ { style: { flex: 1, minWidth: 0, display: 'flex', alignItems: 'center', gap: 10 } },
1743
+ h(IconTile, { name: iconForGroup(current.group || 'action'), active: true }),
1744
+ h(
1745
+ 'span',
1746
+ {
1747
+ style: {
1748
+ minWidth: 0,
1749
+ overflow: 'hidden',
1750
+ textOverflow: 'ellipsis',
1751
+ whiteSpace: 'nowrap',
1752
+ fontSize: 14,
1753
+ fontWeight: 600,
1754
+ color: C.text,
1755
+ letterSpacing: '-.005em',
1756
+ },
1757
+ },
1758
+ current.title,
1759
+ ),
1760
+ ),
1761
+ h(Kbd, null, 'esc'),
1762
+ );
1763
+ } else {
1764
+ header = h(
1765
+ 'div',
1766
+ { style: headerStyle },
1767
+ h(
1768
+ 'div',
1769
+ { style: fieldStyle },
1770
+ h(Icon, { name: 'search', size: 17 }),
1771
+ h('input', {
1772
+ ref: inputRef,
1773
+ value: query,
1774
+ placeholder: t.placeholder,
1775
+ className: 'dsh-cmdk-input',
1776
+ onChange: (event) => {
1777
+ setQuery(event.target.value);
1778
+ setIndex(0);
1779
+ },
1780
+ onFocus: () => setFocused(true),
1781
+ onBlur: () => setFocused(false),
1782
+ style: inputStyle,
1783
+ 'aria-label': t.placeholder,
1784
+ 'aria-controls': 'dsh-cmdk-list',
1785
+ 'aria-activedescendant': items.length ? 'dsh-cmdk-opt-' + active : undefined,
1786
+ spellCheck: false,
1787
+ autoComplete: 'off',
1788
+ }),
1789
+ query
1790
+ ? h(
1791
+ 'button',
1792
+ {
1793
+ type: 'button',
1794
+ className: 'dsh-cmdk-clear',
1795
+ 'aria-label': t.clear,
1796
+ onClick: () => {
1797
+ setQuery('');
1798
+ setIndex(0);
1799
+ if (inputRef.current) inputRef.current.focus({ preventScroll: true });
1800
+ },
1801
+ style: {
1802
+ flex: '0 0 auto',
1803
+ width: 22,
1804
+ height: 22,
1805
+ display: 'inline-flex',
1806
+ alignItems: 'center',
1807
+ justifyContent: 'center',
1808
+ padding: 0,
1809
+ border: 'none',
1810
+ borderRadius: 6,
1811
+ background: 'transparent',
1812
+ color: C.sub,
1813
+ cursor: 'pointer',
1814
+ transition: 'color 120ms ease',
1815
+ },
1816
+ },
1817
+ h(Icon, { name: 'x', size: 14 }),
1818
+ )
1819
+ : null,
1820
+ ),
1821
+ h(Kbd, null, 'esc'),
1822
+ );
1823
+ }
1824
+
1825
+ var statusKind = status && status.indexOf(t.failed) === 0 ? 'err' : 'ok';
1826
+ var footerLeft;
1827
+ if (status) {
1828
+ footerLeft = h(
1829
+ 'span',
1830
+ {
1831
+ style: {
1832
+ display: 'inline-flex',
1833
+ alignItems: 'center',
1834
+ gap: 7,
1835
+ minWidth: 0,
1836
+ overflow: 'hidden',
1837
+ color: statusKind === 'err' ? C.err : C.ok,
1838
+ fontWeight: 500,
1839
+ textOverflow: 'ellipsis',
1840
+ whiteSpace: 'nowrap',
1841
+ },
1842
+ },
1843
+ h('span', {
1844
+ style: {
1845
+ flex: '0 0 auto',
1846
+ width: 6,
1847
+ height: 6,
1848
+ borderRadius: 3,
1849
+ background: 'currentColor',
1850
+ },
1851
+ }),
1852
+ status,
1853
+ );
1854
+ } else if (busy) {
1855
+ footerLeft = h(
1856
+ 'span',
1857
+ {
1858
+ style: {
1859
+ display: 'inline-flex',
1860
+ alignItems: 'center',
1861
+ gap: 7,
1862
+ color: C.brand,
1863
+ },
1864
+ },
1865
+ h('span', {
1866
+ style: {
1867
+ width: 11,
1868
+ height: 11,
1869
+ borderRadius: 6,
1870
+ border: '1.6px solid ' + mix(C.brand, 35),
1871
+ borderTopColor: C.brand,
1872
+ animation: 'dsh-cmdk-spin .7s linear infinite',
1873
+ },
1874
+ }),
1875
+ t.searching,
1876
+ );
1877
+ } else {
1878
+ var hints;
1879
+ if (!items.length) {
1880
+ hints = [['esc', t.hintClose]];
1881
+ } else if (current) {
1882
+ hints = [
1883
+ ['↵', t.hintRun],
1884
+ ['←', t.hintBack],
1885
+ ['esc', t.hintClose],
1886
+ ];
1887
+ } else {
1888
+ hints = [
1889
+ ['↑↓', t.hintSelect],
1890
+ ['↵', t.hintOpen],
1891
+ ['→', t.hintActions],
1892
+ ['esc', t.hintClose],
1893
+ ];
1894
+ }
1895
+ footerLeft = h(Hints, { items: hints });
1896
+ }
1897
+
1898
+ var tree = h(
1899
+ 'div',
1900
+ {
1901
+ className: 'dsh-cmdk-scrim',
1902
+ style: {
1903
+ position: 'fixed',
1904
+ inset: 0,
1905
+ zIndex: 60,
1906
+ display: 'flex',
1907
+ justifyContent: 'center',
1908
+ alignItems: 'flex-start',
1909
+ padding: 'clamp(48px, 12vh, 120px) 20px 20px',
1910
+ boxSizing: 'border-box',
1911
+ background: 'color-mix(in srgb, #000 36%, transparent)',
1912
+ animation: 'dsh-cmdk-fade 140ms ease-out',
1913
+ },
1914
+ onMouseDown: (event) => {
1915
+ if (event.target === event.currentTarget) close();
1916
+ },
1917
+ },
1918
+ h(
1919
+ 'div',
1920
+ {
1921
+ role: 'dialog',
1922
+ 'aria-modal': 'true',
1923
+ 'aria-label': t.palette,
1924
+ className: 'dsh-cmdk-panel',
1925
+ ref: panelRef,
1926
+ tabIndex: -1,
1927
+ onKeyDown: onKeyDown,
1928
+ style: {
1929
+ position: 'relative',
1930
+ width: 'min(680px, calc(100vw - 40px))',
1931
+ maxHeight: 'min(72vh, 720px)',
1932
+ display: 'flex',
1933
+ flexDirection: 'column',
1934
+ boxSizing: 'border-box',
1935
+ background: C.overlay,
1936
+ color: C.text,
1937
+ border: '1px solid ' + mix(C.lineStrong, 72),
1938
+ borderRadius: 16,
1939
+ boxShadow:
1940
+ '0 0 0 1px ' +
1941
+ mix(C.text, 4) +
1942
+ ' inset, 0 32px 80px -18px rgba(0,0,0,.6), 0 12px 28px -14px rgba(0,0,0,.45)',
1943
+ overflow: 'hidden',
1944
+ outline: 'none',
1945
+ fontFamily: 'inherit',
1946
+ animation: 'dsh-cmdk-in 180ms cubic-bezier(.16,1,.3,1)',
1947
+ },
1948
+ },
1949
+ h('style', null, PANEL_CSS),
1950
+ h('div', {
1951
+ 'aria-hidden': 'true',
1952
+ style: {
1953
+ position: 'absolute',
1954
+ left: 0,
1955
+ right: 0,
1956
+ top: 0,
1957
+ height: 110,
1958
+ pointerEvents: 'none',
1959
+ background:
1960
+ 'radial-gradient(120% 100% at 50% -30%, ' + mix(C.brand, 12) + ', transparent 72%)',
1961
+ },
1962
+ }),
1963
+ h('div', {
1964
+ 'aria-hidden': 'true',
1965
+ style: {
1966
+ position: 'absolute',
1967
+ top: 0,
1968
+ left: '12%',
1969
+ right: '12%',
1970
+ height: 1,
1971
+ zIndex: 3,
1972
+ pointerEvents: 'none',
1973
+ background:
1974
+ 'linear-gradient(90deg, transparent, ' + mix(C.brand, 55) + ', transparent)',
1975
+ },
1976
+ }),
1977
+ header,
1978
+ h(
1979
+ 'div',
1980
+ {
1981
+ id: 'dsh-cmdk-list',
1982
+ role: 'listbox',
1983
+ 'aria-label': input ? input.title : t.resultsLabel,
1984
+ className: 'dsh-cmdk-scroll',
1985
+ ref: listRef,
1986
+ onScroll: syncScrollFade,
1987
+ style: {
1988
+ overflowY: 'auto',
1989
+ flex: 1,
1990
+ minHeight: 0,
1991
+ padding: '4px 8px 10px',
1992
+ WebkitMaskImage: canFade
1993
+ ? 'linear-gradient(to bottom, #000 calc(100% - 26px), transparent)'
1994
+ : undefined,
1995
+ maskImage: canFade
1996
+ ? 'linear-gradient(to bottom, #000 calc(100% - 26px), transparent)'
1997
+ : undefined,
1998
+ },
1999
+ },
2000
+ input
2001
+ ? null
2002
+ : items.length
2003
+ ? rows
2004
+ : catalog.loading
2005
+ ? h(Skeleton)
2006
+ : h(EmptyState, { t: t, query: query }),
2007
+ ),
2008
+ h(
2009
+ 'div',
2010
+ {
2011
+ style: {
2012
+ display: 'flex',
2013
+ alignItems: 'center',
2014
+ justifyContent: 'space-between',
2015
+ gap: 12,
2016
+ padding: '8px 14px',
2017
+ borderTop: '1px solid ' + mix(C.lineStrong, 50),
2018
+ background: mix(C.layerAlt, 34),
2019
+ fontSize: 11,
2020
+ color: C.sub,
2021
+ minHeight: 37,
2022
+ boxSizing: 'border-box',
2023
+ },
2024
+ },
2025
+ h(
2026
+ 'span',
2027
+ {
2028
+ role: 'status',
2029
+ 'aria-live': 'polite',
2030
+ 'aria-atomic': 'true',
2031
+ style: {
2032
+ position: 'absolute',
2033
+ width: 1,
2034
+ height: 1,
2035
+ padding: 0,
2036
+ margin: -1,
2037
+ overflow: 'hidden',
2038
+ clip: 'rect(0 0 0 0)',
2039
+ whiteSpace: 'nowrap',
2040
+ border: 0,
2041
+ },
2042
+ },
2043
+ !input && query && !catalog.loading ? items.length + ' ' + t.results : '',
2044
+ ),
2045
+ footerLeft,
2046
+ h(
2047
+ 'span',
2048
+ {
2049
+ style: {
2050
+ flex: '0 0 auto',
2051
+ fontFamily: MONO,
2052
+ fontSize: 10.5,
2053
+ fontVariantNumeric: 'tabular-nums',
2054
+ color: mix(C.sub, 80),
2055
+ },
2056
+ },
2057
+ items.length ? active + 1 + ' / ' + items.length : '',
2058
+ ),
2059
+ ),
2060
+ ),
2061
+ );
2062
+ return tree;
2063
+ }
2064
+
2065
+ function renderRow(entry, active, onRun, onActions, onHover, position, moreLabel, query) {
2066
+ return h(
2067
+ 'div',
2068
+ {
2069
+ key: entry.key,
2070
+ id: 'dsh-cmdk-opt-' + position,
2071
+ role: 'option',
2072
+ 'aria-selected': active ? 'true' : 'false',
2073
+ onClick: onRun,
2074
+ onMouseEnter: onHover,
2075
+ onDoubleClick: onActions,
2076
+ style: {
2077
+ display: 'flex',
2078
+ alignItems: 'center',
2079
+ gap: 11,
2080
+ margin: '1px 0',
2081
+ padding: '7px 10px',
2082
+ borderRadius: 10,
2083
+ cursor: 'pointer',
2084
+ scrollMarginTop: 30,
2085
+ scrollMarginBottom: 30,
2086
+ background: active ? mix(C.brand, 11, C.layerAlt) : 'transparent',
2087
+ boxShadow: active ? 'inset 0 0 0 1px ' + mix(C.brand, 20) : 'none',
2088
+ transition: 'background 110ms ease, box-shadow 110ms ease',
2089
+ outline: 'none',
2090
+ },
2091
+ },
2092
+ h(IconTile, { name: iconForEntry(entry), active: active, dot: entry.dot }),
2093
+ h(
2094
+ 'div',
2095
+ { style: { minWidth: 0, flex: 1, display: 'flex', flexDirection: 'column', gap: 2 } },
2096
+ h(
2097
+ 'div',
2098
+ {
2099
+ style: {
2100
+ fontSize: 13.5,
2101
+ fontWeight: 500,
2102
+ color: C.text,
2103
+ letterSpacing: '-.005em',
2104
+ overflow: 'hidden',
2105
+ textOverflow: 'ellipsis',
2106
+ whiteSpace: 'nowrap',
2107
+ },
2108
+ },
2109
+ h(Highlight, { text: entry.title, query: query }),
2110
+ ),
2111
+ entry.sub
2112
+ ? h(
2113
+ 'div',
2114
+ {
2115
+ style: {
2116
+ fontSize: 11.5,
2117
+ color: C.sub,
2118
+ overflow: 'hidden',
2119
+ textOverflow: 'ellipsis',
2120
+ whiteSpace: 'nowrap',
2121
+ },
2122
+ },
2123
+ h(Highlight, { text: entry.sub, query: query }),
2124
+ )
2125
+ : null,
2126
+ ),
2127
+ active ? h(Kbd, null, '↵') : null,
2128
+ entry.actions
2129
+ ? h(
2130
+ 'button',
2131
+ {
2132
+ type: 'button',
2133
+ className: 'dsh-cmdk-more',
2134
+ title: moreLabel,
2135
+ 'aria-label': moreLabel,
2136
+ tabIndex: -1,
2137
+ onClick: (event) => {
2138
+ event.stopPropagation();
2139
+ onActions();
2140
+ },
2141
+ style: {
2142
+ flex: '0 0 auto',
2143
+ width: 24,
2144
+ height: 24,
2145
+ display: 'inline-flex',
2146
+ alignItems: 'center',
2147
+ justifyContent: 'center',
2148
+ padding: 0,
2149
+ border: 'none',
2150
+ borderRadius: 6,
2151
+ background: 'transparent',
2152
+ color: C.sub,
2153
+ cursor: 'pointer',
2154
+ opacity: active ? 0.95 : 0.45,
2155
+ transition: 'opacity 120ms ease, background 120ms ease, color 120ms ease',
2156
+ },
2157
+ },
2158
+ h(Icon, { name: 'more', size: 15 }),
2159
+ )
2160
+ : null,
2161
+ );
2162
+ }
2163
+
2164
+ function FooterButton(props) {
2165
+ var lang = useLang(props.ctx);
2166
+ var t = copy(lang);
2167
+ var [hover, setHover] = useState(false);
2168
+ return h(
2169
+ 'button',
2170
+ {
2171
+ type: 'button',
2172
+ onClick: () => store.toggle(),
2173
+ title: HOTKEY,
2174
+ onMouseEnter: () => setHover(true),
2175
+ onMouseLeave: () => setHover(false),
2176
+ style: {
2177
+ display: 'flex',
2178
+ alignItems: 'center',
2179
+ gap: 8,
2180
+ width: '100%',
2181
+ padding: '7px 9px',
2182
+ boxSizing: 'border-box',
2183
+ border: '1px solid ' + (hover ? mix(C.lineStrong, 72) : mix(C.lineStrong, 45)),
2184
+ borderRadius: 9,
2185
+ background: hover ? mix(C.layerAlt, 80) : 'transparent',
2186
+ color: hover ? C.text : C.sub,
2187
+ cursor: 'pointer',
2188
+ fontSize: 12,
2189
+ fontFamily: 'inherit',
2190
+ textAlign: 'left',
2191
+ transition: 'background 120ms ease, border-color 120ms ease, color 120ms ease',
2192
+ },
2193
+ },
2194
+ h(Icon, { name: 'search', size: 14 }),
2195
+ h(
2196
+ 'span',
2197
+ { style: { flex: 1, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } },
2198
+ t.footer || '搜索',
2199
+ ),
2200
+ h(Kbd, null, HOTKEY),
2201
+ );
2202
+ }
2203
+
2204
+ // ---------------------------------------------------------------------
2205
+ // registration
2206
+ // ---------------------------------------------------------------------
2207
+ var inject = ['slots', 'sessions', 'uiWorkspace', 'workspaces', 'theme', 'locale'];
2208
+
2209
+ var hotkey = false;
2210
+
2211
+ function onKey(event) {
2212
+ var mod = event.metaKey || event.ctrlKey;
2213
+ if (!mod || event.altKey) return;
2214
+ if (String(event.key || '').toLowerCase() !== 'k') return;
2215
+ event.preventDefault();
2216
+ event.stopPropagation();
2217
+ store.toggle();
2218
+ }
2219
+
2220
+ function apply(ctx) {
2221
+ var overlay = ctx.slots.inject('shell.overlay', () =>
2222
+ ctx.slots.register({ name: 'shell.overlay', id: 'dsh-cmdk-panel', order: 500 }, () =>
2223
+ h(Palette, { ctx: ctx }),
2224
+ ),
2225
+ );
2226
+ var button = ctx.slots.inject('sidebar.footer.action', () =>
2227
+ ctx.slots.register({ name: 'sidebar.footer.action', id: 'dsh-cmdk-button', order: 40 }, () =>
2228
+ h(FooterButton, { ctx: ctx }),
2229
+ ),
2230
+ );
2231
+ window.addEventListener('keydown', onKey, true);
2232
+ hotkey = true;
2233
+
2234
+ // Extension point: another plugin can contribute rows.
2235
+ // window.__DSH_CMDK__.register({ id, title, sub, run(ctx) })
2236
+ var api = {
2237
+ version: 1,
2238
+ register: registerCommand,
2239
+ unregister: unregisterCommand,
2240
+ open: () => store.set(true),
2241
+ close: () => store.set(false),
2242
+ };
2243
+ window.__DSH_CMDK__ = api;
2244
+ function onExternal(event) {
2245
+ if (event && event.detail) registerCommand(event.detail);
2246
+ }
2247
+ window.addEventListener('dsh-cmdk:command', onExternal);
2248
+
2249
+ return () => {
2250
+ if (typeof overlay === 'function') overlay();
2251
+ if (typeof button === 'function') button();
2252
+ if (hotkey) window.removeEventListener('keydown', onKey, true);
2253
+ hotkey = false;
2254
+ window.removeEventListener('dsh-cmdk:command', onExternal);
2255
+ if (window.__DSH_CMDK__ === api) delete window.__DSH_CMDK__;
2256
+ };
2257
+ }
2258
+
2259
+ exports.apply = apply;
2260
+ exports.inject = inject;
2261
+ return module.exports;
2262
+ },
2263
+ });