@stacksjs/desktop 0.2.198 → 0.2.199
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/dist/browser.js +1 -223
- package/dist/chunk-0954hbsb.js +315 -0
- package/dist/chunk-ts9f0mxv.js +3 -0
- package/dist/index.js +78 -2256
- package/dist/test-utils.js +1 -105
- package/package.json +1 -1
- package/dist/chunk-2mx7fq49.js +0 -4
- package/dist/chunk-ys4frvmj.js +0 -3960
package/dist/index.js
CHANGED
|
@@ -1,1155 +1,86 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
MIN_WATCH_INTERVAL_MS,
|
|
6
|
-
MODAL_STYLES,
|
|
7
|
-
TOAST_STYLES,
|
|
8
|
-
alert,
|
|
9
|
-
app,
|
|
10
|
-
appleScript,
|
|
11
|
-
audio,
|
|
12
|
-
battery,
|
|
13
|
-
biometric,
|
|
14
|
-
bluetooth,
|
|
15
|
-
bonjour,
|
|
16
|
-
caffeinate,
|
|
17
|
-
clipboard,
|
|
18
|
-
closeAllModals,
|
|
19
|
-
confirm,
|
|
20
|
-
continuityCamera,
|
|
21
|
-
coreml,
|
|
22
|
-
crashReporter,
|
|
23
|
-
createInterval,
|
|
24
|
-
createTimer,
|
|
25
|
-
decaffeinate,
|
|
26
|
-
deepLinks,
|
|
27
|
-
delay,
|
|
28
|
-
dismissAlertById,
|
|
29
|
-
dismissAllAlerts,
|
|
30
|
-
dragOut,
|
|
31
|
-
fileAssociations,
|
|
32
|
-
focus,
|
|
33
|
-
focusShortcutsReady,
|
|
34
|
-
formatCompact,
|
|
35
|
-
formatDuration,
|
|
36
|
-
formatRemainingTime,
|
|
37
|
-
formatShortcut,
|
|
38
|
-
formatTime,
|
|
39
|
-
fs,
|
|
40
|
-
getActiveAlertCount,
|
|
41
|
-
getActiveModalCount,
|
|
42
|
-
getCaffeinateStatus,
|
|
43
|
-
getCapabilities,
|
|
44
|
-
getCapability,
|
|
45
|
-
getDialogBridgeScript,
|
|
46
|
-
getRegisteredHotkeys,
|
|
47
|
-
globalShortcuts,
|
|
48
|
-
handoff,
|
|
49
|
-
hasBridge,
|
|
50
|
-
hasFocusShortcuts,
|
|
51
|
-
iap,
|
|
52
|
-
isAvailable,
|
|
53
|
-
isCaffeinated,
|
|
54
|
-
isDragOutAvailable,
|
|
55
|
-
keychain,
|
|
56
|
-
liveActivities,
|
|
57
|
-
localServer,
|
|
58
|
-
location,
|
|
59
|
-
log,
|
|
60
|
-
menu,
|
|
61
|
-
midi,
|
|
62
|
-
nativeAutoLaunch,
|
|
63
|
-
network,
|
|
64
|
-
notifications,
|
|
65
|
-
notify,
|
|
66
|
-
parseShortcut,
|
|
67
|
-
pdf,
|
|
68
|
-
permissions,
|
|
69
|
-
printing,
|
|
70
|
-
prompt,
|
|
71
|
-
redactPII,
|
|
72
|
-
registerHotkey,
|
|
73
|
-
requestNotificationPermission,
|
|
74
|
-
screen,
|
|
75
|
-
screenCapture,
|
|
76
|
-
screenSharing,
|
|
77
|
-
serial,
|
|
78
|
-
serviceMenu,
|
|
79
|
-
shell,
|
|
80
|
-
showAlert,
|
|
81
|
-
showAlertDialog,
|
|
82
|
-
showColorPicker,
|
|
83
|
-
showConfirmDialog,
|
|
84
|
-
showErrorDialog,
|
|
85
|
-
showErrorModal,
|
|
86
|
-
showErrorToast,
|
|
87
|
-
showInfoModal,
|
|
88
|
-
showInfoToast,
|
|
89
|
-
showMessageBox,
|
|
90
|
-
showModal,
|
|
91
|
-
showOpenDialog,
|
|
92
|
-
showQuestionModal,
|
|
93
|
-
showSaveDialog,
|
|
94
|
-
showSuccessModal,
|
|
95
|
-
showSuccessToast,
|
|
96
|
-
showToast,
|
|
97
|
-
showWarningDialog,
|
|
98
|
-
showWarningModal,
|
|
99
|
-
showWarningToast,
|
|
100
|
-
signPayload,
|
|
101
|
-
speech,
|
|
102
|
-
speechRecognition,
|
|
103
|
-
spotlight,
|
|
104
|
-
tags,
|
|
105
|
-
theme,
|
|
106
|
-
touchbar,
|
|
107
|
-
unregisterAllHotkeys,
|
|
108
|
-
unregisterHotkey,
|
|
109
|
-
updater,
|
|
110
|
-
vision,
|
|
111
|
-
watchScreenSharing,
|
|
112
|
-
windowEvents
|
|
113
|
-
} from "./chunk-ys4frvmj.js";
|
|
114
|
-
import {
|
|
115
|
-
__require
|
|
116
|
-
} from "./chunk-2mx7fq49.js";
|
|
117
|
-
// src/components.ts
|
|
118
|
-
function generateId(prefix = "stx") {
|
|
119
|
-
return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
120
|
-
}
|
|
121
|
-
function escapeHtml(str) {
|
|
122
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
123
|
-
}
|
|
124
|
-
function buildClasses(...classes) {
|
|
125
|
-
return classes.filter(Boolean).join(" ");
|
|
126
|
-
}
|
|
127
|
-
function buildStyles(styles) {
|
|
128
|
-
if (!styles)
|
|
129
|
-
return "";
|
|
130
|
-
return Object.entries(styles).map(([key, value]) => `${key.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${value}`).join("; ");
|
|
131
|
-
}
|
|
132
|
-
function createButton(props) {
|
|
133
|
-
const {
|
|
134
|
-
text,
|
|
135
|
-
variant = "primary",
|
|
136
|
-
size = "medium",
|
|
137
|
-
disabled = false,
|
|
138
|
-
loading = false,
|
|
139
|
-
icon,
|
|
140
|
-
iconPosition = "left",
|
|
141
|
-
id = generateId("btn"),
|
|
142
|
-
className,
|
|
143
|
-
style
|
|
144
|
-
} = props;
|
|
145
|
-
const classes = buildClasses("stx-button", `stx-button--${variant}`, `stx-button--${size}`, disabled && "stx-button--disabled", loading && "stx-button--loading", className);
|
|
146
|
-
const styleStr = buildStyles(style);
|
|
147
|
-
const iconHtml = icon ? `<span class="stx-button-icon">${icon}</span>` : "";
|
|
148
|
-
const loadingHtml = loading ? '<span class="stx-button-spinner"></span>' : "";
|
|
149
|
-
const content = iconPosition === "left" ? `${iconHtml}${loadingHtml}<span class="stx-button-text">${escapeHtml(text)}</span>` : `<span class="stx-button-text">${escapeHtml(text)}</span>${iconHtml}${loadingHtml}`;
|
|
150
|
-
return `<button id="${id}" class="${classes}" ${disabled || loading ? "disabled" : ""} ${styleStr ? `style='${styleStr}'` : ""}>${content}</button>`;
|
|
151
|
-
}
|
|
152
|
-
function createTextInput(props) {
|
|
153
|
-
const {
|
|
154
|
-
value = "",
|
|
155
|
-
placeholder = "",
|
|
156
|
-
type = "text",
|
|
157
|
-
disabled = false,
|
|
158
|
-
readonly = false,
|
|
159
|
-
maxLength,
|
|
160
|
-
minLength,
|
|
161
|
-
pattern,
|
|
162
|
-
required = false,
|
|
163
|
-
autocomplete,
|
|
164
|
-
label,
|
|
165
|
-
error,
|
|
166
|
-
hint,
|
|
167
|
-
id = generateId("input"),
|
|
168
|
-
className,
|
|
169
|
-
style
|
|
170
|
-
} = props;
|
|
171
|
-
const classes = buildClasses("stx-input", error && "stx-input--error", disabled && "stx-input--disabled", className);
|
|
172
|
-
const styleStr = buildStyles(style);
|
|
173
|
-
const attrs = [
|
|
174
|
-
`type="${type}"`,
|
|
175
|
-
`id="${id}"`,
|
|
176
|
-
`class="${classes}"`,
|
|
177
|
-
value && `value="${escapeHtml(value)}"`,
|
|
178
|
-
placeholder && `placeholder="${escapeHtml(placeholder)}"`,
|
|
179
|
-
disabled && "disabled",
|
|
180
|
-
readonly && "readonly",
|
|
181
|
-
required && "required",
|
|
182
|
-
maxLength && `maxlength="${maxLength}"`,
|
|
183
|
-
minLength && `minlength="${minLength}"`,
|
|
184
|
-
pattern && `pattern="${escapeHtml(pattern)}"`,
|
|
185
|
-
autocomplete && `autocomplete="${autocomplete}"`,
|
|
186
|
-
styleStr && `style="${styleStr}"`
|
|
187
|
-
].filter(Boolean).join(" ");
|
|
188
|
-
let html = "";
|
|
189
|
-
if (label) {
|
|
190
|
-
html += `<label class="stx-input-label" for="${id}">${escapeHtml(label)}</label>`;
|
|
191
|
-
}
|
|
192
|
-
html += `<input ${attrs} />`;
|
|
193
|
-
if (error) {
|
|
194
|
-
html += `<div class="stx-input-error">${escapeHtml(error)}</div>`;
|
|
195
|
-
} else if (hint) {
|
|
196
|
-
html += `<div class="stx-input-hint">${escapeHtml(hint)}</div>`;
|
|
197
|
-
}
|
|
198
|
-
return `<div class="stx-input-wrapper">${html}</div>`;
|
|
199
|
-
}
|
|
200
|
-
function createCheckbox(props) {
|
|
201
|
-
const {
|
|
202
|
-
checked = false,
|
|
203
|
-
label,
|
|
204
|
-
disabled = false,
|
|
205
|
-
indeterminate = false,
|
|
206
|
-
id = generateId("checkbox"),
|
|
207
|
-
className,
|
|
208
|
-
style
|
|
209
|
-
} = props;
|
|
210
|
-
const classes = buildClasses("stx-checkbox", disabled && "stx-checkbox--disabled", className);
|
|
211
|
-
const styleStr = buildStyles(style);
|
|
212
|
-
const inputAttrs = [
|
|
213
|
-
'type="checkbox"',
|
|
214
|
-
`id="${id}"`,
|
|
215
|
-
checked && "checked",
|
|
216
|
-
disabled && "disabled",
|
|
217
|
-
indeterminate && 'data-indeterminate="true"'
|
|
218
|
-
].filter(Boolean).join(" ");
|
|
219
|
-
return `
|
|
220
|
-
<label class="${classes}" ${styleStr ? `style="${styleStr}"` : ""}>
|
|
221
|
-
<input ${inputAttrs} />
|
|
2
|
+
import{$ as hZ,$a as h0,A as FZ,Aa as B0,B as jZ,Ba as F0,C as DZ,Ca as j0,D as VZ,Da as D0,E as LZ,Ea as V0,F as OZ,Fa as L0,G as zZ,Ga as O0,H as MZ,Ha as z0,I as TZ,Ia as M0,J as WZ,Ja as T0,K as PZ,Ka as W0,L as AZ,La as P0,M as NZ,Ma as A0,N as kZ,Na as N0,O as xZ,Oa as k0,P as CZ,Pa as x0,Q as IZ,Qa as C0,R as HZ,Ra as I0,S as vZ,Sa as H0,T as wZ,Ta as v0,U as fZ,Ua as w0,V as SZ,Va as f0,W as gZ,Wa as S0,X as bZ,Xa as g0,Y as m,Ya as b0,Z as uZ,Za as u0,_ as yZ,_a as y0,a as cY,aa as mZ,ab as m0,b as dY,ba as cZ,bb as c0,c as pY,ca as dZ,d as rY,da as pZ,e as nY,ea as rZ,f as oY,fa as nZ,g as lY,ga as oZ,h as aY,ha as lZ,i as iY,ia as aZ,j as sY,ja as iZ,k as tY,ka as sZ,l as eY,la as tZ,m as QZ,ma as eZ,n as YZ,na as Q0,o as ZZ,oa as Y0,p as XZ,pa as Z0,q as $Z,qa as X0,r as GZ,ra as $0,s as JZ,sa as G0,t as qZ,ta as J0,u as RZ,ua as q0,v as UZ,va as R0,w as KZ,wa as U0,x as _Z,xa as K0,y as EZ,ya as _0,z as BZ,za as E0}from"./chunk-0954hbsb.js";import{cb as N}from"./chunk-ts9f0mxv.js";function L(Y="stx"){return`${Y}-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}function B(Y){return Y.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function V(...Y){return Y.filter(Boolean).join(" ")}function D(Y){if(!Y)return"";return Object.entries(Y).map(([Q,Z])=>`${Q.replace(/([A-Z])/g,"-$1").toLowerCase()}: ${Z}`).join("; ")}function UQ(Y){let{text:Q,variant:Z="primary",size:X="medium",disabled:$=!1,loading:J=!1,icon:U,iconPosition:q="left",id:G=L("btn"),className:_,style:K}=Y,E=V("stx-button",`stx-button--${Z}`,`stx-button--${X}`,$&&"stx-button--disabled",J&&"stx-button--loading",_),R=D(K),F=U?`<span class="stx-button-icon">${U}</span>`:"",j=J?'<span class="stx-button-spinner"></span>':"",O=q==="left"?`${F}${j}<span class="stx-button-text">${B(Q)}</span>`:`<span class="stx-button-text">${B(Q)}</span>${F}${j}`;return`<button id="${G}" class="${E}" ${$||J?"disabled":""} ${R?`style='${R}'`:""}>${O}</button>`}function KQ(Y){let{value:Q="",placeholder:Z="",type:X="text",disabled:$=!1,readonly:J=!1,maxLength:U,minLength:q,pattern:G,required:_=!1,autocomplete:K,label:E,error:R,hint:F,id:j=L("input"),className:O,style:z}=Y,M=V("stx-input",R&&"stx-input--error",$&&"stx-input--disabled",O),v=D(z),RQ=[`type="${X}"`,`id="${j}"`,`class="${M}"`,Q&&`value="${B(Q)}"`,Z&&`placeholder="${B(Z)}"`,$&&"disabled",J&&"readonly",_&&"required",U&&`maxlength="${U}"`,q&&`minlength="${q}"`,G&&`pattern="${B(G)}"`,K&&`autocomplete="${K}"`,v&&`style="${v}"`].filter(Boolean).join(" "),I="";if(E)I+=`<label class="stx-input-label" for="${j}">${B(E)}</label>`;if(I+=`<input ${RQ} />`,R)I+=`<div class="stx-input-error">${B(R)}</div>`;else if(F)I+=`<div class="stx-input-hint">${B(F)}</div>`;return`<div class="stx-input-wrapper">${I}</div>`}function _Q(Y){let{checked:Q=!1,label:Z,disabled:X=!1,indeterminate:$=!1,id:J=L("checkbox"),className:U,style:q}=Y,G=V("stx-checkbox",X&&"stx-checkbox--disabled",U),_=D(q),K=['type="checkbox"',`id="${J}"`,Q&&"checked",X&&"disabled",$&&'data-indeterminate="true"'].filter(Boolean).join(" ");return`
|
|
3
|
+
<label class="${G}" ${_?`style="${_}"`:""}>
|
|
4
|
+
<input ${K} />
|
|
222
5
|
<span class="stx-checkbox-box"></span>
|
|
223
|
-
${
|
|
6
|
+
${Z?`<span class="stx-checkbox-label">${B(Z)}</span>`:""}
|
|
224
7
|
</label>
|
|
225
|
-
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
value = 50,
|
|
230
|
-
min = 0,
|
|
231
|
-
max = 100,
|
|
232
|
-
step = 1,
|
|
233
|
-
disabled = false,
|
|
234
|
-
label,
|
|
235
|
-
showValue = true,
|
|
236
|
-
id = generateId("slider"),
|
|
237
|
-
className,
|
|
238
|
-
style
|
|
239
|
-
} = props;
|
|
240
|
-
const classes = buildClasses("stx-slider", disabled && "stx-slider--disabled", className);
|
|
241
|
-
const styleStr = buildStyles(style);
|
|
242
|
-
const inputAttrs = [
|
|
243
|
-
'type="range"',
|
|
244
|
-
`id="${id}"`,
|
|
245
|
-
`value="${value}"`,
|
|
246
|
-
`min="${min}"`,
|
|
247
|
-
`max="${max}"`,
|
|
248
|
-
`step="${step}"`,
|
|
249
|
-
disabled && "disabled"
|
|
250
|
-
].filter(Boolean).join(" ");
|
|
251
|
-
let html = "";
|
|
252
|
-
if (label) {
|
|
253
|
-
html += `<label class="stx-slider-label" for="${id}">${escapeHtml(label)}</label>`;
|
|
254
|
-
}
|
|
255
|
-
html += `<div class="stx-slider-track"><input ${inputAttrs} /></div>`;
|
|
256
|
-
if (showValue) {
|
|
257
|
-
html += `<span class="stx-slider-value">${value}</span>`;
|
|
258
|
-
}
|
|
259
|
-
return `<div class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
260
|
-
}
|
|
261
|
-
function createProgressBar(props) {
|
|
262
|
-
const {
|
|
263
|
-
value,
|
|
264
|
-
max = 100,
|
|
265
|
-
variant = "default",
|
|
266
|
-
size = "medium",
|
|
267
|
-
showLabel = false,
|
|
268
|
-
indeterminate = false,
|
|
269
|
-
id = generateId("progress"),
|
|
270
|
-
className,
|
|
271
|
-
style
|
|
272
|
-
} = props;
|
|
273
|
-
const percentage = Math.min(100, Math.max(0, value / max * 100));
|
|
274
|
-
const classes = buildClasses("stx-progress", `stx-progress--${variant}`, `stx-progress--${size}`, indeterminate && "stx-progress--indeterminate", className);
|
|
275
|
-
const styleStr = buildStyles(style);
|
|
276
|
-
return `
|
|
277
|
-
<div id="${id}" class="${classes}" role="progressbar" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}" ${styleStr ? `style="${styleStr}"` : ""}>
|
|
278
|
-
<div class="stx-progress-bar" style="width: ${indeterminate ? "100%" : `${percentage}%`}"></div>
|
|
279
|
-
${showLabel ? `<span class="stx-progress-label">${Math.round(percentage)}%</span>` : ""}
|
|
8
|
+
`}function EQ(Y){let{value:Q=50,min:Z=0,max:X=100,step:$=1,disabled:J=!1,label:U,showValue:q=!0,id:G=L("slider"),className:_,style:K}=Y,E=V("stx-slider",J&&"stx-slider--disabled",_),R=D(K),F=['type="range"',`id="${G}"`,`value="${Q}"`,`min="${Z}"`,`max="${X}"`,`step="${$}"`,J&&"disabled"].filter(Boolean).join(" "),j="";if(U)j+=`<label class="stx-slider-label" for="${G}">${B(U)}</label>`;if(j+=`<div class="stx-slider-track"><input ${F} /></div>`,q)j+=`<span class="stx-slider-value">${Q}</span>`;return`<div class="${E}" ${R?`style='${R}'`:""}>${j}</div>`}function BQ(Y){let{value:Q,max:Z=100,variant:X="default",size:$="medium",showLabel:J=!1,indeterminate:U=!1,id:q=L("progress"),className:G,style:_}=Y,K=Math.min(100,Math.max(0,Q/Z*100)),E=V("stx-progress",`stx-progress--${X}`,`stx-progress--${$}`,U&&"stx-progress--indeterminate",G),R=D(_);return`
|
|
9
|
+
<div id="${q}" class="${E}" role="progressbar" aria-valuenow="${Q}" aria-valuemin="0" aria-valuemax="${Z}" ${R?`style="${R}"`:""}>
|
|
10
|
+
<div class="stx-progress-bar" style="width: ${U?"100%":`${K}%`}"></div>
|
|
11
|
+
${J?`<span class="stx-progress-label">${Math.round(K)}%</span>`:""}
|
|
280
12
|
</div>
|
|
281
|
-
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
id = generateId("badge"),
|
|
289
|
-
className,
|
|
290
|
-
style
|
|
291
|
-
} = props;
|
|
292
|
-
const classes = buildClasses("stx-badge", `stx-badge--${variant}`, `stx-badge--${size}`, className);
|
|
293
|
-
const styleStr = buildStyles(style);
|
|
294
|
-
return `<span id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${escapeHtml(text)}</span>`;
|
|
295
|
-
}
|
|
296
|
-
function createAvatar(props) {
|
|
297
|
-
const {
|
|
298
|
-
src,
|
|
299
|
-
alt = "",
|
|
300
|
-
name,
|
|
301
|
-
size = "medium",
|
|
302
|
-
shape = "circle",
|
|
303
|
-
id = generateId("avatar"),
|
|
304
|
-
className,
|
|
305
|
-
style
|
|
306
|
-
} = props;
|
|
307
|
-
const sizeClass = typeof size === "number" ? "" : `stx-avatar--${size}`;
|
|
308
|
-
const sizeStyle = typeof size === "number" ? `width: ${size}px; height: ${size}px;` : "";
|
|
309
|
-
const classes = buildClasses("stx-avatar", sizeClass, `stx-avatar--${shape}`, className);
|
|
310
|
-
const combinedStyle = [sizeStyle, buildStyles(style)].filter(Boolean).join(" ");
|
|
311
|
-
const initials = name ? name.split(" ").map((n) => n[0]).join("").toUpperCase().slice(0, 2) : "";
|
|
312
|
-
if (src) {
|
|
313
|
-
return `<div id="${id}" class="${classes}" ${combinedStyle ? `style="${combinedStyle}"` : ""}>
|
|
314
|
-
<img src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" class="stx-avatar-img" />
|
|
315
|
-
</div>`;
|
|
316
|
-
}
|
|
317
|
-
return `<div id="${id}" class="${classes}" ${combinedStyle ? `style="${combinedStyle}"` : ""}>
|
|
318
|
-
<span class="stx-avatar-initials">${initials}</span>
|
|
319
|
-
</div>`;
|
|
320
|
-
}
|
|
321
|
-
function createCard(props) {
|
|
322
|
-
const {
|
|
323
|
-
title,
|
|
324
|
-
subtitle,
|
|
325
|
-
content,
|
|
326
|
-
image,
|
|
327
|
-
footer,
|
|
328
|
-
variant = "default",
|
|
329
|
-
id = generateId("card"),
|
|
330
|
-
className,
|
|
331
|
-
style
|
|
332
|
-
} = props;
|
|
333
|
-
const classes = buildClasses("stx-card", `stx-card--${variant}`, className);
|
|
334
|
-
const styleStr = buildStyles(style);
|
|
335
|
-
let html = "";
|
|
336
|
-
if (image) {
|
|
337
|
-
html += `<div class="stx-card-image"><img src="${escapeHtml(image)}" alt="" /></div>`;
|
|
338
|
-
}
|
|
339
|
-
html += '<div class="stx-card-body">';
|
|
340
|
-
if (title) {
|
|
341
|
-
html += `<h3 class="stx-card-title">${escapeHtml(title)}</h3>`;
|
|
342
|
-
}
|
|
343
|
-
if (subtitle) {
|
|
344
|
-
html += `<p class="stx-card-subtitle">${escapeHtml(subtitle)}</p>`;
|
|
345
|
-
}
|
|
346
|
-
if (content) {
|
|
347
|
-
html += `<div class="stx-card-content">${escapeHtml(content)}</div>`;
|
|
348
|
-
}
|
|
349
|
-
html += "</div>";
|
|
350
|
-
if (footer) {
|
|
351
|
-
html += `<div class="stx-card-footer">${escapeHtml(footer)}</div>`;
|
|
352
|
-
}
|
|
353
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
354
|
-
}
|
|
355
|
-
function createTabs(props) {
|
|
356
|
-
const {
|
|
357
|
-
tabs,
|
|
358
|
-
activeTab,
|
|
359
|
-
variant = "default",
|
|
360
|
-
id = generateId("tabs"),
|
|
361
|
-
className,
|
|
362
|
-
style
|
|
363
|
-
} = props;
|
|
364
|
-
const classes = buildClasses("stx-tabs", `stx-tabs--${variant}`, className);
|
|
365
|
-
const styleStr = buildStyles(style);
|
|
366
|
-
const tabsHtml = tabs.map((tab, index) => {
|
|
367
|
-
const isActive = activeTab ? tab.value === activeTab : index === 0;
|
|
368
|
-
const tabClasses = buildClasses("stx-tab", isActive && "stx-tab--active", tab.disabled && "stx-tab--disabled");
|
|
369
|
-
return `<button class="${tabClasses}" data-value="${escapeHtml(tab.value)}" ${tab.disabled ? "disabled" : ""} role="tab" aria-selected="${isActive}">${escapeHtml(tab.label)}</button>`;
|
|
370
|
-
}).join("");
|
|
371
|
-
return `<div id="${id}" class="${classes}" role="tablist" ${styleStr ? `style='${styleStr}'` : ""}>${tabsHtml}</div>`;
|
|
372
|
-
}
|
|
373
|
-
function createDropdown(props) {
|
|
374
|
-
const {
|
|
375
|
-
options,
|
|
376
|
-
value,
|
|
377
|
-
placeholder = "Select...",
|
|
378
|
-
disabled = false,
|
|
379
|
-
id = generateId("dropdown"),
|
|
380
|
-
className,
|
|
381
|
-
style
|
|
382
|
-
} = props;
|
|
383
|
-
const classes = buildClasses("stx-dropdown", disabled && "stx-dropdown--disabled", className);
|
|
384
|
-
const styleStr = buildStyles(style);
|
|
385
|
-
const optionsHtml = options.map((opt) => {
|
|
386
|
-
const selected = opt.value === value ? "selected" : "";
|
|
387
|
-
const disabledAttr = opt.disabled ? "disabled" : "";
|
|
388
|
-
return `<option value="${escapeHtml(opt.value)}" ${selected} ${disabledAttr}>${escapeHtml(opt.label)}</option>`;
|
|
389
|
-
}).join("");
|
|
390
|
-
const placeholderOption = value ? "" : `<option value="" disabled selected>${escapeHtml(placeholder)}</option>`;
|
|
391
|
-
return `<select id="${id}" class="${classes}" ${disabled ? "disabled" : ""} ${styleStr ? `style='${styleStr}'` : ""}>${placeholderOption}${optionsHtml}</select>`;
|
|
392
|
-
}
|
|
393
|
-
function createRating(props) {
|
|
394
|
-
const {
|
|
395
|
-
value = 0,
|
|
396
|
-
max = 5,
|
|
397
|
-
readonly = false,
|
|
398
|
-
size = "medium",
|
|
399
|
-
allowHalf = false,
|
|
400
|
-
id = generateId("rating"),
|
|
401
|
-
className,
|
|
402
|
-
style
|
|
403
|
-
} = props;
|
|
404
|
-
const classes = buildClasses("stx-rating", `stx-rating--${size}`, readonly && "stx-rating--readonly", className);
|
|
405
|
-
const styleStr = buildStyles(style);
|
|
406
|
-
let starsHtml = "";
|
|
407
|
-
for (let i = 1;i <= max; i++) {
|
|
408
|
-
const filled = i <= value;
|
|
409
|
-
const halfFilled = allowHalf && i - 0.5 === value;
|
|
410
|
-
const starClass = filled ? "stx-star--filled" : halfFilled ? "stx-star--half" : "";
|
|
411
|
-
starsHtml += `<span class="stx-star ${starClass}" data-value="${i}">\u2605</span>`;
|
|
412
|
-
}
|
|
413
|
-
return `<div id="${id}" class="${classes}" role="slider" aria-valuenow="${value}" aria-valuemin="0" aria-valuemax="${max}" ${styleStr ? `style='${styleStr}'` : ""}>${starsHtml}</div>`;
|
|
414
|
-
}
|
|
415
|
-
function createRadioButton(props) {
|
|
416
|
-
const {
|
|
417
|
-
value,
|
|
418
|
-
name,
|
|
419
|
-
checked = false,
|
|
420
|
-
label,
|
|
421
|
-
disabled = false,
|
|
422
|
-
id = generateId("radio"),
|
|
423
|
-
className,
|
|
424
|
-
style
|
|
425
|
-
} = props;
|
|
426
|
-
const classes = buildClasses("stx-radio", disabled && "stx-radio--disabled", className);
|
|
427
|
-
const styleStr = buildStyles(style);
|
|
428
|
-
const inputAttrs = [
|
|
429
|
-
'type="radio"',
|
|
430
|
-
`id="${id}"`,
|
|
431
|
-
`name="${escapeHtml(name)}"`,
|
|
432
|
-
`value="${escapeHtml(value)}"`,
|
|
433
|
-
checked && "checked",
|
|
434
|
-
disabled && "disabled"
|
|
435
|
-
].filter(Boolean).join(" ");
|
|
436
|
-
return `
|
|
437
|
-
<label class="${classes}" ${styleStr ? `style="${styleStr}"` : ""}>
|
|
438
|
-
<input ${inputAttrs} />
|
|
13
|
+
`}function FQ(Y){let{text:Q,variant:Z="default",size:X="medium",id:$=L("badge"),className:J,style:U}=Y,q=V("stx-badge",`stx-badge--${Z}`,`stx-badge--${X}`,J),G=D(U);return`<span id="${$}" class="${q}" ${G?`style='${G}'`:""}>${B(Q)}</span>`}function jQ(Y){let{src:Q,alt:Z="",name:X,size:$="medium",shape:J="circle",id:U=L("avatar"),className:q,style:G}=Y,_=typeof $==="number"?"":`stx-avatar--${$}`,K=typeof $==="number"?`width: ${$}px; height: ${$}px;`:"",E=V("stx-avatar",_,`stx-avatar--${J}`,q),R=[K,D(G)].filter(Boolean).join(" "),F=X?X.split(" ").map((j)=>j[0]).join("").toUpperCase().slice(0,2):"";if(Q)return`<div id="${U}" class="${E}" ${R?`style="${R}"`:""}>
|
|
14
|
+
<img src="${B(Q)}" alt="${B(Z)}" class="stx-avatar-img" />
|
|
15
|
+
</div>`;return`<div id="${U}" class="${E}" ${R?`style="${R}"`:""}>
|
|
16
|
+
<span class="stx-avatar-initials">${F}</span>
|
|
17
|
+
</div>`}function DQ(Y){let{title:Q,subtitle:Z,content:X,image:$,footer:J,variant:U="default",id:q=L("card"),className:G,style:_}=Y,K=V("stx-card",`stx-card--${U}`,G),E=D(_),R="";if($)R+=`<div class="stx-card-image"><img src="${B($)}" alt="" /></div>`;if(R+='<div class="stx-card-body">',Q)R+=`<h3 class="stx-card-title">${B(Q)}</h3>`;if(Z)R+=`<p class="stx-card-subtitle">${B(Z)}</p>`;if(X)R+=`<div class="stx-card-content">${B(X)}</div>`;if(R+="</div>",J)R+=`<div class="stx-card-footer">${B(J)}</div>`;return`<div id="${q}" class="${K}" ${E?`style='${E}'`:""}>${R}</div>`}function VQ(Y){let{tabs:Q,activeTab:Z,variant:X="default",id:$=L("tabs"),className:J,style:U}=Y,q=V("stx-tabs",`stx-tabs--${X}`,J),G=D(U),_=Q.map((K,E)=>{let R=Z?K.value===Z:E===0;return`<button class="${V("stx-tab",R&&"stx-tab--active",K.disabled&&"stx-tab--disabled")}" data-value="${B(K.value)}" ${K.disabled?"disabled":""} role="tab" aria-selected="${R}">${B(K.label)}</button>`}).join("");return`<div id="${$}" class="${q}" role="tablist" ${G?`style='${G}'`:""}>${_}</div>`}function LQ(Y){let{options:Q,value:Z,placeholder:X="Select...",disabled:$=!1,id:J=L("dropdown"),className:U,style:q}=Y,G=V("stx-dropdown",$&&"stx-dropdown--disabled",U),_=D(q),K=Q.map((R)=>{let F=R.value===Z?"selected":"",j=R.disabled?"disabled":"";return`<option value="${B(R.value)}" ${F} ${j}>${B(R.label)}</option>`}).join(""),E=Z?"":`<option value="" disabled selected>${B(X)}</option>`;return`<select id="${J}" class="${G}" ${$?"disabled":""} ${_?`style='${_}'`:""}>${E}${K}</select>`}function OQ(Y){let{value:Q=0,max:Z=5,readonly:X=!1,size:$="medium",allowHalf:J=!1,id:U=L("rating"),className:q,style:G}=Y,_=V("stx-rating",`stx-rating--${$}`,X&&"stx-rating--readonly",q),K=D(G),E="";for(let R=1;R<=Z;R++){let F=R<=Q,j=J&&R-0.5===Q;E+=`<span class="stx-star ${F?"stx-star--filled":j?"stx-star--half":""}" data-value="${R}">\u2605</span>`}return`<div id="${U}" class="${_}" role="slider" aria-valuenow="${Q}" aria-valuemin="0" aria-valuemax="${Z}" ${K?`style='${K}'`:""}>${E}</div>`}function zQ(Y){let{value:Q,name:Z,checked:X=!1,label:$,disabled:J=!1,id:U=L("radio"),className:q,style:G}=Y,_=V("stx-radio",J&&"stx-radio--disabled",q),K=D(G),E=['type="radio"',`id="${U}"`,`name="${B(Z)}"`,`value="${B(Q)}"`,X&&"checked",J&&"disabled"].filter(Boolean).join(" ");return`
|
|
18
|
+
<label class="${_}" ${K?`style="${K}"`:""}>
|
|
19
|
+
<input ${E} />
|
|
439
20
|
<span class="stx-radio-circle"></span>
|
|
440
|
-
${
|
|
21
|
+
${$?`<span class="stx-radio-label">${B($)}</span>`:""}
|
|
441
22
|
</label>
|
|
442
|
-
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
<input type="color" id="${id}" value="${escapeHtml(value)}" ${disabled ? "disabled" : ""} />
|
|
462
|
-
<span class="stx-color-picker-value">${escapeHtml(value)}</span>
|
|
463
|
-
</div>`;
|
|
464
|
-
if (presetColors.length > 0) {
|
|
465
|
-
html += '<div class="stx-color-picker-presets">';
|
|
466
|
-
for (const color of presetColors) {
|
|
467
|
-
html += `<button class="stx-color-preset" style="background: ${escapeHtml(color)}" data-color="${escapeHtml(color)}" ${disabled ? "disabled" : ""}></button>`;
|
|
468
|
-
}
|
|
469
|
-
html += "</div>";
|
|
470
|
-
}
|
|
471
|
-
return `<div class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
472
|
-
}
|
|
473
|
-
function createDatePicker(props) {
|
|
474
|
-
const {
|
|
475
|
-
value,
|
|
476
|
-
min,
|
|
477
|
-
max,
|
|
478
|
-
disabled = false,
|
|
479
|
-
label,
|
|
480
|
-
placeholder = "Select date",
|
|
481
|
-
showClear = true,
|
|
482
|
-
id = generateId("date"),
|
|
483
|
-
className,
|
|
484
|
-
style
|
|
485
|
-
} = props;
|
|
486
|
-
const classes = buildClasses("stx-date-picker", disabled && "stx-date-picker--disabled", className);
|
|
487
|
-
const styleStr = buildStyles(style);
|
|
488
|
-
const dateValue = value instanceof Date ? value.toISOString().split("T")[0] : value || "";
|
|
489
|
-
const minValue = min instanceof Date ? min.toISOString().split("T")[0] : min;
|
|
490
|
-
const maxValue = max instanceof Date ? max.toISOString().split("T")[0] : max;
|
|
491
|
-
const inputAttrs = [
|
|
492
|
-
'type="date"',
|
|
493
|
-
`id="${id}"`,
|
|
494
|
-
dateValue && `value="${dateValue}"`,
|
|
495
|
-
minValue && `min="${minValue}"`,
|
|
496
|
-
maxValue && `max="${maxValue}"`,
|
|
497
|
-
disabled && "disabled",
|
|
498
|
-
`placeholder="${escapeHtml(placeholder)}"`
|
|
499
|
-
].filter(Boolean).join(" ");
|
|
500
|
-
let html = "";
|
|
501
|
-
if (label) {
|
|
502
|
-
html += `<label class="stx-date-picker-label" for="${id}">${escapeHtml(label)}</label>`;
|
|
503
|
-
}
|
|
504
|
-
html += `<div class="stx-date-picker-input">
|
|
505
|
-
<input ${inputAttrs} />
|
|
506
|
-
${showClear && dateValue ? '<button class="stx-date-picker-clear" type="button">×</button>' : ""}
|
|
507
|
-
</div>`;
|
|
508
|
-
return `<div class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
509
|
-
}
|
|
510
|
-
function createTimePicker(props) {
|
|
511
|
-
const {
|
|
512
|
-
value = "",
|
|
513
|
-
disabled = false,
|
|
514
|
-
label,
|
|
515
|
-
step = 60,
|
|
516
|
-
min,
|
|
517
|
-
max,
|
|
518
|
-
id = generateId("time"),
|
|
519
|
-
className,
|
|
520
|
-
style
|
|
521
|
-
} = props;
|
|
522
|
-
const classes = buildClasses("stx-time-picker", disabled && "stx-time-picker--disabled", className);
|
|
523
|
-
const styleStr = buildStyles(style);
|
|
524
|
-
const inputAttrs = [
|
|
525
|
-
'type="time"',
|
|
526
|
-
`id="${id}"`,
|
|
527
|
-
value && `value="${escapeHtml(value)}"`,
|
|
528
|
-
`step="${step}"`,
|
|
529
|
-
min && `min="${escapeHtml(min)}"`,
|
|
530
|
-
max && `max="${escapeHtml(max)}"`,
|
|
531
|
-
disabled && "disabled"
|
|
532
|
-
].filter(Boolean).join(" ");
|
|
533
|
-
let html = "";
|
|
534
|
-
if (label) {
|
|
535
|
-
html += `<label class="stx-time-picker-label" for="${id}">${escapeHtml(label)}</label>`;
|
|
536
|
-
}
|
|
537
|
-
html += `<input ${inputAttrs} class="stx-time-picker-input" />`;
|
|
538
|
-
return `<div class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
539
|
-
}
|
|
540
|
-
function createAutocomplete(props) {
|
|
541
|
-
const {
|
|
542
|
-
options,
|
|
543
|
-
value = "",
|
|
544
|
-
placeholder = "Search...",
|
|
545
|
-
disabled = false,
|
|
546
|
-
label,
|
|
547
|
-
loading = false,
|
|
548
|
-
id = generateId("autocomplete"),
|
|
549
|
-
className,
|
|
550
|
-
style
|
|
551
|
-
} = props;
|
|
552
|
-
const classes = buildClasses("stx-autocomplete", disabled && "stx-autocomplete--disabled", className);
|
|
553
|
-
const styleStr = buildStyles(style);
|
|
554
|
-
const selectedOption = options.find((opt) => opt.value === value);
|
|
555
|
-
const displayValue = selectedOption ? selectedOption.label : value;
|
|
556
|
-
let html = "";
|
|
557
|
-
if (label) {
|
|
558
|
-
html += `<label class="stx-autocomplete-label" for="${id}">${escapeHtml(label)}</label>`;
|
|
559
|
-
}
|
|
560
|
-
html += `<div class="stx-autocomplete-input-wrapper">
|
|
561
|
-
<input type="text" id="${id}" value="${escapeHtml(displayValue)}" placeholder="${escapeHtml(placeholder)}" ${disabled ? "disabled" : ""} autocomplete="off" class="stx-autocomplete-input" />
|
|
562
|
-
${loading ? '<span class="stx-autocomplete-spinner"></span>' : ""}
|
|
563
|
-
</div>`;
|
|
564
|
-
html += '<ul class="stx-autocomplete-list">';
|
|
565
|
-
for (const opt of options) {
|
|
566
|
-
html += `<li class="stx-autocomplete-item ${opt.value === value ? "stx-autocomplete-item--selected" : ""}" data-value="${escapeHtml(opt.value)}">${escapeHtml(opt.label)}</li>`;
|
|
567
|
-
}
|
|
568
|
-
html += "</ul>";
|
|
569
|
-
return `<div class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
570
|
-
}
|
|
571
|
-
function createLabel(props) {
|
|
572
|
-
const {
|
|
573
|
-
text,
|
|
574
|
-
htmlFor,
|
|
575
|
-
required = false,
|
|
576
|
-
size = "medium",
|
|
577
|
-
id = generateId("label"),
|
|
578
|
-
className,
|
|
579
|
-
style
|
|
580
|
-
} = props;
|
|
581
|
-
const classes = buildClasses("stx-label", `stx-label--${size}`, className);
|
|
582
|
-
const styleStr = buildStyles(style);
|
|
583
|
-
return `<label id="${id}" class="${classes}" ${htmlFor ? `for='${escapeHtml(htmlFor)}'` : ""} ${styleStr ? `style='${styleStr}'` : ""}>${escapeHtml(text)}${required ? '<span class="stx-label-required">*</span>' : ""}</label>`;
|
|
584
|
-
}
|
|
585
|
-
function createImageView(props) {
|
|
586
|
-
const {
|
|
587
|
-
src,
|
|
588
|
-
alt = "",
|
|
589
|
-
width,
|
|
590
|
-
height,
|
|
591
|
-
objectFit = "cover",
|
|
592
|
-
fallback,
|
|
593
|
-
loading = "lazy",
|
|
594
|
-
id = generateId("image"),
|
|
595
|
-
className,
|
|
596
|
-
style
|
|
597
|
-
} = props;
|
|
598
|
-
const classes = buildClasses("stx-image", className);
|
|
599
|
-
const imageStyles = { objectFit };
|
|
600
|
-
if (width)
|
|
601
|
-
imageStyles.width = typeof width === "number" ? `${width}px` : width;
|
|
602
|
-
if (height)
|
|
603
|
-
imageStyles.height = typeof height === "number" ? `${height}px` : height;
|
|
604
|
-
const combinedStyle = [buildStyles(imageStyles), buildStyles(style)].filter(Boolean).join("; ");
|
|
605
|
-
const fallbackAttr = fallback ? `onerror="this.src='${escapeHtml(fallback)}'"` : "";
|
|
606
|
-
return `<img id="${id}" class="${classes}" src="${escapeHtml(src)}" alt="${escapeHtml(alt)}" loading="${loading}" ${combinedStyle ? `style='${combinedStyle}'` : ""} ${fallbackAttr} />`;
|
|
607
|
-
}
|
|
608
|
-
function createChip(props) {
|
|
609
|
-
const {
|
|
610
|
-
text,
|
|
611
|
-
variant = "default",
|
|
612
|
-
size = "medium",
|
|
613
|
-
removable = false,
|
|
614
|
-
icon,
|
|
615
|
-
id = generateId("chip"),
|
|
616
|
-
className,
|
|
617
|
-
style
|
|
618
|
-
} = props;
|
|
619
|
-
const classes = buildClasses("stx-chip", `stx-chip--${variant}`, `stx-chip--${size}`, className);
|
|
620
|
-
const styleStr = buildStyles(style);
|
|
621
|
-
let html = "";
|
|
622
|
-
if (icon) {
|
|
623
|
-
html += `<span class="stx-chip-icon">${icon}</span>`;
|
|
624
|
-
}
|
|
625
|
-
html += `<span class="stx-chip-text">${escapeHtml(text)}</span>`;
|
|
626
|
-
if (removable) {
|
|
627
|
-
html += '<button class="stx-chip-remove" type="button">×</button>';
|
|
628
|
-
}
|
|
629
|
-
return `<span id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</span>`;
|
|
630
|
-
}
|
|
631
|
-
function createTooltip(props) {
|
|
632
|
-
const {
|
|
633
|
-
text,
|
|
634
|
-
position = "top",
|
|
635
|
-
delay: delay2 = 200,
|
|
636
|
-
children,
|
|
637
|
-
id = generateId("tooltip"),
|
|
638
|
-
className,
|
|
639
|
-
style
|
|
640
|
-
} = props;
|
|
641
|
-
const classes = buildClasses("stx-tooltip-wrapper", className);
|
|
642
|
-
const styleStr = buildStyles(style);
|
|
643
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style="${styleStr}"` : ""} data-tooltip="${escapeHtml(text)}" data-position="${position}" data-delay="${delay2}">
|
|
644
|
-
${children}
|
|
645
|
-
<span class="stx-tooltip stx-tooltip--${position}">${escapeHtml(text)}</span>
|
|
646
|
-
</div>`;
|
|
647
|
-
}
|
|
648
|
-
function createScrollView(props) {
|
|
649
|
-
const {
|
|
650
|
-
direction = "vertical",
|
|
651
|
-
showScrollbar = true,
|
|
652
|
-
smooth = true,
|
|
653
|
-
height,
|
|
654
|
-
width,
|
|
655
|
-
children,
|
|
656
|
-
id = generateId("scroll"),
|
|
657
|
-
className,
|
|
658
|
-
style
|
|
659
|
-
} = props;
|
|
660
|
-
const classes = buildClasses("stx-scroll-view", `stx-scroll-view--${direction}`, !showScrollbar && "stx-scroll-view--hide-scrollbar", smooth && "stx-scroll-view--smooth", className);
|
|
661
|
-
const scrollStyles = {};
|
|
662
|
-
if (height)
|
|
663
|
-
scrollStyles.height = typeof height === "number" ? `${height}px` : height;
|
|
664
|
-
if (width)
|
|
665
|
-
scrollStyles.width = typeof width === "number" ? `${width}px` : width;
|
|
666
|
-
const combinedStyle = [buildStyles(scrollStyles), buildStyles(style)].filter(Boolean).join("; ");
|
|
667
|
-
return `<div id="${id}" class="${classes}" ${combinedStyle ? `style='${combinedStyle}'` : ""}>${children}</div>`;
|
|
668
|
-
}
|
|
669
|
-
function createSplitView(props) {
|
|
670
|
-
const {
|
|
671
|
-
direction = "horizontal",
|
|
672
|
-
sizes = [50, 50],
|
|
673
|
-
resizable = true,
|
|
674
|
-
children,
|
|
675
|
-
id = generateId("split"),
|
|
676
|
-
className,
|
|
677
|
-
style
|
|
678
|
-
} = props;
|
|
679
|
-
const classes = buildClasses("stx-split-view", `stx-split-view--${direction}`, resizable && "stx-split-view--resizable", className);
|
|
680
|
-
const styleStr = buildStyles(style);
|
|
681
|
-
const sizeUnit = direction === "horizontal" ? "width" : "height";
|
|
682
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style="${styleStr}"` : ""}>
|
|
683
|
-
<div class="stx-split-pane" style="${sizeUnit}: ${sizes[0]}%">${children[0]}</div>
|
|
684
|
-
${resizable ? '<div class="stx-split-divider"></div>' : ""}
|
|
685
|
-
<div class="stx-split-pane" style="${sizeUnit}: ${sizes[1]}%">${children[1]}</div>
|
|
686
|
-
</div>`;
|
|
687
|
-
}
|
|
688
|
-
function createAccordion(props) {
|
|
689
|
-
const {
|
|
690
|
-
items,
|
|
691
|
-
multiple = false,
|
|
692
|
-
defaultOpen = [],
|
|
693
|
-
id = generateId("accordion"),
|
|
694
|
-
className,
|
|
695
|
-
style
|
|
696
|
-
} = props;
|
|
697
|
-
const classes = buildClasses("stx-accordion", className);
|
|
698
|
-
const styleStr = buildStyles(style);
|
|
699
|
-
let html = "";
|
|
700
|
-
items.forEach((item, index) => {
|
|
701
|
-
const isOpen = defaultOpen.includes(index);
|
|
702
|
-
const itemClasses = buildClasses("stx-accordion-item", isOpen && "stx-accordion-item--open", item.disabled && "stx-accordion-item--disabled");
|
|
703
|
-
html += `<div class="${itemClasses}" data-index="${index}">
|
|
704
|
-
<button class="stx-accordion-header" ${item.disabled ? "disabled" : ""} aria-expanded="${isOpen}" data-multiple="${multiple}">
|
|
705
|
-
<span class="stx-accordion-title">${escapeHtml(item.title)}</span>
|
|
23
|
+
`}function MQ(Y){let{value:Q="#3498db",disabled:Z=!1,label:X,presetColors:$=["#e74c3c","#f39c12","#27ae60","#3498db","#9b59b6","#1abc9c","#34495e","#000000"],id:J=L("color"),className:U,style:q}=Y,G=V("stx-color-picker",Z&&"stx-color-picker--disabled",U),_=D(q),K="";if(X)K+=`<label class="stx-color-picker-label" for="${J}">${B(X)}</label>`;if(K+=`<div class="stx-color-picker-input">
|
|
24
|
+
<input type="color" id="${J}" value="${B(Q)}" ${Z?"disabled":""} />
|
|
25
|
+
<span class="stx-color-picker-value">${B(Q)}</span>
|
|
26
|
+
</div>`,$.length>0){K+='<div class="stx-color-picker-presets">';for(let E of $)K+=`<button class="stx-color-preset" style="background: ${B(E)}" data-color="${B(E)}" ${Z?"disabled":""}></button>`;K+="</div>"}return`<div class="${G}" ${_?`style='${_}'`:""}>${K}</div>`}function TQ(Y){let{value:Q,min:Z,max:X,disabled:$=!1,label:J,placeholder:U="Select date",showClear:q=!0,id:G=L("date"),className:_,style:K}=Y,E=V("stx-date-picker",$&&"stx-date-picker--disabled",_),R=D(K),F=Q instanceof Date?Q.toISOString().split("T")[0]:Q||"",j=Z instanceof Date?Z.toISOString().split("T")[0]:Z,O=X instanceof Date?X.toISOString().split("T")[0]:X,z=['type="date"',`id="${G}"`,F&&`value="${F}"`,j&&`min="${j}"`,O&&`max="${O}"`,$&&"disabled",`placeholder="${B(U)}"`].filter(Boolean).join(" "),M="";if(J)M+=`<label class="stx-date-picker-label" for="${G}">${B(J)}</label>`;return M+=`<div class="stx-date-picker-input">
|
|
27
|
+
<input ${z} />
|
|
28
|
+
${q&&F?'<button class="stx-date-picker-clear" type="button">×</button>':""}
|
|
29
|
+
</div>`,`<div class="${E}" ${R?`style='${R}'`:""}>${M}</div>`}function WQ(Y){let{value:Q="",disabled:Z=!1,label:X,step:$=60,min:J,max:U,id:q=L("time"),className:G,style:_}=Y,K=V("stx-time-picker",Z&&"stx-time-picker--disabled",G),E=D(_),R=['type="time"',`id="${q}"`,Q&&`value="${B(Q)}"`,`step="${$}"`,J&&`min="${B(J)}"`,U&&`max="${B(U)}"`,Z&&"disabled"].filter(Boolean).join(" "),F="";if(X)F+=`<label class="stx-time-picker-label" for="${q}">${B(X)}</label>`;return F+=`<input ${R} class="stx-time-picker-input" />`,`<div class="${K}" ${E?`style='${E}'`:""}>${F}</div>`}function PQ(Y){let{options:Q,value:Z="",placeholder:X="Search...",disabled:$=!1,label:J,loading:U=!1,id:q=L("autocomplete"),className:G,style:_}=Y,K=V("stx-autocomplete",$&&"stx-autocomplete--disabled",G),E=D(_),R=Q.find((O)=>O.value===Z),F=R?R.label:Z,j="";if(J)j+=`<label class="stx-autocomplete-label" for="${q}">${B(J)}</label>`;j+=`<div class="stx-autocomplete-input-wrapper">
|
|
30
|
+
<input type="text" id="${q}" value="${B(F)}" placeholder="${B(X)}" ${$?"disabled":""} autocomplete="off" class="stx-autocomplete-input" />
|
|
31
|
+
${U?'<span class="stx-autocomplete-spinner"></span>':""}
|
|
32
|
+
</div>`,j+='<ul class="stx-autocomplete-list">';for(let O of Q)j+=`<li class="stx-autocomplete-item ${O.value===Z?"stx-autocomplete-item--selected":""}" data-value="${B(O.value)}">${B(O.label)}</li>`;return j+="</ul>",`<div class="${K}" ${E?`style='${E}'`:""}>${j}</div>`}function AQ(Y){let{text:Q,htmlFor:Z,required:X=!1,size:$="medium",id:J=L("label"),className:U,style:q}=Y,G=V("stx-label",`stx-label--${$}`,U),_=D(q);return`<label id="${J}" class="${G}" ${Z?`for='${B(Z)}'`:""} ${_?`style='${_}'`:""}>${B(Q)}${X?'<span class="stx-label-required">*</span>':""}</label>`}function NQ(Y){let{src:Q,alt:Z="",width:X,height:$,objectFit:J="cover",fallback:U,loading:q="lazy",id:G=L("image"),className:_,style:K}=Y,E=V("stx-image",_),R={objectFit:J};if(X)R.width=typeof X==="number"?`${X}px`:X;if($)R.height=typeof $==="number"?`${$}px`:$;let F=[D(R),D(K)].filter(Boolean).join("; "),j=U?`onerror="this.src='${B(U)}'"`:"";return`<img id="${G}" class="${E}" src="${B(Q)}" alt="${B(Z)}" loading="${q}" ${F?`style='${F}'`:""} ${j} />`}function kQ(Y){let{text:Q,variant:Z="default",size:X="medium",removable:$=!1,icon:J,id:U=L("chip"),className:q,style:G}=Y,_=V("stx-chip",`stx-chip--${Z}`,`stx-chip--${X}`,q),K=D(G),E="";if(J)E+=`<span class="stx-chip-icon">${J}</span>`;if(E+=`<span class="stx-chip-text">${B(Q)}</span>`,$)E+='<button class="stx-chip-remove" type="button">×</button>';return`<span id="${U}" class="${_}" ${K?`style='${K}'`:""}>${E}</span>`}function xQ(Y){let{text:Q,position:Z="top",delay:X=200,children:$,id:J=L("tooltip"),className:U,style:q}=Y,G=V("stx-tooltip-wrapper",U),_=D(q);return`<div id="${J}" class="${G}" ${_?`style="${_}"`:""} data-tooltip="${B(Q)}" data-position="${Z}" data-delay="${X}">
|
|
33
|
+
${$}
|
|
34
|
+
<span class="stx-tooltip stx-tooltip--${Z}">${B(Q)}</span>
|
|
35
|
+
</div>`}function CQ(Y){let{direction:Q="vertical",showScrollbar:Z=!0,smooth:X=!0,height:$,width:J,children:U,id:q=L("scroll"),className:G,style:_}=Y,K=V("stx-scroll-view",`stx-scroll-view--${Q}`,!Z&&"stx-scroll-view--hide-scrollbar",X&&"stx-scroll-view--smooth",G),E={};if($)E.height=typeof $==="number"?`${$}px`:$;if(J)E.width=typeof J==="number"?`${J}px`:J;let R=[D(E),D(_)].filter(Boolean).join("; ");return`<div id="${q}" class="${K}" ${R?`style='${R}'`:""}>${U}</div>`}function IQ(Y){let{direction:Q="horizontal",sizes:Z=[50,50],resizable:X=!0,children:$,id:J=L("split"),className:U,style:q}=Y,G=V("stx-split-view",`stx-split-view--${Q}`,X&&"stx-split-view--resizable",U),_=D(q),K=Q==="horizontal"?"width":"height";return`<div id="${J}" class="${G}" ${_?`style="${_}"`:""}>
|
|
36
|
+
<div class="stx-split-pane" style="${K}: ${Z[0]}%">${$[0]}</div>
|
|
37
|
+
${X?'<div class="stx-split-divider"></div>':""}
|
|
38
|
+
<div class="stx-split-pane" style="${K}: ${Z[1]}%">${$[1]}</div>
|
|
39
|
+
</div>`}function HQ(Y){let{items:Q,multiple:Z=!1,defaultOpen:X=[],id:$=L("accordion"),className:J,style:U}=Y,q=V("stx-accordion",J),G=D(U),_="";return Q.forEach((K,E)=>{let R=X.includes(E),F=V("stx-accordion-item",R&&"stx-accordion-item--open",K.disabled&&"stx-accordion-item--disabled");_+=`<div class="${F}" data-index="${E}">
|
|
40
|
+
<button class="stx-accordion-header" ${K.disabled?"disabled":""} aria-expanded="${R}" data-multiple="${Z}">
|
|
41
|
+
<span class="stx-accordion-title">${B(K.title)}</span>
|
|
706
42
|
<span class="stx-accordion-icon">\u25BC</span>
|
|
707
43
|
</button>
|
|
708
|
-
<div class="stx-accordion-content" ${
|
|
709
|
-
${
|
|
44
|
+
<div class="stx-accordion-content" ${R?"":"hidden"}>
|
|
45
|
+
${B(K.content)}
|
|
710
46
|
</div>
|
|
711
|
-
</div
|
|
712
|
-
});
|
|
713
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
714
|
-
}
|
|
715
|
-
function createStepper(props) {
|
|
716
|
-
const {
|
|
717
|
-
steps,
|
|
718
|
-
currentStep,
|
|
719
|
-
orientation = "horizontal",
|
|
720
|
-
id = generateId("stepper"),
|
|
721
|
-
className,
|
|
722
|
-
style
|
|
723
|
-
} = props;
|
|
724
|
-
const classes = buildClasses("stx-stepper", `stx-stepper--${orientation}`, className);
|
|
725
|
-
const styleStr = buildStyles(style);
|
|
726
|
-
let html = "";
|
|
727
|
-
steps.forEach((step, index) => {
|
|
728
|
-
const stepClasses = buildClasses("stx-step", index < currentStep && "stx-step--completed", index === currentStep && "stx-step--active");
|
|
729
|
-
html += `<div class="${stepClasses}" data-step="${index}">
|
|
47
|
+
</div>`}),`<div id="${$}" class="${q}" ${G?`style='${G}'`:""}>${_}</div>`}function vQ(Y){let{steps:Q,currentStep:Z,orientation:X="horizontal",id:$=L("stepper"),className:J,style:U}=Y,q=V("stx-stepper",`stx-stepper--${X}`,J),G=D(U),_="";return Q.forEach((K,E)=>{let R=V("stx-step",E<Z&&"stx-step--completed",E===Z&&"stx-step--active");if(_+=`<div class="${R}" data-step="${E}">
|
|
730
48
|
<div class="stx-step-indicator">
|
|
731
|
-
${
|
|
49
|
+
${E<Z?"\u2713":E+1}
|
|
732
50
|
</div>
|
|
733
51
|
<div class="stx-step-content">
|
|
734
|
-
<div class="stx-step-label">${
|
|
735
|
-
${
|
|
52
|
+
<div class="stx-step-label">${B(K.label)}</div>
|
|
53
|
+
${K.description?`<div class="stx-step-description">${B(K.description)}</div>`:""}
|
|
736
54
|
</div>
|
|
737
|
-
</div>`;
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
}
|
|
741
|
-
});
|
|
742
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
743
|
-
}
|
|
744
|
-
function createModalComponent(props) {
|
|
745
|
-
const {
|
|
746
|
-
open = false,
|
|
747
|
-
title,
|
|
748
|
-
size = "medium",
|
|
749
|
-
closable = true,
|
|
750
|
-
children,
|
|
751
|
-
footer,
|
|
752
|
-
id = generateId("modal"),
|
|
753
|
-
className,
|
|
754
|
-
style
|
|
755
|
-
} = props;
|
|
756
|
-
const classes = buildClasses("stx-modal-component", `stx-modal-component--${size}`, className);
|
|
757
|
-
const styleStr = buildStyles(style);
|
|
758
|
-
if (!open) {
|
|
759
|
-
return `<div id="${id}" class="${classes} stx-modal-component--hidden" ${styleStr ? `style='${styleStr}'` : ""}></div>`;
|
|
760
|
-
}
|
|
761
|
-
let html = '<div class="stx-modal-component-overlay">';
|
|
762
|
-
html += '<div class="stx-modal-component-dialog">';
|
|
763
|
-
if (title || closable) {
|
|
764
|
-
html += '<div class="stx-modal-component-header">';
|
|
765
|
-
if (title) {
|
|
766
|
-
html += `<h3 class="stx-modal-component-title">${escapeHtml(title)}</h3>`;
|
|
767
|
-
}
|
|
768
|
-
if (closable) {
|
|
769
|
-
html += '<button class="stx-modal-component-close">×</button>';
|
|
770
|
-
}
|
|
771
|
-
html += "</div>";
|
|
772
|
-
}
|
|
773
|
-
html += `<div class="stx-modal-component-body">${children}</div>`;
|
|
774
|
-
if (footer) {
|
|
775
|
-
html += `<div class="stx-modal-component-footer">${footer}</div>`;
|
|
776
|
-
}
|
|
777
|
-
html += "</div></div>";
|
|
778
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
779
|
-
}
|
|
780
|
-
function createListView(props) {
|
|
781
|
-
const {
|
|
782
|
-
items,
|
|
783
|
-
selectable = false,
|
|
784
|
-
multiSelect = false,
|
|
785
|
-
emptyMessage = "No items",
|
|
786
|
-
id = generateId("list"),
|
|
787
|
-
className,
|
|
788
|
-
style
|
|
789
|
-
} = props;
|
|
790
|
-
const classes = buildClasses("stx-list-view", selectable && "stx-list-view--selectable", multiSelect && "stx-list-view--multi", className);
|
|
791
|
-
const styleStr = buildStyles(style);
|
|
792
|
-
if (items.length === 0) {
|
|
793
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style="${styleStr}"` : ""}>
|
|
794
|
-
<div class="stx-list-view-empty">${escapeHtml(emptyMessage)}</div>
|
|
795
|
-
</div>`;
|
|
796
|
-
}
|
|
797
|
-
let html = '<ul class="stx-list-view-items">';
|
|
798
|
-
for (const item of items) {
|
|
799
|
-
const itemClasses = buildClasses("stx-list-view-item", item.selected && "stx-list-view-item--selected");
|
|
800
|
-
html += `<li class="${itemClasses}" data-id="${escapeHtml(item.id)}" ${selectable ? 'tabindex="0"' : ""}>${item.content}</li>`;
|
|
801
|
-
}
|
|
802
|
-
html += "</ul>";
|
|
803
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
804
|
-
}
|
|
805
|
-
function createTable(props) {
|
|
806
|
-
const {
|
|
807
|
-
columns,
|
|
808
|
-
data,
|
|
809
|
-
striped = false,
|
|
810
|
-
bordered = false,
|
|
811
|
-
hoverable = true,
|
|
812
|
-
sortBy,
|
|
813
|
-
sortOrder,
|
|
814
|
-
id = generateId("table"),
|
|
815
|
-
className,
|
|
816
|
-
style
|
|
817
|
-
} = props;
|
|
818
|
-
const classes = buildClasses("stx-table", striped && "stx-table--striped", bordered && "stx-table--bordered", hoverable && "stx-table--hoverable", className);
|
|
819
|
-
const styleStr = buildStyles(style);
|
|
820
|
-
let html = "<table>";
|
|
821
|
-
html += "<thead><tr>";
|
|
822
|
-
for (const col of columns) {
|
|
823
|
-
const isSorted = col.key === sortBy;
|
|
824
|
-
const sortClass = isSorted ? `stx-table-sorted stx-table-sorted--${sortOrder}` : "";
|
|
825
|
-
const sortable = col.sortable ? 'data-sortable="true"' : "";
|
|
826
|
-
const widthStyle = col.width ? `style="width: ${col.width}"` : "";
|
|
827
|
-
html += `<th class="${sortClass}" ${sortable} ${widthStyle} data-key="${escapeHtml(col.key)}">${escapeHtml(col.label)}${col.sortable ? '<span class="stx-table-sort-icon"></span>' : ""}</th>`;
|
|
828
|
-
}
|
|
829
|
-
html += "</tr></thead>";
|
|
830
|
-
html += "<tbody>";
|
|
831
|
-
for (const row of data) {
|
|
832
|
-
html += "<tr>";
|
|
833
|
-
for (const col of columns) {
|
|
834
|
-
const cellValue = row[col.key];
|
|
835
|
-
html += `<td>${cellValue != null ? escapeHtml(String(cellValue)) : ""}</td>`;
|
|
836
|
-
}
|
|
837
|
-
html += "</tr>";
|
|
838
|
-
}
|
|
839
|
-
html += "</tbody></table>";
|
|
840
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
841
|
-
}
|
|
842
|
-
function renderTreeNode(node, expandedKeys, selectedKeys, checkable) {
|
|
843
|
-
const isExpanded = expandedKeys.includes(node.key);
|
|
844
|
-
const isSelected = selectedKeys.includes(node.key);
|
|
845
|
-
const hasChildren = node.children && node.children.length > 0;
|
|
846
|
-
const nodeClasses = buildClasses("stx-tree-node", isSelected && "stx-tree-node--selected", node.disabled && "stx-tree-node--disabled");
|
|
847
|
-
let html = `<div class="${nodeClasses}" data-key="${escapeHtml(node.key)}">`;
|
|
848
|
-
html += '<div class="stx-tree-node-content">';
|
|
849
|
-
if (hasChildren) {
|
|
850
|
-
html += `<span class="stx-tree-toggle ${isExpanded ? "stx-tree-toggle--expanded" : ""}">\u25B6</span>`;
|
|
851
|
-
} else {
|
|
852
|
-
html += '<span class="stx-tree-toggle-placeholder"></span>';
|
|
853
|
-
}
|
|
854
|
-
if (checkable) {
|
|
855
|
-
html += `<input type="checkbox" class="stx-tree-checkbox" ${isSelected ? "checked" : ""} ${node.disabled ? "disabled" : ""} />`;
|
|
856
|
-
}
|
|
857
|
-
if (node.icon) {
|
|
858
|
-
html += `<span class="stx-tree-icon">${node.icon}</span>`;
|
|
859
|
-
}
|
|
860
|
-
html += `<span class="stx-tree-label">${escapeHtml(node.label)}</span>`;
|
|
861
|
-
html += "</div>";
|
|
862
|
-
if (hasChildren && isExpanded) {
|
|
863
|
-
html += '<div class="stx-tree-children">';
|
|
864
|
-
for (const child of node.children) {
|
|
865
|
-
html += renderTreeNode(child, expandedKeys, selectedKeys, checkable);
|
|
866
|
-
}
|
|
867
|
-
html += "</div>";
|
|
868
|
-
}
|
|
869
|
-
html += "</div>";
|
|
870
|
-
return html;
|
|
871
|
-
}
|
|
872
|
-
function createTreeView(props) {
|
|
873
|
-
const {
|
|
874
|
-
nodes,
|
|
875
|
-
expandedKeys = [],
|
|
876
|
-
selectedKeys = [],
|
|
877
|
-
checkable = false,
|
|
878
|
-
id = generateId("tree"),
|
|
879
|
-
className,
|
|
880
|
-
style
|
|
881
|
-
} = props;
|
|
882
|
-
const classes = buildClasses("stx-tree-view", checkable && "stx-tree-view--checkable", className);
|
|
883
|
-
const styleStr = buildStyles(style);
|
|
884
|
-
let html = "";
|
|
885
|
-
for (const node of nodes) {
|
|
886
|
-
html += renderTreeNode(node, expandedKeys, selectedKeys, checkable);
|
|
887
|
-
}
|
|
888
|
-
return `<div id="${id}" class="${classes}" role="tree" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
889
|
-
}
|
|
890
|
-
function createDataGrid(props) {
|
|
891
|
-
const {
|
|
892
|
-
columns,
|
|
893
|
-
data,
|
|
894
|
-
pagination,
|
|
895
|
-
selectable = false,
|
|
896
|
-
id = generateId("datagrid"),
|
|
897
|
-
className,
|
|
898
|
-
style
|
|
899
|
-
} = props;
|
|
900
|
-
const classes = buildClasses("stx-data-grid", selectable && "stx-data-grid--selectable", className);
|
|
901
|
-
const styleStr = buildStyles(style);
|
|
902
|
-
let html = '<div class="stx-data-grid-table-wrapper">';
|
|
903
|
-
html += '<table class="stx-data-grid-table">';
|
|
904
|
-
html += "<thead><tr>";
|
|
905
|
-
if (selectable) {
|
|
906
|
-
html += '<th class="stx-data-grid-select-all"><input type="checkbox" /></th>';
|
|
907
|
-
}
|
|
908
|
-
for (const col of columns) {
|
|
909
|
-
const widthStyle = col.width ? `style="width: ${col.width}"` : "";
|
|
910
|
-
html += `<th ${widthStyle}>
|
|
55
|
+
</div>`,E<Q.length-1)_+='<div class="stx-step-connector"></div>'}),`<div id="${$}" class="${q}" ${G?`style='${G}'`:""}>${_}</div>`}function wQ(Y){let{open:Q=!1,title:Z,size:X="medium",closable:$=!0,children:J,footer:U,id:q=L("modal"),className:G,style:_}=Y,K=V("stx-modal-component",`stx-modal-component--${X}`,G),E=D(_);if(!Q)return`<div id="${q}" class="${K} stx-modal-component--hidden" ${E?`style='${E}'`:""}></div>`;let R='<div class="stx-modal-component-overlay">';if(R+='<div class="stx-modal-component-dialog">',Z||$){if(R+='<div class="stx-modal-component-header">',Z)R+=`<h3 class="stx-modal-component-title">${B(Z)}</h3>`;if($)R+='<button class="stx-modal-component-close">×</button>';R+="</div>"}if(R+=`<div class="stx-modal-component-body">${J}</div>`,U)R+=`<div class="stx-modal-component-footer">${U}</div>`;return R+="</div></div>",`<div id="${q}" class="${K}" ${E?`style='${E}'`:""}>${R}</div>`}function fQ(Y){let{items:Q,selectable:Z=!1,multiSelect:X=!1,emptyMessage:$="No items",id:J=L("list"),className:U,style:q}=Y,G=V("stx-list-view",Z&&"stx-list-view--selectable",X&&"stx-list-view--multi",U),_=D(q);if(Q.length===0)return`<div id="${J}" class="${G}" ${_?`style="${_}"`:""}>
|
|
56
|
+
<div class="stx-list-view-empty">${B($)}</div>
|
|
57
|
+
</div>`;let K='<ul class="stx-list-view-items">';for(let E of Q){let R=V("stx-list-view-item",E.selected&&"stx-list-view-item--selected");K+=`<li class="${R}" data-id="${B(E.id)}" ${Z?'tabindex="0"':""}>${E.content}</li>`}return K+="</ul>",`<div id="${J}" class="${G}" ${_?`style='${_}'`:""}>${K}</div>`}function SQ(Y){let{columns:Q,data:Z,striped:X=!1,bordered:$=!1,hoverable:J=!0,sortBy:U,sortOrder:q,id:G=L("table"),className:_,style:K}=Y,E=V("stx-table",X&&"stx-table--striped",$&&"stx-table--bordered",J&&"stx-table--hoverable",_),R=D(K),F="<table>";F+="<thead><tr>";for(let j of Q){let z=j.key===U?`stx-table-sorted stx-table-sorted--${q}`:"",M=j.sortable?'data-sortable="true"':"",v=j.width?`style="width: ${j.width}"`:"";F+=`<th class="${z}" ${M} ${v} data-key="${B(j.key)}">${B(j.label)}${j.sortable?'<span class="stx-table-sort-icon"></span>':""}</th>`}F+="</tr></thead>",F+="<tbody>";for(let j of Z){F+="<tr>";for(let O of Q){let z=j[O.key];F+=`<td>${z!=null?B(String(z)):""}</td>`}F+="</tr>"}return F+="</tbody></table>",`<div id="${G}" class="${E}" ${R?`style='${R}'`:""}>${F}</div>`}function c(Y,Q,Z,X){let $=Q.includes(Y.key),J=Z.includes(Y.key),U=Y.children&&Y.children.length>0,G=`<div class="${V("stx-tree-node",J&&"stx-tree-node--selected",Y.disabled&&"stx-tree-node--disabled")}" data-key="${B(Y.key)}">`;if(G+='<div class="stx-tree-node-content">',U)G+=`<span class="stx-tree-toggle ${$?"stx-tree-toggle--expanded":""}">\u25B6</span>`;else G+='<span class="stx-tree-toggle-placeholder"></span>';if(X)G+=`<input type="checkbox" class="stx-tree-checkbox" ${J?"checked":""} ${Y.disabled?"disabled":""} />`;if(Y.icon)G+=`<span class="stx-tree-icon">${Y.icon}</span>`;if(G+=`<span class="stx-tree-label">${B(Y.label)}</span>`,G+="</div>",U&&$){G+='<div class="stx-tree-children">';for(let _ of Y.children)G+=c(_,Q,Z,X);G+="</div>"}return G+="</div>",G}function gQ(Y){let{nodes:Q,expandedKeys:Z=[],selectedKeys:X=[],checkable:$=!1,id:J=L("tree"),className:U,style:q}=Y,G=V("stx-tree-view",$&&"stx-tree-view--checkable",U),_=D(q),K="";for(let E of Q)K+=c(E,Z,X,$);return`<div id="${J}" class="${G}" role="tree" ${_?`style='${_}'`:""}>${K}</div>`}function bQ(Y){let{columns:Q,data:Z,pagination:X,selectable:$=!1,id:J=L("datagrid"),className:U,style:q}=Y,G=V("stx-data-grid",$&&"stx-data-grid--selectable",U),_=D(q),K='<div class="stx-data-grid-table-wrapper">';if(K+='<table class="stx-data-grid-table">',K+="<thead><tr>",$)K+='<th class="stx-data-grid-select-all"><input type="checkbox" /></th>';for(let E of Q){let R=E.width?`style="width: ${E.width}"`:"";K+=`<th ${R}>
|
|
911
58
|
<div class="stx-data-grid-header-cell">
|
|
912
|
-
<span>${
|
|
913
|
-
${
|
|
914
|
-
${
|
|
59
|
+
<span>${B(E.label)}</span>
|
|
60
|
+
${E.sortable?'<button class="stx-data-grid-sort">\u21C5</button>':""}
|
|
61
|
+
${E.filterable?'<button class="stx-data-grid-filter">\u22BB</button>':""}
|
|
915
62
|
</div>
|
|
916
|
-
</th
|
|
917
|
-
|
|
918
|
-
html += "</tr></thead>";
|
|
919
|
-
html += "<tbody>";
|
|
920
|
-
for (const row of data) {
|
|
921
|
-
html += "<tr>";
|
|
922
|
-
if (selectable) {
|
|
923
|
-
html += '<td class="stx-data-grid-select"><input type="checkbox" /></td>';
|
|
924
|
-
}
|
|
925
|
-
for (const col of columns) {
|
|
926
|
-
const cellValue = row[col.key];
|
|
927
|
-
html += `<td>${cellValue != null ? escapeHtml(String(cellValue)) : ""}</td>`;
|
|
928
|
-
}
|
|
929
|
-
html += "</tr>";
|
|
930
|
-
}
|
|
931
|
-
html += "</tbody></table></div>";
|
|
932
|
-
if (pagination) {
|
|
933
|
-
const totalPages = Math.ceil(pagination.total / pagination.pageSize);
|
|
934
|
-
html += `<div class="stx-data-grid-pagination">
|
|
935
|
-
<span class="stx-data-grid-page-info">Page ${pagination.page} of ${totalPages} (${pagination.total} items)</span>
|
|
63
|
+
</th>`}K+="</tr></thead>",K+="<tbody>";for(let E of Z){if(K+="<tr>",$)K+='<td class="stx-data-grid-select"><input type="checkbox" /></td>';for(let R of Q){let F=E[R.key];K+=`<td>${F!=null?B(String(F)):""}</td>`}K+="</tr>"}if(K+="</tbody></table></div>",X){let E=Math.ceil(X.total/X.pageSize);K+=`<div class="stx-data-grid-pagination">
|
|
64
|
+
<span class="stx-data-grid-page-info">Page ${X.page} of ${E} (${X.total} items)</span>
|
|
936
65
|
<div class="stx-data-grid-page-buttons">
|
|
937
|
-
<button class="stx-data-grid-page-btn" ${
|
|
938
|
-
<button class="stx-data-grid-page-btn" ${
|
|
66
|
+
<button class="stx-data-grid-page-btn" ${X.page<=1?"disabled":""}>\u25C0</button>
|
|
67
|
+
<button class="stx-data-grid-page-btn" ${X.page>=E?"disabled":""}>\u25B6</button>
|
|
939
68
|
</div>
|
|
940
|
-
</div
|
|
941
|
-
}
|
|
942
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
943
|
-
}
|
|
944
|
-
function createChart(props) {
|
|
945
|
-
const {
|
|
946
|
-
type,
|
|
947
|
-
data,
|
|
948
|
-
options = {},
|
|
949
|
-
width = "100%",
|
|
950
|
-
height = 300,
|
|
951
|
-
id = generateId("chart"),
|
|
952
|
-
className,
|
|
953
|
-
style
|
|
954
|
-
} = props;
|
|
955
|
-
const classes = buildClasses("stx-chart", `stx-chart--${type}`, className);
|
|
956
|
-
const chartStyles = {
|
|
957
|
-
width: typeof width === "number" ? `${width}px` : width,
|
|
958
|
-
height: typeof height === "number" ? `${height}px` : height
|
|
959
|
-
};
|
|
960
|
-
const combinedStyle = [buildStyles(chartStyles), buildStyles(style)].filter(Boolean).join("; ");
|
|
961
|
-
const chartData = JSON.stringify({ type, data, options });
|
|
962
|
-
return `<div id="${id}" class="${classes}" style="${combinedStyle}" data-chart='${escapeHtml(chartData)}'>
|
|
69
|
+
</div>`}return`<div id="${J}" class="${G}" ${_?`style='${_}'`:""}>${K}</div>`}function uQ(Y){let{type:Q,data:Z,options:X={},width:$="100%",height:J=300,id:U=L("chart"),className:q,style:G}=Y,_=V("stx-chart",`stx-chart--${Q}`,q),K={width:typeof $==="number"?`${$}px`:$,height:typeof J==="number"?`${J}px`:J},E=[D(K),D(G)].filter(Boolean).join("; "),R=JSON.stringify({type:Q,data:Z,options:X});return`<div id="${U}" class="${_}" style="${E}" data-chart='${B(R)}'>
|
|
963
70
|
<div class="stx-chart-placeholder">
|
|
964
|
-
${
|
|
965
|
-
<div class="stx-chart-type">${
|
|
966
|
-
<div class="stx-chart-info">${
|
|
71
|
+
${X.title?`<div class="stx-chart-title">${B(X.title)}</div>`:""}
|
|
72
|
+
<div class="stx-chart-type">${Q.charAt(0).toUpperCase()+Q.slice(1)} Chart</div>
|
|
73
|
+
<div class="stx-chart-info">${Z.datasets.length} dataset(s), ${Z.labels.length} labels</div>
|
|
967
74
|
</div>
|
|
968
|
-
</div
|
|
969
|
-
}
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
height = 300,
|
|
978
|
-
tabSize = 2,
|
|
979
|
-
wordWrap = false,
|
|
980
|
-
id = generateId("code"),
|
|
981
|
-
className,
|
|
982
|
-
style
|
|
983
|
-
} = props;
|
|
984
|
-
const classes = buildClasses("stx-code-editor", `stx-code-editor--${theme2}`, lineNumbers && "stx-code-editor--line-numbers", readOnly && "stx-code-editor--readonly", wordWrap && "stx-code-editor--wrap", className);
|
|
985
|
-
const editorStyles = {
|
|
986
|
-
height: typeof height === "number" ? `${height}px` : height
|
|
987
|
-
};
|
|
988
|
-
const combinedStyle = [buildStyles(editorStyles), buildStyles(style)].filter(Boolean).join("; ");
|
|
989
|
-
const lines = value.split(`
|
|
990
|
-
`);
|
|
991
|
-
let codeHtml = "";
|
|
992
|
-
if (lineNumbers) {
|
|
993
|
-
codeHtml += '<div class="stx-code-editor-gutter">';
|
|
994
|
-
for (let i = 1;i <= lines.length; i++) {
|
|
995
|
-
codeHtml += `<div class="stx-code-editor-line-number">${i}</div>`;
|
|
996
|
-
}
|
|
997
|
-
codeHtml += "</div>";
|
|
998
|
-
}
|
|
999
|
-
codeHtml += `<pre class="stx-code-editor-content"><code class="language-${escapeHtml(language)}">${escapeHtml(value)}</code></pre>`;
|
|
1000
|
-
return `<div id="${id}" class="${classes}" style="${combinedStyle}" data-language="${escapeHtml(language)}" data-tab-size="${tabSize}">${codeHtml}</div>`;
|
|
1001
|
-
}
|
|
1002
|
-
function createMediaPlayer(props) {
|
|
1003
|
-
const {
|
|
1004
|
-
src,
|
|
1005
|
-
type = "video",
|
|
1006
|
-
poster,
|
|
1007
|
-
autoplay = false,
|
|
1008
|
-
loop = false,
|
|
1009
|
-
muted = false,
|
|
1010
|
-
controls = true,
|
|
1011
|
-
width,
|
|
1012
|
-
height,
|
|
1013
|
-
id = generateId("media"),
|
|
1014
|
-
className,
|
|
1015
|
-
style
|
|
1016
|
-
} = props;
|
|
1017
|
-
const classes = buildClasses("stx-media-player", `stx-media-player--${type}`, className);
|
|
1018
|
-
const mediaStyles = {};
|
|
1019
|
-
if (width)
|
|
1020
|
-
mediaStyles.width = typeof width === "number" ? `${width}px` : width;
|
|
1021
|
-
if (height)
|
|
1022
|
-
mediaStyles.height = typeof height === "number" ? `${height}px` : height;
|
|
1023
|
-
const combinedStyle = [buildStyles(mediaStyles), buildStyles(style)].filter(Boolean).join("; ");
|
|
1024
|
-
const mediaAttrs = [
|
|
1025
|
-
`id="${id}-media"`,
|
|
1026
|
-
`src="${escapeHtml(src)}"`,
|
|
1027
|
-
controls && "controls",
|
|
1028
|
-
autoplay && "autoplay",
|
|
1029
|
-
loop && "loop",
|
|
1030
|
-
muted && "muted",
|
|
1031
|
-
type === "video" && poster && `poster="${escapeHtml(poster)}"`
|
|
1032
|
-
].filter(Boolean).join(" ");
|
|
1033
|
-
const mediaElement = type === "video" ? `<video ${mediaAttrs}>Your browser does not support the video tag.</video>` : `<audio ${mediaAttrs}>Your browser does not support the audio tag.</audio>`;
|
|
1034
|
-
return `<div id="${id}" class="${classes}" ${combinedStyle ? `style='${combinedStyle}'` : ""}>${mediaElement}</div>`;
|
|
1035
|
-
}
|
|
1036
|
-
function formatFileSize(bytes) {
|
|
1037
|
-
if (bytes === undefined)
|
|
1038
|
-
return "";
|
|
1039
|
-
const units = ["B", "KB", "MB", "GB"];
|
|
1040
|
-
let size = bytes;
|
|
1041
|
-
let unitIndex = 0;
|
|
1042
|
-
while (size >= 1024 && unitIndex < units.length - 1) {
|
|
1043
|
-
size /= 1024;
|
|
1044
|
-
unitIndex++;
|
|
1045
|
-
}
|
|
1046
|
-
return `${size.toFixed(1)} ${units[unitIndex]}`;
|
|
1047
|
-
}
|
|
1048
|
-
function createFileExplorer(props) {
|
|
1049
|
-
const {
|
|
1050
|
-
files,
|
|
1051
|
-
viewMode = "list",
|
|
1052
|
-
showHidden = false,
|
|
1053
|
-
selectable = true,
|
|
1054
|
-
id = generateId("files"),
|
|
1055
|
-
className,
|
|
1056
|
-
style
|
|
1057
|
-
} = props;
|
|
1058
|
-
const classes = buildClasses("stx-file-explorer", `stx-file-explorer--${viewMode}`, className);
|
|
1059
|
-
const styleStr = buildStyles(style);
|
|
1060
|
-
const filteredFiles = showHidden ? files : files.filter((f) => !f.name.startsWith("."));
|
|
1061
|
-
let html = "";
|
|
1062
|
-
if (viewMode === "list") {
|
|
1063
|
-
html = '<table class="stx-file-explorer-list"><thead><tr><th>Name</th><th>Size</th><th>Modified</th></tr></thead><tbody>';
|
|
1064
|
-
for (const file of filteredFiles) {
|
|
1065
|
-
const icon = file.icon || (file.type === "folder" ? "\uD83D\uDCC1" : "\uD83D\uDCC4");
|
|
1066
|
-
const size = file.type === "file" ? formatFileSize(file.size) : "";
|
|
1067
|
-
const modified = file.modified ? file.modified.toLocaleDateString() : "";
|
|
1068
|
-
html += `<tr class="stx-file-explorer-item ${selectable ? "stx-file-explorer-item--selectable" : ""}" data-path="${escapeHtml(file.path)}" data-type="${file.type}">
|
|
1069
|
-
<td><span class="stx-file-explorer-icon">${icon}</span>${escapeHtml(file.name)}</td>
|
|
1070
|
-
<td>${size}</td>
|
|
1071
|
-
<td>${modified}</td>
|
|
1072
|
-
</tr>`;
|
|
1073
|
-
}
|
|
1074
|
-
html += "</tbody></table>";
|
|
1075
|
-
} else {
|
|
1076
|
-
html = '<div class="stx-file-explorer-grid">';
|
|
1077
|
-
for (const file of filteredFiles) {
|
|
1078
|
-
const icon = file.icon || (file.type === "folder" ? "\uD83D\uDCC1" : "\uD83D\uDCC4");
|
|
1079
|
-
html += `<div class="stx-file-explorer-item ${selectable ? "stx-file-explorer-item--selectable" : ""}" data-path="${escapeHtml(file.path)}" data-type="${file.type}">
|
|
1080
|
-
<div class="stx-file-explorer-icon">${icon}</div>
|
|
1081
|
-
<div class="stx-file-explorer-name">${escapeHtml(file.name)}</div>
|
|
1082
|
-
</div>`;
|
|
1083
|
-
}
|
|
1084
|
-
html += "</div>";
|
|
1085
|
-
}
|
|
1086
|
-
return `<div id="${id}" class="${classes}" ${styleStr ? `style='${styleStr}'` : ""}>${html}</div>`;
|
|
1087
|
-
}
|
|
1088
|
-
function createWebView(props) {
|
|
1089
|
-
const {
|
|
1090
|
-
url,
|
|
1091
|
-
width = "100%",
|
|
1092
|
-
height = 400,
|
|
1093
|
-
sandbox = true,
|
|
1094
|
-
allowScripts = true,
|
|
1095
|
-
id = generateId("webview"),
|
|
1096
|
-
className,
|
|
1097
|
-
style
|
|
1098
|
-
} = props;
|
|
1099
|
-
const classes = buildClasses("stx-webview", className);
|
|
1100
|
-
const webviewStyles = {
|
|
1101
|
-
width: typeof width === "number" ? `${width}px` : width,
|
|
1102
|
-
height: typeof height === "number" ? `${height}px` : height
|
|
1103
|
-
};
|
|
1104
|
-
const combinedStyle = [buildStyles(webviewStyles), buildStyles(style)].filter(Boolean).join("; ");
|
|
1105
|
-
const sandboxAttrs = [];
|
|
1106
|
-
if (sandbox) {
|
|
1107
|
-
sandboxAttrs.push("allow-same-origin");
|
|
1108
|
-
if (allowScripts) {
|
|
1109
|
-
sandboxAttrs.push("allow-scripts");
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
const sandboxAttr = sandbox ? `sandbox="${sandboxAttrs.join(" ")}"` : "";
|
|
1113
|
-
return `<iframe id="${id}" class="${classes}" src="${escapeHtml(url)}" style="${combinedStyle}" ${sandboxAttr} loading="lazy" frameborder="0"></iframe>`;
|
|
1114
|
-
}
|
|
1115
|
-
var AVAILABLE_COMPONENTS = [
|
|
1116
|
-
"Button",
|
|
1117
|
-
"TextInput",
|
|
1118
|
-
"Checkbox",
|
|
1119
|
-
"RadioButton",
|
|
1120
|
-
"Slider",
|
|
1121
|
-
"ColorPicker",
|
|
1122
|
-
"DatePicker",
|
|
1123
|
-
"TimePicker",
|
|
1124
|
-
"Autocomplete",
|
|
1125
|
-
"Label",
|
|
1126
|
-
"ImageView",
|
|
1127
|
-
"ProgressBar",
|
|
1128
|
-
"Avatar",
|
|
1129
|
-
"Badge",
|
|
1130
|
-
"Chip",
|
|
1131
|
-
"Card",
|
|
1132
|
-
"Tooltip",
|
|
1133
|
-
"Toast",
|
|
1134
|
-
"ScrollView",
|
|
1135
|
-
"SplitView",
|
|
1136
|
-
"Accordion",
|
|
1137
|
-
"Stepper",
|
|
1138
|
-
"Modal",
|
|
1139
|
-
"Tabs",
|
|
1140
|
-
"Dropdown",
|
|
1141
|
-
"ListView",
|
|
1142
|
-
"Table",
|
|
1143
|
-
"TreeView",
|
|
1144
|
-
"DataGrid",
|
|
1145
|
-
"Chart",
|
|
1146
|
-
"Rating",
|
|
1147
|
-
"CodeEditor",
|
|
1148
|
-
"MediaPlayer",
|
|
1149
|
-
"FileExplorer",
|
|
1150
|
-
"WebView"
|
|
1151
|
-
];
|
|
1152
|
-
var COMPONENT_STYLES = `
|
|
75
|
+
</div>`}function yQ(Y){let{value:Q="",language:Z="plaintext",theme:X="dark",lineNumbers:$=!0,readOnly:J=!1,height:U=300,tabSize:q=2,wordWrap:G=!1,id:_=L("code"),className:K,style:E}=Y,R=V("stx-code-editor",`stx-code-editor--${X}`,$&&"stx-code-editor--line-numbers",J&&"stx-code-editor--readonly",G&&"stx-code-editor--wrap",K),F={height:typeof U==="number"?`${U}px`:U},j=[D(F),D(E)].filter(Boolean).join("; "),O=Q.split(`
|
|
76
|
+
`),z="";if($){z+='<div class="stx-code-editor-gutter">';for(let M=1;M<=O.length;M++)z+=`<div class="stx-code-editor-line-number">${M}</div>`;z+="</div>"}return z+=`<pre class="stx-code-editor-content"><code class="language-${B(Z)}">${B(Q)}</code></pre>`,`<div id="${_}" class="${R}" style="${j}" data-language="${B(Z)}" data-tab-size="${q}">${z}</div>`}function hQ(Y){let{src:Q,type:Z="video",poster:X,autoplay:$=!1,loop:J=!1,muted:U=!1,controls:q=!0,width:G,height:_,id:K=L("media"),className:E,style:R}=Y,F=V("stx-media-player",`stx-media-player--${Z}`,E),j={};if(G)j.width=typeof G==="number"?`${G}px`:G;if(_)j.height=typeof _==="number"?`${_}px`:_;let O=[D(j),D(R)].filter(Boolean).join("; "),z=[`id="${K}-media"`,`src="${B(Q)}"`,q&&"controls",$&&"autoplay",J&&"loop",U&&"muted",Z==="video"&&X&&`poster="${B(X)}"`].filter(Boolean).join(" "),M=Z==="video"?`<video ${z}>Your browser does not support the video tag.</video>`:`<audio ${z}>Your browser does not support the audio tag.</audio>`;return`<div id="${K}" class="${F}" ${O?`style='${O}'`:""}>${M}</div>`}function mQ(Y){if(Y===void 0)return"";let Q=["B","KB","MB","GB"],Z=Y,X=0;while(Z>=1024&&X<Q.length-1)Z/=1024,X++;return`${Z.toFixed(1)} ${Q[X]}`}function cQ(Y){let{files:Q,viewMode:Z="list",showHidden:X=!1,selectable:$=!0,id:J=L("files"),className:U,style:q}=Y,G=V("stx-file-explorer",`stx-file-explorer--${Z}`,U),_=D(q),K=X?Q:Q.filter((R)=>!R.name.startsWith(".")),E="";if(Z==="list"){E='<table class="stx-file-explorer-list"><thead><tr><th>Name</th><th>Size</th><th>Modified</th></tr></thead><tbody>';for(let R of K){let F=R.icon||(R.type==="folder"?"\uD83D\uDCC1":"\uD83D\uDCC4"),j=R.type==="file"?mQ(R.size):"",O=R.modified?R.modified.toLocaleDateString():"";E+=`<tr class="stx-file-explorer-item ${$?"stx-file-explorer-item--selectable":""}" data-path="${B(R.path)}" data-type="${R.type}">
|
|
77
|
+
<td><span class="stx-file-explorer-icon">${F}</span>${B(R.name)}</td>
|
|
78
|
+
<td>${j}</td>
|
|
79
|
+
<td>${O}</td>
|
|
80
|
+
</tr>`}E+="</tbody></table>"}else{E='<div class="stx-file-explorer-grid">';for(let R of K){let F=R.icon||(R.type==="folder"?"\uD83D\uDCC1":"\uD83D\uDCC4");E+=`<div class="stx-file-explorer-item ${$?"stx-file-explorer-item--selectable":""}" data-path="${B(R.path)}" data-type="${R.type}">
|
|
81
|
+
<div class="stx-file-explorer-icon">${F}</div>
|
|
82
|
+
<div class="stx-file-explorer-name">${B(R.name)}</div>
|
|
83
|
+
</div>`}E+="</div>"}return`<div id="${J}" class="${G}" ${_?`style='${_}'`:""}>${E}</div>`}function dQ(Y){let{url:Q,width:Z="100%",height:X=400,sandbox:$=!0,allowScripts:J=!0,id:U=L("webview"),className:q,style:G}=Y,_=V("stx-webview",q),K={width:typeof Z==="number"?`${Z}px`:Z,height:typeof X==="number"?`${X}px`:X},E=[D(K),D(G)].filter(Boolean).join("; "),R=[];if($){if(R.push("allow-same-origin"),J)R.push("allow-scripts")}let F=$?`sandbox="${R.join(" ")}"`:"";return`<iframe id="${U}" class="${_}" src="${B(Q)}" style="${E}" ${F} loading="lazy" frameborder="0"></iframe>`}var pQ=["Button","TextInput","Checkbox","RadioButton","Slider","ColorPicker","DatePicker","TimePicker","Autocomplete","Label","ImageView","ProgressBar","Avatar","Badge","Chip","Card","Tooltip","Toast","ScrollView","SplitView","Accordion","Stepper","Modal","Tabs","Dropdown","ListView","Table","TreeView","DataGrid","Chart","Rating","CodeEditor","MediaPlayer","FileExplorer","WebView"],rQ=`
|
|
1153
84
|
/* Button */
|
|
1154
85
|
.stx-button {
|
|
1155
86
|
display: inline-flex;
|
|
@@ -1506,266 +437,7 @@ var COMPONENT_STYLES = `
|
|
|
1506
437
|
.stx-chip--warning { background: #3a2a1a; }
|
|
1507
438
|
.stx-chip--error { background: #3a1a1a; }
|
|
1508
439
|
}
|
|
1509
|
-
`;
|
|
1510
|
-
// src/system-tray.ts
|
|
1511
|
-
import process2 from "process";
|
|
1512
|
-
function getPlatform() {
|
|
1513
|
-
if (process2.platform) {
|
|
1514
|
-
return process2.platform;
|
|
1515
|
-
}
|
|
1516
|
-
return "unknown";
|
|
1517
|
-
}
|
|
1518
|
-
function isInCraftWindow() {
|
|
1519
|
-
if (typeof window !== "undefined" && window.craft?.tray) {
|
|
1520
|
-
return true;
|
|
1521
|
-
}
|
|
1522
|
-
return false;
|
|
1523
|
-
}
|
|
1524
|
-
function convertMenuItem(item, index) {
|
|
1525
|
-
if (item.type === "separator") {
|
|
1526
|
-
return {
|
|
1527
|
-
id: `sep-${index}`,
|
|
1528
|
-
label: "",
|
|
1529
|
-
type: "separator"
|
|
1530
|
-
};
|
|
1531
|
-
}
|
|
1532
|
-
const menuItem = {
|
|
1533
|
-
id: `item-${index}-${item.label.replace(/\s+/g, "-").toLowerCase()}`,
|
|
1534
|
-
label: item.label,
|
|
1535
|
-
type: item.type || "normal",
|
|
1536
|
-
enabled: item.enabled !== false
|
|
1537
|
-
};
|
|
1538
|
-
if (item.accelerator) {
|
|
1539
|
-
menuItem.shortcut = item.accelerator;
|
|
1540
|
-
}
|
|
1541
|
-
if (item.type === "checkbox") {
|
|
1542
|
-
menuItem.checked = item.checked || false;
|
|
1543
|
-
}
|
|
1544
|
-
if (item.type === "submenu" && item.submenu) {
|
|
1545
|
-
menuItem.submenu = item.submenu.map((subItem, subIndex) => convertMenuItem(subItem, subIndex));
|
|
1546
|
-
}
|
|
1547
|
-
return menuItem;
|
|
1548
|
-
}
|
|
1549
|
-
function convertMenuItems(items) {
|
|
1550
|
-
return items.map((item, index) => convertMenuItem(item, index));
|
|
1551
|
-
}
|
|
1552
|
-
function renderMenuItem(item, level = 0) {
|
|
1553
|
-
if (item.type === "separator") {
|
|
1554
|
-
return '<hr class="stx-tray-separator" />';
|
|
1555
|
-
}
|
|
1556
|
-
const indent = " ".repeat(level);
|
|
1557
|
-
const disabled = item.enabled === false ? "disabled" : "";
|
|
1558
|
-
const checked = item.checked ? "\u2713 " : "";
|
|
1559
|
-
const accelerator = item.accelerator ? `<span class="accelerator">${item.accelerator}</span>` : "";
|
|
1560
|
-
let html = `${indent}<div class="stx-tray-item ${disabled}" data-action="${item.label}">`;
|
|
1561
|
-
html += `<span class="label">${checked}${item.label}</span>${accelerator}`;
|
|
1562
|
-
if (item.type === "submenu" && item.submenu) {
|
|
1563
|
-
html += '<span class="arrow">\u25B8</span>';
|
|
1564
|
-
html += '<div class="stx-tray-submenu">';
|
|
1565
|
-
for (const subItem of item.submenu) {
|
|
1566
|
-
html += renderMenuItem(subItem, level + 1);
|
|
1567
|
-
}
|
|
1568
|
-
html += "</div>";
|
|
1569
|
-
}
|
|
1570
|
-
html += "</div>";
|
|
1571
|
-
return html;
|
|
1572
|
-
}
|
|
1573
|
-
function renderTrayMenu(menu2) {
|
|
1574
|
-
let html = '<div class="stx-tray-menu">';
|
|
1575
|
-
for (const item of menu2) {
|
|
1576
|
-
html += renderMenuItem(item);
|
|
1577
|
-
}
|
|
1578
|
-
html += "</div>";
|
|
1579
|
-
return html;
|
|
1580
|
-
}
|
|
1581
|
-
var activeTrayInstances = new Map;
|
|
1582
|
-
function generateTrayId() {
|
|
1583
|
-
return `tray-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
|
|
1584
|
-
}
|
|
1585
|
-
var craftTrayListenerSetup = false;
|
|
1586
|
-
function setupCraftTrayListener() {
|
|
1587
|
-
if (craftTrayListenerSetup || typeof window === "undefined")
|
|
1588
|
-
return;
|
|
1589
|
-
window.addEventListener("craft:tray:menu", (event) => {
|
|
1590
|
-
const { action } = event.detail;
|
|
1591
|
-
for (const instance of activeTrayInstances.values()) {
|
|
1592
|
-
const handler = instance.handlers.get(action);
|
|
1593
|
-
if (handler) {
|
|
1594
|
-
handler();
|
|
1595
|
-
break;
|
|
1596
|
-
}
|
|
1597
|
-
}
|
|
1598
|
-
});
|
|
1599
|
-
craftTrayListenerSetup = true;
|
|
1600
|
-
}
|
|
1601
|
-
async function createSystemTray(options = {}) {
|
|
1602
|
-
const id = generateTrayId();
|
|
1603
|
-
const platform = getPlatform();
|
|
1604
|
-
const inCraft = isInCraftWindow();
|
|
1605
|
-
const state = {
|
|
1606
|
-
icon: options.icon || "",
|
|
1607
|
-
tooltip: options.tooltip || "stx Application",
|
|
1608
|
-
menu: options.menu || [],
|
|
1609
|
-
visible: true
|
|
1610
|
-
};
|
|
1611
|
-
const handlers = new Map;
|
|
1612
|
-
for (const item of options.menu || []) {
|
|
1613
|
-
if (item.type !== "separator" && item.onClick) {
|
|
1614
|
-
handlers.set(item.label, item.onClick);
|
|
1615
|
-
}
|
|
1616
|
-
if (item.type === "submenu" && item.submenu) {
|
|
1617
|
-
for (const subItem of item.submenu) {
|
|
1618
|
-
if (subItem.type !== "separator" && subItem.onClick) {
|
|
1619
|
-
handlers.set(subItem.label, subItem.onClick);
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
activeTrayInstances.set(id, { state, handlers });
|
|
1625
|
-
if (inCraft) {
|
|
1626
|
-
setupCraftTrayListener();
|
|
1627
|
-
const craftWindow = window;
|
|
1628
|
-
try {
|
|
1629
|
-
if (state.tooltip) {
|
|
1630
|
-
await craftWindow.craft.tray.setTitle({ title: state.tooltip });
|
|
1631
|
-
await craftWindow.craft.tray.setTooltip({ tooltip: state.tooltip });
|
|
1632
|
-
}
|
|
1633
|
-
if (state.icon) {
|
|
1634
|
-
await craftWindow.craft.tray.setIcon({ icon: state.icon });
|
|
1635
|
-
}
|
|
1636
|
-
const craftMenu = convertMenuItems(state.menu);
|
|
1637
|
-
await craftWindow.craft.tray.setMenu({ items: craftMenu });
|
|
1638
|
-
console.log(`[stx-tray] Native tray created for ${platform}`);
|
|
1639
|
-
} catch (error) {
|
|
1640
|
-
console.warn("[stx-tray] Failed to create native tray:", error);
|
|
1641
|
-
}
|
|
1642
|
-
} else {
|
|
1643
|
-
console.log(`[stx-tray] Created simulated tray (not in Craft window)`);
|
|
1644
|
-
console.log(`[stx-tray] ID: ${id}`);
|
|
1645
|
-
console.log(`[stx-tray] Tooltip: ${state.tooltip}`);
|
|
1646
|
-
console.log(`[stx-tray] Menu items: ${state.menu.length}`);
|
|
1647
|
-
}
|
|
1648
|
-
const instance = {
|
|
1649
|
-
id,
|
|
1650
|
-
setIcon: (icon) => {
|
|
1651
|
-
state.icon = icon;
|
|
1652
|
-
if (inCraft) {
|
|
1653
|
-
const craftWindow = window;
|
|
1654
|
-
craftWindow.craft.tray.setIcon({ icon }).catch((e) => {
|
|
1655
|
-
console.warn("[stx-tray] Failed to set icon:", e);
|
|
1656
|
-
});
|
|
1657
|
-
}
|
|
1658
|
-
console.log(`[stx-tray:${id}] Icon updated`);
|
|
1659
|
-
},
|
|
1660
|
-
setTooltip: (tooltip) => {
|
|
1661
|
-
state.tooltip = tooltip;
|
|
1662
|
-
if (inCraft) {
|
|
1663
|
-
const craftWindow = window;
|
|
1664
|
-
craftWindow.craft.tray.setTooltip({ tooltip }).catch((e) => {
|
|
1665
|
-
console.warn("[stx-tray] Failed to set tooltip:", e);
|
|
1666
|
-
});
|
|
1667
|
-
}
|
|
1668
|
-
console.log(`[stx-tray:${id}] Tooltip: ${tooltip}`);
|
|
1669
|
-
},
|
|
1670
|
-
setMenu: (menu2) => {
|
|
1671
|
-
state.menu = menu2;
|
|
1672
|
-
handlers.clear();
|
|
1673
|
-
for (const item of menu2) {
|
|
1674
|
-
if (item.type !== "separator" && item.onClick) {
|
|
1675
|
-
handlers.set(item.label, item.onClick);
|
|
1676
|
-
}
|
|
1677
|
-
if (item.type === "submenu" && item.submenu) {
|
|
1678
|
-
for (const subItem of item.submenu) {
|
|
1679
|
-
if (subItem.type !== "separator" && subItem.onClick) {
|
|
1680
|
-
handlers.set(subItem.label, subItem.onClick);
|
|
1681
|
-
}
|
|
1682
|
-
}
|
|
1683
|
-
}
|
|
1684
|
-
}
|
|
1685
|
-
if (inCraft) {
|
|
1686
|
-
const craftWindow = window;
|
|
1687
|
-
const craftMenu = convertMenuItems(menu2);
|
|
1688
|
-
craftWindow.craft.tray.setMenu({ items: craftMenu }).catch((e) => {
|
|
1689
|
-
console.warn("[stx-tray] Failed to set menu:", e);
|
|
1690
|
-
});
|
|
1691
|
-
}
|
|
1692
|
-
console.log(`[stx-tray:${id}] Menu updated (${menu2.length} items)`);
|
|
1693
|
-
},
|
|
1694
|
-
destroy: () => {
|
|
1695
|
-
state.visible = false;
|
|
1696
|
-
activeTrayInstances.delete(id);
|
|
1697
|
-
if (inCraft) {
|
|
1698
|
-
const craftWindow = window;
|
|
1699
|
-
craftWindow.craft.tray.destroy?.().catch((e) => {
|
|
1700
|
-
console.warn("[stx-tray] Failed to destroy tray:", e);
|
|
1701
|
-
});
|
|
1702
|
-
}
|
|
1703
|
-
console.log(`[stx-tray:${id}] Destroyed`);
|
|
1704
|
-
}
|
|
1705
|
-
};
|
|
1706
|
-
return instance;
|
|
1707
|
-
}
|
|
1708
|
-
var createMenubar = createSystemTray;
|
|
1709
|
-
function getActiveTrayInstances() {
|
|
1710
|
-
return Array.from(activeTrayInstances.keys());
|
|
1711
|
-
}
|
|
1712
|
-
function getTrayInstance(id) {
|
|
1713
|
-
const instance = activeTrayInstances.get(id);
|
|
1714
|
-
if (!instance)
|
|
1715
|
-
return null;
|
|
1716
|
-
const inCraft = isInCraftWindow();
|
|
1717
|
-
return {
|
|
1718
|
-
id,
|
|
1719
|
-
setIcon: (icon) => {
|
|
1720
|
-
instance.state.icon = icon;
|
|
1721
|
-
if (inCraft) {
|
|
1722
|
-
const craftWindow = window;
|
|
1723
|
-
craftWindow.craft.tray.setIcon({ icon }).catch(() => {});
|
|
1724
|
-
}
|
|
1725
|
-
},
|
|
1726
|
-
setTooltip: (tooltip) => {
|
|
1727
|
-
instance.state.tooltip = tooltip;
|
|
1728
|
-
if (inCraft) {
|
|
1729
|
-
const craftWindow = window;
|
|
1730
|
-
craftWindow.craft.tray.setTooltip({ tooltip }).catch(() => {});
|
|
1731
|
-
}
|
|
1732
|
-
},
|
|
1733
|
-
setMenu: (menu2) => {
|
|
1734
|
-
instance.state.menu = menu2;
|
|
1735
|
-
if (inCraft) {
|
|
1736
|
-
const craftWindow = window;
|
|
1737
|
-
const craftMenu = convertMenuItems(menu2);
|
|
1738
|
-
craftWindow.craft.tray.setMenu({ items: craftMenu }).catch(() => {});
|
|
1739
|
-
}
|
|
1740
|
-
},
|
|
1741
|
-
destroy: () => {
|
|
1742
|
-
activeTrayInstances.delete(id);
|
|
1743
|
-
if (inCraft) {
|
|
1744
|
-
const craftWindow = window;
|
|
1745
|
-
craftWindow.craft.tray.destroy?.().catch(() => {});
|
|
1746
|
-
}
|
|
1747
|
-
}
|
|
1748
|
-
};
|
|
1749
|
-
}
|
|
1750
|
-
function triggerTrayAction(trayId, actionLabel) {
|
|
1751
|
-
const instance = activeTrayInstances.get(trayId);
|
|
1752
|
-
if (!instance)
|
|
1753
|
-
return false;
|
|
1754
|
-
const handler = instance.handlers.get(actionLabel);
|
|
1755
|
-
if (handler) {
|
|
1756
|
-
handler();
|
|
1757
|
-
return true;
|
|
1758
|
-
}
|
|
1759
|
-
return false;
|
|
1760
|
-
}
|
|
1761
|
-
function getSimulatedTrayHTML(trayId) {
|
|
1762
|
-
const instance = activeTrayInstances.get(trayId);
|
|
1763
|
-
if (!instance)
|
|
1764
|
-
return null;
|
|
1765
|
-
return renderTrayMenu(instance.state.menu);
|
|
1766
|
-
}
|
|
1767
|
-
function getTrayBridgeScript() {
|
|
1768
|
-
return `
|
|
440
|
+
`;import d from"process";function nQ(){if(d.platform)return d.platform;return"unknown"}function r(){if(typeof window<"u"&&window.craft?.tray)return!0;return!1}function n(Y,Q){if(Y.type==="separator")return{id:`sep-${Q}`,label:"",type:"separator"};let Z={id:`item-${Q}-${Y.label.replace(/\s+/g,"-").toLowerCase()}`,label:Y.label,type:Y.type||"normal",enabled:Y.enabled!==!1};if(Y.accelerator)Z.shortcut=Y.accelerator;if(Y.type==="checkbox")Z.checked=Y.checked||!1;if(Y.type==="submenu"&&Y.submenu)Z.submenu=Y.submenu.map((X,$)=>n(X,$));return Z}function g(Y){return Y.map((Q,Z)=>n(Q,Z))}function o(Y,Q=0){if(Y.type==="separator")return'<hr class="stx-tray-separator" />';let Z=" ".repeat(Q),X=Y.enabled===!1?"disabled":"",$=Y.checked?"\u2713 ":"",J=Y.accelerator?`<span class="accelerator">${Y.accelerator}</span>`:"",U=`${Z}<div class="stx-tray-item ${X}" data-action="${Y.label}">`;if(U+=`<span class="label">${$}${Y.label}</span>${J}`,Y.type==="submenu"&&Y.submenu){U+='<span class="arrow">\u25B8</span>',U+='<div class="stx-tray-submenu">';for(let q of Y.submenu)U+=o(q,Q+1);U+="</div>"}return U+="</div>",U}function oQ(Y){let Q='<div class="stx-tray-menu">';for(let Z of Y)Q+=o(Z);return Q+="</div>",Q}var A=new Map;function lQ(){return`tray-${Date.now()}-${Math.random().toString(36).substring(2,9)}`}var p=!1;function aQ(){if(p||typeof window>"u")return;window.addEventListener("craft:tray:menu",(Y)=>{let{action:Q}=Y.detail;for(let Z of A.values()){let X=Z.handlers.get(Q);if(X){X();break}}}),p=!0}async function l(Y={}){let Q=lQ(),Z=nQ(),X=r(),$={icon:Y.icon||"",tooltip:Y.tooltip||"stx Application",menu:Y.menu||[],visible:!0},J=new Map;for(let q of Y.menu||[]){if(q.type!=="separator"&&q.onClick)J.set(q.label,q.onClick);if(q.type==="submenu"&&q.submenu){for(let G of q.submenu)if(G.type!=="separator"&&G.onClick)J.set(G.label,G.onClick)}}if(A.set(Q,{state:$,handlers:J}),X){aQ();let q=window;try{if($.tooltip)await q.craft.tray.setTitle({title:$.tooltip}),await q.craft.tray.setTooltip({tooltip:$.tooltip});if($.icon)await q.craft.tray.setIcon({icon:$.icon});let G=g($.menu);await q.craft.tray.setMenu({items:G}),console.log(`[stx-tray] Native tray created for ${Z}`)}catch(G){console.warn("[stx-tray] Failed to create native tray:",G)}}else console.log("[stx-tray] Created simulated tray (not in Craft window)"),console.log(`[stx-tray] ID: ${Q}`),console.log(`[stx-tray] Tooltip: ${$.tooltip}`),console.log(`[stx-tray] Menu items: ${$.menu.length}`);return{id:Q,setIcon:(q)=>{if($.icon=q,X)window.craft.tray.setIcon({icon:q}).catch((_)=>{console.warn("[stx-tray] Failed to set icon:",_)});console.log(`[stx-tray:${Q}] Icon updated`)},setTooltip:(q)=>{if($.tooltip=q,X)window.craft.tray.setTooltip({tooltip:q}).catch((_)=>{console.warn("[stx-tray] Failed to set tooltip:",_)});console.log(`[stx-tray:${Q}] Tooltip: ${q}`)},setMenu:(q)=>{$.menu=q,J.clear();for(let G of q){if(G.type!=="separator"&&G.onClick)J.set(G.label,G.onClick);if(G.type==="submenu"&&G.submenu){for(let _ of G.submenu)if(_.type!=="separator"&&_.onClick)J.set(_.label,_.onClick)}}if(X){let G=window,_=g(q);G.craft.tray.setMenu({items:_}).catch((K)=>{console.warn("[stx-tray] Failed to set menu:",K)})}console.log(`[stx-tray:${Q}] Menu updated (${q.length} items)`)},destroy:()=>{if($.visible=!1,A.delete(Q),X)window.craft.tray.destroy?.().catch((G)=>{console.warn("[stx-tray] Failed to destroy tray:",G)});console.log(`[stx-tray:${Q}] Destroyed`)}}}var iQ=l;function sQ(){return Array.from(A.keys())}function tQ(Y){let Q=A.get(Y);if(!Q)return null;let Z=r();return{id:Y,setIcon:(X)=>{if(Q.state.icon=X,Z)window.craft.tray.setIcon({icon:X}).catch(()=>{})},setTooltip:(X)=>{if(Q.state.tooltip=X,Z)window.craft.tray.setTooltip({tooltip:X}).catch(()=>{})},setMenu:(X)=>{if(Q.state.menu=X,Z){let $=window,J=g(X);$.craft.tray.setMenu({items:J}).catch(()=>{})}},destroy:()=>{if(A.delete(Y),Z)window.craft.tray.destroy?.().catch(()=>{})}}}function eQ(Y,Q){let Z=A.get(Y);if(!Z)return!1;let X=Z.handlers.get(Q);if(X)return X(),!0;return!1}function QY(Y){let Q=A.get(Y);if(!Q)return null;return oQ(Q.state.menu)}function YY(){return`
|
|
1769
441
|
// STX Desktop Tray Bridge
|
|
1770
442
|
// Provides convenient wrappers around window.craft.tray APIs
|
|
1771
443
|
window.stxTray = {
|
|
@@ -1778,9 +450,7 @@ window.stxTray = {
|
|
|
1778
450
|
// Check if tray is available
|
|
1779
451
|
isAvailable: () => typeof window.craft?.tray !== 'undefined',
|
|
1780
452
|
};
|
|
1781
|
-
|
|
1782
|
-
}
|
|
1783
|
-
var TRAY_MENU_STYLES = `
|
|
453
|
+
`}var ZY=`
|
|
1784
454
|
.stx-tray-menu {
|
|
1785
455
|
background: #2d2d2d;
|
|
1786
456
|
border-radius: 8px;
|
|
@@ -1846,315 +516,7 @@ var TRAY_MENU_STYLES = `
|
|
|
1846
516
|
.stx-tray-item:hover > .stx-tray-submenu {
|
|
1847
517
|
display: block;
|
|
1848
518
|
}
|
|
1849
|
-
`;
|
|
1850
|
-
// src/window.ts
|
|
1851
|
-
import process3 from "process";
|
|
1852
|
-
import { existsSync } from "fs";
|
|
1853
|
-
import { dirname, join } from "path";
|
|
1854
|
-
import { craftBinaryNotFoundMessage, resolveCraftBinary } from "craft-native";
|
|
1855
|
-
var currentConfig = {};
|
|
1856
|
-
function setDesktopConfig(config) {
|
|
1857
|
-
currentConfig = { ...currentConfig, ...config };
|
|
1858
|
-
}
|
|
1859
|
-
function getDesktopConfig() {
|
|
1860
|
-
return { ...currentConfig };
|
|
1861
|
-
}
|
|
1862
|
-
function resetDesktopConfig() {
|
|
1863
|
-
currentConfig = {};
|
|
1864
|
-
}
|
|
1865
|
-
function prepareSidebarConfig(options) {
|
|
1866
|
-
if (!options.sidebarConfig)
|
|
1867
|
-
return;
|
|
1868
|
-
const config = { ...options.sidebarConfig };
|
|
1869
|
-
if (config.variant === "desktop") {
|
|
1870
|
-
config.material = config.material ?? "sidebar";
|
|
1871
|
-
config.backgroundEffect = config.backgroundEffect ?? "shimmer";
|
|
1872
|
-
config.allowsVibrancy = config.allowsVibrancy ?? true;
|
|
1873
|
-
}
|
|
1874
|
-
return config;
|
|
1875
|
-
}
|
|
1876
|
-
function getCraftBinaryPath() {
|
|
1877
|
-
const overrides = [
|
|
1878
|
-
process3.env.CRAFT_BINARY_PATH,
|
|
1879
|
-
currentConfig.craftBinaryPath,
|
|
1880
|
-
...currentConfig.additionalSearchPaths || [],
|
|
1881
|
-
join(dirname(process3.execPath), "craft")
|
|
1882
|
-
];
|
|
1883
|
-
for (const candidate of overrides) {
|
|
1884
|
-
if (candidate && existsSync(candidate))
|
|
1885
|
-
return candidate;
|
|
1886
|
-
}
|
|
1887
|
-
return resolveCraftBinary();
|
|
1888
|
-
}
|
|
1889
|
-
var activeWindows = new Map;
|
|
1890
|
-
function getActiveWindowIds() {
|
|
1891
|
-
return Array.from(activeWindows.keys());
|
|
1892
|
-
}
|
|
1893
|
-
function getWindow(id) {
|
|
1894
|
-
const windowData = activeWindows.get(id);
|
|
1895
|
-
if (!windowData)
|
|
1896
|
-
return null;
|
|
1897
|
-
return createWindowInstance(id, windowData.app);
|
|
1898
|
-
}
|
|
1899
|
-
function closeAllWindows() {
|
|
1900
|
-
for (const [id, windowData] of activeWindows) {
|
|
1901
|
-
try {
|
|
1902
|
-
windowData.app?.close?.();
|
|
1903
|
-
} catch (e) {
|
|
1904
|
-
console.warn(`Failed to close window ${id}:`, e);
|
|
1905
|
-
}
|
|
1906
|
-
}
|
|
1907
|
-
activeWindows.clear();
|
|
1908
|
-
}
|
|
1909
|
-
function createWindowInstance(id, app2) {
|
|
1910
|
-
return {
|
|
1911
|
-
id,
|
|
1912
|
-
show: () => {
|
|
1913
|
-
console.log(`[stx/desktop] Window ${id} shown`);
|
|
1914
|
-
},
|
|
1915
|
-
hide: () => {
|
|
1916
|
-
console.log(`[stx/desktop] To hide window, use window.craft.window.hide() from inside the webview`);
|
|
1917
|
-
},
|
|
1918
|
-
close: () => {
|
|
1919
|
-
const windowData = activeWindows.get(id);
|
|
1920
|
-
if (windowData?.app) {
|
|
1921
|
-
windowData.app.close();
|
|
1922
|
-
activeWindows.delete(id);
|
|
1923
|
-
console.log(`[stx/desktop] Window ${id} closed`);
|
|
1924
|
-
}
|
|
1925
|
-
},
|
|
1926
|
-
focus: () => {
|
|
1927
|
-
console.log(`[stx/desktop] To focus window, use window.craft.window.focus() from inside the webview`);
|
|
1928
|
-
},
|
|
1929
|
-
minimize: () => {
|
|
1930
|
-
console.log(`[stx/desktop] To minimize window, use window.craft.window.minimize() from inside the webview`);
|
|
1931
|
-
},
|
|
1932
|
-
maximize: () => {
|
|
1933
|
-
console.log(`[stx/desktop] To maximize window, use window.craft.window.maximize() from inside the webview`);
|
|
1934
|
-
},
|
|
1935
|
-
restore: () => {
|
|
1936
|
-
console.log(`[stx/desktop] To restore window, use window.craft.window.show() from inside the webview`);
|
|
1937
|
-
},
|
|
1938
|
-
setTitle: (title) => {
|
|
1939
|
-
console.log(`[stx/desktop] To set title, use window.craft.window.setTitle({ title: "${title}" }) from inside the webview`);
|
|
1940
|
-
},
|
|
1941
|
-
loadURL: (url) => {
|
|
1942
|
-
console.log(`[stx/desktop] To navigate, use window.location.href = "${url}" from inside the webview`);
|
|
1943
|
-
},
|
|
1944
|
-
reload: () => {
|
|
1945
|
-
console.log(`[stx/desktop] To reload, use window.craft.window.reload() from inside the webview`);
|
|
1946
|
-
}
|
|
1947
|
-
};
|
|
1948
|
-
}
|
|
1949
|
-
function craftWindowArguments(url, options = {}) {
|
|
1950
|
-
const args = [
|
|
1951
|
-
"--url",
|
|
1952
|
-
url,
|
|
1953
|
-
"--title",
|
|
1954
|
-
options.title || "stx Desktop",
|
|
1955
|
-
"--width",
|
|
1956
|
-
String(options.width ?? 1200),
|
|
1957
|
-
"--height",
|
|
1958
|
-
String(options.height ?? 800)
|
|
1959
|
-
];
|
|
1960
|
-
if (options.darkMode)
|
|
1961
|
-
args.push("--dark");
|
|
1962
|
-
if (options.hotReload)
|
|
1963
|
-
args.push("--hot-reload");
|
|
1964
|
-
if (options.resizable === false)
|
|
1965
|
-
args.push("--no-resize");
|
|
1966
|
-
if (options.frameless)
|
|
1967
|
-
args.push("--frameless");
|
|
1968
|
-
if (options.alwaysOnTop)
|
|
1969
|
-
args.push("--always-on-top");
|
|
1970
|
-
if (options.titlebarHidden)
|
|
1971
|
-
args.push("--titlebar-hidden");
|
|
1972
|
-
if (options.systemTray)
|
|
1973
|
-
args.push("--system-tray");
|
|
1974
|
-
if (options.hideDockIcon)
|
|
1975
|
-
args.push("--hide-dock-icon");
|
|
1976
|
-
if (options.devTools === false)
|
|
1977
|
-
args.push("--no-devtools");
|
|
1978
|
-
if (options.nativeSidebar)
|
|
1979
|
-
args.push("--native-sidebar");
|
|
1980
|
-
if (options.sidebarWidth !== undefined)
|
|
1981
|
-
args.push("--sidebar-width", String(options.sidebarWidth));
|
|
1982
|
-
const sidebarConfig = prepareSidebarConfig(options);
|
|
1983
|
-
if (sidebarConfig)
|
|
1984
|
-
args.push("--sidebar-config", JSON.stringify(sidebarConfig));
|
|
1985
|
-
return args;
|
|
1986
|
-
}
|
|
1987
|
-
async function createWindow(url, options = {}) {
|
|
1988
|
-
const id = `craft-window-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1989
|
-
const craftPath = getCraftBinaryPath();
|
|
1990
|
-
try {
|
|
1991
|
-
const { createApp } = await import("craft-native");
|
|
1992
|
-
const app2 = createApp({
|
|
1993
|
-
url,
|
|
1994
|
-
craftPath,
|
|
1995
|
-
window: {
|
|
1996
|
-
title: options.title || "stx Desktop",
|
|
1997
|
-
width: options.width ?? 1200,
|
|
1998
|
-
height: options.height ?? 800,
|
|
1999
|
-
darkMode: options.darkMode ?? false,
|
|
2000
|
-
hotReload: options.hotReload ?? false,
|
|
2001
|
-
resizable: options.resizable ?? true,
|
|
2002
|
-
frameless: options.frameless ?? false,
|
|
2003
|
-
alwaysOnTop: options.alwaysOnTop ?? false,
|
|
2004
|
-
titlebarHidden: options.titlebarHidden ?? false,
|
|
2005
|
-
systemTray: options.systemTray ?? false,
|
|
2006
|
-
hideDockIcon: options.hideDockIcon ?? false,
|
|
2007
|
-
devTools: options.devTools ?? false,
|
|
2008
|
-
nativeSidebar: options.nativeSidebar ?? false,
|
|
2009
|
-
sidebarWidth: options.sidebarWidth,
|
|
2010
|
-
sidebarConfig: prepareSidebarConfig(options)
|
|
2011
|
-
}
|
|
2012
|
-
});
|
|
2013
|
-
activeWindows.set(id, { app: app2, url, options });
|
|
2014
|
-
await app2.show();
|
|
2015
|
-
return createWindowInstance(id, app2);
|
|
2016
|
-
} catch {
|
|
2017
|
-
try {
|
|
2018
|
-
const { spawn } = await import("child_process");
|
|
2019
|
-
const child = spawn(craftPath, craftWindowArguments(url, options), { stdio: "inherit" });
|
|
2020
|
-
child.on("error", (err) => {
|
|
2021
|
-
console.error(err.code === "ENOENT" ? craftBinaryNotFoundMessage(craftPath) : `craft child error: ${err.message}`);
|
|
2022
|
-
});
|
|
2023
|
-
const app2 = { close: () => child.kill() };
|
|
2024
|
-
activeWindows.set(id, { app: app2, url, options });
|
|
2025
|
-
return createWindowInstance(id, app2);
|
|
2026
|
-
} catch (binaryError) {
|
|
2027
|
-
console.error("Failed to spawn craft binary:", binaryError.message);
|
|
2028
|
-
return null;
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
async function openDevWindow(port, options = {}) {
|
|
2033
|
-
const url = `http://localhost:${port}/`;
|
|
2034
|
-
const isTestEnv = process3.env.NODE_ENV === "test" || process3.env.BUN_TEST;
|
|
2035
|
-
if (isTestEnv) {
|
|
2036
|
-
console.warn("\u26A0 Skipping native window in test environment");
|
|
2037
|
-
console.log("(Skipping browser fallback in test environment)");
|
|
2038
|
-
return false;
|
|
2039
|
-
}
|
|
2040
|
-
try {
|
|
2041
|
-
const { createApp } = await import("craft-native");
|
|
2042
|
-
console.log("\u26A1 Opening native window via craft-native\u2026");
|
|
2043
|
-
const useSystemTray = !options.nativeSidebar;
|
|
2044
|
-
const sidebarConfig = prepareSidebarConfig(options);
|
|
2045
|
-
const app2 = createApp({
|
|
2046
|
-
url,
|
|
2047
|
-
craftPath: getCraftBinaryPath(),
|
|
2048
|
-
window: {
|
|
2049
|
-
title: options.title || "stx Development",
|
|
2050
|
-
width: options.width || 1400,
|
|
2051
|
-
height: options.height || 900,
|
|
2052
|
-
resizable: true,
|
|
2053
|
-
systemTray: useSystemTray,
|
|
2054
|
-
darkMode: options.darkMode ?? true,
|
|
2055
|
-
hotReload: options.hotReload ?? true,
|
|
2056
|
-
devTools: true,
|
|
2057
|
-
titlebarHidden: options.titlebarHidden ?? false,
|
|
2058
|
-
nativeSidebar: options.nativeSidebar ?? false,
|
|
2059
|
-
sidebarWidth: options.sidebarWidth ?? 260,
|
|
2060
|
-
sidebarConfig
|
|
2061
|
-
}
|
|
2062
|
-
});
|
|
2063
|
-
const id = `dev-window-${port}`;
|
|
2064
|
-
activeWindows.set(id, { app: app2, url, options });
|
|
2065
|
-
await app2.show();
|
|
2066
|
-
console.log(`\u2713 Native window opened at ${url}`);
|
|
2067
|
-
return true;
|
|
2068
|
-
} catch {
|
|
2069
|
-
const craftPath = getCraftBinaryPath();
|
|
2070
|
-
try {
|
|
2071
|
-
console.log(`\u26A1 Opening native window via craft binary (${craftPath})\u2026`);
|
|
2072
|
-
const { spawn } = await import("child_process");
|
|
2073
|
-
const child = spawn(craftPath, craftWindowArguments(url, {
|
|
2074
|
-
title: "stx Development",
|
|
2075
|
-
width: 1400,
|
|
2076
|
-
height: 900,
|
|
2077
|
-
hotReload: true,
|
|
2078
|
-
...options
|
|
2079
|
-
}), { stdio: "inherit" });
|
|
2080
|
-
child.on("exit", () => process3.exit(0));
|
|
2081
|
-
child.on("error", (err) => {
|
|
2082
|
-
console.warn(err.code === "ENOENT" ? craftBinaryNotFoundMessage(craftPath) : `craft child error: ${err.message}`);
|
|
2083
|
-
});
|
|
2084
|
-
const id = `dev-window-${port}`;
|
|
2085
|
-
activeWindows.set(id, { app: { close: () => child.kill() }, url, options });
|
|
2086
|
-
console.log(`\u2713 Native window opened at ${url}`);
|
|
2087
|
-
return true;
|
|
2088
|
-
} catch (binaryErr) {
|
|
2089
|
-
console.warn("\u26A0 Could not spawn craft binary:", binaryErr.message);
|
|
2090
|
-
}
|
|
2091
|
-
if (process3.env.NODE_ENV === "test" || process3.env.BUN_TEST) {
|
|
2092
|
-
console.log("(Skipping browser fallback in test environment)");
|
|
2093
|
-
return false;
|
|
2094
|
-
}
|
|
2095
|
-
console.log("\uD83D\uDCF1 Opening in browser instead\u2026");
|
|
2096
|
-
try {
|
|
2097
|
-
const { spawn } = await import("child_process");
|
|
2098
|
-
const platform = process3.platform;
|
|
2099
|
-
const command = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
|
|
2100
|
-
const args = platform === "win32" ? ["/c", "start", url] : [url];
|
|
2101
|
-
spawn(command, args, { detached: true, stdio: "ignore" }).unref();
|
|
2102
|
-
console.log(`\u2713 Browser opened at ${url}`);
|
|
2103
|
-
return true;
|
|
2104
|
-
} catch (browserError) {
|
|
2105
|
-
console.error("Could not open browser:", browserError);
|
|
2106
|
-
console.log(`Please open manually: ${url}`);
|
|
2107
|
-
return false;
|
|
2108
|
-
}
|
|
2109
|
-
}
|
|
2110
|
-
}
|
|
2111
|
-
async function createWindowWithHTML(html, options = {}) {
|
|
2112
|
-
const {
|
|
2113
|
-
title = "stx Desktop",
|
|
2114
|
-
width = 1200,
|
|
2115
|
-
height = 800,
|
|
2116
|
-
darkMode = false,
|
|
2117
|
-
hotReload = false,
|
|
2118
|
-
resizable = true,
|
|
2119
|
-
frameless = false,
|
|
2120
|
-
alwaysOnTop = false
|
|
2121
|
-
} = options;
|
|
2122
|
-
try {
|
|
2123
|
-
const { createApp } = await import("craft-native");
|
|
2124
|
-
const craftPath = getCraftBinaryPath();
|
|
2125
|
-
const app2 = createApp({
|
|
2126
|
-
html,
|
|
2127
|
-
craftPath,
|
|
2128
|
-
window: {
|
|
2129
|
-
title,
|
|
2130
|
-
width,
|
|
2131
|
-
height,
|
|
2132
|
-
darkMode,
|
|
2133
|
-
hotReload,
|
|
2134
|
-
resizable,
|
|
2135
|
-
frameless,
|
|
2136
|
-
alwaysOnTop
|
|
2137
|
-
}
|
|
2138
|
-
});
|
|
2139
|
-
const id = `craft-window-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
2140
|
-
activeWindows.set(id, { app: app2, url: "html-content", options });
|
|
2141
|
-
await app2.show();
|
|
2142
|
-
return createWindowInstance(id, app2);
|
|
2143
|
-
} catch (error) {
|
|
2144
|
-
console.error("Failed to create window with HTML:", error);
|
|
2145
|
-
return null;
|
|
2146
|
-
}
|
|
2147
|
-
}
|
|
2148
|
-
function isWebviewAvailable() {
|
|
2149
|
-
try {
|
|
2150
|
-
__require.resolve("craft-native");
|
|
2151
|
-
return true;
|
|
2152
|
-
} catch {
|
|
2153
|
-
return false;
|
|
2154
|
-
}
|
|
2155
|
-
}
|
|
2156
|
-
function getWindowBridgeScript() {
|
|
2157
|
-
return `
|
|
519
|
+
`;import P from"process";import{existsSync as XY}from"fs";import{dirname as $Y,join as GY}from"path";import{craftBinaryNotFoundMessage as a,resolveCraftBinary as JY}from"craft-native";var k={};function qY(Y){k={...k,...Y}}function RY(){return{...k}}function UY(){k={}}function b(Y){if(!Y.sidebarConfig)return;let Q={...Y.sidebarConfig};if(Q.variant==="desktop")Q.material=Q.material??"sidebar",Q.backgroundEffect=Q.backgroundEffect??"shimmer",Q.allowsVibrancy=Q.allowsVibrancy??!0;return Q}function w(){let Y=[P.env.CRAFT_BINARY_PATH,k.craftBinaryPath,...k.additionalSearchPaths||[],GY($Y(P.execPath),"craft")];for(let Q of Y)if(Q&&XY(Q))return Q;return JY()}var W=new Map;function KY(){return Array.from(W.keys())}function _Y(Y){let Q=W.get(Y);if(!Q)return null;return f(Y,Q.app)}function EY(){for(let[Y,Q]of W)try{Q.app?.close?.()}catch(Z){console.warn(`Failed to close window ${Y}:`,Z)}W.clear()}function f(Y,Q){return{id:Y,show:()=>{console.log(`[stx/desktop] Window ${Y} shown`)},hide:()=>{console.log("[stx/desktop] To hide window, use window.craft.window.hide() from inside the webview")},close:()=>{let Z=W.get(Y);if(Z?.app)Z.app.close(),W.delete(Y),console.log(`[stx/desktop] Window ${Y} closed`)},focus:()=>{console.log("[stx/desktop] To focus window, use window.craft.window.focus() from inside the webview")},minimize:()=>{console.log("[stx/desktop] To minimize window, use window.craft.window.minimize() from inside the webview")},maximize:()=>{console.log("[stx/desktop] To maximize window, use window.craft.window.maximize() from inside the webview")},restore:()=>{console.log("[stx/desktop] To restore window, use window.craft.window.show() from inside the webview")},setTitle:(Z)=>{console.log(`[stx/desktop] To set title, use window.craft.window.setTitle({ title: "${Z}" }) from inside the webview`)},loadURL:(Z)=>{console.log(`[stx/desktop] To navigate, use window.location.href = "${Z}" from inside the webview`)},reload:()=>{console.log("[stx/desktop] To reload, use window.craft.window.reload() from inside the webview")}}}function u(Y,Q={}){let Z=["--url",Y,"--title",Q.title||"stx Desktop","--width",String(Q.width??1200),"--height",String(Q.height??800)];if(Q.darkMode)Z.push("--dark");if(Q.hotReload)Z.push("--hot-reload");if(Q.resizable===!1)Z.push("--no-resize");if(Q.frameless)Z.push("--frameless");if(Q.alwaysOnTop)Z.push("--always-on-top");if(Q.titlebarHidden)Z.push("--titlebar-hidden");if(Q.systemTray)Z.push("--system-tray");if(Q.hideDockIcon)Z.push("--hide-dock-icon");if(Q.devTools===!1)Z.push("--no-devtools");if(Q.nativeSidebar)Z.push("--native-sidebar");if(Q.sidebarWidth!==void 0)Z.push("--sidebar-width",String(Q.sidebarWidth));let X=b(Q);if(X)Z.push("--sidebar-config",JSON.stringify(X));return Z}async function BY(Y,Q={}){let Z=`craft-window-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,X=w();try{let{createApp:$}=await import("craft-native"),J=$({url:Y,craftPath:X,window:{title:Q.title||"stx Desktop",width:Q.width??1200,height:Q.height??800,darkMode:Q.darkMode??!1,hotReload:Q.hotReload??!1,resizable:Q.resizable??!0,frameless:Q.frameless??!1,alwaysOnTop:Q.alwaysOnTop??!1,titlebarHidden:Q.titlebarHidden??!1,systemTray:Q.systemTray??!1,hideDockIcon:Q.hideDockIcon??!1,devTools:Q.devTools??!1,nativeSidebar:Q.nativeSidebar??!1,sidebarWidth:Q.sidebarWidth,sidebarConfig:b(Q)}});return W.set(Z,{app:J,url:Y,options:Q}),await J.show(),f(Z,J)}catch{try{let{spawn:$}=await import("child_process"),J=$(X,u(Y,Q),{stdio:"inherit"});J.on("error",(q)=>{console.error(q.code==="ENOENT"?a(X):`craft child error: ${q.message}`)});let U={close:()=>J.kill()};return W.set(Z,{app:U,url:Y,options:Q}),f(Z,U)}catch($){return console.error("Failed to spawn craft binary:",$.message),null}}}async function FY(Y,Q={}){let Z=`http://localhost:${Y}/`;if(P.env.NODE_ENV==="test"||P.env.BUN_TEST)return console.warn("\u26A0 Skipping native window in test environment"),console.log("(Skipping browser fallback in test environment)"),!1;try{let{createApp:$}=await import("craft-native");console.log("\u26A1 Opening native window via craft-native\u2026");let J=!Q.nativeSidebar,U=b(Q),q=$({url:Z,craftPath:w(),window:{title:Q.title||"stx Development",width:Q.width||1400,height:Q.height||900,resizable:!0,systemTray:J,darkMode:Q.darkMode??!0,hotReload:Q.hotReload??!0,devTools:!0,titlebarHidden:Q.titlebarHidden??!1,nativeSidebar:Q.nativeSidebar??!1,sidebarWidth:Q.sidebarWidth??260,sidebarConfig:U}}),G=`dev-window-${Y}`;return W.set(G,{app:q,url:Z,options:Q}),await q.show(),console.log(`\u2713 Native window opened at ${Z}`),!0}catch{let $=w();try{console.log(`\u26A1 Opening native window via craft binary (${$})\u2026`);let{spawn:J}=await import("child_process"),U=J($,u(Z,{title:"stx Development",width:1400,height:900,hotReload:!0,...Q}),{stdio:"inherit"});U.on("exit",()=>P.exit(0)),U.on("error",(G)=>{console.warn(G.code==="ENOENT"?a($):`craft child error: ${G.message}`)});let q=`dev-window-${Y}`;return W.set(q,{app:{close:()=>U.kill()},url:Z,options:Q}),console.log(`\u2713 Native window opened at ${Z}`),!0}catch(J){console.warn("\u26A0 Could not spawn craft binary:",J.message)}if(P.env.NODE_ENV==="test"||P.env.BUN_TEST)return console.log("(Skipping browser fallback in test environment)"),!1;console.log("\uD83D\uDCF1 Opening in browser instead\u2026");try{let{spawn:J}=await import("child_process"),U=P.platform;return J(U==="darwin"?"open":U==="win32"?"cmd":"xdg-open",U==="win32"?["/c","start",Z]:[Z],{detached:!0,stdio:"ignore"}).unref(),console.log(`\u2713 Browser opened at ${Z}`),!0}catch(J){return console.error("Could not open browser:",J),console.log(`Please open manually: ${Z}`),!1}}}async function jY(Y,Q={}){let{title:Z="stx Desktop",width:X=1200,height:$=800,darkMode:J=!1,hotReload:U=!1,resizable:q=!0,frameless:G=!1,alwaysOnTop:_=!1}=Q;try{let{createApp:K}=await import("craft-native"),E=w(),R=K({html:Y,craftPath:E,window:{title:Z,width:X,height:$,darkMode:J,hotReload:U,resizable:q,frameless:G,alwaysOnTop:_}}),F=`craft-window-${Date.now()}-${Math.random().toString(36).slice(2,8)}`;return W.set(F,{app:R,url:"html-content",options:Q}),await R.show(),f(F,R)}catch(K){return console.error("Failed to create window with HTML:",K),null}}function DY(){try{return N.resolve("craft-native"),!0}catch{return!1}}function VY(){return`
|
|
2158
520
|
// STX Desktop Window Bridge
|
|
2159
521
|
// Provides convenient wrappers around window.craft APIs
|
|
2160
522
|
window.stxWindow = {
|
|
@@ -2195,570 +557,30 @@ window.stxWindow = {
|
|
|
2195
557
|
|
|
2196
558
|
// Expose as global for backwards compatibility
|
|
2197
559
|
window.desktop = window.stxWindow;
|
|
2198
|
-
|
|
2199
|
-
}
|
|
2200
|
-
// src/packaging.ts
|
|
2201
|
-
import { pack, packageApp } from "craft-native";
|
|
2202
|
-
import { craftBinaryNotFoundMessage as craftBinaryNotFoundMessage2, resolveCraftBinary as resolveCraftBinary2 } from "craft-native";
|
|
2203
|
-
// src/self-update.ts
|
|
2204
|
-
import { AutoUpdater, generateUpdateManifest } from "craft-native";
|
|
2205
|
-
var UPDATE_MANIFEST_ASSET = "update.json";
|
|
2206
|
-
function githubLatestAssetUrl(repository, asset) {
|
|
2207
|
-
return `https://github.com/${repository}/releases/latest/download/${asset}`;
|
|
2208
|
-
}
|
|
2209
|
-
function githubReleaseAssetUrl(repository, tag, asset) {
|
|
2210
|
-
return `https://github.com/${repository}/releases/download/${tag}/${asset}`;
|
|
2211
|
-
}
|
|
2212
|
-
function createGitHubUpdater(options) {
|
|
2213
|
-
const { repository, manifestAsset = UPDATE_MANIFEST_ASSET, ...config } = options;
|
|
2214
|
-
return new AutoUpdater({
|
|
2215
|
-
...config,
|
|
2216
|
-
updateUrl: githubLatestAssetUrl(repository, manifestAsset)
|
|
2217
|
-
});
|
|
2218
|
-
}
|
|
2219
|
-
function createGitHubUpdateManifest(options) {
|
|
2220
|
-
const tag = options.tag ?? `v${options.version}`;
|
|
2221
|
-
const platforms = {};
|
|
2222
|
-
for (const [platform, path] of Object.entries(options.artifacts)) {
|
|
2223
|
-
if (!path)
|
|
2224
|
-
continue;
|
|
2225
|
-
platforms[platform] = {
|
|
2226
|
-
path,
|
|
2227
|
-
url: githubReleaseAssetUrl(options.repository, tag, path.split("/").pop())
|
|
2228
|
-
};
|
|
2229
|
-
}
|
|
2230
|
-
return generateUpdateManifest({
|
|
2231
|
-
version: options.version,
|
|
2232
|
-
releaseNotes: options.releaseNotes,
|
|
2233
|
-
platforms
|
|
2234
|
-
});
|
|
2235
|
-
}
|
|
2236
|
-
// src/preferences.ts
|
|
2237
|
-
import { existsSync as existsSync2, mkdirSync, readFileSync, watch, writeFileSync } from "fs";
|
|
2238
|
-
import { homedir, platform } from "os";
|
|
2239
|
-
import { dirname as dirname2, join as join2 } from "path";
|
|
2240
|
-
function getDefaultPrefsDir(appName) {
|
|
2241
|
-
const os = platform();
|
|
2242
|
-
const home = homedir();
|
|
2243
|
-
switch (os) {
|
|
2244
|
-
case "darwin":
|
|
2245
|
-
return join2(home, "Library", "Application Support", appName);
|
|
2246
|
-
case "win32":
|
|
2247
|
-
return join2(process.env.APPDATA || join2(home, "AppData", "Roaming"), appName);
|
|
2248
|
-
default:
|
|
2249
|
-
return join2(home, ".config", appName);
|
|
2250
|
-
}
|
|
2251
|
-
}
|
|
2252
|
-
|
|
2253
|
-
class PreferencesImpl {
|
|
2254
|
-
_defaults;
|
|
2255
|
-
_data;
|
|
2256
|
-
_path;
|
|
2257
|
-
_changeHandlers = new Map;
|
|
2258
|
-
_anyChangeHandlers = new Set;
|
|
2259
|
-
_watcher = null;
|
|
2260
|
-
_writeTimer = null;
|
|
2261
|
-
_writing = false;
|
|
2262
|
-
constructor(options) {
|
|
2263
|
-
this._defaults = { ...options.defaults };
|
|
2264
|
-
const dir = options.path ? dirname2(options.path) : getDefaultPrefsDir(options.name);
|
|
2265
|
-
this._path = options.path || join2(dir, "preferences.json");
|
|
2266
|
-
if (!existsSync2(dir)) {
|
|
2267
|
-
mkdirSync(dir, { recursive: true });
|
|
2268
|
-
}
|
|
2269
|
-
this._data = this._load();
|
|
2270
|
-
if (options.watch !== false) {
|
|
2271
|
-
this._setupWatcher();
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
get path() {
|
|
2275
|
-
return this._path;
|
|
2276
|
-
}
|
|
2277
|
-
get(key) {
|
|
2278
|
-
if (key in this._data) {
|
|
2279
|
-
return this._data[key];
|
|
2280
|
-
}
|
|
2281
|
-
return this._defaults[key];
|
|
2282
|
-
}
|
|
2283
|
-
set(key, value) {
|
|
2284
|
-
const oldValue = this.get(key);
|
|
2285
|
-
if (JSON.stringify(oldValue) === JSON.stringify(value))
|
|
2286
|
-
return;
|
|
2287
|
-
this._data[key] = value;
|
|
2288
|
-
this._scheduleSave();
|
|
2289
|
-
this._notifyChange(key, value, oldValue);
|
|
2290
|
-
}
|
|
2291
|
-
getAll() {
|
|
2292
|
-
return { ...this._defaults, ...this._data };
|
|
2293
|
-
}
|
|
2294
|
-
has(key) {
|
|
2295
|
-
return key in this._data;
|
|
2296
|
-
}
|
|
2297
|
-
delete(key) {
|
|
2298
|
-
if (!(key in this._data))
|
|
2299
|
-
return;
|
|
2300
|
-
const oldValue = this._data[key];
|
|
2301
|
-
delete this._data[key];
|
|
2302
|
-
this._scheduleSave();
|
|
2303
|
-
this._notifyChange(key, this._defaults[key], oldValue);
|
|
2304
|
-
}
|
|
2305
|
-
reset() {
|
|
2306
|
-
const oldData = { ...this._data };
|
|
2307
|
-
this._data = {};
|
|
2308
|
-
this._save();
|
|
2309
|
-
for (const key of Object.keys(oldData)) {
|
|
2310
|
-
const defaultVal = this._defaults[key];
|
|
2311
|
-
this._notifyChange(key, defaultVal, oldData[key]);
|
|
2312
|
-
}
|
|
2313
|
-
}
|
|
2314
|
-
onChange(key, handler) {
|
|
2315
|
-
const keyStr = key;
|
|
2316
|
-
if (!this._changeHandlers.has(keyStr)) {
|
|
2317
|
-
this._changeHandlers.set(keyStr, new Set);
|
|
2318
|
-
}
|
|
2319
|
-
this._changeHandlers.get(keyStr).add(handler);
|
|
2320
|
-
return () => {
|
|
2321
|
-
this._changeHandlers.get(keyStr)?.delete(handler);
|
|
2322
|
-
};
|
|
2323
|
-
}
|
|
2324
|
-
onAnyChange(handler) {
|
|
2325
|
-
this._anyChangeHandlers.add(handler);
|
|
2326
|
-
return () => {
|
|
2327
|
-
this._anyChangeHandlers.delete(handler);
|
|
2328
|
-
};
|
|
2329
|
-
}
|
|
2330
|
-
close() {
|
|
2331
|
-
if (this._watcher) {
|
|
2332
|
-
this._watcher.close();
|
|
2333
|
-
this._watcher = null;
|
|
2334
|
-
}
|
|
2335
|
-
if (this._writeTimer) {
|
|
2336
|
-
clearTimeout(this._writeTimer);
|
|
2337
|
-
this._writeTimer = null;
|
|
2338
|
-
this._save();
|
|
2339
|
-
}
|
|
2340
|
-
}
|
|
2341
|
-
_load() {
|
|
2342
|
-
try {
|
|
2343
|
-
if (existsSync2(this._path)) {
|
|
2344
|
-
const content = readFileSync(this._path, "utf-8");
|
|
2345
|
-
return JSON.parse(content);
|
|
2346
|
-
}
|
|
2347
|
-
} catch {}
|
|
2348
|
-
return {};
|
|
2349
|
-
}
|
|
2350
|
-
_save() {
|
|
2351
|
-
this._writing = true;
|
|
2352
|
-
try {
|
|
2353
|
-
const json = JSON.stringify({ ...this._defaults, ...this._data }, null, 2);
|
|
2354
|
-
writeFileSync(this._path, json, "utf-8");
|
|
2355
|
-
} catch (err) {
|
|
2356
|
-
console.error(`Failed to save preferences to ${this._path}:`, err);
|
|
2357
|
-
} finally {
|
|
2358
|
-
setTimeout(() => {
|
|
2359
|
-
this._writing = false;
|
|
2360
|
-
}, 100);
|
|
2361
|
-
}
|
|
2362
|
-
}
|
|
2363
|
-
_scheduleSave() {
|
|
2364
|
-
if (this._writeTimer) {
|
|
2365
|
-
clearTimeout(this._writeTimer);
|
|
2366
|
-
}
|
|
2367
|
-
this._writeTimer = setTimeout(() => {
|
|
2368
|
-
this._writeTimer = null;
|
|
2369
|
-
this._save();
|
|
2370
|
-
}, 50);
|
|
2371
|
-
}
|
|
2372
|
-
_setupWatcher() {
|
|
2373
|
-
try {
|
|
2374
|
-
if (!existsSync2(this._path)) {
|
|
2375
|
-
this._save();
|
|
2376
|
-
}
|
|
2377
|
-
this._watcher = watch(this._path, () => {
|
|
2378
|
-
if (this._writing)
|
|
2379
|
-
return;
|
|
2380
|
-
const newData = this._load();
|
|
2381
|
-
const oldData = { ...this._data };
|
|
2382
|
-
this._data = newData;
|
|
2383
|
-
const allKeys = new Set([...Object.keys(oldData), ...Object.keys(newData)]);
|
|
2384
|
-
for (const key of allKeys) {
|
|
2385
|
-
const oldVal = key in oldData ? oldData[key] : this._defaults[key];
|
|
2386
|
-
const newVal = key in newData ? newData[key] : this._defaults[key];
|
|
2387
|
-
if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
|
2388
|
-
this._notifyChange(key, newVal, oldVal);
|
|
2389
|
-
}
|
|
2390
|
-
}
|
|
2391
|
-
});
|
|
2392
|
-
} catch {}
|
|
2393
|
-
}
|
|
2394
|
-
_notifyChange(key, value, oldValue) {
|
|
2395
|
-
const handlers = this._changeHandlers.get(key);
|
|
2396
|
-
if (handlers) {
|
|
2397
|
-
for (const handler of handlers) {
|
|
2398
|
-
try {
|
|
2399
|
-
handler(value, oldValue);
|
|
2400
|
-
} catch {}
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
for (const handler of this._anyChangeHandlers) {
|
|
2404
|
-
try {
|
|
2405
|
-
handler(key, value, oldValue);
|
|
2406
|
-
} catch {}
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
}
|
|
2410
|
-
function createPreferences(options) {
|
|
2411
|
-
return new PreferencesImpl(options);
|
|
2412
|
-
}
|
|
2413
|
-
// src/autolaunch.ts
|
|
2414
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
2415
|
-
import { homedir as homedir2, platform as platform2 } from "os";
|
|
2416
|
-
import { join as join3 } from "path";
|
|
2417
|
-
function getLaunchAgentPath(appName) {
|
|
2418
|
-
const identifier = appName.toLowerCase().replace(/[^a-z0-9]/g, "-");
|
|
2419
|
-
return join3(homedir2(), "Library", "LaunchAgents", `com.${identifier}.plist`);
|
|
2420
|
-
}
|
|
2421
|
-
function getLinuxAutostartPath(appName) {
|
|
2422
|
-
const configDir = process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config");
|
|
2423
|
-
return join3(configDir, "autostart", `${appName.toLowerCase()}.desktop`);
|
|
2424
|
-
}
|
|
2425
|
-
async function setAutoLaunchMacOS(enabled, options) {
|
|
2426
|
-
const appName = options.appName || "StxApp";
|
|
2427
|
-
const plistPath = getLaunchAgentPath(appName);
|
|
2428
|
-
const launchAgentsDir = join3(homedir2(), "Library", "LaunchAgents");
|
|
2429
|
-
if (enabled) {
|
|
2430
|
-
const appPath = options.appPath || process.execPath;
|
|
2431
|
-
const args = options.args || [];
|
|
2432
|
-
const programArgs = [appPath, ...args];
|
|
2433
|
-
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
560
|
+
`}import{pack as LY,packageApp as OY}from"craft-native";import{craftBinaryNotFoundMessage as zY,resolveCraftBinary as MY}from"craft-native";import{AutoUpdater as i,generateUpdateManifest as s}from"craft-native";var t="update.json";function e(Y,Q){return`https://github.com/${Y}/releases/latest/download/${Q}`}function QQ(Y,Q,Z){return`https://github.com/${Y}/releases/download/${Q}/${Z}`}function TY(Y){let{repository:Q,manifestAsset:Z=t,...X}=Y;return new i({...X,updateUrl:e(Q,Z)})}function WY(Y){let Q=Y.tag??`v${Y.version}`,Z={};for(let[X,$]of Object.entries(Y.artifacts)){if(!$)continue;Z[X]={path:$,url:QQ(Y.repository,Q,$.split("/").pop())}}return s({version:Y.version,releaseNotes:Y.releaseNotes,platforms:Z})}import{existsSync as y,mkdirSync as PY,readFileSync as AY,watch as NY,writeFileSync as kY}from"fs";import{homedir as xY,platform as CY}from"os";import{dirname as IY,join as H}from"path";function HY(Y){let Q=CY(),Z=xY();switch(Q){case"darwin":return H(Z,"Library","Application Support",Y);case"win32":return H(process.env.APPDATA||H(Z,"AppData","Roaming"),Y);default:return H(Z,".config",Y)}}class YQ{_defaults;_data;_path;_changeHandlers=new Map;_anyChangeHandlers=new Set;_watcher=null;_writeTimer=null;_writing=!1;constructor(Y){this._defaults={...Y.defaults};let Q=Y.path?IY(Y.path):HY(Y.name);if(this._path=Y.path||H(Q,"preferences.json"),!y(Q))PY(Q,{recursive:!0});if(this._data=this._load(),Y.watch!==!1)this._setupWatcher()}get path(){return this._path}get(Y){if(Y in this._data)return this._data[Y];return this._defaults[Y]}set(Y,Q){let Z=this.get(Y);if(JSON.stringify(Z)===JSON.stringify(Q))return;this._data[Y]=Q,this._scheduleSave(),this._notifyChange(Y,Q,Z)}getAll(){return{...this._defaults,...this._data}}has(Y){return Y in this._data}delete(Y){if(!(Y in this._data))return;let Q=this._data[Y];delete this._data[Y],this._scheduleSave(),this._notifyChange(Y,this._defaults[Y],Q)}reset(){let Y={...this._data};this._data={},this._save();for(let Q of Object.keys(Y)){let Z=this._defaults[Q];this._notifyChange(Q,Z,Y[Q])}}onChange(Y,Q){let Z=Y;if(!this._changeHandlers.has(Z))this._changeHandlers.set(Z,new Set);return this._changeHandlers.get(Z).add(Q),()=>{this._changeHandlers.get(Z)?.delete(Q)}}onAnyChange(Y){return this._anyChangeHandlers.add(Y),()=>{this._anyChangeHandlers.delete(Y)}}close(){if(this._watcher)this._watcher.close(),this._watcher=null;if(this._writeTimer)clearTimeout(this._writeTimer),this._writeTimer=null,this._save()}_load(){try{if(y(this._path)){let Y=AY(this._path,"utf-8");return JSON.parse(Y)}}catch{}return{}}_save(){this._writing=!0;try{let Y=JSON.stringify({...this._defaults,...this._data},null,2);kY(this._path,Y,"utf-8")}catch(Y){console.error(`Failed to save preferences to ${this._path}:`,Y)}finally{setTimeout(()=>{this._writing=!1},100)}}_scheduleSave(){if(this._writeTimer)clearTimeout(this._writeTimer);this._writeTimer=setTimeout(()=>{this._writeTimer=null,this._save()},50)}_setupWatcher(){try{if(!y(this._path))this._save();this._watcher=NY(this._path,()=>{if(this._writing)return;let Y=this._load(),Q={...this._data};this._data=Y;let Z=new Set([...Object.keys(Q),...Object.keys(Y)]);for(let X of Z){let $=X in Q?Q[X]:this._defaults[X],J=X in Y?Y[X]:this._defaults[X];if(JSON.stringify($)!==JSON.stringify(J))this._notifyChange(X,J,$)}})}catch{}}_notifyChange(Y,Q,Z){let X=this._changeHandlers.get(Y);if(X)for(let $ of X)try{$(Q,Z)}catch{}for(let $ of this._anyChangeHandlers)try{$(Y,Q,Z)}catch{}}}function vY(Y){return new YQ(Y)}import{existsSync as x,mkdirSync as ZQ,readFileSync as wY,unlinkSync as XQ,writeFileSync as $Q}from"fs";import{homedir as S,platform as GQ}from"os";import{join as C}from"path";function JQ(Y){let Q=Y.toLowerCase().replace(/[^a-z0-9]/g,"-");return C(S(),"Library","LaunchAgents",`com.${Q}.plist`)}function qQ(Y){let Q=process.env.XDG_CONFIG_HOME||C(S(),".config");return C(Q,"autostart",`${Y.toLowerCase()}.desktop`)}async function fY(Y,Q){let Z=Q.appName||"StxApp",X=JQ(Z),$=C(S(),"Library","LaunchAgents");if(Y){let J=Q.appPath||process.execPath,U=Q.args||[],q=[J,...U],G=`<?xml version="1.0" encoding="UTF-8"?>
|
|
2434
561
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
2435
562
|
<plist version="1.0">
|
|
2436
563
|
<dict>
|
|
2437
564
|
<key>Label</key>
|
|
2438
|
-
<string>com.${
|
|
565
|
+
<string>com.${Z.toLowerCase().replace(/[^a-z0-9]/g,"-")}</string>
|
|
2439
566
|
<key>ProgramArguments</key>
|
|
2440
567
|
<array>
|
|
2441
|
-
${
|
|
568
|
+
${q.map((_)=>` <string>${uY(_)}</string>`).join(`
|
|
2442
569
|
`)}
|
|
2443
570
|
</array>
|
|
2444
571
|
<key>RunAtLoad</key>
|
|
2445
572
|
<true/>
|
|
2446
573
|
<key>KeepAlive</key>
|
|
2447
574
|
<false/>
|
|
2448
|
-
${
|
|
2449
|
-
<string>Background</string
|
|
575
|
+
${Q.isHidden?` <key>ProcessType</key>
|
|
576
|
+
<string>Background</string>`:""}
|
|
2450
577
|
</dict>
|
|
2451
|
-
</plist>`;
|
|
2452
|
-
if (!existsSync3(launchAgentsDir)) {
|
|
2453
|
-
mkdirSync2(launchAgentsDir, { recursive: true });
|
|
2454
|
-
}
|
|
2455
|
-
writeFileSync2(plistPath, plist, "utf-8");
|
|
2456
|
-
} else {
|
|
2457
|
-
if (existsSync3(plistPath)) {
|
|
2458
|
-
unlinkSync(plistPath);
|
|
2459
|
-
}
|
|
2460
|
-
}
|
|
2461
|
-
}
|
|
2462
|
-
async function setAutoLaunchLinux(enabled, options) {
|
|
2463
|
-
const appName = options.appName || "StxApp";
|
|
2464
|
-
const desktopPath = getLinuxAutostartPath(appName);
|
|
2465
|
-
const autostartDir = join3(process.env.XDG_CONFIG_HOME || join3(homedir2(), ".config"), "autostart");
|
|
2466
|
-
if (enabled) {
|
|
2467
|
-
const appPath = options.appPath || process.execPath;
|
|
2468
|
-
const args = options.args || [];
|
|
2469
|
-
const exec = [appPath, ...args].join(" ");
|
|
2470
|
-
const desktopEntry = `[Desktop Entry]
|
|
578
|
+
</plist>`;if(!x($))ZQ($,{recursive:!0});$Q(X,G,"utf-8")}else if(x(X))XQ(X)}async function SY(Y,Q){let Z=Q.appName||"StxApp",X=qQ(Z),$=C(process.env.XDG_CONFIG_HOME||C(S(),".config"),"autostart");if(Y){let J=Q.appPath||process.execPath,U=Q.args||[],q=[J,...U].join(" "),G=`[Desktop Entry]
|
|
2471
579
|
Type=Application
|
|
2472
|
-
Name=${
|
|
2473
|
-
Exec=${
|
|
580
|
+
Name=${Z}
|
|
581
|
+
Exec=${q}
|
|
2474
582
|
Terminal=false
|
|
2475
583
|
StartupNotify=false
|
|
2476
|
-
${
|
|
2477
|
-
NoDisplay=true
|
|
2478
|
-
`;
|
|
2479
|
-
if (!existsSync3(autostartDir)) {
|
|
2480
|
-
mkdirSync2(autostartDir, { recursive: true });
|
|
2481
|
-
}
|
|
2482
|
-
writeFileSync2(desktopPath, desktopEntry, "utf-8");
|
|
2483
|
-
} else {
|
|
2484
|
-
if (existsSync3(desktopPath)) {
|
|
2485
|
-
unlinkSync(desktopPath);
|
|
2486
|
-
}
|
|
2487
|
-
}
|
|
2488
|
-
}
|
|
2489
|
-
async function isAutoLaunchEnabledMacOS(appName) {
|
|
2490
|
-
return existsSync3(getLaunchAgentPath(appName));
|
|
2491
|
-
}
|
|
2492
|
-
async function isAutoLaunchEnabledLinux(appName) {
|
|
2493
|
-
const path = getLinuxAutostartPath(appName);
|
|
2494
|
-
if (!existsSync3(path))
|
|
2495
|
-
return false;
|
|
2496
|
-
try {
|
|
2497
|
-
const content = readFileSync2(path, "utf-8");
|
|
2498
|
-
if (content.includes("X-GNOME-Autostart-enabled=false"))
|
|
2499
|
-
return false;
|
|
2500
|
-
if (content.includes("Hidden=true"))
|
|
2501
|
-
return false;
|
|
2502
|
-
return true;
|
|
2503
|
-
} catch {
|
|
2504
|
-
return false;
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
function escapeXml(str) {
|
|
2508
|
-
return str.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
2509
|
-
}
|
|
2510
|
-
async function setAutoLaunch(enabled, options = {}) {
|
|
2511
|
-
const os = platform2();
|
|
2512
|
-
switch (os) {
|
|
2513
|
-
case "darwin":
|
|
2514
|
-
return setAutoLaunchMacOS(enabled, options);
|
|
2515
|
-
case "linux":
|
|
2516
|
-
return setAutoLaunchLinux(enabled, options);
|
|
2517
|
-
default:
|
|
2518
|
-
throw new Error(`Auto-launch is not yet supported on ${os}`);
|
|
2519
|
-
}
|
|
2520
|
-
}
|
|
2521
|
-
async function isAutoLaunchEnabled(appName) {
|
|
2522
|
-
const name = appName || "StxApp";
|
|
2523
|
-
const os = platform2();
|
|
2524
|
-
switch (os) {
|
|
2525
|
-
case "darwin":
|
|
2526
|
-
return isAutoLaunchEnabledMacOS(name);
|
|
2527
|
-
case "linux":
|
|
2528
|
-
return isAutoLaunchEnabledLinux(name);
|
|
2529
|
-
default:
|
|
2530
|
-
return false;
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
// src/system.ts
|
|
2534
|
-
var system = {
|
|
2535
|
-
accentColor: () => bridgeOr("system", "accentColor", () => ""),
|
|
2536
|
-
highlightColor: () => bridgeOr("system", "highlightColor", () => ""),
|
|
2537
|
-
language: () => bridgeOr("system", "language", () => {
|
|
2538
|
-
if (typeof navigator === "undefined")
|
|
2539
|
-
return "";
|
|
2540
|
-
return navigator.language?.split("-")[0] || "";
|
|
2541
|
-
}),
|
|
2542
|
-
locale: () => bridgeOr("system", "locale", () => {
|
|
2543
|
-
if (typeof navigator === "undefined")
|
|
2544
|
-
return "";
|
|
2545
|
-
return navigator.language || "";
|
|
2546
|
-
}),
|
|
2547
|
-
timezone: () => bridgeOr("system", "timezone", () => {
|
|
2548
|
-
try {
|
|
2549
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone || "";
|
|
2550
|
-
} catch {
|
|
2551
|
-
return "";
|
|
2552
|
-
}
|
|
2553
|
-
}),
|
|
2554
|
-
is24HourTime: () => bridgeOr("system", "is24HourTime", () => {
|
|
2555
|
-
try {
|
|
2556
|
-
const opts = new Intl.DateTimeFormat([], { hour: "numeric" }).resolvedOptions();
|
|
2557
|
-
return opts.hourCycle === "h23" || opts.hourCycle === "h24";
|
|
2558
|
-
} catch {
|
|
2559
|
-
return false;
|
|
2560
|
-
}
|
|
2561
|
-
}),
|
|
2562
|
-
reduceMotion: () => bridgeOr("system", "reduceMotion", () => mediaMatches("(prefers-reduced-motion: reduce)")),
|
|
2563
|
-
reduceTransparency: () => bridgeOr("system", "reduceTransparency", () => mediaMatches("(prefers-reduced-transparency: reduce)")),
|
|
2564
|
-
increaseContrast: () => bridgeOr("system", "increaseContrast", () => mediaMatches("(prefers-contrast: more)")),
|
|
2565
|
-
systemVersion: () => bridgeOr("system", "systemVersion", () => ""),
|
|
2566
|
-
hostname: () => bridgeOr("system", "hostname", () => ""),
|
|
2567
|
-
username: () => bridgeOr("system", "username", () => ""),
|
|
2568
|
-
async openPreferences() {
|
|
2569
|
-
if (hasBridge("system"))
|
|
2570
|
-
await window.craft.system.openPreferences();
|
|
2571
|
-
}
|
|
2572
|
-
};
|
|
2573
|
-
async function bridgeOr(ns, method, fallback) {
|
|
2574
|
-
if (hasBridge(ns))
|
|
2575
|
-
return await window.craft[ns][method]();
|
|
2576
|
-
return await fallback();
|
|
2577
|
-
}
|
|
2578
|
-
function mediaMatches(query) {
|
|
2579
|
-
if (typeof window === "undefined" || !window.matchMedia)
|
|
2580
|
-
return false;
|
|
2581
|
-
return window.matchMedia(query).matches;
|
|
2582
|
-
}
|
|
2583
|
-
export {
|
|
2584
|
-
windowEvents,
|
|
2585
|
-
watchScreenSharing,
|
|
2586
|
-
vision,
|
|
2587
|
-
updater,
|
|
2588
|
-
unregisterHotkey,
|
|
2589
|
-
unregisterAllHotkeys,
|
|
2590
|
-
triggerTrayAction,
|
|
2591
|
-
touchbar,
|
|
2592
|
-
theme,
|
|
2593
|
-
tags,
|
|
2594
|
-
system,
|
|
2595
|
-
spotlight,
|
|
2596
|
-
speechRecognition,
|
|
2597
|
-
speech,
|
|
2598
|
-
signPayload,
|
|
2599
|
-
showWarningToast,
|
|
2600
|
-
showWarningModal,
|
|
2601
|
-
showWarningDialog,
|
|
2602
|
-
showToast,
|
|
2603
|
-
showSuccessToast,
|
|
2604
|
-
showSuccessModal,
|
|
2605
|
-
showSaveDialog,
|
|
2606
|
-
showQuestionModal,
|
|
2607
|
-
showOpenDialog,
|
|
2608
|
-
showModal,
|
|
2609
|
-
showMessageBox,
|
|
2610
|
-
showInfoToast,
|
|
2611
|
-
showInfoModal,
|
|
2612
|
-
showErrorToast,
|
|
2613
|
-
showErrorModal,
|
|
2614
|
-
showErrorDialog,
|
|
2615
|
-
showConfirmDialog,
|
|
2616
|
-
showColorPicker,
|
|
2617
|
-
showAlertDialog,
|
|
2618
|
-
showAlert,
|
|
2619
|
-
shell,
|
|
2620
|
-
setDesktopConfig,
|
|
2621
|
-
setAutoLaunch,
|
|
2622
|
-
serviceMenu,
|
|
2623
|
-
serial,
|
|
2624
|
-
screenSharing,
|
|
2625
|
-
screenCapture,
|
|
2626
|
-
screen,
|
|
2627
|
-
resolveCraftBinary2 as resolveCraftBinary,
|
|
2628
|
-
resetDesktopConfig,
|
|
2629
|
-
requestNotificationPermission,
|
|
2630
|
-
registerHotkey,
|
|
2631
|
-
redactPII,
|
|
2632
|
-
prompt,
|
|
2633
|
-
printing,
|
|
2634
|
-
permissions,
|
|
2635
|
-
pdf,
|
|
2636
|
-
parseShortcut,
|
|
2637
|
-
packageApp,
|
|
2638
|
-
pack,
|
|
2639
|
-
openDevWindow,
|
|
2640
|
-
notify,
|
|
2641
|
-
notifications,
|
|
2642
|
-
network,
|
|
2643
|
-
nativeAutoLaunch,
|
|
2644
|
-
midi,
|
|
2645
|
-
menu,
|
|
2646
|
-
log,
|
|
2647
|
-
location,
|
|
2648
|
-
localServer,
|
|
2649
|
-
liveActivities,
|
|
2650
|
-
keychain,
|
|
2651
|
-
isWebviewAvailable,
|
|
2652
|
-
isDragOutAvailable,
|
|
2653
|
-
isCaffeinated,
|
|
2654
|
-
isAvailable,
|
|
2655
|
-
isAutoLaunchEnabled,
|
|
2656
|
-
iap,
|
|
2657
|
-
hasFocusShortcuts,
|
|
2658
|
-
handoff,
|
|
2659
|
-
globalShortcuts,
|
|
2660
|
-
githubReleaseAssetUrl,
|
|
2661
|
-
githubLatestAssetUrl,
|
|
2662
|
-
getWindowBridgeScript,
|
|
2663
|
-
getWindow,
|
|
2664
|
-
getTrayInstance,
|
|
2665
|
-
getTrayBridgeScript,
|
|
2666
|
-
getSimulatedTrayHTML,
|
|
2667
|
-
getRegisteredHotkeys,
|
|
2668
|
-
getDialogBridgeScript,
|
|
2669
|
-
getDesktopConfig,
|
|
2670
|
-
getCapability,
|
|
2671
|
-
getCapabilities,
|
|
2672
|
-
getCaffeinateStatus,
|
|
2673
|
-
getActiveWindowIds,
|
|
2674
|
-
getActiveTrayInstances,
|
|
2675
|
-
getActiveModalCount,
|
|
2676
|
-
getActiveAlertCount,
|
|
2677
|
-
generateUpdateManifest,
|
|
2678
|
-
fs,
|
|
2679
|
-
formatTime,
|
|
2680
|
-
formatShortcut,
|
|
2681
|
-
formatRemainingTime,
|
|
2682
|
-
formatDuration,
|
|
2683
|
-
formatCompact,
|
|
2684
|
-
focusShortcutsReady,
|
|
2685
|
-
focus,
|
|
2686
|
-
fileAssociations,
|
|
2687
|
-
dragOut,
|
|
2688
|
-
dismissAllAlerts,
|
|
2689
|
-
dismissAlertById,
|
|
2690
|
-
delay,
|
|
2691
|
-
deepLinks,
|
|
2692
|
-
decaffeinate,
|
|
2693
|
-
createWindowWithHTML,
|
|
2694
|
-
createWindow,
|
|
2695
|
-
createWebView,
|
|
2696
|
-
createTreeView,
|
|
2697
|
-
createTooltip,
|
|
2698
|
-
createTimer,
|
|
2699
|
-
createTimePicker,
|
|
2700
|
-
createTextInput,
|
|
2701
|
-
createTabs,
|
|
2702
|
-
createTable,
|
|
2703
|
-
createSystemTray,
|
|
2704
|
-
createStepper,
|
|
2705
|
-
createSplitView,
|
|
2706
|
-
createSlider,
|
|
2707
|
-
createScrollView,
|
|
2708
|
-
createRating,
|
|
2709
|
-
createRadioButton,
|
|
2710
|
-
createProgressBar,
|
|
2711
|
-
createPreferences,
|
|
2712
|
-
createModalComponent,
|
|
2713
|
-
createMenubar,
|
|
2714
|
-
createMediaPlayer,
|
|
2715
|
-
createListView,
|
|
2716
|
-
createLabel,
|
|
2717
|
-
createInterval,
|
|
2718
|
-
createImageView,
|
|
2719
|
-
createGitHubUpdater,
|
|
2720
|
-
createGitHubUpdateManifest,
|
|
2721
|
-
createFileExplorer,
|
|
2722
|
-
createDropdown,
|
|
2723
|
-
createDatePicker,
|
|
2724
|
-
createDataGrid,
|
|
2725
|
-
createColorPicker,
|
|
2726
|
-
createCodeEditor,
|
|
2727
|
-
createChip,
|
|
2728
|
-
createCheckbox,
|
|
2729
|
-
createChart,
|
|
2730
|
-
createCard,
|
|
2731
|
-
createButton,
|
|
2732
|
-
createBadge,
|
|
2733
|
-
createAvatar,
|
|
2734
|
-
createAutocomplete,
|
|
2735
|
-
createAccordion,
|
|
2736
|
-
crashReporter,
|
|
2737
|
-
craftWindowArguments,
|
|
2738
|
-
craftBinaryNotFoundMessage2 as craftBinaryNotFoundMessage,
|
|
2739
|
-
coreml,
|
|
2740
|
-
continuityCamera,
|
|
2741
|
-
confirm,
|
|
2742
|
-
closeAllWindows,
|
|
2743
|
-
closeAllModals,
|
|
2744
|
-
clipboard,
|
|
2745
|
-
caffeinate,
|
|
2746
|
-
bonjour,
|
|
2747
|
-
bluetooth,
|
|
2748
|
-
biometric,
|
|
2749
|
-
battery,
|
|
2750
|
-
audio,
|
|
2751
|
-
appleScript,
|
|
2752
|
-
app as appInfo,
|
|
2753
|
-
alert,
|
|
2754
|
-
UPDATE_MANIFEST_ASSET,
|
|
2755
|
-
TRAY_MENU_STYLES,
|
|
2756
|
-
TOAST_STYLES,
|
|
2757
|
-
MODAL_STYLES,
|
|
2758
|
-
MIN_WATCH_INTERVAL_MS,
|
|
2759
|
-
MAX_WATCH_INTERVAL_MS,
|
|
2760
|
-
DEFAULT_WATCH_INTERVAL_MS,
|
|
2761
|
-
COMPONENT_STYLES,
|
|
2762
|
-
AutoUpdater,
|
|
2763
|
-
AVAILABLE_COMPONENTS
|
|
2764
|
-
};
|
|
584
|
+
${Q.isHidden?`X-GNOME-Autostart-enabled=true
|
|
585
|
+
NoDisplay=true`:""}
|
|
586
|
+
`;if(!x($))ZQ($,{recursive:!0});$Q(X,G,"utf-8")}else if(x(X))XQ(X)}async function gY(Y){return x(JQ(Y))}async function bY(Y){let Q=qQ(Y);if(!x(Q))return!1;try{let Z=wY(Q,"utf-8");if(Z.includes("X-GNOME-Autostart-enabled=false"))return!1;if(Z.includes("Hidden=true"))return!1;return!0}catch{return!1}}function uY(Y){return Y.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}async function yY(Y,Q={}){let Z=GQ();switch(Z){case"darwin":return fY(Y,Q);case"linux":return SY(Y,Q);default:throw Error(`Auto-launch is not yet supported on ${Z}`)}}async function hY(Y){let Q=Y||"StxApp";switch(GQ()){case"darwin":return gY(Q);case"linux":return bY(Q);default:return!1}}var mY={accentColor:()=>T("system","accentColor",()=>""),highlightColor:()=>T("system","highlightColor",()=>""),language:()=>T("system","language",()=>{if(typeof navigator>"u")return"";return navigator.language?.split("-")[0]||""}),locale:()=>T("system","locale",()=>{if(typeof navigator>"u")return"";return navigator.language||""}),timezone:()=>T("system","timezone",()=>{try{return Intl.DateTimeFormat().resolvedOptions().timeZone||""}catch{return""}}),is24HourTime:()=>T("system","is24HourTime",()=>{try{let Y=new Intl.DateTimeFormat([],{hour:"numeric"}).resolvedOptions();return Y.hourCycle==="h23"||Y.hourCycle==="h24"}catch{return!1}}),reduceMotion:()=>T("system","reduceMotion",()=>h("(prefers-reduced-motion: reduce)")),reduceTransparency:()=>T("system","reduceTransparency",()=>h("(prefers-reduced-transparency: reduce)")),increaseContrast:()=>T("system","increaseContrast",()=>h("(prefers-contrast: more)")),systemVersion:()=>T("system","systemVersion",()=>""),hostname:()=>T("system","hostname",()=>""),username:()=>T("system","username",()=>""),async openPreferences(){if(m("system"))await window.craft.system.openPreferences()}};async function T(Y,Q,Z){if(m(Y))return await window.craft[Y][Q]();return await Z()}function h(Y){if(typeof window>"u"||!window.matchMedia)return!1;return window.matchMedia(Y).matches}export{iZ as windowEvents,O0 as watchScreenSharing,f0 as vision,aZ as updater,IZ as unregisterHotkey,HZ as unregisterAllHotkeys,eQ as triggerTrayAction,$0 as touchbar,dZ as theme,x0 as tags,mY as system,v0 as spotlight,w0 as speechRecognition,J0 as speech,U0 as signPayload,oY as showWarningToast,ZZ as showWarningModal,OZ as showWarningDialog,pY as showToast,nY as showSuccessToast,$Z as showSuccessModal,BZ as showSaveDialog,GZ as showQuestionModal,EZ as showOpenDialog,QZ as showModal,FZ as showMessageBox,rY as showInfoToast,YZ as showInfoModal,lY as showErrorToast,XZ as showErrorModal,LZ as showErrorDialog,VZ as showConfirmDialog,jZ as showColorPicker,DZ as showAlertDialog,dY as showAlert,mZ as shell,qY as setDesktopConfig,yY as setAutoLaunch,u0 as serviceMenu,y0 as serial,L0 as screenSharing,F0 as screenCapture,eZ as screen,MY as resolveCraftBinary,UY as resetDesktopConfig,cY as requestNotificationPermission,CZ as registerHotkey,R0 as redactPII,RZ as prompt,Z0 as printing,Y0 as permissions,C0 as pdf,kZ as parseShortcut,OY as packageApp,LY as pack,FY as openDevWindow,aY as notify,yZ as notifications,lZ as network,X0 as nativeAutoLaunch,S0 as midi,tZ as menu,I0 as log,B0 as location,W0 as localServer,E0 as liveActivities,Q0 as keychain,DY as isWebviewAvailable,rZ as isDragOutAvailable,WZ as isCaffeinated,c0 as isAvailable,hY as isAutoLaunchEnabled,K0 as iap,M0 as hasFocusShortcuts,_0 as handoff,cZ as globalShortcuts,QQ as githubReleaseAssetUrl,e as githubLatestAssetUrl,VY as getWindowBridgeScript,_Y as getWindow,tQ as getTrayInstance,YY as getTrayBridgeScript,QY as getSimulatedTrayHTML,vZ as getRegisteredHotkeys,zZ as getDialogBridgeScript,RY as getDesktopConfig,m0 as getCapability,h0 as getCapabilities,PZ as getCaffeinateStatus,KY as getActiveWindowIds,sQ as getActiveTrayInstances,UZ as getActiveModalCount,tY as getActiveAlertCount,s as generateUpdateManifest,hZ as fs,gZ as formatTime,xZ as formatShortcut,AZ as formatRemainingTime,NZ as formatDuration,bZ as formatCompact,T0 as focusShortcutsReady,z0 as focus,k0 as fileAssociations,pZ as dragOut,sY as dismissAllAlerts,iY as dismissAlertById,SZ as delay,nZ as deepLinks,TZ as decaffeinate,jY as createWindowWithHTML,BY as createWindow,dQ as createWebView,gQ as createTreeView,xQ as createTooltip,wZ as createTimer,WQ as createTimePicker,KQ as createTextInput,VQ as createTabs,SQ as createTable,l as createSystemTray,vQ as createStepper,IQ as createSplitView,EQ as createSlider,CQ as createScrollView,OQ as createRating,zQ as createRadioButton,BQ as createProgressBar,vY as createPreferences,wQ as createModalComponent,iQ as createMenubar,hQ as createMediaPlayer,fQ as createListView,AQ as createLabel,fZ as createInterval,NQ as createImageView,TY as createGitHubUpdater,WY as createGitHubUpdateManifest,cQ as createFileExplorer,LQ as createDropdown,TQ as createDatePicker,bQ as createDataGrid,MQ as createColorPicker,yQ as createCodeEditor,kQ as createChip,_Q as createCheckbox,uQ as createChart,DQ as createCard,UQ as createButton,FQ as createBadge,jQ as createAvatar,PQ as createAutocomplete,HQ as createAccordion,q0 as crashReporter,u as craftWindowArguments,zY as craftBinaryNotFoundMessage,g0 as coreml,b0 as continuityCamera,JZ as confirm,EY as closeAllWindows,KZ as closeAllModals,uZ as clipboard,MZ as caffeinate,H0 as bonjour,G0 as bluetooth,P0 as biometric,oZ as battery,A0 as audio,N0 as appleScript,sZ as appInfo,qZ as alert,t as UPDATE_MANIFEST_ASSET,ZY as TRAY_MENU_STYLES,eY as TOAST_STYLES,_Z as MODAL_STYLES,j0 as MIN_WATCH_INTERVAL_MS,D0 as MAX_WATCH_INTERVAL_MS,V0 as DEFAULT_WATCH_INTERVAL_MS,rQ as COMPONENT_STYLES,i as AutoUpdater,pQ as AVAILABLE_COMPONENTS};
|