@genispace/geniapp 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -24,7 +24,7 @@ frontend/ geniapp/ applications/
24
24
  Install both public packages from npm. GeniApp releases pin their supported SDK version exactly, so applications should use the matching SDK version shown below.
25
25
 
26
26
  ```bash
27
- pnpm add @genispace/geniapp@0.2.0 @genispace/sdk@3.1.0 react react-dom react-router-dom i18next react-i18next
27
+ pnpm add @genispace/geniapp@0.3.0 @genispace/sdk@3.1.0 react react-dom react-router-dom i18next react-i18next
28
28
  ```
29
29
 
30
30
  ## Public entries
@@ -42,6 +42,8 @@ pnpm add @genispace/geniapp@0.2.0 @genispace/sdk@3.1.0 react react-dom react-rou
42
42
  | `@genispace/geniapp/dashboard` | stable | Dashboard filters, KPI and chart patterns |
43
43
  | `@genispace/geniapp/case-workspace` | stable | Case workspace contract |
44
44
  | `@genispace/geniapp/task-workspace` | stable | Task workspace contract |
45
+ | `@genispace/geniapp/workbench` | stable | Versioned renderer for GeniApps exported from Workbench |
46
+ | `@genispace/geniapp/workbench/styles.css` | stable | Responsive shell and component styles for exported Workbench apps |
45
47
 
46
48
  Only symbols exported by these entries are public. Files below `src/` and `dist/` are implementation details and cannot be imported through package exports.
47
49
 
@@ -93,6 +95,20 @@ export default {
93
95
 
94
96
  The stylesheet contains the platform light/dark semantic tokens, local fonts, responsive application layout rules and component CSS. Locale text remains owned by each application; shared components accept labels or use the host `react-i18next` provider.
95
97
 
98
+ ### Workbench export runtime
99
+
100
+ Workbench exports pin an exact GeniApp version and keep each page and component in a separate source module. The public runtime renders that portable configuration without importing the private Workbench editor:
101
+
102
+ ```ts
103
+ import { mountWorkbench } from '@genispace/geniapp/workbench';
104
+ import '@genispace/geniapp/workbench/styles.css';
105
+ import workbenchConfig from './config/workbench.config';
106
+
107
+ mountWorkbench(document.getElementById('root')!, workbenchConfig);
108
+ ```
109
+
110
+ The runtime owns portable component behavior, desktop/mobile navigation, the theme bridge and the locale bridge. Exported component modules own application-specific props, data and custom styles, so developers can edit or replace one component without reading a monolithic snapshot. The exported prebuilt bundle remains frozen to the same runtime version recorded in `contracts/workbench-export.lock.json`.
111
+
96
112
  ## Vite
97
113
 
98
114
  ```ts
@@ -0,0 +1,3 @@
1
+ import { WorkbenchConfig } from './types';
2
+
3
+ export declare const mountWorkbench: (root: HTMLElement, config: WorkbenchConfig) => void;
@@ -0,0 +1,197 @@
1
+ :root {
2
+ color-scheme: light;
3
+ font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
4
+ font-synthesis: none;
5
+ --background: 0 0% 98%;
6
+ --foreground: 0 0% 10%;
7
+ --card: 0 0% 100%;
8
+ --card-foreground: 0 0% 10%;
9
+ --muted: 0 0% 94%;
10
+ --muted-foreground: 0 0% 42%;
11
+ --accent: 0 0% 92%;
12
+ --accent-foreground: 0 0% 12%;
13
+ --border: 0 0% 88%;
14
+ --primary: 225 70% 52%;
15
+ --primary-foreground: 0 0% 100%;
16
+ --portable-accent: hsl(var(--primary));
17
+ --portable-accent-soft: hsl(225 70% 96%);
18
+ --portable-surface: hsl(var(--card));
19
+ --portable-line: hsl(var(--border));
20
+ --portable-muted: hsl(var(--muted-foreground));
21
+ --portable-radius: 14px;
22
+ color: hsl(var(--foreground));
23
+ background: hsl(var(--background));
24
+ }
25
+
26
+ :root.dark {
27
+ color-scheme: dark;
28
+ --background: 0 0% 4%;
29
+ --foreground: 0 0% 95%;
30
+ --card: 0 0% 8%;
31
+ --card-foreground: 0 0% 95%;
32
+ --muted: 0 0% 14%;
33
+ --muted-foreground: 0 0% 64%;
34
+ --accent: 0 0% 17%;
35
+ --accent-foreground: 0 0% 96%;
36
+ --border: 0 0% 20%;
37
+ --primary: 225 82% 66%;
38
+ --primary-foreground: 0 0% 100%;
39
+ --portable-accent-soft: hsl(225 30% 18%);
40
+ }
41
+
42
+ * { box-sizing: border-box; }
43
+ html, body, #root { min-height: 100%; margin: 0; }
44
+ body { min-width: 320px; overflow-x: hidden; background: hsl(var(--background)); color: hsl(var(--foreground)); }
45
+ button, input, textarea { font: inherit; }
46
+ button { cursor: pointer; }
47
+ .portable-icon { width: 18px; height: 18px; flex: 0 0 auto; }
48
+
49
+ .portable-shell { min-height: 100vh; background: hsl(var(--background)); }
50
+ .portable-sidebar {
51
+ position: fixed; inset: 0 auto 0 0; z-index: 20; display: flex; width: 256px; flex-direction: column;
52
+ overflow: visible; border-right: 1px solid hsl(var(--border)); background: hsl(var(--muted));
53
+ transition: width 220ms ease, background 180ms ease, border-color 180ms ease;
54
+ }
55
+ .sidebar-collapsed .portable-sidebar { width: 80px; }
56
+ .portable-sidebar-header { display: flex; height: 69px; flex: 0 0 69px; align-items: center; padding: 0 16px; border-bottom: 1px solid hsl(var(--border)); }
57
+ .sidebar-collapsed .portable-sidebar-header { justify-content: center; padding: 0 8px; }
58
+ .portable-brand { display: flex; min-width: 0; align-items: center; gap: 10px; }
59
+ .portable-brand > span { display: grid; width: 36px; height: 36px; flex: 0 0 36px; place-items: center; border-radius: 12px; background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); font-weight: 750; box-shadow: 0 1px 3px rgb(0 0 0 / 0.12); }
60
+ .portable-brand > div { min-width: 0; }
61
+ .portable-brand strong, .portable-brand small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
62
+ .portable-brand strong { color: hsl(var(--foreground)); font-size: 14px; font-weight: 650; }
63
+ .portable-brand small { max-width: 175px; margin-top: 2px; color: hsl(var(--muted-foreground)); font-size: 10px; }
64
+ .portable-sidebar nav, .portable-mobile-drawer nav { display: grid; min-height: 0; flex: 1; align-content: start; gap: 4px; overflow-y: auto; padding: 12px; }
65
+ .portable-nav-item { display: flex; width: 100%; min-height: 44px; align-items: center; gap: 10px; padding: 8px 12px 8px calc(12px + var(--nav-depth, 0) * 14px); border: 0; border-radius: 12px; background: transparent; color: hsl(var(--foreground)); text-align: left; transition: color 150ms ease, background 150ms ease; }
66
+ .portable-nav-item span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 520; }
67
+ .portable-nav-item:hover { background: hsl(var(--accent)); color: hsl(var(--accent-foreground)); }
68
+ .portable-nav-item.active { background: hsl(var(--primary)); color: hsl(var(--primary-foreground)); box-shadow: 0 1px 3px rgb(0 0 0 / 0.12); }
69
+ .sidebar-collapsed .portable-nav-item { width: 44px; justify-content: center; margin-inline: auto; padding: 0; }
70
+ .sidebar-collapsed .portable-nav-item span { display: none; }
71
+ .portable-sidebar footer, .portable-mobile-drawer footer { margin-top: auto; padding: 12px; border-top: 1px solid hsl(var(--border)); }
72
+ .portable-controls { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
73
+ .portable-controls button { display: flex; min-height: 40px; align-items: center; justify-content: center; gap: 7px; border: 1px solid hsl(var(--border)); border-radius: 10px; background: hsl(var(--background)); color: hsl(var(--muted-foreground)); }
74
+ .portable-controls button:hover { background: hsl(var(--accent)); color: hsl(var(--accent-foreground)); }
75
+ .portable-controls button span { font-size: 11px; font-weight: 650; }
76
+ .sidebar-collapsed .portable-controls { grid-template-columns: 1fr; }
77
+ .sidebar-collapsed .portable-controls button span, .portable-controls.compact button span { display: none; }
78
+ .portable-controls.compact { display: flex; margin-left: auto; }
79
+ .portable-controls.compact button { width: 38px; min-height: 38px; }
80
+ .portable-collapse { position: absolute; z-index: 10; top: 69px; right: -12px; display: grid; width: 24px; height: 24px; place-items: center; transform: translateY(-50%); border: 1px solid hsl(var(--border)); border-radius: 999px; background: hsl(var(--muted)); color: hsl(var(--muted-foreground)); box-shadow: 0 1px 4px rgb(0 0 0 / 0.1); }
81
+ .portable-collapse .portable-icon { width: 15px; height: 15px; }
82
+ .portable-content { min-width: 0; min-height: 100vh; padding-left: 256px; transition: padding-left 220ms ease; }
83
+ .sidebar-collapsed .portable-content { padding-left: 80px; }
84
+ .portable-mobile-header, .portable-mobile-nav { display: none; }
85
+
86
+ .portable-page { min-height: 100vh; padding: 30px clamp(18px, 3vw, 44px) 48px; background: hsl(var(--background)); color: hsl(var(--foreground)); transition: color 180ms ease, background 180ms ease; }
87
+ .portable-page-header { margin-bottom: 22px; }
88
+ .portable-page-header h1 { margin: 4px 0 5px; color: hsl(var(--foreground)); font-size: clamp(24px, 3vw, 34px); letter-spacing: -0.035em; }
89
+ .portable-page-header p { max-width: 760px; margin: 0; color: var(--portable-muted); line-height: 1.6; }
90
+ .portable-eyebrow { color: var(--portable-accent); font-size: 11px; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; }
91
+ .portable-page-grid { display: grid; gap: 18px; }
92
+ .portable-page-grid.grid-24 { grid-template-columns: repeat(24, minmax(0, 1fr)); grid-auto-rows: minmax(48px, auto); align-items: stretch; }
93
+ .portable-placement { min-width: 0; }
94
+ .portable-component { height: 100%; overflow: hidden; padding: 20px; border: 1px solid var(--portable-line); border-radius: var(--portable-radius); background: var(--portable-surface); color: hsl(var(--card-foreground)); box-shadow: 0 5px 18px rgb(0 0 0 / 0.045); transition: color 180ms ease, background 180ms ease, border-color 180ms ease; }
95
+ .dark .portable-component { box-shadow: 0 8px 24px rgb(0 0 0 / 0.22); }
96
+ .portable-type-Typography, .portable-type-Text, .portable-type-Title, .portable-type-Paragraph { padding: 0; border: 0; background: transparent; box-shadow: none; }
97
+ .portable-typography { margin: 0; line-height: 1.55; }
98
+ .portable-typography-title, .portable-typography-h1, .portable-typography-h2 { letter-spacing: -0.03em; }
99
+ .portable-section-heading { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
100
+ .portable-section-heading h2 { margin: 0; color: hsl(var(--card-foreground)); font-size: 17px; }
101
+ .portable-section-heading p { margin: 5px 0 0; color: var(--portable-muted); font-size: 13px; }
102
+ .portable-stat-grid { display: grid; grid-template-columns: repeat(var(--stat-columns), minmax(0, 1fr)); gap: 14px; }
103
+ .portable-stat { min-width: 0; padding: 17px; border: 1px solid var(--portable-line); border-radius: 12px; background: hsl(var(--background)); }
104
+ .portable-stat-title { color: var(--portable-muted); font-size: 12px; font-weight: 600; }
105
+ .portable-stat-value { margin-top: 9px; color: hsl(var(--foreground)); font-size: 27px; font-weight: 760; letter-spacing: -0.04em; }
106
+ .portable-stat-trend { margin-top: 7px; color: #07855b; font-size: 12px; font-weight: 700; }
107
+ .portable-stat-trend.down { color: #d64545; }
108
+ .portable-stat-trend span { color: var(--portable-muted); font-weight: 400; }
109
+ .portable-table-wrap { max-width: 100%; overflow: auto; }
110
+ .portable-table-wrap table { width: 100%; border-collapse: collapse; font-size: 13px; }
111
+ .portable-table-wrap th { padding: 11px 13px; color: var(--portable-muted); background: hsl(var(--muted)); text-align: left; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; }
112
+ .portable-table-wrap td { padding: 13px; border-top: 1px solid var(--portable-line); color: hsl(var(--card-foreground)); white-space: nowrap; }
113
+ .portable-table-wrap tr:hover td { background: hsl(var(--accent)); }
114
+ .portable-grid-search { margin-bottom: 14px; }
115
+ .portable-grid-search input { width: min(100%, 360px); padding: 10px 12px; border: 1px solid var(--portable-line); border-radius: 9px; color: hsl(var(--foreground)); background: hsl(var(--background)); }
116
+ .portable-card-grid { display: grid; gap: 10px; }
117
+ .portable-card-grid article { padding: 15px; border: 1px solid var(--portable-line); border-radius: 11px; background: hsl(var(--background)); }
118
+ .portable-card-grid header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
119
+ .portable-card-grid header strong { color: hsl(var(--foreground)); font-size: 14px; }
120
+ .portable-card-grid header p { margin: 4px 0 0; color: var(--portable-muted); font-size: 12px; }
121
+ .portable-card-grid header > span { color: var(--portable-muted); font-size: 22px; line-height: 1; }
122
+ .portable-card-grid dl { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 11px 18px; margin: 14px 0 0; padding-top: 13px; border-top: 1px solid var(--portable-line); }
123
+ .portable-card-grid dl > div { min-width: 0; }
124
+ .portable-card-grid dt { color: var(--portable-muted); font-size: 10px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
125
+ .portable-card-grid dd { display: flex; align-items: center; gap: 7px; margin: 5px 0 0; color: hsl(var(--card-foreground)); font-size: 12px; }
126
+ .portable-progress { width: 72px; height: 6px; overflow: hidden; border-radius: 999px; background: hsl(var(--muted)); }
127
+ .portable-progress > span { display: block; height: 100%; border-radius: inherit; background: var(--portable-accent); }
128
+ .portable-tag { display: inline-flex; padding: 3px 7px; border-radius: 999px; color: hsl(var(--primary)); background: var(--portable-accent-soft); font-size: 11px; font-weight: 700; }
129
+ .portable-chart { width: 100%; overflow: hidden; }
130
+ .portable-chart svg { display: block; width: 100%; max-height: 330px; }
131
+ .portable-chart text { fill: var(--portable-muted); font-size: 11px; }
132
+ .portable-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 15px; }
133
+ .portable-form label { display: grid; gap: 7px; color: var(--portable-muted); font-size: 12px; font-weight: 650; }
134
+ .portable-form input, .portable-form textarea { width: 100%; padding: 10px 12px; border: 1px solid var(--portable-line); border-radius: 9px; color: hsl(var(--foreground)); background: hsl(var(--background)); outline: 0; }
135
+ .portable-form input:focus, .portable-form textarea:focus { border-color: var(--portable-accent); box-shadow: 0 0 0 3px var(--portable-accent-soft); }
136
+ .portable-form textarea { min-height: 92px; resize: vertical; }
137
+ .portable-form button { align-self: end; min-height: 40px; padding: 0 18px; border: 0; border-radius: 9px; color: hsl(var(--primary-foreground)); background: var(--portable-accent); font-weight: 700; }
138
+ .portable-task-input { display: grid; gap: 14px; }
139
+ .portable-task-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
140
+ .portable-task-fields label { display: grid; gap: 6px; color: var(--portable-muted); font-size: 12px; font-weight: 650; }
141
+ .portable-task-fields input { min-width: 0; padding: 10px 12px; border: 1px solid var(--portable-line); border-radius: 9px; color: hsl(var(--foreground)); background: hsl(var(--background)); }
142
+ .portable-file-drop { display: grid; min-height: 150px; place-items: center; align-content: center; gap: 6px; padding: 22px; border: 1px dashed hsl(var(--primary) / 0.5); border-radius: 12px; background: var(--portable-accent-soft); text-align: center; }
143
+ .portable-file-drop input { position: absolute; width: 1px; height: 1px; opacity: 0; }
144
+ .portable-file-drop strong { font-size: 13px; }
145
+ .portable-file-drop small { color: var(--portable-muted); font-size: 11px; font-weight: 400; }
146
+ .portable-file-icon { display: grid; width: 34px; height: 34px; place-items: center; border-radius: 999px; color: hsl(var(--primary-foreground)); background: var(--portable-accent); font-size: 19px; }
147
+ .portable-file-list { display: grid; gap: 7px; }
148
+ .portable-file-list > div { display: flex; justify-content: space-between; gap: 12px; padding: 9px 11px; border: 1px solid var(--portable-line); border-radius: 8px; background: hsl(var(--background)); font-size: 12px; }
149
+ .portable-file-list small { color: var(--portable-muted); }
150
+ .portable-task-submit { justify-self: end; min-height: 40px; padding: 0 18px; border: 0; border-radius: 9px; color: hsl(var(--primary-foreground)); background: var(--portable-accent); font-weight: 700; }
151
+ .portable-list { display: grid; gap: 0; }
152
+ .portable-list article { padding: 13px 2px; border-top: 1px solid var(--portable-line); }
153
+ .portable-list article:first-child { border-top: 0; }
154
+ .portable-list strong { font-size: 13px; }
155
+ .portable-list p { margin: 5px 0 0; color: var(--portable-muted); font-size: 12px; line-height: 1.5; }
156
+ .portable-tab-list { display: flex; gap: 5px; margin: -7px -7px 18px; padding: 6px; overflow-x: auto; border-radius: 10px; background: hsl(var(--muted)); }
157
+ .portable-tab-list button { padding: 8px 13px; border: 0; border-radius: 7px; color: var(--portable-muted); background: transparent; font-size: 12px; font-weight: 650; white-space: nowrap; }
158
+ .portable-tab-list button.active { color: hsl(var(--primary)); background: hsl(var(--card)); box-shadow: 0 2px 7px rgb(0 0 0 / 0.08); }
159
+ .portable-tab-panel, .portable-container { display: grid; gap: 14px; }
160
+ .portable-empty, .portable-unsupported { padding: 24px; color: var(--portable-muted); text-align: center; }
161
+ .portable-unsupported { border: 1px dashed #f0a8a8; border-radius: 9px; color: #b83a3a; background: #fff5f5; }
162
+
163
+ .portable-mobile-backdrop, .portable-mobile-drawer { display: none; }
164
+
165
+ @media (max-width: 1023px) {
166
+ .portable-shell { display: flex; min-height: 100dvh; flex-direction: column; }
167
+ .portable-sidebar { display: none; }
168
+ .portable-content, .sidebar-collapsed .portable-content { min-height: 0; flex: 1; padding-left: 0; }
169
+ .portable-mobile-header { position: sticky; top: 0; z-index: 30; display: flex; min-height: 60px; flex: 0 0 60px; align-items: center; gap: 10px; padding: 8px 12px; border-bottom: 1px solid hsl(var(--border)); background: hsl(var(--background) / 0.96); backdrop-filter: blur(12px); }
170
+ .portable-mobile-header > button, .portable-mobile-drawer-close button { display: grid; width: 40px; height: 40px; flex: 0 0 40px; place-items: center; border: 1px solid hsl(var(--border)); border-radius: 12px; background: hsl(var(--card)); color: hsl(var(--foreground)); }
171
+ .portable-mobile-header .portable-brand { flex: 1; }
172
+ .portable-mobile-header .portable-brand > span { width: 34px; height: 34px; flex-basis: 34px; }
173
+ .portable-mobile-header .portable-brand small { display: none; }
174
+ .portable-mobile-header .portable-controls { flex: 0 0 auto; }
175
+ .portable-mobile-nav { position: sticky; z-index: 30; bottom: 0; display: flex; min-height: 70px; flex: 0 0 auto; align-items: stretch; padding: 7px 5px max(env(safe-area-inset-bottom, 0px), 10px); border-top: 1px solid hsl(var(--border)); background: hsl(var(--background) / 0.98); backdrop-filter: blur(12px); }
176
+ .portable-mobile-nav button { display: flex; min-width: 0; flex: 1; flex-direction: column; align-items: center; justify-content: center; gap: 3px; padding: 5px 2px; border: 0; background: transparent; color: hsl(var(--muted-foreground)); }
177
+ .portable-mobile-nav button.active { color: hsl(var(--primary)); }
178
+ .portable-mobile-nav button .portable-icon { width: 25px; height: 25px; }
179
+ .portable-mobile-nav button span { width: 100%; overflow: hidden; text-align: center; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; font-weight: 600; }
180
+ .portable-mobile-backdrop { position: fixed; inset: 0; z-index: 300; display: block; background: rgb(10 10 10 / 0.5); backdrop-filter: blur(3px); }
181
+ .portable-mobile-drawer { position: fixed; inset: 0 auto 0 0; z-index: 400; display: flex; width: min(304px, 88vw); flex-direction: column; overflow: hidden; border-right: 1px solid hsl(var(--border)); border-radius: 0 18px 18px 0; background: hsl(var(--background) / 0.98); box-shadow: 0 16px 50px rgb(0 0 0 / 0.25); backdrop-filter: blur(14px); }
182
+ .portable-mobile-drawer-close { display: flex; justify-content: flex-end; padding: 10px 12px; border-bottom: 1px solid hsl(var(--border)); }
183
+ .portable-mobile-drawer .portable-sidebar-header { background: hsl(var(--muted)); }
184
+ .portable-page-grid.grid-24 { grid-template-columns: 1fr; }
185
+ .portable-page-grid.grid-24 > .portable-placement { grid-column: 1 !important; grid-row: auto !important; }
186
+ .portable-stat-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
187
+ }
188
+
189
+ @media (max-width: 560px) {
190
+ .portable-mobile-header { gap: 8px; padding-inline: 10px; }
191
+ .portable-mobile-header .portable-brand strong { max-width: 150px; }
192
+ .portable-page { min-height: 0; padding: 20px 14px 30px; }
193
+ .portable-page-header { margin-bottom: 16px; }
194
+ .portable-page-header h1 { font-size: 25px; }
195
+ .portable-stat-grid, .portable-form, .portable-task-fields, .portable-card-grid dl { grid-template-columns: 1fr; }
196
+ .portable-component { padding: 15px; border-radius: 12px; }
197
+ }
@@ -0,0 +1,48 @@
1
+ export declare const PORTABLE_WORKBENCH_COMPONENT_TYPES: readonly ["Typography", "Text", "Title", "Paragraph", "Statistic", "StatisticGroup", "Table", "EditableTable", "AnalyticsTable", "DataGridCard", "Chart", "EChartsChart", "RadarChart", "Form", "TaskInput", "TaskInputRenderer", "List", "Tabs", "Container", "Card", "CustomContent", "FilterPanel"];
2
+ export type PortableWorkbenchComponentType = typeof PORTABLE_WORKBENCH_COMPONENT_TYPES[number];
3
+ export type WorkbenchNavigationItem = {
4
+ key?: string;
5
+ title?: string | Record<string, string>;
6
+ icon?: string;
7
+ linkedPage?: string;
8
+ children?: WorkbenchNavigationItem[];
9
+ visibility?: {
10
+ devices?: Array<'desktop' | 'mobile'>;
11
+ };
12
+ [key: string]: unknown;
13
+ };
14
+ export type WorkbenchComponentConfig = {
15
+ id: string;
16
+ type: PortableWorkbenchComponentType | string;
17
+ props?: Record<string, unknown>;
18
+ components?: WorkbenchComponentConfig[];
19
+ children?: WorkbenchComponentConfig[];
20
+ customStyles?: Record<string, unknown>;
21
+ mockData?: unknown[];
22
+ [key: string]: unknown;
23
+ };
24
+ export type WorkbenchPageConfig = {
25
+ title?: string | Record<string, string>;
26
+ description?: string | Record<string, string>;
27
+ layout?: Record<string, unknown>;
28
+ components?: WorkbenchComponentConfig[];
29
+ customStyles?: Record<string, unknown>;
30
+ [key: string]: unknown;
31
+ };
32
+ export type WorkbenchAppConfig = {
33
+ appId?: string;
34
+ name?: string | Record<string, string>;
35
+ description?: string | Record<string, string>;
36
+ defaultPage?: string;
37
+ navigation?: {
38
+ items?: WorkbenchNavigationItem[];
39
+ };
40
+ [key: string]: unknown;
41
+ };
42
+ export type WorkbenchConfig = {
43
+ schemaVersion?: number;
44
+ appConfig?: WorkbenchAppConfig;
45
+ pages?: Record<string, WorkbenchPageConfig>;
46
+ metadata?: Record<string, unknown>;
47
+ [key: string]: unknown;
48
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Stable compatibility runtime for GeniApps exported from Workbench.
3
+ *
4
+ * Applications should import only this public entry. The implementation is
5
+ * deliberately independent from the private Workbench editor and API source.
6
+ */
7
+ export { mountWorkbench } from './workbench/runtime';
8
+ export { PORTABLE_WORKBENCH_COMPONENT_TYPES, type PortableWorkbenchComponentType, type WorkbenchAppConfig, type WorkbenchComponentConfig, type WorkbenchConfig, type WorkbenchNavigationItem, type WorkbenchPageConfig, } from './workbench/types';
@@ -0,0 +1,356 @@
1
+ function ce() {
2
+ const s = {
3
+ sourceConfig: null,
4
+ config: null,
5
+ root: null,
6
+ activePage: null,
7
+ activeTabs: /* @__PURE__ */ new Map(),
8
+ locale: "en",
9
+ theme: "light",
10
+ collapsed: !1,
11
+ mobileDrawerOpen: !1,
12
+ allowedShellOrigins: /* @__PURE__ */ new Set()
13
+ }, n = (e) => String(e ?? "").replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&#039;"), C = (e) => String(e || "").toLowerCase().startsWith("zh") ? "zh" : "en", x = (e) => e === "dark" ? "dark" : "light", y = (e) => e && typeof e == "object" && !Array.isArray(e), q = (e) => JSON.parse(JSON.stringify(e)), L = (e, t) => ["key", "dataIndex", "id", "value", "name"].map((r) => e?.[r]).find((r) => r != null && String(r).trim() !== "") ?? `__index_${t}`, A = (e, t) => {
14
+ if (Array.isArray(e) && Array.isArray(t)) {
15
+ const r = new Map(t.map((a, o) => [String(L(a, o)), a]));
16
+ return e.map((a, o) => {
17
+ const l = r.get(String(L(a, o)));
18
+ return y(a) && y(l) ? A(a, l) : a;
19
+ });
20
+ }
21
+ if (y(e) && y(t)) {
22
+ const r = { ...e };
23
+ return Object.entries(t).forEach(([a, o]) => {
24
+ o !== void 0 && (r[a] = A(r[a], o));
25
+ }), r;
26
+ }
27
+ return t === void 0 ? e : t;
28
+ }, k = (e, t) => {
29
+ const r = e?.id ? t?.[e.id] : null, a = r ? A(e, r) : { ...e };
30
+ return ["components", "children"].forEach((o) => {
31
+ Array.isArray(a[o]) && (a[o] = a[o].map((l) => k(l, t)));
32
+ }), Array.isArray(a.props?.components) && (a.props = { ...a.props, components: a.props.components.map((o) => k(o, t)) }), Array.isArray(a.props?.items) && (a.props = {
33
+ ...a.props,
34
+ items: a.props.items.map((o) => ({
35
+ ...o,
36
+ ...o.component ? { component: k(o.component, t) } : {},
37
+ ...Array.isArray(o.components) ? { components: o.components.map((l) => k(l, t)) } : {}
38
+ }))
39
+ }), a;
40
+ }, E = (e, t) => {
41
+ const r = q(e || {}), a = r.metadata?.locales?.[t];
42
+ return a && (a.appConfig && (r.appConfig = A(r.appConfig || {}, a.appConfig)), Object.entries(a.pages || {}).forEach(([o, l]) => {
43
+ const i = r.pages?.[o];
44
+ if (!i) return;
45
+ const p = { ...i };
46
+ l.title !== void 0 && (p.title = l.title), l.description !== void 0 && (p.description = l.description), Array.isArray(p.components) && (p.components = p.components.map((d) => k(d, l.components || {}))), r.pages[o] = p;
47
+ })), r;
48
+ }, B = () => s.sourceConfig?.metadata?.locales?.[s.locale]?.labels || {}, O = (e) => {
49
+ const t = String(e ?? ""), r = B();
50
+ return r[t] ? r[t] : Object.keys(r).sort((a, o) => o.length - a.length).reduce((a, o) => o && a.includes(o) ? a.split(o).join(r[o]) : a, t);
51
+ }, c = (e) => {
52
+ if (e == null) return "";
53
+ if (y(e)) {
54
+ const t = e[s.locale] ?? e.zh ?? e.en;
55
+ return t === void 0 || y(t) ? "" : O(t);
56
+ }
57
+ return O(e);
58
+ }, G = (e) => e.replace(/[A-Z]/g, (t) => `-${t.toLowerCase()}`), M = (e) => Object.entries(e || {}).filter(([, t]) => t != null && t !== "").map(([t, r]) => `${G(t)}:${String(r)}`).join(";"), H = (e) => {
59
+ const t = String(e || "");
60
+ return /@import|javascript:|expression\s*\(|url\s*\(\s*['"]?data:text\/html/i.test(t) ? "" : t;
61
+ }, N = (e, t) => {
62
+ const r = e?.customStyles || e?.props?.customStyles;
63
+ if (!r) return "";
64
+ const a = [];
65
+ Object.entries(r.childStyles || {}).forEach(([l, i]) => a.push(`${t} ${l}{${M(i)}}`)), Object.entries(r.stateStyles || {}).forEach(([l, i]) => {
66
+ const p = l.startsWith(":") ? l : `:${l}`;
67
+ a.push(`${t}${p}{${M(i)}}`);
68
+ });
69
+ const o = H(r.customCss);
70
+ return o && a.push(o.replaceAll("&", t)), a.length ? `<style>${a.join(`
71
+ `)}</style>` : "";
72
+ }, $ = (e, t = "portable-icon") => {
73
+ const a = {
74
+ LayoutDashboard: '<rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/>',
75
+ Activity: '<path d="M3 12h4l3-8 4 16 3-8h4"/>',
76
+ ClipboardList: '<rect x="5" y="4" width="14" height="17" rx="2"/><path d="M9 4V2h6v2M9 10h6M9 14h6M9 18h4"/>',
77
+ Menu: '<path d="M4 7h16M4 12h16M4 17h16"/>',
78
+ X: '<path d="m6 6 12 12M18 6 6 18"/>',
79
+ ChevronLeft: '<path d="m15 18-6-6 6-6"/>',
80
+ ChevronRight: '<path d="m9 18 6-6-6-6"/>',
81
+ Languages: '<path d="M4 5h7M7.5 3v2c0 4-2 7-5 9M5 9c1 2 3 4 6 5M13 20l4-9 4 9M14.5 17h5"/>',
82
+ Sun: '<circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"/>',
83
+ Moon: '<path d="M20 15.5A8.5 8.5 0 0 1 8.5 4 8.5 8.5 0 1 0 20 15.5Z"/>'
84
+ }[e] || '<circle cx="12" cy="12" r="8"/><path d="M9 12h6"/>';
85
+ return `<svg class="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${a}</svg>`;
86
+ }, I = (e, t) => {
87
+ if (e == null) return "—";
88
+ if (t?.render === "currency") {
89
+ const r = Number(e);
90
+ return Number.isFinite(r) ? new Intl.NumberFormat(s.locale === "zh" ? "zh-CN" : "en-US", { style: "currency", currency: "USD" }).format(r) : e;
91
+ }
92
+ return typeof e == "boolean" ? e ? "Yes" : "No" : Array.isArray(e) ? e.map(c).join(", ") : typeof e == "object" ? JSON.stringify(e) : c(e);
93
+ }, f = (e, t) => e ? `<div class="portable-section-heading"><div><h2>${n(c(e))}</h2>${t ? `<p>${n(c(t))}</p>` : ""}</div></div>` : "", W = (e) => {
94
+ const t = e.props || {}, r = t.content ?? t.text ?? t.children ?? t.title ?? "", a = String(t.variant || "paragraph").toLowerCase(), o = a === "title" || a.startsWith("h") ? a.match(/^h[1-6]$/)?.[0] || "h2" : "p";
95
+ return `<${o} class="portable-typography portable-typography-${n(a)}">${n(c(r))}</${o}>`;
96
+ }, U = (e) => {
97
+ const t = e.props || {}, r = t.items || e.mockData || [];
98
+ return `<div class="portable-stat-grid" style="--stat-columns:${Math.max(1, Math.min(6, Number(t.grid?.cols || t.columns || r.length || 1)))}">${r.map((o) => {
99
+ const l = o.trend, i = l?.type === "down" ? "down" : "up", p = l ? `${i === "down" ? "↓" : "↑"} ${l.value ?? ""}${l.suffix ?? ""}` : "";
100
+ return `<article class="portable-stat"><div class="portable-stat-title">${n(c(o.title || o.label))}</div><div class="portable-stat-value">${n(o.prefix || "")}${n(o.value)}${n(o.suffix || "")}</div>${l ? `<div class="portable-stat-trend ${i}">${n(p)} <span>${n(c(l.description || ""))}</span></div>` : ""}</article>`;
101
+ }).join("")}</div>`;
102
+ }, V = (e) => {
103
+ const t = e.props || {}, r = e.mockData || t.data || t.rows || [], a = t.columns?.length ? t.columns : Object.keys(r[0] || {}).map((o) => ({ key: o, dataIndex: o, title: o }));
104
+ return `${f(t.title, t.description)}<div class="portable-table-wrap"><table><thead><tr>${a.map((o) => `<th>${n(c(o.title || o.label || o.key))}</th>`).join("")}</tr></thead><tbody>${r.map((o) => `<tr>${a.map((l) => `<td>${n(I(o[l.dataIndex || l.key], l))}</td>`).join("")}</tr>`).join("")}</tbody></table>${r.length === 0 ? '<div class="portable-empty">No data</div>' : ""}</div>`;
105
+ }, K = (e) => {
106
+ const t = e.props || {}, r = e.mockData || t.mockData || t.data || t.rows || [], a = t.columns || [], o = a.find((d) => d.primary) || a[0], l = a.find((d) => d.secondary) || a[1], i = a.filter((d) => d !== o && d !== l), p = (d, h) => {
107
+ const w = d?.[h?.dataIndex || h?.key], b = h?.render?.text?.[w] ?? w;
108
+ if (h?.render?.type === "Progress") {
109
+ const g = Math.max(0, Math.min(100, Number(w) || 0));
110
+ return `<span class="portable-progress"><span style="width:${g}%"></span></span><small>${n(`${g}%`)}</small>`;
111
+ }
112
+ return h?.render?.type === "Tag" ? `<span class="portable-tag">${n(c(b))}</span>` : n(I(b, h));
113
+ };
114
+ return `${f(t.title, t.description)}${t.showSearch ? `<div class="portable-grid-search"><input type="search" placeholder="${n(c(t.searchPlaceholder || "Search..."))}" /></div>` : ""}<div class="portable-card-grid">${r.map((d) => `<article><header><div><strong>${o ? p(d, o) : ""}</strong>${l ? `<p>${p(d, l)}</p>` : ""}</div><span aria-hidden="true">›</span></header>${i.length ? `<dl>${i.map((h) => `<div><dt>${n(c(h.title || h.label || h.key))}</dt><dd>${p(d, h)}</dd></div>`).join("")}</dl>` : ""}</article>`).join("")}${r.length === 0 ? '<div class="portable-empty">No data</div>' : ""}</div>`;
115
+ }, J = (e) => Object.entries(e || {}).filter(([, t]) => typeof t == "number"), Z = (e) => {
116
+ const t = e.props || {}, r = e.mockData || t.data || [], a = r.map((b) => J(b)[0]?.[1] || 0), o = r.map((b, g) => c(Object.values(b).find((m) => typeof m == "string") || g + 1)), l = Math.max(...a, 1), i = 720, p = Math.max(180, Number(t.height || 260)), d = String(t.chartType || t.type || "bar").toLowerCase();
117
+ let h = "";
118
+ if (d.includes("line")) {
119
+ const b = a.map((g, m) => {
120
+ const v = a.length === 1 ? i / 2 : 24 + m * ((i - 48) / Math.max(1, a.length - 1)), ie = p - 36 - g / l * (p - 72);
121
+ return `${v},${ie}`;
122
+ }).join(" ");
123
+ h = `<polyline points="${b}" fill="none" stroke="var(--portable-accent)" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>${b.split(" ").map((g) => {
124
+ const [m, v] = g.split(",");
125
+ return `<circle cx="${m}" cy="${v}" r="5" fill="var(--portable-surface)" stroke="var(--portable-accent)" stroke-width="3"/>`;
126
+ }).join("")}`;
127
+ } else {
128
+ const b = (i - 48) / Math.max(1, a.length);
129
+ h = a.map((g, m) => {
130
+ const v = g / l * (p - 72);
131
+ return `<rect x="${24 + m * b + b * 0.16}" y="${p - 36 - v}" width="${b * 0.68}" height="${v}" rx="5" fill="var(--portable-accent)" opacity="${0.7 + m % 3 * 0.12}"/>`;
132
+ }).join("");
133
+ }
134
+ const w = o.map((b, g) => `<text x="${a.length === 1 ? i / 2 : 24 + g * ((i - 48) / Math.max(1, a.length - 1))}" y="${p - 10}" text-anchor="middle">${n(b)}</text>`).join("");
135
+ return `${f(t.title, t.description)}<div class="portable-chart"><svg viewBox="0 0 ${i} ${p}" role="img" aria-label="${n(c(t.title || "Chart"))}">${h}${w}</svg></div>`;
136
+ }, D = (e) => {
137
+ const t = e.props || {}, r = t.fields || t.items || [];
138
+ return `${f(t.title, t.description)}<form class="portable-form" onsubmit="return false">${r.map((a) => {
139
+ const l = (a.type === "textarea" ? "textarea" : "input") === "textarea" ? `<textarea placeholder="${n(c(a.placeholder || ""))}">${n(c(a.defaultValue || ""))}</textarea>` : `<input type="${n(a.type === "number" ? "number" : "text")}" value="${n(c(a.defaultValue || ""))}" placeholder="${n(c(a.placeholder || ""))}"/>`;
140
+ return `<label><span>${n(c(a.label || a.title || a.name))}</span>${l}</label>`;
141
+ }).join("")}<button type="button">${n(c(t.submitButtonText || t.submitText || "Submit"))}</button></form>`;
142
+ }, Y = (e) => {
143
+ const t = e.props || {}, r = t.title || e.mockTitle, a = t.description || e.mockDescription, o = t.mockFileData?.files || e.mockFileData?.files || [], l = t.fields || e.parameterConfig?.fields || [];
144
+ return `${f(t.showTitle === !1 ? "" : r, t.showDescription === !1 ? "" : a)}<div class="portable-task-input">${l.length ? `<div class="portable-task-fields">${l.map((i) => `<label><span>${n(c(i.label || i.title || i.name))}</span><input type="text" placeholder="${n(c(i.placeholder || ""))}" /></label>`).join("")}</div>` : ""}<label class="portable-file-drop"><input type="file" multiple /><span class="portable-file-icon">↑</span><strong>${n(c(t.uploadText || "Choose files or drop them here"))}</strong><small>${n(c(t.uploadHint || "Files remain local in this portable preview"))}</small></label>${o.length ? `<div class="portable-file-list">${o.map((i) => `<div><span>${n(i.name || "File")}</span><small>${n(i.type || "")}</small></div>`).join("")}</div>` : ""}<button type="button" class="portable-task-submit">${n(c(t.submitButtonText || "Run task"))}</button></div>`;
145
+ }, X = (e) => {
146
+ const t = e.props || {}, r = e.mockData || t.items || [];
147
+ return `${f(t.title, t.description)}<div class="portable-list">${r.map((a) => {
148
+ const o = typeof a == "object" ? a.title || a.name || a.label || Object.values(a)[0] : a, l = typeof a == "object" ? a.description || a.subtitle || Object.values(a)[1] : "";
149
+ return `<article><strong>${n(c(o))}</strong>${l ? `<p>${n(c(l))}</p>` : ""}</article>`;
150
+ }).join("")}</div>`;
151
+ }, Q = (e) => {
152
+ const t = e.props || {}, r = t.items || t.tabs || [], a = s.activeTabs.get(e.id) || r[0]?.key || r[0]?.id, o = r.find((i) => (i.key || i.id) === a) || r[0], l = o?.components || (o?.component ? [o.component] : []);
153
+ return `<div class="portable-tabs" data-tabs="${n(e.id)}"><div class="portable-tab-list">${r.map((i) => `<button type="button" data-tab-key="${n(i.key || i.id)}" class="${(i.key || i.id) === a ? "active" : ""}">${n(c(i.title || i.label))}</button>`).join("")}</div><div class="portable-tab-panel">${l.map(T).join("") || n(c(o?.content || ""))}</div></div>`;
154
+ }, ee = (e) => {
155
+ const t = e.props || {}, r = e.components || e.children || t.components || t.children;
156
+ return Array.isArray(r) ? `<div class="portable-container">${r.map(T).join("")}</div>` : `${f(t.title, t.subtitle)}${t.content ? `<p>${n(c(t.content))}</p>` : ""}`;
157
+ }, te = (e) => {
158
+ const t = document.createElement("template");
159
+ return t.innerHTML = String(e || ""), t.content.querySelectorAll("script,iframe,object,embed,link,meta").forEach((r) => r.remove()), t.content.querySelectorAll("*").forEach((r) => {
160
+ [...r.attributes].forEach((a) => {
161
+ (/^on/i.test(a.name) || /javascript:/i.test(a.value)) && r.removeAttribute(a.name);
162
+ });
163
+ }), t.innerHTML;
164
+ };
165
+ function T(e) {
166
+ const t = e?.props || {}, r = `portable-component-${String(e?.id || "anonymous").replace(/[^a-zA-Z0-9_-]/g, "-")}`, a = e?.customStyles?.rootStyles || t.customStyles?.rootStyles || {};
167
+ let o;
168
+ switch (e?.type) {
169
+ case "Typography":
170
+ case "Text":
171
+ case "Title":
172
+ case "Paragraph":
173
+ o = W(e);
174
+ break;
175
+ case "Statistic":
176
+ case "StatisticGroup":
177
+ o = U(e);
178
+ break;
179
+ case "Table":
180
+ case "EditableTable":
181
+ case "AnalyticsTable":
182
+ o = V(e);
183
+ break;
184
+ case "DataGridCard":
185
+ o = K(e);
186
+ break;
187
+ case "Chart":
188
+ case "EChartsChart":
189
+ case "RadarChart":
190
+ o = Z(e);
191
+ break;
192
+ case "Form":
193
+ o = D(e);
194
+ break;
195
+ case "TaskInput":
196
+ case "TaskInputRenderer":
197
+ o = Y(e);
198
+ break;
199
+ case "List":
200
+ o = X(e);
201
+ break;
202
+ case "Tabs":
203
+ o = Q(e);
204
+ break;
205
+ case "Container":
206
+ case "Card":
207
+ o = ee(e);
208
+ break;
209
+ case "CustomContent":
210
+ o = te(t.html || t.content || "");
211
+ break;
212
+ case "FilterPanel":
213
+ o = D({ ...e, props: { ...t, submitText: t.submitText || "Apply filters" } });
214
+ break;
215
+ default:
216
+ o = `<div class="portable-unsupported">Unsupported component: ${n(e?.type)}</div>`;
217
+ }
218
+ return `${N(e, `.${r}`)}<section class="portable-component ${r} portable-type-${n(e?.type || "unknown")}" style="${n(M(a))}" data-component-id="${n(e?.id)}">${o}</section>`;
219
+ }
220
+ const z = (e, t) => !e?.visibility?.devices?.length || e.visibility.devices.includes(t), R = (e, t) => {
221
+ if (!z(e, t)) return null;
222
+ if (e.linkedPage) return e.linkedPage;
223
+ for (const r of e.children || []) {
224
+ const a = R(r, t);
225
+ if (a) return a;
226
+ }
227
+ return null;
228
+ }, _ = (e, t, r = 0) => (e || []).flatMap((a) => z(a, t) ? (a.linkedPage ? [{ ...a, depth: r }] : []).concat(_(a.children, t, r + 1)) : []), ae = (e) => (e || []).flatMap((t) => {
229
+ const r = R(t, "mobile");
230
+ return r ? [{ ...t, linkedPage: r }] : [];
231
+ }), F = (e, t) => _(e, t).map((r) => `
232
+ <button type="button" data-page="${n(r.linkedPage)}" class="portable-nav-item ${r.linkedPage === s.activePage ? "active" : ""}" style="--nav-depth:${r.depth}">
233
+ ${$(r.icon)}<span>${n(c(r.title || r.key))}</span>
234
+ </button>`).join(""), j = (e = !1) => `<div class="portable-controls ${e ? "compact" : ""}">
235
+ <button type="button" data-locale-toggle aria-label="Change language">${$("Languages")}<span>${s.locale === "zh" ? "EN" : "ZH"}</span></button>
236
+ <button type="button" data-theme-toggle aria-label="Change color theme">${$(s.theme === "dark" ? "Sun" : "Moon")}<span>${s.theme === "dark" ? "Light" : "Dark"}</span></button>
237
+ </div>`, P = (e = !1) => {
238
+ const t = s.config.appConfig || {};
239
+ return `<div class="portable-brand ${e ? "collapsed" : ""}"><span>${n(c(t.name || "G").slice(0, 1))}</span>${e ? "" : `<div><strong>${n(c(t.name || "GeniApp"))}</strong><small>${n(c(t.description || "Exported from Workbench"))}</small></div>`}</div>`;
240
+ }, re = () => {
241
+ const e = s.config.pages?.[s.activePage] || Object.values(s.config.pages || {})[0], t = s.activePage || Object.keys(s.config.pages || {})[0];
242
+ if (!e) return '<main class="portable-page"><div class="portable-empty">No pages were exported.</div></main>';
243
+ const r = `.portable-page-${String(t).replace(/[^a-zA-Z0-9_-]/g, "-")}`, a = e.customStyles?.rootStyles || {}, l = (e.layout?.type === "grid-24" ? e.layout.components || [] : []).reduce((p, d) => (d?.id && (p[d.id] = d), p), e.layout?.placements || {}), i = (e.components || []).map((p) => {
244
+ const d = l[p.id];
245
+ return `<div class="portable-placement" style="${d ? `grid-column:${Number(d.colStart || 0) + 1} / span ${Number(d.colSpan || 24)};grid-row:${Number(d.rowStart || 0) + 1} / span ${Number(d.rowSpan || 1)};` : ""}">${T(p)}</div>`;
246
+ }).join("");
247
+ return `${N(e, r)}<main class="portable-page ${r}" style="${n(M(a))}"><header class="portable-page-header"><div><span class="portable-eyebrow">${n(c(s.config.appConfig?.name || ""))}</span><h1>${n(c(e.title || t))}</h1>${e.description ? `<p>${n(c(e.description))}</p>` : ""}</div></header><div class="portable-page-grid ${e.layout?.type === "grid-24" ? "grid-24" : ""}">${i}</div></main>`;
248
+ }, S = () => {
249
+ document.documentElement.lang = s.locale === "zh" ? "zh-CN" : "en", document.documentElement.classList.toggle("dark", s.theme === "dark"), document.documentElement.dataset.colorMode = s.theme, document.documentElement.style.colorScheme = s.theme;
250
+ }, oe = (e) => {
251
+ s.locale = C(e), s.config = E(s.sourceConfig, s.locale);
252
+ try {
253
+ localStorage.setItem("language", s.locale);
254
+ } catch {
255
+ }
256
+ S(), u();
257
+ }, se = (e) => {
258
+ s.theme = x(e);
259
+ try {
260
+ localStorage.setItem("theme", s.theme);
261
+ } catch {
262
+ }
263
+ S(), u();
264
+ }, ne = (e) => {
265
+ s.config.pages?.[e] && (s.activePage = e, s.mobileDrawerOpen = !1, decodeURIComponent(window.location.hash.replace(/^#/, "")) !== e && (window.location.hash = encodeURIComponent(e)), u());
266
+ }, le = () => {
267
+ window.addEventListener("message", (e) => {
268
+ const t = e.data;
269
+ if (!t || t.v !== 1 || typeof t != "object") return;
270
+ const r = e.origin.replace(/\/$/, "");
271
+ if (t.type === "GENISPACE_SHELL_INIT") {
272
+ const a = t.payload || {}, o = [a.shellOrigin, ...Array.isArray(a.allowedShellOrigins) ? a.allowedShellOrigins : []].filter(Boolean).map((l) => String(l).replace(/\/$/, ""));
273
+ if (o.length && !o.includes(r)) return;
274
+ s.allowedShellOrigins = new Set(o.length ? o : [r]), a.locale && (s.locale = C(a.locale)), a.theme && (s.theme = x(a.theme)), s.config = E(s.sourceConfig, s.locale), S(), u(), window.parent.postMessage({ type: "GENISPACE_IFRAME_READY", v: 1, identifier: s.config.appConfig?.appId || "" }, e.origin);
275
+ return;
276
+ }
277
+ t.type === "GENISPACE_SHELL_UI" && s.allowedShellOrigins.has(r) && (t.locale && (s.locale = C(t.locale)), t.theme && (s.theme = x(t.theme)), s.config = E(s.sourceConfig, s.locale), S(), u());
278
+ });
279
+ };
280
+ function u() {
281
+ const e = s.root;
282
+ if (!e || !s.config) return;
283
+ const t = s.config.appConfig?.navigation?.items || [], r = ae(t);
284
+ e.innerHTML = `<div class="portable-shell ${s.collapsed ? "sidebar-collapsed" : ""}">
285
+ <aside class="portable-sidebar">
286
+ <div class="portable-sidebar-header">${P(s.collapsed)}</div>
287
+ <button type="button" class="portable-collapse" data-collapse aria-label="${s.collapsed ? "Expand sidebar" : "Collapse sidebar"}">${$(s.collapsed ? "ChevronRight" : "ChevronLeft")}</button>
288
+ <nav aria-label="Application navigation">${F(t, "desktop")}</nav>
289
+ <footer>${j(s.collapsed)}</footer>
290
+ </aside>
291
+ <header class="portable-mobile-header"><button type="button" data-mobile-drawer aria-label="Open navigation">${$("Menu")}</button>${P(!1)}${j(!0)}</header>
292
+ ${s.mobileDrawerOpen ? `<div class="portable-mobile-backdrop" data-mobile-close></div><aside class="portable-mobile-drawer"><div class="portable-mobile-drawer-close"><button type="button" data-mobile-close aria-label="Close navigation">${$("X")}</button></div><div class="portable-sidebar-header">${P(!1)}</div><nav>${F(t, "mobile")}</nav><footer>${j(!1)}</footer></aside>` : ""}
293
+ <div class="portable-content">${re()}</div>
294
+ <nav class="portable-mobile-nav" aria-label="Workbench bottom navigation">${r.map((a) => `<button type="button" data-page="${n(a.linkedPage)}" class="${a.linkedPage === s.activePage ? "active" : ""}" aria-current="${a.linkedPage === s.activePage ? "page" : "false"}">${$(a.icon)}<span>${n(c(a.title || a.key))}</span></button>`).join("")}</nav>
295
+ </div>`, e.querySelectorAll("[data-page]").forEach((a) => a.addEventListener("click", () => ne(a.dataset.page))), e.querySelectorAll("[data-tabs] [data-tab-key]").forEach((a) => a.addEventListener("click", () => {
296
+ const o = a.closest("[data-tabs]");
297
+ s.activeTabs.set(o.dataset.tabs, a.dataset.tabKey), u();
298
+ })), e.querySelectorAll("[data-locale-toggle]").forEach((a) => a.addEventListener("click", () => oe(s.locale === "zh" ? "en" : "zh"))), e.querySelectorAll("[data-theme-toggle]").forEach((a) => a.addEventListener("click", () => se(s.theme === "dark" ? "light" : "dark"))), e.querySelector("[data-collapse]")?.addEventListener("click", () => {
299
+ s.collapsed = !s.collapsed;
300
+ try {
301
+ localStorage.setItem("portable_sidebar_collapsed", JSON.stringify(s.collapsed));
302
+ } catch {
303
+ }
304
+ u();
305
+ }), e.querySelector("[data-mobile-drawer]")?.addEventListener("click", () => {
306
+ s.mobileDrawerOpen = !0, u();
307
+ }), e.querySelectorAll("[data-mobile-close]").forEach((a) => a.addEventListener("click", () => {
308
+ s.mobileDrawerOpen = !1, u();
309
+ }));
310
+ }
311
+ return { mountWorkbench: (e, t) => {
312
+ if (!e) throw new Error("A root element is required.");
313
+ s.root = e, s.sourceConfig = t || {};
314
+ const r = new URLSearchParams(window.location.search);
315
+ let a = "", o = "", l = !1;
316
+ try {
317
+ a = localStorage.getItem("language") || "", o = localStorage.getItem("theme") || "", l = JSON.parse(localStorage.getItem("portable_sidebar_collapsed") || "false");
318
+ } catch {
319
+ }
320
+ s.locale = C(r.get("lng") || a || document.documentElement.lang || "en"), s.theme = x(r.get("theme") || o || (window.matchMedia?.("(prefers-color-scheme: dark)").matches ? "dark" : "light")), s.collapsed = !!l, s.config = E(s.sourceConfig, s.locale);
321
+ const i = decodeURIComponent(window.location.hash.replace(/^#/, ""));
322
+ s.activePage = s.config.pages?.[i] ? i : s.config.appConfig?.defaultPage || Object.keys(s.config.pages || {})[0], s.allowedShellOrigins.add(window.location.origin.replace(/\/$/, "")), S(), le(), window.addEventListener("hashchange", () => {
323
+ const p = decodeURIComponent(window.location.hash.replace(/^#/, ""));
324
+ s.config.pages?.[p] && p !== s.activePage && (s.activePage = p, u());
325
+ }), u(), window.parent !== window && window.parent.postMessage({ type: "GENIAPP_READY", app: s.config.appConfig?.appId || "" }, "*");
326
+ } };
327
+ }
328
+ const pe = ce(), he = pe.mountWorkbench, be = [
329
+ "Typography",
330
+ "Text",
331
+ "Title",
332
+ "Paragraph",
333
+ "Statistic",
334
+ "StatisticGroup",
335
+ "Table",
336
+ "EditableTable",
337
+ "AnalyticsTable",
338
+ "DataGridCard",
339
+ "Chart",
340
+ "EChartsChart",
341
+ "RadarChart",
342
+ "Form",
343
+ "TaskInput",
344
+ "TaskInputRenderer",
345
+ "List",
346
+ "Tabs",
347
+ "Container",
348
+ "Card",
349
+ "CustomContent",
350
+ "FilterPanel"
351
+ ];
352
+ export {
353
+ be as PORTABLE_WORKBENCH_COMPONENT_TYPES,
354
+ he as mountWorkbench
355
+ };
356
+ //# sourceMappingURL=workbench.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workbench.js","sources":["../src/workbench/runtime.ts","../src/workbench/types.ts"],"sourcesContent":["// @ts-nocheck -- The runtime intentionally accepts forward-compatible Workbench JSON.\nimport type { WorkbenchConfig } from './types';\n\nfunction createPortableRuntime() {\n const state = {\n sourceConfig: null,\n config: null,\n root: null,\n activePage: null,\n activeTabs: new Map(),\n locale: 'en',\n theme: 'light',\n collapsed: false,\n mobileDrawerOpen: false,\n allowedShellOrigins: new Set(),\n };\n\n const escapeHtml = (value) => String(value ?? '')\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#039;');\n const normalizeLocale = (value) => String(value || '').toLowerCase().startsWith('zh') ? 'zh' : 'en';\n const normalizeTheme = (value) => value === 'dark' ? 'dark' : 'light';\n const isPlainObject = (value) => value && typeof value === 'object' && !Array.isArray(value);\n const clone = (value) => JSON.parse(JSON.stringify(value));\n const itemKey = (item, index) => ['key', 'dataIndex', 'id', 'value', 'name']\n .map((key) => item?.[key])\n .find((value) => value !== undefined && value !== null && String(value).trim() !== '') ?? `__index_${index}`;\n\n const mergeLocaleValue = (base, patch) => {\n if (Array.isArray(base) && Array.isArray(patch)) {\n const patches = new Map(patch.map((item, index) => [String(itemKey(item, index)), item]));\n return base.map((item, index) => {\n const match = patches.get(String(itemKey(item, index)));\n return isPlainObject(item) && isPlainObject(match) ? mergeLocaleValue(item, match) : item;\n });\n }\n if (isPlainObject(base) && isPlainObject(patch)) {\n const result = { ...base };\n Object.entries(patch).forEach(([key, value]) => {\n if (value !== undefined) result[key] = mergeLocaleValue(result[key], value);\n });\n return result;\n }\n return patch === undefined ? base : patch;\n };\n\n const localizeComponentTree = (component, patches) => {\n const ownPatch = component?.id ? patches?.[component.id] : null;\n const result = ownPatch ? mergeLocaleValue(component, ownPatch) : { ...component };\n ['components', 'children'].forEach((key) => {\n if (Array.isArray(result[key])) result[key] = result[key].map((child) => localizeComponentTree(child, patches));\n });\n if (Array.isArray(result.props?.components)) {\n result.props = { ...result.props, components: result.props.components.map((child) => localizeComponentTree(child, patches)) };\n }\n if (Array.isArray(result.props?.items)) {\n result.props = {\n ...result.props,\n items: result.props.items.map((item) => ({\n ...item,\n ...(item.component ? { component: localizeComponentTree(item.component, patches) } : {}),\n ...(Array.isArray(item.components) ? { components: item.components.map((child) => localizeComponentTree(child, patches)) } : {}),\n })),\n };\n }\n return result;\n };\n\n const applyLocale = (config, locale) => {\n const result = clone(config || {});\n const localePatch = result.metadata?.locales?.[locale];\n if (!localePatch) return result;\n if (localePatch.appConfig) result.appConfig = mergeLocaleValue(result.appConfig || {}, localePatch.appConfig);\n Object.entries(localePatch.pages || {}).forEach(([pageId, patch]) => {\n const page = result.pages?.[pageId];\n if (!page) return;\n const localized = { ...page };\n if (patch.title !== undefined) localized.title = patch.title;\n if (patch.description !== undefined) localized.description = patch.description;\n if (Array.isArray(localized.components)) {\n localized.components = localized.components.map((component) => localizeComponentTree(component, patch.components || {}));\n }\n result.pages[pageId] = localized;\n });\n return result;\n };\n\n const labelMap = () => state.sourceConfig?.metadata?.locales?.[state.locale]?.labels || {};\n const localizeLabel = (value) => {\n const raw = String(value ?? '');\n const labels = labelMap();\n if (labels[raw]) return labels[raw];\n return Object.keys(labels).sort((left, right) => right.length - left.length)\n .reduce((result, key) => key && result.includes(key) ? result.split(key).join(labels[key]) : result, raw);\n };\n const textValue = (value) => {\n if (value === null || value === undefined) return '';\n if (isPlainObject(value)) {\n const picked = value[state.locale] ?? value.zh ?? value.en;\n return picked === undefined || isPlainObject(picked) ? '' : localizeLabel(picked);\n }\n return localizeLabel(value);\n };\n\n const toKebab = (value) => value.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);\n const styleText = (styles) => Object.entries(styles || {})\n .filter(([, value]) => value !== null && value !== undefined && value !== '')\n .map(([key, value]) => `${toKebab(key)}:${String(value)}`)\n .join(';');\n const safeCustomCss = (css) => {\n const source = String(css || '');\n if (/@import|javascript:|expression\\s*\\(|url\\s*\\(\\s*['\"]?data:text\\/html/i.test(source)) return '';\n return source;\n };\n const customStyleTag = (entity, scope) => {\n const customStyles = entity?.customStyles || entity?.props?.customStyles;\n if (!customStyles) return '';\n const rules = [];\n Object.entries(customStyles.childStyles || {}).forEach(([selector, styles]) => rules.push(`${scope} ${selector}{${styleText(styles)}}`));\n Object.entries(customStyles.stateStyles || {}).forEach(([selector, styles]) => {\n const normalized = selector.startsWith(':') ? selector : `:${selector}`;\n rules.push(`${scope}${normalized}{${styleText(styles)}}`);\n });\n const customCss = safeCustomCss(customStyles.customCss);\n if (customCss) rules.push(customCss.replaceAll('&', scope));\n return rules.length ? `<style>${rules.join('\\n')}</style>` : '';\n };\n\n const iconSvg = (name, className = 'portable-icon') => {\n const paths = {\n LayoutDashboard: '<rect x=\"3\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"3\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"3\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/><rect x=\"14\" y=\"14\" width=\"7\" height=\"7\" rx=\"1\"/>',\n Activity: '<path d=\"M3 12h4l3-8 4 16 3-8h4\"/>',\n ClipboardList: '<rect x=\"5\" y=\"4\" width=\"14\" height=\"17\" rx=\"2\"/><path d=\"M9 4V2h6v2M9 10h6M9 14h6M9 18h4\"/>',\n Menu: '<path d=\"M4 7h16M4 12h16M4 17h16\"/>',\n X: '<path d=\"m6 6 12 12M18 6 6 18\"/>',\n ChevronLeft: '<path d=\"m15 18-6-6 6-6\"/>',\n ChevronRight: '<path d=\"m9 18 6-6-6-6\"/>',\n Languages: '<path d=\"M4 5h7M7.5 3v2c0 4-2 7-5 9M5 9c1 2 3 4 6 5M13 20l4-9 4 9M14.5 17h5\"/>',\n Sun: '<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4\"/>',\n Moon: '<path d=\"M20 15.5A8.5 8.5 0 0 1 8.5 4 8.5 8.5 0 1 0 20 15.5Z\"/>',\n };\n const body = paths[name] || '<circle cx=\"12\" cy=\"12\" r=\"8\"/><path d=\"M9 12h6\"/>';\n return `<svg class=\"${className}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">${body}</svg>`;\n };\n\n const formatValue = (value, column) => {\n if (value === null || value === undefined) return '—';\n if (column?.render === 'currency') {\n const number = Number(value);\n return Number.isFinite(number) ? new Intl.NumberFormat(state.locale === 'zh' ? 'zh-CN' : 'en-US', { style: 'currency', currency: 'USD' }).format(number) : value;\n }\n if (typeof value === 'boolean') return value ? 'Yes' : 'No';\n if (Array.isArray(value)) return value.map(textValue).join(', ');\n if (typeof value === 'object') return JSON.stringify(value);\n return textValue(value);\n };\n const titleBlock = (title, subtitle) => title\n ? `<div class=\"portable-section-heading\"><div><h2>${escapeHtml(textValue(title))}</h2>${subtitle ? `<p>${escapeHtml(textValue(subtitle))}</p>` : ''}</div></div>`\n : '';\n const renderTypography = (component) => {\n const props = component.props || {};\n const text = props.content ?? props.text ?? props.children ?? props.title ?? '';\n const variant = String(props.variant || 'paragraph').toLowerCase();\n const tag = variant === 'title' || variant.startsWith('h') ? (variant.match(/^h[1-6]$/)?.[0] || 'h2') : 'p';\n return `<${tag} class=\"portable-typography portable-typography-${escapeHtml(variant)}\">${escapeHtml(textValue(text))}</${tag}>`;\n };\n const renderStatistics = (component) => {\n const props = component.props || {};\n const items = props.items || component.mockData || [];\n const columns = Math.max(1, Math.min(6, Number(props.grid?.cols || props.columns || items.length || 1)));\n return `<div class=\"portable-stat-grid\" style=\"--stat-columns:${columns}\">${items.map((item) => {\n const trend = item.trend;\n const direction = trend?.type === 'down' ? 'down' : 'up';\n const trendText = trend ? `${direction === 'down' ? '↓' : '↑'} ${trend.value ?? ''}${trend.suffix ?? ''}` : '';\n return `<article class=\"portable-stat\"><div class=\"portable-stat-title\">${escapeHtml(textValue(item.title || item.label))}</div><div class=\"portable-stat-value\">${escapeHtml(item.prefix || '')}${escapeHtml(item.value)}${escapeHtml(item.suffix || '')}</div>${trend ? `<div class=\"portable-stat-trend ${direction}\">${escapeHtml(trendText)} <span>${escapeHtml(textValue(trend.description || ''))}</span></div>` : ''}</article>`;\n }).join('')}</div>`;\n };\n const renderTable = (component) => {\n const props = component.props || {};\n const rows = component.mockData || props.data || props.rows || [];\n const columns = props.columns?.length ? props.columns : Object.keys(rows[0] || {}).map((key) => ({ key, dataIndex: key, title: key }));\n return `${titleBlock(props.title, props.description)}<div class=\"portable-table-wrap\"><table><thead><tr>${columns.map((column) => `<th>${escapeHtml(textValue(column.title || column.label || column.key))}</th>`).join('')}</tr></thead><tbody>${rows.map((row) => `<tr>${columns.map((column) => `<td>${escapeHtml(formatValue(row[column.dataIndex || column.key], column))}</td>`).join('')}</tr>`).join('')}</tbody></table>${rows.length === 0 ? '<div class=\"portable-empty\">No data</div>' : ''}</div>`;\n };\n const renderDataGridCard = (component) => {\n const props = component.props || {};\n const rows = component.mockData || props.mockData || props.data || props.rows || [];\n const columns = props.columns || [];\n const primary = columns.find((column) => column.primary) || columns[0];\n const secondary = columns.find((column) => column.secondary) || columns[1];\n const details = columns.filter((column) => column !== primary && column !== secondary);\n const gridValue = (row, column) => {\n const value = row?.[column?.dataIndex || column?.key];\n const mapped = column?.render?.text?.[value] ?? value;\n if (column?.render?.type === 'Progress') {\n const progress = Math.max(0, Math.min(100, Number(value) || 0));\n return `<span class=\"portable-progress\"><span style=\"width:${progress}%\"></span></span><small>${escapeHtml(`${progress}%`)}</small>`;\n }\n if (column?.render?.type === 'Tag') {\n return `<span class=\"portable-tag\">${escapeHtml(textValue(mapped))}</span>`;\n }\n return escapeHtml(formatValue(mapped, column));\n };\n return `${titleBlock(props.title, props.description)}${props.showSearch ? `<div class=\"portable-grid-search\"><input type=\"search\" placeholder=\"${escapeHtml(textValue(props.searchPlaceholder || 'Search...'))}\" /></div>` : ''}<div class=\"portable-card-grid\">${rows.map((row) => `<article><header><div><strong>${primary ? gridValue(row, primary) : ''}</strong>${secondary ? `<p>${gridValue(row, secondary)}</p>` : ''}</div><span aria-hidden=\"true\">›</span></header>${details.length ? `<dl>${details.map((column) => `<div><dt>${escapeHtml(textValue(column.title || column.label || column.key))}</dt><dd>${gridValue(row, column)}</dd></div>`).join('')}</dl>` : ''}</article>`).join('')}${rows.length === 0 ? '<div class=\"portable-empty\">No data</div>' : ''}</div>`;\n };\n const numericEntries = (row) => Object.entries(row || {}).filter(([, value]) => typeof value === 'number');\n const renderChart = (component) => {\n const props = component.props || {};\n const rows = component.mockData || props.data || [];\n const values = rows.map((row) => numericEntries(row)[0]?.[1] || 0);\n const labels = rows.map((row, index) => textValue(Object.values(row).find((value) => typeof value === 'string') || index + 1));\n const max = Math.max(...values, 1);\n const width = 720;\n const height = Math.max(180, Number(props.height || 260));\n const chartType = String(props.chartType || props.type || 'bar').toLowerCase();\n let graphic = '';\n if (chartType.includes('line')) {\n const points = values.map((value, index) => {\n const x = values.length === 1 ? width / 2 : 24 + index * ((width - 48) / Math.max(1, values.length - 1));\n const y = height - 36 - (value / max) * (height - 72);\n return `${x},${y}`;\n }).join(' ');\n graphic = `<polyline points=\"${points}\" fill=\"none\" stroke=\"var(--portable-accent)\" stroke-width=\"4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>${points.split(' ').map((point) => { const [x, y] = point.split(','); return `<circle cx=\"${x}\" cy=\"${y}\" r=\"5\" fill=\"var(--portable-surface)\" stroke=\"var(--portable-accent)\" stroke-width=\"3\"/>`; }).join('')}`;\n } else {\n const step = (width - 48) / Math.max(1, values.length);\n graphic = values.map((value, index) => {\n const barHeight = (value / max) * (height - 72);\n return `<rect x=\"${24 + index * step + step * 0.16}\" y=\"${height - 36 - barHeight}\" width=\"${step * 0.68}\" height=\"${barHeight}\" rx=\"5\" fill=\"var(--portable-accent)\" opacity=\"${0.7 + (index % 3) * 0.12}\"/>`;\n }).join('');\n }\n const axis = labels.map((label, index) => {\n const x = values.length === 1 ? width / 2 : 24 + index * ((width - 48) / Math.max(1, values.length - 1));\n return `<text x=\"${x}\" y=\"${height - 10}\" text-anchor=\"middle\">${escapeHtml(label)}</text>`;\n }).join('');\n return `${titleBlock(props.title, props.description)}<div class=\"portable-chart\"><svg viewBox=\"0 0 ${width} ${height}\" role=\"img\" aria-label=\"${escapeHtml(textValue(props.title || 'Chart'))}\">${graphic}${axis}</svg></div>`;\n };\n const renderForm = (component) => {\n const props = component.props || {};\n const fields = props.fields || props.items || [];\n return `${titleBlock(props.title, props.description)}<form class=\"portable-form\" onsubmit=\"return false\">${fields.map((field) => {\n const type = field.type === 'textarea' ? 'textarea' : 'input';\n const control = type === 'textarea'\n ? `<textarea placeholder=\"${escapeHtml(textValue(field.placeholder || ''))}\">${escapeHtml(textValue(field.defaultValue || ''))}</textarea>`\n : `<input type=\"${escapeHtml(field.type === 'number' ? 'number' : 'text')}\" value=\"${escapeHtml(textValue(field.defaultValue || ''))}\" placeholder=\"${escapeHtml(textValue(field.placeholder || ''))}\"/>`;\n return `<label><span>${escapeHtml(textValue(field.label || field.title || field.name))}</span>${control}</label>`;\n }).join('')}<button type=\"button\">${escapeHtml(textValue(props.submitButtonText || props.submitText || 'Submit'))}</button></form>`;\n };\n const renderTaskInput = (component) => {\n const props = component.props || {};\n const title = props.title || component.mockTitle;\n const description = props.description || component.mockDescription;\n const files = props.mockFileData?.files || component.mockFileData?.files || [];\n const fields = props.fields || component.parameterConfig?.fields || [];\n return `${titleBlock(props.showTitle === false ? '' : title, props.showDescription === false ? '' : description)}<div class=\"portable-task-input\">${fields.length ? `<div class=\"portable-task-fields\">${fields.map((field) => `<label><span>${escapeHtml(textValue(field.label || field.title || field.name))}</span><input type=\"text\" placeholder=\"${escapeHtml(textValue(field.placeholder || ''))}\" /></label>`).join('')}</div>` : ''}<label class=\"portable-file-drop\"><input type=\"file\" multiple /><span class=\"portable-file-icon\">↑</span><strong>${escapeHtml(textValue(props.uploadText || 'Choose files or drop them here'))}</strong><small>${escapeHtml(textValue(props.uploadHint || 'Files remain local in this portable preview'))}</small></label>${files.length ? `<div class=\"portable-file-list\">${files.map((file) => `<div><span>${escapeHtml(file.name || 'File')}</span><small>${escapeHtml(file.type || '')}</small></div>`).join('')}</div>` : ''}<button type=\"button\" class=\"portable-task-submit\">${escapeHtml(textValue(props.submitButtonText || 'Run task'))}</button></div>`;\n };\n const renderList = (component) => {\n const props = component.props || {};\n const rows = component.mockData || props.items || [];\n return `${titleBlock(props.title, props.description)}<div class=\"portable-list\">${rows.map((row) => {\n const title = typeof row === 'object' ? row.title || row.name || row.label || Object.values(row)[0] : row;\n const description = typeof row === 'object' ? row.description || row.subtitle || Object.values(row)[1] : '';\n return `<article><strong>${escapeHtml(textValue(title))}</strong>${description ? `<p>${escapeHtml(textValue(description))}</p>` : ''}</article>`;\n }).join('')}</div>`;\n };\n const renderTabs = (component) => {\n const props = component.props || {};\n const items = props.items || props.tabs || [];\n const activeKey = state.activeTabs.get(component.id) || items[0]?.key || items[0]?.id;\n const active = items.find((item) => (item.key || item.id) === activeKey) || items[0];\n const activeComponents = active?.components || (active?.component ? [active.component] : []);\n return `<div class=\"portable-tabs\" data-tabs=\"${escapeHtml(component.id)}\"><div class=\"portable-tab-list\">${items.map((item) => `<button type=\"button\" data-tab-key=\"${escapeHtml(item.key || item.id)}\" class=\"${(item.key || item.id) === activeKey ? 'active' : ''}\">${escapeHtml(textValue(item.title || item.label))}</button>`).join('')}</div><div class=\"portable-tab-panel\">${activeComponents.map(renderComponent).join('') || escapeHtml(textValue(active?.content || ''))}</div></div>`;\n };\n const renderContainer = (component) => {\n const props = component.props || {};\n const children = component.components || component.children || props.components || props.children;\n if (Array.isArray(children)) return `<div class=\"portable-container\">${children.map(renderComponent).join('')}</div>`;\n return `${titleBlock(props.title, props.subtitle)}${props.content ? `<p>${escapeHtml(textValue(props.content))}</p>` : ''}`;\n };\n const sanitizeHtml = (html) => {\n const template = document.createElement('template');\n template.innerHTML = String(html || '');\n template.content.querySelectorAll('script,iframe,object,embed,link,meta').forEach((node) => node.remove());\n template.content.querySelectorAll('*').forEach((node) => {\n [...node.attributes].forEach((attribute) => {\n if (/^on/i.test(attribute.name) || /javascript:/i.test(attribute.value)) node.removeAttribute(attribute.name);\n });\n });\n return template.innerHTML;\n };\n\n function renderComponent(component) {\n const props = component?.props || {};\n const scopeClass = `portable-component-${String(component?.id || 'anonymous').replace(/[^a-zA-Z0-9_-]/g, '-')}`;\n const rootStyles = component?.customStyles?.rootStyles || props.customStyles?.rootStyles || {};\n let content;\n switch (component?.type) {\n case 'Typography': case 'Text': case 'Title': case 'Paragraph': content = renderTypography(component); break;\n case 'Statistic': case 'StatisticGroup': content = renderStatistics(component); break;\n case 'Table': case 'EditableTable': case 'AnalyticsTable': content = renderTable(component); break;\n case 'DataGridCard': content = renderDataGridCard(component); break;\n case 'Chart': case 'EChartsChart': case 'RadarChart': content = renderChart(component); break;\n case 'Form': content = renderForm(component); break;\n case 'TaskInput': case 'TaskInputRenderer': content = renderTaskInput(component); break;\n case 'List': content = renderList(component); break;\n case 'Tabs': content = renderTabs(component); break;\n case 'Container': case 'Card': content = renderContainer(component); break;\n case 'CustomContent': content = sanitizeHtml(props.html || props.content || ''); break;\n case 'FilterPanel': content = renderForm({ ...component, props: { ...props, submitText: props.submitText || 'Apply filters' } }); break;\n default: content = `<div class=\"portable-unsupported\">Unsupported component: ${escapeHtml(component?.type)}</div>`;\n }\n return `${customStyleTag(component, `.${scopeClass}`)}<section class=\"portable-component ${scopeClass} portable-type-${escapeHtml(component?.type || 'unknown')}\" style=\"${escapeHtml(styleText(rootStyles))}\" data-component-id=\"${escapeHtml(component?.id)}\">${content}</section>`;\n }\n\n const isVisibleForDevice = (item, device) => !item?.visibility?.devices?.length || item.visibility.devices.includes(device);\n const firstPageForNavigation = (item, device) => {\n if (!isVisibleForDevice(item, device)) return null;\n if (item.linkedPage) return item.linkedPage;\n for (const child of item.children || []) {\n const page = firstPageForNavigation(child, device);\n if (page) return page;\n }\n return null;\n };\n const flattenNavigation = (items, device, depth = 0) => (items || []).flatMap((item) => {\n if (!isVisibleForDevice(item, device)) return [];\n const current = item.linkedPage ? [{ ...item, depth }] : [];\n return current.concat(flattenNavigation(item.children, device, depth + 1));\n });\n const mobileTabs = (items) => (items || []).flatMap((item) => {\n const page = firstPageForNavigation(item, 'mobile');\n return page ? [{ ...item, linkedPage: page }] : [];\n });\n const renderNavItems = (items, device) => flattenNavigation(items, device).map((item) => `\n <button type=\"button\" data-page=\"${escapeHtml(item.linkedPage)}\" class=\"portable-nav-item ${item.linkedPage === state.activePage ? 'active' : ''}\" style=\"--nav-depth:${item.depth}\">\n ${iconSvg(item.icon)}<span>${escapeHtml(textValue(item.title || item.key))}</span>\n </button>`).join('');\n const renderControls = (compact = false) => `<div class=\"portable-controls ${compact ? 'compact' : ''}\">\n <button type=\"button\" data-locale-toggle aria-label=\"Change language\">${iconSvg('Languages')}<span>${state.locale === 'zh' ? 'EN' : 'ZH'}</span></button>\n <button type=\"button\" data-theme-toggle aria-label=\"Change color theme\">${iconSvg(state.theme === 'dark' ? 'Sun' : 'Moon')}<span>${state.theme === 'dark' ? 'Light' : 'Dark'}</span></button>\n </div>`;\n const renderBrand = (collapsed = false) => {\n const appConfig = state.config.appConfig || {};\n return `<div class=\"portable-brand ${collapsed ? 'collapsed' : ''}\"><span>${escapeHtml(textValue(appConfig.name || 'G').slice(0, 1))}</span>${collapsed ? '' : `<div><strong>${escapeHtml(textValue(appConfig.name || 'GeniApp'))}</strong><small>${escapeHtml(textValue(appConfig.description || 'Exported from Workbench'))}</small></div>`}</div>`;\n };\n\n const renderPage = () => {\n const page = state.config.pages?.[state.activePage] || Object.values(state.config.pages || {})[0];\n const pageKey = state.activePage || Object.keys(state.config.pages || {})[0];\n if (!page) return '<main class=\"portable-page\"><div class=\"portable-empty\">No pages were exported.</div></main>';\n const pageScope = `.portable-page-${String(pageKey).replace(/[^a-zA-Z0-9_-]/g, '-')}`;\n const pageRoot = page.customStyles?.rootStyles || {};\n const placementList = page.layout?.type === 'grid-24' ? page.layout.components || [] : [];\n const placements = placementList.reduce((result, placement) => {\n if (placement?.id) result[placement.id] = placement;\n return result;\n }, page.layout?.placements || {});\n const components = (page.components || []).map((component) => {\n const placement = placements[component.id];\n const placementStyle = placement\n ? `grid-column:${Number(placement.colStart || 0) + 1} / span ${Number(placement.colSpan || 24)};grid-row:${Number(placement.rowStart || 0) + 1} / span ${Number(placement.rowSpan || 1)};`\n : '';\n return `<div class=\"portable-placement\" style=\"${placementStyle}\">${renderComponent(component)}</div>`;\n }).join('');\n return `${customStyleTag(page, pageScope)}<main class=\"portable-page ${pageScope}\" style=\"${escapeHtml(styleText(pageRoot))}\"><header class=\"portable-page-header\"><div><span class=\"portable-eyebrow\">${escapeHtml(textValue(state.config.appConfig?.name || ''))}</span><h1>${escapeHtml(textValue(page.title || pageKey))}</h1>${page.description ? `<p>${escapeHtml(textValue(page.description))}</p>` : ''}</div></header><div class=\"portable-page-grid ${page.layout?.type === 'grid-24' ? 'grid-24' : ''}\">${components}</div></main>`;\n };\n\n const applyDocumentUi = () => {\n document.documentElement.lang = state.locale === 'zh' ? 'zh-CN' : 'en';\n document.documentElement.classList.toggle('dark', state.theme === 'dark');\n document.documentElement.dataset.colorMode = state.theme;\n document.documentElement.style.colorScheme = state.theme;\n };\n const renderAndPersistLocale = (locale) => {\n state.locale = normalizeLocale(locale);\n state.config = applyLocale(state.sourceConfig, state.locale);\n try { localStorage.setItem('language', state.locale); } catch { /* ignore */ }\n applyDocumentUi();\n renderApp();\n };\n const renderAndPersistTheme = (theme) => {\n state.theme = normalizeTheme(theme);\n try { localStorage.setItem('theme', state.theme); } catch { /* ignore */ }\n applyDocumentUi();\n renderApp();\n };\n const navigatePage = (page) => {\n if (!state.config.pages?.[page]) return;\n state.activePage = page;\n state.mobileDrawerOpen = false;\n if (decodeURIComponent(window.location.hash.replace(/^#/, '')) !== page) window.location.hash = encodeURIComponent(page);\n renderApp();\n };\n\n const bindShellBridge = () => {\n window.addEventListener('message', (event) => {\n const message = event.data;\n if (!message || message.v !== 1 || typeof message !== 'object') return;\n const normalizedOrigin = event.origin.replace(/\\/$/, '');\n if (message.type === 'GENISPACE_SHELL_INIT') {\n const payload = message.payload || {};\n const origins = [payload.shellOrigin, ...(Array.isArray(payload.allowedShellOrigins) ? payload.allowedShellOrigins : [])]\n .filter(Boolean).map((origin) => String(origin).replace(/\\/$/, ''));\n if (origins.length && !origins.includes(normalizedOrigin)) return;\n state.allowedShellOrigins = new Set(origins.length ? origins : [normalizedOrigin]);\n if (payload.locale) state.locale = normalizeLocale(payload.locale);\n if (payload.theme) state.theme = normalizeTheme(payload.theme);\n state.config = applyLocale(state.sourceConfig, state.locale);\n applyDocumentUi();\n renderApp();\n window.parent.postMessage({ type: 'GENISPACE_IFRAME_READY', v: 1, identifier: state.config.appConfig?.appId || '' }, event.origin);\n return;\n }\n if (message.type === 'GENISPACE_SHELL_UI' && state.allowedShellOrigins.has(normalizedOrigin)) {\n if (message.locale) state.locale = normalizeLocale(message.locale);\n if (message.theme) state.theme = normalizeTheme(message.theme);\n state.config = applyLocale(state.sourceConfig, state.locale);\n applyDocumentUi();\n renderApp();\n }\n });\n };\n\n function renderApp() {\n const root = state.root;\n if (!root || !state.config) return;\n const navigation = state.config.appConfig?.navigation?.items || [];\n const mobileNavigation = mobileTabs(navigation);\n root.innerHTML = `<div class=\"portable-shell ${state.collapsed ? 'sidebar-collapsed' : ''}\">\n <aside class=\"portable-sidebar\">\n <div class=\"portable-sidebar-header\">${renderBrand(state.collapsed)}</div>\n <button type=\"button\" class=\"portable-collapse\" data-collapse aria-label=\"${state.collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\">${iconSvg(state.collapsed ? 'ChevronRight' : 'ChevronLeft')}</button>\n <nav aria-label=\"Application navigation\">${renderNavItems(navigation, 'desktop')}</nav>\n <footer>${renderControls(state.collapsed)}</footer>\n </aside>\n <header class=\"portable-mobile-header\"><button type=\"button\" data-mobile-drawer aria-label=\"Open navigation\">${iconSvg('Menu')}</button>${renderBrand(false)}${renderControls(true)}</header>\n ${state.mobileDrawerOpen ? `<div class=\"portable-mobile-backdrop\" data-mobile-close></div><aside class=\"portable-mobile-drawer\"><div class=\"portable-mobile-drawer-close\"><button type=\"button\" data-mobile-close aria-label=\"Close navigation\">${iconSvg('X')}</button></div><div class=\"portable-sidebar-header\">${renderBrand(false)}</div><nav>${renderNavItems(navigation, 'mobile')}</nav><footer>${renderControls(false)}</footer></aside>` : ''}\n <div class=\"portable-content\">${renderPage()}</div>\n <nav class=\"portable-mobile-nav\" aria-label=\"Workbench bottom navigation\">${mobileNavigation.map((item) => `<button type=\"button\" data-page=\"${escapeHtml(item.linkedPage)}\" class=\"${item.linkedPage === state.activePage ? 'active' : ''}\" aria-current=\"${item.linkedPage === state.activePage ? 'page' : 'false'}\">${iconSvg(item.icon)}<span>${escapeHtml(textValue(item.title || item.key))}</span></button>`).join('')}</nav>\n </div>`;\n root.querySelectorAll('[data-page]').forEach((button) => button.addEventListener('click', () => navigatePage(button.dataset.page)));\n root.querySelectorAll('[data-tabs] [data-tab-key]').forEach((button) => button.addEventListener('click', () => {\n const tabs = button.closest('[data-tabs]');\n state.activeTabs.set(tabs.dataset.tabs, button.dataset.tabKey);\n renderApp();\n }));\n root.querySelectorAll('[data-locale-toggle]').forEach((button) => button.addEventListener('click', () => renderAndPersistLocale(state.locale === 'zh' ? 'en' : 'zh')));\n root.querySelectorAll('[data-theme-toggle]').forEach((button) => button.addEventListener('click', () => renderAndPersistTheme(state.theme === 'dark' ? 'light' : 'dark')));\n root.querySelector('[data-collapse]')?.addEventListener('click', () => {\n state.collapsed = !state.collapsed;\n try { localStorage.setItem('portable_sidebar_collapsed', JSON.stringify(state.collapsed)); } catch { /* ignore */ }\n renderApp();\n });\n root.querySelector('[data-mobile-drawer]')?.addEventListener('click', () => { state.mobileDrawerOpen = true; renderApp(); });\n root.querySelectorAll('[data-mobile-close]').forEach((button) => button.addEventListener('click', () => { state.mobileDrawerOpen = false; renderApp(); }));\n }\n\n const mountWorkbench = (root, config) => {\n if (!root) throw new Error('A root element is required.');\n state.root = root;\n state.sourceConfig = config || {};\n const search = new URLSearchParams(window.location.search);\n let savedLocale = '';\n let savedTheme = '';\n let savedCollapsed = false;\n try {\n savedLocale = localStorage.getItem('language') || '';\n savedTheme = localStorage.getItem('theme') || '';\n savedCollapsed = JSON.parse(localStorage.getItem('portable_sidebar_collapsed') || 'false');\n } catch { /* ignore */ }\n state.locale = normalizeLocale(search.get('lng') || savedLocale || document.documentElement.lang || 'en');\n state.theme = normalizeTheme(search.get('theme') || savedTheme || (window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'));\n state.collapsed = Boolean(savedCollapsed);\n state.config = applyLocale(state.sourceConfig, state.locale);\n const requestedPage = decodeURIComponent(window.location.hash.replace(/^#/, ''));\n state.activePage = state.config.pages?.[requestedPage]\n ? requestedPage\n : state.config.appConfig?.defaultPage || Object.keys(state.config.pages || {})[0];\n state.allowedShellOrigins.add(window.location.origin.replace(/\\/$/, ''));\n applyDocumentUi();\n bindShellBridge();\n window.addEventListener('hashchange', () => {\n const requested = decodeURIComponent(window.location.hash.replace(/^#/, ''));\n if (state.config.pages?.[requested] && requested !== state.activePage) {\n state.activePage = requested;\n renderApp();\n }\n });\n renderApp();\n if (window.parent !== window) window.parent.postMessage({ type: 'GENIAPP_READY', app: state.config.appConfig?.appId || '' }, '*');\n };\n\n return { mountWorkbench };\n}\n\n\nconst portableRuntime = createPortableRuntime();\n\nexport const mountWorkbench = portableRuntime.mountWorkbench as (\n root: HTMLElement,\n config: WorkbenchConfig,\n) => void;\n\n","export const PORTABLE_WORKBENCH_COMPONENT_TYPES = [\n 'Typography', 'Text', 'Title', 'Paragraph', 'Statistic', 'StatisticGroup',\n 'Table', 'EditableTable', 'AnalyticsTable', 'DataGridCard', 'Chart',\n 'EChartsChart', 'RadarChart', 'Form', 'TaskInput', 'TaskInputRenderer',\n 'List', 'Tabs', 'Container', 'Card', 'CustomContent', 'FilterPanel',\n] as const;\n\nexport type PortableWorkbenchComponentType = typeof PORTABLE_WORKBENCH_COMPONENT_TYPES[number];\n\nexport type WorkbenchNavigationItem = {\n key?: string;\n title?: string | Record<string, string>;\n icon?: string;\n linkedPage?: string;\n children?: WorkbenchNavigationItem[];\n visibility?: { devices?: Array<'desktop' | 'mobile'> };\n [key: string]: unknown;\n};\n\nexport type WorkbenchComponentConfig = {\n id: string;\n type: PortableWorkbenchComponentType | string;\n props?: Record<string, unknown>;\n components?: WorkbenchComponentConfig[];\n children?: WorkbenchComponentConfig[];\n customStyles?: Record<string, unknown>;\n mockData?: unknown[];\n [key: string]: unknown;\n};\n\nexport type WorkbenchPageConfig = {\n title?: string | Record<string, string>;\n description?: string | Record<string, string>;\n layout?: Record<string, unknown>;\n components?: WorkbenchComponentConfig[];\n customStyles?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport type WorkbenchAppConfig = {\n appId?: string;\n name?: string | Record<string, string>;\n description?: string | Record<string, string>;\n defaultPage?: string;\n navigation?: { items?: WorkbenchNavigationItem[] };\n [key: string]: unknown;\n};\n\nexport type WorkbenchConfig = {\n schemaVersion?: number;\n appConfig?: WorkbenchAppConfig;\n pages?: Record<string, WorkbenchPageConfig>;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n};\n"],"names":["createPortableRuntime","state","escapeHtml","value","normalizeLocale","normalizeTheme","isPlainObject","clone","itemKey","item","index","key","mergeLocaleValue","base","patch","patches","match","result","localizeComponentTree","component","ownPatch","child","applyLocale","config","locale","localePatch","pageId","page","localized","labelMap","localizeLabel","raw","labels","left","right","textValue","picked","toKebab","letter","styleText","styles","safeCustomCss","css","source","customStyleTag","entity","scope","customStyles","rules","selector","normalized","customCss","iconSvg","name","className","body","formatValue","column","number","titleBlock","title","subtitle","renderTypography","props","text","variant","tag","renderStatistics","items","trend","direction","trendText","renderTable","rows","columns","row","renderDataGridCard","primary","secondary","details","gridValue","mapped","progress","numericEntries","renderChart","values","max","width","height","chartType","graphic","points","x","y","point","step","barHeight","axis","label","renderForm","fields","field","control","renderTaskInput","description","files","file","renderList","renderTabs","activeKey","active","activeComponents","renderComponent","renderContainer","children","sanitizeHtml","html","template","node","attribute","scopeClass","rootStyles","content","isVisibleForDevice","device","firstPageForNavigation","flattenNavigation","depth","mobileTabs","renderNavItems","renderControls","compact","renderBrand","collapsed","appConfig","renderPage","pageKey","pageScope","pageRoot","placements","placement","components","applyDocumentUi","renderAndPersistLocale","renderApp","renderAndPersistTheme","theme","navigatePage","bindShellBridge","event","message","normalizedOrigin","payload","origins","origin","root","navigation","mobileNavigation","button","tabs","search","savedLocale","savedTheme","savedCollapsed","requestedPage","requested","mountWorkbench","portableRuntime","PORTABLE_WORKBENCH_COMPONENT_TYPES"],"mappings":"AAGA,SAASA,KAAwB;AAC/B,QAAMC,IAAQ;AAAA,IACZ,cAAc;AAAA,IACd,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,gCAAgB,IAAA;AAAA,IAChB,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,WAAW;AAAA,IACX,kBAAkB;AAAA,IAClB,yCAAyB,IAAA;AAAA,EAAI,GAGzBC,IAAa,CAACC,MAAU,OAAOA,KAAS,EAAE,EAC7C,WAAW,KAAK,OAAO,EACvB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,MAAM,EACtB,WAAW,KAAK,QAAQ,EACxB,WAAW,KAAK,QAAQ,GACrBC,IAAkB,CAACD,MAAU,OAAOA,KAAS,EAAE,EAAE,YAAA,EAAc,WAAW,IAAI,IAAI,OAAO,MACzFE,IAAiB,CAACF,MAAUA,MAAU,SAAS,SAAS,SACxDG,IAAgB,CAACH,MAAUA,KAAS,OAAOA,KAAU,YAAY,CAAC,MAAM,QAAQA,CAAK,GACrFI,IAAQ,CAACJ,MAAU,KAAK,MAAM,KAAK,UAAUA,CAAK,CAAC,GACnDK,IAAU,CAACC,GAAMC,MAAU,CAAC,OAAO,aAAa,MAAM,SAAS,MAAM,EACxE,IAAI,CAACC,MAAQF,IAAOE,CAAG,CAAC,EACxB,KAAK,CAACR,MAAiCA,KAAU,QAAQ,OAAOA,CAAK,EAAE,KAAA,MAAW,EAAE,KAAK,WAAWO,CAAK,IAEtGE,IAAmB,CAACC,GAAMC,MAAU;AACxC,QAAI,MAAM,QAAQD,CAAI,KAAK,MAAM,QAAQC,CAAK,GAAG;AAC/C,YAAMC,IAAU,IAAI,IAAID,EAAM,IAAI,CAACL,GAAMC,MAAU,CAAC,OAAOF,EAAQC,GAAMC,CAAK,CAAC,GAAGD,CAAI,CAAC,CAAC;AACxF,aAAOI,EAAK,IAAI,CAACJ,GAAMC,MAAU;AAC/B,cAAMM,IAAQD,EAAQ,IAAI,OAAOP,EAAQC,GAAMC,CAAK,CAAC,CAAC;AACtD,eAAOJ,EAAcG,CAAI,KAAKH,EAAcU,CAAK,IAAIJ,EAAiBH,GAAMO,CAAK,IAAIP;AAAA,MACvF,CAAC;AAAA,IACH;AACA,QAAIH,EAAcO,CAAI,KAAKP,EAAcQ,CAAK,GAAG;AAC/C,YAAMG,IAAS,EAAE,GAAGJ,EAAA;AACpB,oBAAO,QAAQC,CAAK,EAAE,QAAQ,CAAC,CAACH,GAAKR,CAAK,MAAM;AAC9C,QAAIA,MAAU,WAAWc,EAAON,CAAG,IAAIC,EAAiBK,EAAON,CAAG,GAAGR,CAAK;AAAA,MAC5E,CAAC,GACMc;AAAA,IACT;AACA,WAAOH,MAAU,SAAYD,IAAOC;AAAA,EACtC,GAEMI,IAAwB,CAACC,GAAWJ,MAAY;AACpD,UAAMK,IAAWD,GAAW,KAAKJ,IAAUI,EAAU,EAAE,IAAI,MACrDF,IAASG,IAAWR,EAAiBO,GAAWC,CAAQ,IAAI,EAAE,GAAGD,EAAA;AACvE,YAAC,cAAc,UAAU,EAAE,QAAQ,CAACR,MAAQ;AAC1C,MAAI,MAAM,QAAQM,EAAON,CAAG,CAAC,QAAUA,CAAG,IAAIM,EAAON,CAAG,EAAE,IAAI,CAACU,MAAUH,EAAsBG,GAAON,CAAO,CAAC;AAAA,IAChH,CAAC,GACG,MAAM,QAAQE,EAAO,OAAO,UAAU,MACxCA,EAAO,QAAQ,EAAE,GAAGA,EAAO,OAAO,YAAYA,EAAO,MAAM,WAAW,IAAI,CAACI,MAAUH,EAAsBG,GAAON,CAAO,CAAC,EAAA,IAExH,MAAM,QAAQE,EAAO,OAAO,KAAK,MACnCA,EAAO,QAAQ;AAAA,MACb,GAAGA,EAAO;AAAA,MACV,OAAOA,EAAO,MAAM,MAAM,IAAI,CAACR,OAAU;AAAA,QACvC,GAAGA;AAAA,QACH,GAAIA,EAAK,YAAY,EAAE,WAAWS,EAAsBT,EAAK,WAAWM,CAAO,EAAA,IAAM,CAAA;AAAA,QACrF,GAAI,MAAM,QAAQN,EAAK,UAAU,IAAI,EAAE,YAAYA,EAAK,WAAW,IAAI,CAACY,MAAUH,EAAsBG,GAAON,CAAO,CAAC,MAAM,CAAA;AAAA,MAAC,EAC9H;AAAA,IAAA,IAGCE;AAAA,EACT,GAEMK,IAAc,CAACC,GAAQC,MAAW;AACtC,UAAMP,IAASV,EAAMgB,KAAU,EAAE,GAC3BE,IAAcR,EAAO,UAAU,UAAUO,CAAM;AACrD,WAAKC,MACDA,EAAY,cAAWR,EAAO,YAAYL,EAAiBK,EAAO,aAAa,CAAA,GAAIQ,EAAY,SAAS,IAC5G,OAAO,QAAQA,EAAY,SAAS,CAAA,CAAE,EAAE,QAAQ,CAAC,CAACC,GAAQZ,CAAK,MAAM;AACnE,YAAMa,IAAOV,EAAO,QAAQS,CAAM;AAClC,UAAI,CAACC,EAAM;AACX,YAAMC,IAAY,EAAE,GAAGD,EAAA;AACvB,MAAIb,EAAM,UAAU,WAAWc,EAAU,QAAQd,EAAM,QACnDA,EAAM,gBAAgB,WAAWc,EAAU,cAAcd,EAAM,cAC/D,MAAM,QAAQc,EAAU,UAAU,MACpCA,EAAU,aAAaA,EAAU,WAAW,IAAI,CAACT,MAAcD,EAAsBC,GAAWL,EAAM,cAAc,CAAA,CAAE,CAAC,IAEzHG,EAAO,MAAMS,CAAM,IAAIE;AAAA,IACzB,CAAC,IACMX;AAAA,EACT,GAEMY,IAAW,MAAM5B,EAAM,cAAc,UAAU,UAAUA,EAAM,MAAM,GAAG,UAAU,CAAA,GAClF6B,IAAgB,CAAC3B,MAAU;AAC/B,UAAM4B,IAAM,OAAO5B,KAAS,EAAE,GACxB6B,IAASH,EAAA;AACf,WAAIG,EAAOD,CAAG,IAAUC,EAAOD,CAAG,IAC3B,OAAO,KAAKC,CAAM,EAAE,KAAK,CAACC,GAAMC,MAAUA,EAAM,SAASD,EAAK,MAAM,EACxE,OAAO,CAAChB,GAAQN,MAAQA,KAAOM,EAAO,SAASN,CAAG,IAAIM,EAAO,MAAMN,CAAG,EAAE,KAAKqB,EAAOrB,CAAG,CAAC,IAAIM,GAAQc,CAAG;AAAA,EAC5G,GACMI,IAAY,CAAChC,MAAU;AAC3B,QAAIA,KAAU,KAA6B,QAAO;AAClD,QAAIG,EAAcH,CAAK,GAAG;AACxB,YAAMiC,IAASjC,EAAMF,EAAM,MAAM,KAAKE,EAAM,MAAMA,EAAM;AACxD,aAAOiC,MAAW,UAAa9B,EAAc8B,CAAM,IAAI,KAAKN,EAAcM,CAAM;AAAA,IAClF;AACA,WAAON,EAAc3B,CAAK;AAAA,EAC5B,GAEMkC,IAAU,CAAClC,MAAUA,EAAM,QAAQ,UAAU,CAACmC,MAAW,IAAIA,EAAO,YAAA,CAAa,EAAE,GACnFC,IAAY,CAACC,MAAW,OAAO,QAAQA,KAAU,EAAE,EACtD,OAAO,CAAC,CAAA,EAAGrC,CAAK,MAAMA,KAAU,QAA+BA,MAAU,EAAE,EAC3E,IAAI,CAAC,CAACQ,GAAKR,CAAK,MAAM,GAAGkC,EAAQ1B,CAAG,CAAC,IAAI,OAAOR,CAAK,CAAC,EAAE,EACxD,KAAK,GAAG,GACLsC,IAAgB,CAACC,MAAQ;AAC7B,UAAMC,IAAS,OAAOD,KAAO,EAAE;AAC/B,WAAI,uEAAuE,KAAKC,CAAM,IAAU,KACzFA;AAAA,EACT,GACMC,IAAiB,CAACC,GAAQC,MAAU;AACxC,UAAMC,IAAeF,GAAQ,gBAAgBA,GAAQ,OAAO;AAC5D,QAAI,CAACE,EAAc,QAAO;AAC1B,UAAMC,IAAQ,CAAA;AACd,WAAO,QAAQD,EAAa,eAAe,CAAA,CAAE,EAAE,QAAQ,CAAC,CAACE,GAAUT,CAAM,MAAMQ,EAAM,KAAK,GAAGF,CAAK,IAAIG,CAAQ,IAAIV,EAAUC,CAAM,CAAC,GAAG,CAAC,GACvI,OAAO,QAAQO,EAAa,eAAe,CAAA,CAAE,EAAE,QAAQ,CAAC,CAACE,GAAUT,CAAM,MAAM;AAC7E,YAAMU,IAAaD,EAAS,WAAW,GAAG,IAAIA,IAAW,IAAIA,CAAQ;AACrE,MAAAD,EAAM,KAAK,GAAGF,CAAK,GAAGI,CAAU,IAAIX,EAAUC,CAAM,CAAC,GAAG;AAAA,IAC1D,CAAC;AACD,UAAMW,IAAYV,EAAcM,EAAa,SAAS;AACtD,WAAII,KAAWH,EAAM,KAAKG,EAAU,WAAW,KAAKL,CAAK,CAAC,GACnDE,EAAM,SAAS,UAAUA,EAAM,KAAK;AAAA,CAAI,CAAC,aAAa;AAAA,EAC/D,GAEMI,IAAU,CAACC,GAAMC,IAAY,oBAAoB;AAarD,UAAMC,IAZQ;AAAA,MACZ,iBAAiB;AAAA,MACjB,UAAU;AAAA,MACV,eAAe;AAAA,MACf,MAAM;AAAA,MACN,GAAG;AAAA,MACH,aAAa;AAAA,MACb,cAAc;AAAA,MACd,WAAW;AAAA,MACX,KAAK;AAAA,MACL,MAAM;AAAA,IAAA,EAEWF,CAAI,KAAK;AAC5B,WAAO,eAAeC,CAAS,gJAAgJC,CAAI;AAAA,EACrL,GAEMC,IAAc,CAACrD,GAAOsD,MAAW;AACrC,QAAItD,KAAU,KAA6B,QAAO;AAClD,QAAIsD,GAAQ,WAAW,YAAY;AACjC,YAAMC,IAAS,OAAOvD,CAAK;AAC3B,aAAO,OAAO,SAASuD,CAAM,IAAI,IAAI,KAAK,aAAazD,EAAM,WAAW,OAAO,UAAU,SAAS,EAAE,OAAO,YAAY,UAAU,OAAO,EAAE,OAAOyD,CAAM,IAAIvD;AAAA,IAC7J;AACA,WAAI,OAAOA,KAAU,YAAkBA,IAAQ,QAAQ,OACnD,MAAM,QAAQA,CAAK,IAAUA,EAAM,IAAIgC,CAAS,EAAE,KAAK,IAAI,IAC3D,OAAOhC,KAAU,WAAiB,KAAK,UAAUA,CAAK,IACnDgC,EAAUhC,CAAK;AAAA,EACxB,GACMwD,IAAa,CAACC,GAAOC,MAAaD,IACpC,kDAAkD1D,EAAWiC,EAAUyB,CAAK,CAAC,CAAC,QAAQC,IAAW,MAAM3D,EAAWiC,EAAU0B,CAAQ,CAAC,CAAC,SAAS,EAAE,iBACjJ,IACEC,IAAmB,CAAC3C,MAAc;AACtC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3B6C,IAAOD,EAAM,WAAWA,EAAM,QAAQA,EAAM,YAAYA,EAAM,SAAS,IACvEE,IAAU,OAAOF,EAAM,WAAW,WAAW,EAAE,YAAA,GAC/CG,IAAMD,MAAY,WAAWA,EAAQ,WAAW,GAAG,IAAKA,EAAQ,MAAM,UAAU,IAAI,CAAC,KAAK,OAAQ;AACxG,WAAO,IAAIC,CAAG,mDAAmDhE,EAAW+D,CAAO,CAAC,KAAK/D,EAAWiC,EAAU6B,CAAI,CAAC,CAAC,KAAKE,CAAG;AAAA,EAC9H,GACMC,IAAmB,CAAChD,MAAc;AACtC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BiD,IAAQL,EAAM,SAAS5C,EAAU,YAAY,CAAA;AAEnD,WAAO,yDADS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO4C,EAAM,MAAM,QAAQA,EAAM,WAAWK,EAAM,UAAU,CAAC,CAAC,CAAC,CAChC,KAAKA,EAAM,IAAI,CAAC3D,MAAS;AAC9F,YAAM4D,IAAQ5D,EAAK,OACb6D,IAAYD,GAAO,SAAS,SAAS,SAAS,MAC9CE,IAAYF,IAAQ,GAAGC,MAAc,SAAS,MAAM,GAAG,IAAID,EAAM,SAAS,EAAE,GAAGA,EAAM,UAAU,EAAE,KAAK;AAC5G,aAAO,mEAAmEnE,EAAWiC,EAAU1B,EAAK,SAASA,EAAK,KAAK,CAAC,CAAC,0CAA0CP,EAAWO,EAAK,UAAU,EAAE,CAAC,GAAGP,EAAWO,EAAK,KAAK,CAAC,GAAGP,EAAWO,EAAK,UAAU,EAAE,CAAC,SAAS4D,IAAQ,mCAAmCC,CAAS,KAAKpE,EAAWqE,CAAS,CAAC,UAAUrE,EAAWiC,EAAUkC,EAAM,eAAe,EAAE,CAAC,CAAC,kBAAkB,EAAE;AAAA,IAC9Z,CAAC,EAAE,KAAK,EAAE,CAAC;AAAA,EACb,GACMG,IAAc,CAACrD,MAAc;AACjC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BsD,IAAOtD,EAAU,YAAY4C,EAAM,QAAQA,EAAM,QAAQ,CAAA,GACzDW,IAAUX,EAAM,SAAS,SAASA,EAAM,UAAU,OAAO,KAAKU,EAAK,CAAC,KAAK,CAAA,CAAE,EAAE,IAAI,CAAC9D,OAAS,EAAE,KAAAA,GAAK,WAAWA,GAAK,OAAOA,EAAA,EAAM;AACrI,WAAO,GAAGgD,EAAWI,EAAM,OAAOA,EAAM,WAAW,CAAC,sDAAsDW,EAAQ,IAAI,CAACjB,MAAW,OAAOvD,EAAWiC,EAAUsB,EAAO,SAASA,EAAO,SAASA,EAAO,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,uBAAuBgB,EAAK,IAAI,CAACE,MAAQ,OAAOD,EAAQ,IAAI,CAACjB,MAAW,OAAOvD,EAAWsD,EAAYmB,EAAIlB,EAAO,aAAaA,EAAO,GAAG,GAAGA,CAAM,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,mBAAmBgB,EAAK,WAAW,IAAI,8CAA8C,EAAE;AAAA,EACze,GACMG,IAAqB,CAACzD,MAAc;AACxC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BsD,IAAOtD,EAAU,YAAY4C,EAAM,YAAYA,EAAM,QAAQA,EAAM,QAAQ,CAAA,GAC3EW,IAAUX,EAAM,WAAW,CAAA,GAC3Bc,IAAUH,EAAQ,KAAK,CAACjB,MAAWA,EAAO,OAAO,KAAKiB,EAAQ,CAAC,GAC/DI,IAAYJ,EAAQ,KAAK,CAACjB,MAAWA,EAAO,SAAS,KAAKiB,EAAQ,CAAC,GACnEK,IAAUL,EAAQ,OAAO,CAACjB,MAAWA,MAAWoB,KAAWpB,MAAWqB,CAAS,GAC/EE,IAAY,CAACL,GAAKlB,MAAW;AACjC,YAAMtD,IAAQwE,IAAMlB,GAAQ,aAAaA,GAAQ,GAAG,GAC9CwB,IAASxB,GAAQ,QAAQ,OAAOtD,CAAK,KAAKA;AAChD,UAAIsD,GAAQ,QAAQ,SAAS,YAAY;AACvC,cAAMyB,IAAW,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,OAAO/E,CAAK,KAAK,CAAC,CAAC;AAC9D,eAAO,sDAAsD+E,CAAQ,2BAA2BhF,EAAW,GAAGgF,CAAQ,GAAG,CAAC;AAAA,MAC5H;AACA,aAAIzB,GAAQ,QAAQ,SAAS,QACpB,8BAA8BvD,EAAWiC,EAAU8C,CAAM,CAAC,CAAC,YAE7D/E,EAAWsD,EAAYyB,GAAQxB,CAAM,CAAC;AAAA,IAC/C;AACA,WAAO,GAAGE,EAAWI,EAAM,OAAOA,EAAM,WAAW,CAAC,GAAGA,EAAM,aAAa,uEAAuE7D,EAAWiC,EAAU4B,EAAM,qBAAqB,WAAW,CAAC,CAAC,eAAe,EAAE,mCAAmCU,EAAK,IAAI,CAACE,MAAQ,iCAAiCE,IAAUG,EAAUL,GAAKE,CAAO,IAAI,EAAE,YAAYC,IAAY,MAAME,EAAUL,GAAKG,CAAS,CAAC,SAAS,EAAE,mDAAmDC,EAAQ,SAAS,OAAOA,EAAQ,IAAI,CAACtB,MAAW,YAAYvD,EAAWiC,EAAUsB,EAAO,SAASA,EAAO,SAASA,EAAO,GAAG,CAAC,CAAC,YAAYuB,EAAUL,GAAKlB,CAAM,CAAC,aAAa,EAAE,KAAK,EAAE,CAAC,UAAU,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,GAAGgB,EAAK,WAAW,IAAI,8CAA8C,EAAE;AAAA,EACjvB,GACMU,IAAiB,CAACR,MAAQ,OAAO,QAAQA,KAAO,CAAA,CAAE,EAAE,OAAO,CAAC,CAAA,EAAGxE,CAAK,MAAM,OAAOA,KAAU,QAAQ,GACnGiF,IAAc,CAACjE,MAAc;AACjC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BsD,IAAOtD,EAAU,YAAY4C,EAAM,QAAQ,CAAA,GAC3CsB,IAASZ,EAAK,IAAI,CAACE,MAAQQ,EAAeR,CAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAC3D3C,IAASyC,EAAK,IAAI,CAACE,GAAKjE,MAAUyB,EAAU,OAAO,OAAOwC,CAAG,EAAE,KAAK,CAACxE,MAAU,OAAOA,KAAU,QAAQ,KAAKO,IAAQ,CAAC,CAAC,GACvH4E,IAAM,KAAK,IAAI,GAAGD,GAAQ,CAAC,GAC3BE,IAAQ,KACRC,IAAS,KAAK,IAAI,KAAK,OAAOzB,EAAM,UAAU,GAAG,CAAC,GAClD0B,IAAY,OAAO1B,EAAM,aAAaA,EAAM,QAAQ,KAAK,EAAE,YAAA;AACjE,QAAI2B,IAAU;AACd,QAAID,EAAU,SAAS,MAAM,GAAG;AAC9B,YAAME,IAASN,EAAO,IAAI,CAAClF,GAAOO,MAAU;AAC1C,cAAMkF,IAAIP,EAAO,WAAW,IAAIE,IAAQ,IAAI,KAAK7E,MAAU6E,IAAQ,MAAM,KAAK,IAAI,GAAGF,EAAO,SAAS,CAAC,IAChGQ,KAAIL,IAAS,KAAMrF,IAAQmF,KAAQE,IAAS;AAClD,eAAO,GAAGI,CAAC,IAAIC,EAAC;AAAA,MAClB,CAAC,EAAE,KAAK,GAAG;AACX,MAAAH,IAAU,qBAAqBC,CAAM,kHAAkHA,EAAO,MAAM,GAAG,EAAE,IAAI,CAACG,MAAU;AAAE,cAAM,CAACF,GAAGC,CAAC,IAAIC,EAAM,MAAM,GAAG;AAAG,eAAO,eAAeF,CAAC,SAASC,CAAC;AAAA,MAA6F,CAAC,EAAE,KAAK,EAAE,CAAC;AAAA,IACtW,OAAO;AACL,YAAME,KAAQR,IAAQ,MAAM,KAAK,IAAI,GAAGF,EAAO,MAAM;AACrD,MAAAK,IAAUL,EAAO,IAAI,CAAClF,GAAOO,MAAU;AACrC,cAAMsF,IAAa7F,IAAQmF,KAAQE,IAAS;AAC5C,eAAO,YAAY,KAAK9E,IAAQqF,IAAOA,IAAO,IAAI,QAAQP,IAAS,KAAKQ,CAAS,YAAYD,IAAO,IAAI,aAAaC,CAAS,mDAAmD,MAAOtF,IAAQ,IAAK,IAAI;AAAA,MAC3M,CAAC,EAAE,KAAK,EAAE;AAAA,IACZ;AACA,UAAMuF,IAAOjE,EAAO,IAAI,CAACkE,GAAOxF,MAEvB,YADG2E,EAAO,WAAW,IAAIE,IAAQ,IAAI,KAAK7E,MAAU6E,IAAQ,MAAM,KAAK,IAAI,GAAGF,EAAO,SAAS,CAAC,EAClF,QAAQG,IAAS,EAAE,0BAA0BtF,EAAWgG,CAAK,CAAC,SACnF,EAAE,KAAK,EAAE;AACV,WAAO,GAAGvC,EAAWI,EAAM,OAAOA,EAAM,WAAW,CAAC,iDAAiDwB,CAAK,IAAIC,CAAM,4BAA4BtF,EAAWiC,EAAU4B,EAAM,SAAS,OAAO,CAAC,CAAC,KAAK2B,CAAO,GAAGO,CAAI;AAAA,EAClN,GACME,IAAa,CAAChF,MAAc;AAChC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BiF,IAASrC,EAAM,UAAUA,EAAM,SAAS,CAAA;AAC9C,WAAO,GAAGJ,EAAWI,EAAM,OAAOA,EAAM,WAAW,CAAC,uDAAuDqC,EAAO,IAAI,CAACC,MAAU;AAE/H,YAAMC,KADOD,EAAM,SAAS,aAAa,aAAa,aAC7B,aACrB,0BAA0BnG,EAAWiC,EAAUkE,EAAM,eAAe,EAAE,CAAC,CAAC,KAAKnG,EAAWiC,EAAUkE,EAAM,gBAAgB,EAAE,CAAC,CAAC,gBAC5H,gBAAgBnG,EAAWmG,EAAM,SAAS,WAAW,WAAW,MAAM,CAAC,YAAYnG,EAAWiC,EAAUkE,EAAM,gBAAgB,EAAE,CAAC,CAAC,kBAAkBnG,EAAWiC,EAAUkE,EAAM,eAAe,EAAE,CAAC,CAAC;AACtM,aAAO,gBAAgBnG,EAAWiC,EAAUkE,EAAM,SAASA,EAAM,SAASA,EAAM,IAAI,CAAC,CAAC,UAAUC,CAAO;AAAA,IACzG,CAAC,EAAE,KAAK,EAAE,CAAC,yBAAyBpG,EAAWiC,EAAU4B,EAAM,oBAAoBA,EAAM,cAAc,QAAQ,CAAC,CAAC;AAAA,EACnH,GACMwC,IAAkB,CAACpF,MAAc;AACrC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3ByC,IAAQG,EAAM,SAAS5C,EAAU,WACjCqF,IAAczC,EAAM,eAAe5C,EAAU,iBAC7CsF,IAAQ1C,EAAM,cAAc,SAAS5C,EAAU,cAAc,SAAS,CAAA,GACtEiF,IAASrC,EAAM,UAAU5C,EAAU,iBAAiB,UAAU,CAAA;AACpE,WAAO,GAAGwC,EAAWI,EAAM,cAAc,KAAQ,KAAKH,GAAOG,EAAM,oBAAoB,KAAQ,KAAKyC,CAAW,CAAC,oCAAoCJ,EAAO,SAAS,qCAAqCA,EAAO,IAAI,CAACC,MAAU,gBAAgBnG,EAAWiC,EAAUkE,EAAM,SAASA,EAAM,SAASA,EAAM,IAAI,CAAC,CAAC,0CAA0CnG,EAAWiC,EAAUkE,EAAM,eAAe,EAAE,CAAC,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,oHAAoHnG,EAAWiC,EAAU4B,EAAM,cAAc,gCAAgC,CAAC,CAAC,mBAAmB7D,EAAWiC,EAAU4B,EAAM,cAAc,6CAA6C,CAAC,CAAC,mBAAmB0C,EAAM,SAAS,mCAAmCA,EAAM,IAAI,CAACC,MAAS,cAAcxG,EAAWwG,EAAK,QAAQ,MAAM,CAAC,iBAAiBxG,EAAWwG,EAAK,QAAQ,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,sDAAsDxG,EAAWiC,EAAU4B,EAAM,oBAAoB,UAAU,CAAC,CAAC;AAAA,EACjiC,GACM4C,IAAa,CAACxF,MAAc;AAChC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BsD,IAAOtD,EAAU,YAAY4C,EAAM,SAAS,CAAA;AAClD,WAAO,GAAGJ,EAAWI,EAAM,OAAOA,EAAM,WAAW,CAAC,8BAA8BU,EAAK,IAAI,CAACE,MAAQ;AAClG,YAAMf,IAAQ,OAAOe,KAAQ,WAAWA,EAAI,SAASA,EAAI,QAAQA,EAAI,SAAS,OAAO,OAAOA,CAAG,EAAE,CAAC,IAAIA,GAChG6B,IAAc,OAAO7B,KAAQ,WAAWA,EAAI,eAAeA,EAAI,YAAY,OAAO,OAAOA,CAAG,EAAE,CAAC,IAAI;AACzG,aAAO,oBAAoBzE,EAAWiC,EAAUyB,CAAK,CAAC,CAAC,YAAY4C,IAAc,MAAMtG,EAAWiC,EAAUqE,CAAW,CAAC,CAAC,SAAS,EAAE;AAAA,IACtI,CAAC,EAAE,KAAK,EAAE,CAAC;AAAA,EACb,GACMI,IAAa,CAACzF,MAAc;AAChC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3BiD,IAAQL,EAAM,SAASA,EAAM,QAAQ,CAAA,GACrC8C,IAAY5G,EAAM,WAAW,IAAIkB,EAAU,EAAE,KAAKiD,EAAM,CAAC,GAAG,OAAOA,EAAM,CAAC,GAAG,IAC7E0C,IAAS1C,EAAM,KAAK,CAAC3D,OAAUA,EAAK,OAAOA,EAAK,QAAQoG,CAAS,KAAKzC,EAAM,CAAC,GAC7E2C,IAAmBD,GAAQ,eAAeA,GAAQ,YAAY,CAACA,EAAO,SAAS,IAAI;AACzF,WAAO,yCAAyC5G,EAAWiB,EAAU,EAAE,CAAC,oCAAoCiD,EAAM,IAAI,CAAC3D,MAAS,uCAAuCP,EAAWO,EAAK,OAAOA,EAAK,EAAE,CAAC,aAAaA,EAAK,OAAOA,EAAK,QAAQoG,IAAY,WAAW,EAAE,KAAK3G,EAAWiC,EAAU1B,EAAK,SAASA,EAAK,KAAK,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,yCAAyCsG,EAAiB,IAAIC,CAAe,EAAE,KAAK,EAAE,KAAK9G,EAAWiC,EAAU2E,GAAQ,WAAW,EAAE,CAAC,CAAC;AAAA,EACvd,GACMG,KAAkB,CAAC9F,MAAc;AACrC,UAAM4C,IAAQ5C,EAAU,SAAS,CAAA,GAC3B+F,IAAW/F,EAAU,cAAcA,EAAU,YAAY4C,EAAM,cAAcA,EAAM;AACzF,WAAI,MAAM,QAAQmD,CAAQ,IAAU,mCAAmCA,EAAS,IAAIF,CAAe,EAAE,KAAK,EAAE,CAAC,WACtG,GAAGrD,EAAWI,EAAM,OAAOA,EAAM,QAAQ,CAAC,GAAGA,EAAM,UAAU,MAAM7D,EAAWiC,EAAU4B,EAAM,OAAO,CAAC,CAAC,SAAS,EAAE;AAAA,EAC3H,GACMoD,KAAe,CAACC,MAAS;AAC7B,UAAMC,IAAW,SAAS,cAAc,UAAU;AAClD,WAAAA,EAAS,YAAY,OAAOD,KAAQ,EAAE,GACtCC,EAAS,QAAQ,iBAAiB,sCAAsC,EAAE,QAAQ,CAACC,MAASA,EAAK,QAAQ,GACzGD,EAAS,QAAQ,iBAAiB,GAAG,EAAE,QAAQ,CAACC,MAAS;AACvD,OAAC,GAAGA,EAAK,UAAU,EAAE,QAAQ,CAACC,MAAc;AAC1C,SAAI,OAAO,KAAKA,EAAU,IAAI,KAAK,eAAe,KAAKA,EAAU,KAAK,MAAGD,EAAK,gBAAgBC,EAAU,IAAI;AAAA,MAC9G,CAAC;AAAA,IACH,CAAC,GACMF,EAAS;AAAA,EAClB;AAEA,WAASL,EAAgB7F,GAAW;AAClC,UAAM4C,IAAQ5C,GAAW,SAAS,CAAA,GAC5BqG,IAAa,sBAAsB,OAAOrG,GAAW,MAAM,WAAW,EAAE,QAAQ,mBAAmB,GAAG,CAAC,IACvGsG,IAAatG,GAAW,cAAc,cAAc4C,EAAM,cAAc,cAAc,CAAA;AAC5F,QAAI2D;AACJ,YAAQvG,GAAW,MAAA;AAAA,MACjB,KAAK;AAAA,MAAc,KAAK;AAAA,MAAQ,KAAK;AAAA,MAAS,KAAK;AAAa,QAAAuG,IAAU5D,EAAiB3C,CAAS;AAAG;AAAA,MACvG,KAAK;AAAA,MAAa,KAAK;AAAkB,QAAAuG,IAAUvD,EAAiBhD,CAAS;AAAG;AAAA,MAChF,KAAK;AAAA,MAAS,KAAK;AAAA,MAAiB,KAAK;AAAkB,QAAAuG,IAAUlD,EAAYrD,CAAS;AAAG;AAAA,MAC7F,KAAK;AAAgB,QAAAuG,IAAU9C,EAAmBzD,CAAS;AAAG;AAAA,MAC9D,KAAK;AAAA,MAAS,KAAK;AAAA,MAAgB,KAAK;AAAc,QAAAuG,IAAUtC,EAAYjE,CAAS;AAAG;AAAA,MACxF,KAAK;AAAQ,QAAAuG,IAAUvB,EAAWhF,CAAS;AAAG;AAAA,MAC9C,KAAK;AAAA,MAAa,KAAK;AAAqB,QAAAuG,IAAUnB,EAAgBpF,CAAS;AAAG;AAAA,MAClF,KAAK;AAAQ,QAAAuG,IAAUf,EAAWxF,CAAS;AAAG;AAAA,MAC9C,KAAK;AAAQ,QAAAuG,IAAUd,EAAWzF,CAAS;AAAG;AAAA,MAC9C,KAAK;AAAA,MAAa,KAAK;AAAQ,QAAAuG,IAAUT,GAAgB9F,CAAS;AAAG;AAAA,MACrE,KAAK;AAAiB,QAAAuG,IAAUP,GAAapD,EAAM,QAAQA,EAAM,WAAW,EAAE;AAAG;AAAA,MACjF,KAAK;AAAe,QAAA2D,IAAUvB,EAAW,EAAE,GAAGhF,GAAW,OAAO,EAAE,GAAG4C,GAAO,YAAYA,EAAM,cAAc,gBAAA,GAAmB;AAAG;AAAA,MAClI;AAAS,QAAA2D,IAAU,4DAA4DxH,EAAWiB,GAAW,IAAI,CAAC;AAAA,IAAA;AAE5G,WAAO,GAAGyB,EAAezB,GAAW,IAAIqG,CAAU,EAAE,CAAC,sCAAsCA,CAAU,kBAAkBtH,EAAWiB,GAAW,QAAQ,SAAS,CAAC,YAAYjB,EAAWqC,EAAUkF,CAAU,CAAC,CAAC,wBAAwBvH,EAAWiB,GAAW,EAAE,CAAC,KAAKuG,CAAO;AAAA,EAC3Q;AAEA,QAAMC,IAAqB,CAAClH,GAAMmH,MAAW,CAACnH,GAAM,YAAY,SAAS,UAAUA,EAAK,WAAW,QAAQ,SAASmH,CAAM,GACpHC,IAAyB,CAACpH,GAAMmH,MAAW;AAC/C,QAAI,CAACD,EAAmBlH,GAAMmH,CAAM,EAAG,QAAO;AAC9C,QAAInH,EAAK,WAAY,QAAOA,EAAK;AACjC,eAAWY,KAASZ,EAAK,YAAY,CAAA,GAAI;AACvC,YAAMkB,IAAOkG,EAAuBxG,GAAOuG,CAAM;AACjD,UAAIjG,EAAM,QAAOA;AAAA,IACnB;AACA,WAAO;AAAA,EACT,GACMmG,IAAoB,CAAC1D,GAAOwD,GAAQG,IAAQ,OAAO3D,KAAS,CAAA,GAAI,QAAQ,CAAC3D,MACxEkH,EAAmBlH,GAAMmH,CAAM,KACpBnH,EAAK,aAAa,CAAC,EAAE,GAAGA,GAAM,OAAAsH,EAAA,CAAO,IAAI,CAAA,GAC1C,OAAOD,EAAkBrH,EAAK,UAAUmH,GAAQG,IAAQ,CAAC,CAAC,IAF3B,CAAA,CAG/C,GACKC,KAAa,CAAC5D,OAAWA,KAAS,IAAI,QAAQ,CAAC3D,MAAS;AAC5D,UAAMkB,IAAOkG,EAAuBpH,GAAM,QAAQ;AAClD,WAAOkB,IAAO,CAAC,EAAE,GAAGlB,GAAM,YAAYkB,EAAA,CAAM,IAAI,CAAA;AAAA,EAClD,CAAC,GACKsG,IAAiB,CAAC7D,GAAOwD,MAAWE,EAAkB1D,GAAOwD,CAAM,EAAE,IAAI,CAACnH,MAAS;AAAA,uCACpDP,EAAWO,EAAK,UAAU,CAAC,8BAA8BA,EAAK,eAAeR,EAAM,aAAa,WAAW,EAAE,wBAAwBQ,EAAK,KAAK;AAAA,QAC9K2C,EAAQ3C,EAAK,IAAI,CAAC,SAASP,EAAWiC,EAAU1B,EAAK,SAASA,EAAK,GAAG,CAAC,CAAC;AAAA,cAClE,EAAE,KAAK,EAAE,GACfyH,IAAiB,CAACC,IAAU,OAAU,iCAAiCA,IAAU,YAAY,EAAE;AAAA,4EAC3B/E,EAAQ,WAAW,CAAC,SAASnD,EAAM,WAAW,OAAO,OAAO,IAAI;AAAA,8EAC9DmD,EAAQnD,EAAM,UAAU,SAAS,QAAQ,MAAM,CAAC,SAASA,EAAM,UAAU,SAAS,UAAU,MAAM;AAAA,WAExKmI,IAAc,CAACC,IAAY,OAAU;AACzC,UAAMC,IAAYrI,EAAM,OAAO,aAAa,CAAA;AAC5C,WAAO,8BAA8BoI,IAAY,cAAc,EAAE,WAAWnI,EAAWiC,EAAUmG,EAAU,QAAQ,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,UAAUD,IAAY,KAAK,gBAAgBnI,EAAWiC,EAAUmG,EAAU,QAAQ,SAAS,CAAC,CAAC,mBAAmBpI,EAAWiC,EAAUmG,EAAU,eAAe,yBAAyB,CAAC,CAAC,gBAAgB;AAAA,EAC/U,GAEMC,KAAa,MAAM;AACvB,UAAM5G,IAAO1B,EAAM,OAAO,QAAQA,EAAM,UAAU,KAAK,OAAO,OAAOA,EAAM,OAAO,SAAS,CAAA,CAAE,EAAE,CAAC,GAC1FuI,IAAUvI,EAAM,cAAc,OAAO,KAAKA,EAAM,OAAO,SAAS,CAAA,CAAE,EAAE,CAAC;AAC3E,QAAI,CAAC0B,EAAM,QAAO;AAClB,UAAM8G,IAAY,kBAAkB,OAAOD,CAAO,EAAE,QAAQ,mBAAmB,GAAG,CAAC,IAC7EE,IAAW/G,EAAK,cAAc,cAAc,CAAA,GAE5CgH,KADgBhH,EAAK,QAAQ,SAAS,YAAYA,EAAK,OAAO,cAAc,CAAA,IAAK,CAAA,GACtD,OAAO,CAACV,GAAQ2H,OAC3CA,GAAW,OAAI3H,EAAO2H,EAAU,EAAE,IAAIA,IACnC3H,IACNU,EAAK,QAAQ,cAAc,CAAA,CAAE,GAC1BkH,KAAclH,EAAK,cAAc,CAAA,GAAI,IAAI,CAACR,MAAc;AAC5D,YAAMyH,IAAYD,EAAWxH,EAAU,EAAE;AAIzC,aAAO,0CAHgByH,IACnB,eAAe,OAAOA,EAAU,YAAY,CAAC,IAAI,CAAC,WAAW,OAAOA,EAAU,WAAW,EAAE,CAAC,aAAa,OAAOA,EAAU,YAAY,CAAC,IAAI,CAAC,WAAW,OAAOA,EAAU,WAAW,CAAC,CAAC,MACrL,EAC2D,KAAK5B,EAAgB7F,CAAS,CAAC;AAAA,IAChG,CAAC,EAAE,KAAK,EAAE;AACV,WAAO,GAAGyB,EAAejB,GAAM8G,CAAS,CAAC,8BAA8BA,CAAS,YAAYvI,EAAWqC,EAAUmG,CAAQ,CAAC,CAAC,8EAA8ExI,EAAWiC,EAAUlC,EAAM,OAAO,WAAW,QAAQ,EAAE,CAAC,CAAC,cAAcC,EAAWiC,EAAUR,EAAK,SAAS6G,CAAO,CAAC,CAAC,QAAQ7G,EAAK,cAAc,MAAMzB,EAAWiC,EAAUR,EAAK,WAAW,CAAC,CAAC,SAAS,EAAE,iDAAiDA,EAAK,QAAQ,SAAS,YAAY,YAAY,EAAE,KAAKkH,CAAU;AAAA,EACjgB,GAEMC,IAAkB,MAAM;AAC5B,aAAS,gBAAgB,OAAO7I,EAAM,WAAW,OAAO,UAAU,MAClE,SAAS,gBAAgB,UAAU,OAAO,QAAQA,EAAM,UAAU,MAAM,GACxE,SAAS,gBAAgB,QAAQ,YAAYA,EAAM,OACnD,SAAS,gBAAgB,MAAM,cAAcA,EAAM;AAAA,EACrD,GACM8I,KAAyB,CAACvH,MAAW;AACzC,IAAAvB,EAAM,SAASG,EAAgBoB,CAAM,GACrCvB,EAAM,SAASqB,EAAYrB,EAAM,cAAcA,EAAM,MAAM;AAC3D,QAAI;AAAE,mBAAa,QAAQ,YAAYA,EAAM,MAAM;AAAA,IAAG,QAAQ;AAAA,IAAe;AAC7E,IAAA6I,EAAA,GACAE,EAAA;AAAA,EACF,GACMC,KAAwB,CAACC,MAAU;AACvC,IAAAjJ,EAAM,QAAQI,EAAe6I,CAAK;AAClC,QAAI;AAAE,mBAAa,QAAQ,SAASjJ,EAAM,KAAK;AAAA,IAAG,QAAQ;AAAA,IAAe;AACzE,IAAA6I,EAAA,GACAE,EAAA;AAAA,EACF,GACMG,KAAe,CAACxH,MAAS;AAC7B,IAAK1B,EAAM,OAAO,QAAQ0B,CAAI,MAC9B1B,EAAM,aAAa0B,GACnB1B,EAAM,mBAAmB,IACrB,mBAAmB,OAAO,SAAS,KAAK,QAAQ,MAAM,EAAE,CAAC,MAAM0B,MAAM,OAAO,SAAS,OAAO,mBAAmBA,CAAI,IACvHqH,EAAA;AAAA,EACF,GAEMI,KAAkB,MAAM;AAC5B,WAAO,iBAAiB,WAAW,CAACC,MAAU;AAC5C,YAAMC,IAAUD,EAAM;AACtB,UAAI,CAACC,KAAWA,EAAQ,MAAM,KAAK,OAAOA,KAAY,SAAU;AAChE,YAAMC,IAAmBF,EAAM,OAAO,QAAQ,OAAO,EAAE;AACvD,UAAIC,EAAQ,SAAS,wBAAwB;AAC3C,cAAME,IAAUF,EAAQ,WAAW,CAAA,GAC7BG,IAAU,CAACD,EAAQ,aAAa,GAAI,MAAM,QAAQA,EAAQ,mBAAmB,IAAIA,EAAQ,sBAAsB,CAAA,CAAG,EACrH,OAAO,OAAO,EAAE,IAAI,CAACE,MAAW,OAAOA,CAAM,EAAE,QAAQ,OAAO,EAAE,CAAC;AACpE,YAAID,EAAQ,UAAU,CAACA,EAAQ,SAASF,CAAgB,EAAG;AAC3D,QAAAtJ,EAAM,sBAAsB,IAAI,IAAIwJ,EAAQ,SAASA,IAAU,CAACF,CAAgB,CAAC,GAC7EC,EAAQ,WAAQvJ,EAAM,SAASG,EAAgBoJ,EAAQ,MAAM,IAC7DA,EAAQ,UAAOvJ,EAAM,QAAQI,EAAemJ,EAAQ,KAAK,IAC7DvJ,EAAM,SAASqB,EAAYrB,EAAM,cAAcA,EAAM,MAAM,GAC3D6I,EAAA,GACAE,EAAA,GACA,OAAO,OAAO,YAAY,EAAE,MAAM,0BAA0B,GAAG,GAAG,YAAY/I,EAAM,OAAO,WAAW,SAAS,GAAA,GAAMoJ,EAAM,MAAM;AACjI;AAAA,MACF;AACA,MAAIC,EAAQ,SAAS,wBAAwBrJ,EAAM,oBAAoB,IAAIsJ,CAAgB,MACrFD,EAAQ,WAAQrJ,EAAM,SAASG,EAAgBkJ,EAAQ,MAAM,IAC7DA,EAAQ,UAAOrJ,EAAM,QAAQI,EAAeiJ,EAAQ,KAAK,IAC7DrJ,EAAM,SAASqB,EAAYrB,EAAM,cAAcA,EAAM,MAAM,GAC3D6I,EAAA,GACAE,EAAA;AAAA,IAEJ,CAAC;AAAA,EACH;AAEA,WAASA,IAAY;AACnB,UAAMW,IAAO1J,EAAM;AACnB,QAAI,CAAC0J,KAAQ,CAAC1J,EAAM,OAAQ;AAC5B,UAAM2J,IAAa3J,EAAM,OAAO,WAAW,YAAY,SAAS,CAAA,GAC1D4J,IAAmB7B,GAAW4B,CAAU;AAC9C,IAAAD,EAAK,YAAY,8BAA8B1J,EAAM,YAAY,sBAAsB,EAAE;AAAA;AAAA,+CAE9CmI,EAAYnI,EAAM,SAAS,CAAC;AAAA,oFACSA,EAAM,YAAY,mBAAmB,kBAAkB,KAAKmD,EAAQnD,EAAM,YAAY,iBAAiB,aAAa,CAAC;AAAA,mDACtJgI,EAAe2B,GAAY,SAAS,CAAC;AAAA,kBACtE1B,EAAejI,EAAM,SAAS,CAAC;AAAA;AAAA,qHAEoEmD,EAAQ,MAAM,CAAC,YAAYgF,EAAY,EAAK,CAAC,GAAGF,EAAe,EAAI,CAAC;AAAA,QACjLjI,EAAM,mBAAmB,uNAAuNmD,EAAQ,GAAG,CAAC,uDAAuDgF,EAAY,EAAK,CAAC,cAAcH,EAAe2B,GAAY,QAAQ,CAAC,iBAAiB1B,EAAe,EAAK,CAAC,sBAAsB,EAAE;AAAA,sCACvZK,IAAY;AAAA,kFACgCsB,EAAiB,IAAI,CAACpJ,MAAS,oCAAoCP,EAAWO,EAAK,UAAU,CAAC,YAAYA,EAAK,eAAeR,EAAM,aAAa,WAAW,EAAE,mBAAmBQ,EAAK,eAAeR,EAAM,aAAa,SAAS,OAAO,KAAKmD,EAAQ3C,EAAK,IAAI,CAAC,SAASP,EAAWiC,EAAU1B,EAAK,SAASA,EAAK,GAAG,CAAC,CAAC,kBAAkB,EAAE,KAAK,EAAE,CAAC;AAAA,aAE/ZkJ,EAAK,iBAAiB,aAAa,EAAE,QAAQ,CAACG,MAAWA,EAAO,iBAAiB,SAAS,MAAMX,GAAaW,EAAO,QAAQ,IAAI,CAAC,CAAC,GAClIH,EAAK,iBAAiB,4BAA4B,EAAE,QAAQ,CAACG,MAAWA,EAAO,iBAAiB,SAAS,MAAM;AAC7G,YAAMC,IAAOD,EAAO,QAAQ,aAAa;AACzC,MAAA7J,EAAM,WAAW,IAAI8J,EAAK,QAAQ,MAAMD,EAAO,QAAQ,MAAM,GAC7Dd,EAAA;AAAA,IACF,CAAC,CAAC,GACFW,EAAK,iBAAiB,sBAAsB,EAAE,QAAQ,CAACG,MAAWA,EAAO,iBAAiB,SAAS,MAAMf,GAAuB9I,EAAM,WAAW,OAAO,OAAO,IAAI,CAAC,CAAC,GACrK0J,EAAK,iBAAiB,qBAAqB,EAAE,QAAQ,CAACG,MAAWA,EAAO,iBAAiB,SAAS,MAAMb,GAAsBhJ,EAAM,UAAU,SAAS,UAAU,MAAM,CAAC,CAAC,GACzK0J,EAAK,cAAc,iBAAiB,GAAG,iBAAiB,SAAS,MAAM;AACrE,MAAA1J,EAAM,YAAY,CAACA,EAAM;AACzB,UAAI;AAAE,qBAAa,QAAQ,8BAA8B,KAAK,UAAUA,EAAM,SAAS,CAAC;AAAA,MAAG,QAAQ;AAAA,MAAe;AAClH,MAAA+I,EAAA;AAAA,IACF,CAAC,GACDW,EAAK,cAAc,sBAAsB,GAAG,iBAAiB,SAAS,MAAM;AAAE,MAAA1J,EAAM,mBAAmB,IAAM+I,EAAA;AAAA,IAAa,CAAC,GAC3HW,EAAK,iBAAiB,qBAAqB,EAAE,QAAQ,CAACG,MAAWA,EAAO,iBAAiB,SAAS,MAAM;AAAE,MAAA7J,EAAM,mBAAmB,IAAO+I,EAAA;AAAA,IAAa,CAAC,CAAC;AAAA,EAC3J;AAqCA,SAAO,EAAE,gBAnCc,CAACW,GAAMpI,MAAW;AACvC,QAAI,CAACoI,EAAM,OAAM,IAAI,MAAM,6BAA6B;AACxD,IAAA1J,EAAM,OAAO0J,GACb1J,EAAM,eAAesB,KAAU,CAAA;AAC/B,UAAMyI,IAAS,IAAI,gBAAgB,OAAO,SAAS,MAAM;AACzD,QAAIC,IAAc,IACdC,IAAa,IACbC,IAAiB;AACrB,QAAI;AACF,MAAAF,IAAc,aAAa,QAAQ,UAAU,KAAK,IAClDC,IAAa,aAAa,QAAQ,OAAO,KAAK,IAC9CC,IAAiB,KAAK,MAAM,aAAa,QAAQ,4BAA4B,KAAK,OAAO;AAAA,IAC3F,QAAQ;AAAA,IAAe;AACvB,IAAAlK,EAAM,SAASG,EAAgB4J,EAAO,IAAI,KAAK,KAAKC,KAAe,SAAS,gBAAgB,QAAQ,IAAI,GACxGhK,EAAM,QAAQI,EAAe2J,EAAO,IAAI,OAAO,KAAKE,MAAe,OAAO,aAAa,8BAA8B,EAAE,UAAU,SAAS,QAAQ,GAClJjK,EAAM,YAAY,EAAQkK,GAC1BlK,EAAM,SAASqB,EAAYrB,EAAM,cAAcA,EAAM,MAAM;AAC3D,UAAMmK,IAAgB,mBAAmB,OAAO,SAAS,KAAK,QAAQ,MAAM,EAAE,CAAC;AAC/E,IAAAnK,EAAM,aAAaA,EAAM,OAAO,QAAQmK,CAAa,IACjDA,IACAnK,EAAM,OAAO,WAAW,eAAe,OAAO,KAAKA,EAAM,OAAO,SAAS,EAAE,EAAE,CAAC,GAClFA,EAAM,oBAAoB,IAAI,OAAO,SAAS,OAAO,QAAQ,OAAO,EAAE,CAAC,GACvE6I,EAAA,GACAM,GAAA,GACA,OAAO,iBAAiB,cAAc,MAAM;AAC1C,YAAMiB,IAAY,mBAAmB,OAAO,SAAS,KAAK,QAAQ,MAAM,EAAE,CAAC;AAC3E,MAAIpK,EAAM,OAAO,QAAQoK,CAAS,KAAKA,MAAcpK,EAAM,eACzDA,EAAM,aAAaoK,GACnBrB,EAAA;AAAA,IAEJ,CAAC,GACDA,EAAA,GACI,OAAO,WAAW,UAAQ,OAAO,OAAO,YAAY,EAAE,MAAM,iBAAiB,KAAK/I,EAAM,OAAO,WAAW,SAAS,GAAA,GAAM,GAAG;AAAA,EAClI,EAESqK;AACX;AAGA,MAAMC,KAAkBvK,GAAA,GAEXsK,KAAiBC,GAAgB,gBCnfjCC,KAAqC;AAAA,EAChD;AAAA,EAAc;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAa;AAAA,EAAa;AAAA,EACzD;AAAA,EAAS;AAAA,EAAiB;AAAA,EAAkB;AAAA,EAAgB;AAAA,EAC5D;AAAA,EAAgB;AAAA,EAAc;AAAA,EAAQ;AAAA,EAAa;AAAA,EACnD;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAiB;AACxD;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@genispace/geniapp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Public runtime, UI, Shell protocol and build contracts for GeniSpace applications",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -88,6 +88,11 @@
88
88
  "types": "./dist/vite.d.ts",
89
89
  "import": "./dist/vite.js"
90
90
  },
91
+ "./workbench": {
92
+ "types": "./dist/workbench.d.ts",
93
+ "import": "./dist/workbench.js"
94
+ },
95
+ "./workbench/styles.css": "./dist/workbench/styles.css",
91
96
  "./styles.css": "./dist/styles/base.css",
92
97
  "./fonts.css": "./dist/fonts.css",
93
98
  "./tailwind-preset": "./dist/styles/tailwind-preset.js"
@@ -96,6 +101,16 @@
96
101
  "access": "public",
97
102
  "provenance": true
98
103
  },
104
+ "scripts": {
105
+ "clean": "rimraf dist",
106
+ "build": "pnpm clean && vite build && node scripts/copy-assets.mjs",
107
+ "type-check": "tsc --noEmit && tsc -p tsconfig.build.json --noEmit",
108
+ "test": "vitest run",
109
+ "test:coverage": "vitest run --coverage",
110
+ "check:sdk-version": "node scripts/check-sdk-version.mjs",
111
+ "pack:check": "pnpm check:sdk-version && pnpm build && pnpm pack --pack-destination .pack",
112
+ "prepublishOnly": "pnpm check:sdk-version && pnpm type-check && pnpm test && pnpm build"
113
+ },
99
114
  "dependencies": {
100
115
  "@fontsource/geist-mono": "^5.1.0",
101
116
  "@fontsource/inter": "^5.1.0",
@@ -178,14 +193,5 @@
178
193
  "engines": {
179
194
  "node": ">=20"
180
195
  },
181
- "packageManager": "pnpm@8.15.0",
182
- "scripts": {
183
- "clean": "rimraf dist",
184
- "build": "pnpm clean && vite build && node scripts/copy-assets.mjs",
185
- "type-check": "tsc --noEmit && tsc -p tsconfig.build.json --noEmit",
186
- "test": "vitest run",
187
- "test:coverage": "vitest run --coverage",
188
- "check:sdk-version": "node scripts/check-sdk-version.mjs",
189
- "pack:check": "pnpm check:sdk-version && pnpm build && pnpm pack --pack-destination .pack"
190
- }
191
- }
196
+ "packageManager": "pnpm@8.15.0"
197
+ }