imean-service-engine-htmx-plugin 2.4.0 → 2.6.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/dist/index.d.mts +50 -106
- package/dist/index.d.ts +50 -106
- package/dist/index.js +287 -580
- package/dist/index.mjs +287 -577
- package/docs/README.md +0 -38
- package/package.json +1 -1
- package/docs/alpinejs-interactive-components.md +0 -653
- package/docs/custom-form-field-renderers.md +0 -541
- package/docs/field-editor-best-practices.md +0 -320
- package/docs/hono-html-best-practices.md +0 -509
package/dist/index.mjs
CHANGED
|
@@ -78,7 +78,6 @@ function renderActionButton(action, index) {
|
|
|
78
78
|
close,
|
|
79
79
|
submit,
|
|
80
80
|
formId,
|
|
81
|
-
onClick,
|
|
82
81
|
className = "",
|
|
83
82
|
target
|
|
84
83
|
} = action;
|
|
@@ -104,8 +103,7 @@ function renderActionButton(action, index) {
|
|
|
104
103
|
index
|
|
105
104
|
);
|
|
106
105
|
}
|
|
107
|
-
|
|
108
|
-
if (finalOnClick) {
|
|
106
|
+
if (close) {
|
|
109
107
|
const variantStyles = {
|
|
110
108
|
primary: "bg-blue-600 text-white hover:bg-blue-700",
|
|
111
109
|
secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300",
|
|
@@ -123,7 +121,8 @@ function renderActionButton(action, index) {
|
|
|
123
121
|
"button",
|
|
124
122
|
{
|
|
125
123
|
type: "button",
|
|
126
|
-
|
|
124
|
+
"x-data": CLOSE_DIALOG_ALPINE_DATA,
|
|
125
|
+
"x-on:click": "closeDialog()",
|
|
127
126
|
className: `px-4 py-2 rounded transition-colors font-medium ${buttonStyle} ${className}`,
|
|
128
127
|
"data-testid": testId2,
|
|
129
128
|
...confirm && { "data-confirm": confirm },
|
|
@@ -167,15 +166,25 @@ function renderActionButton(action, index) {
|
|
|
167
166
|
function renderActionButtons(actions) {
|
|
168
167
|
return actions.map((action, index) => renderActionButton(action, index));
|
|
169
168
|
}
|
|
170
|
-
var
|
|
169
|
+
var CLOSE_DIALOG_ALPINE_DATA;
|
|
171
170
|
var init_action_button_renderer = __esm({
|
|
172
171
|
"src/utils/action-button-renderer.tsx"() {
|
|
173
172
|
init_button();
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
173
|
+
CLOSE_DIALOG_ALPINE_DATA = `{
|
|
174
|
+
closeDialog() {
|
|
175
|
+
const backdrop = this.$el.closest('.dialog-backdrop');
|
|
176
|
+
if (backdrop) {
|
|
177
|
+
backdrop.classList.add('dialog-exit');
|
|
178
|
+
const content = backdrop.querySelector('.dialog-content');
|
|
179
|
+
if (content) {
|
|
180
|
+
content.classList.add('dialog-content-exit');
|
|
181
|
+
}
|
|
182
|
+
setTimeout(() => {
|
|
183
|
+
backdrop.remove();
|
|
184
|
+
}, 200);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}`;
|
|
179
188
|
}
|
|
180
189
|
});
|
|
181
190
|
|
|
@@ -305,11 +314,6 @@ var init_cdn_cache = __esm({
|
|
|
305
314
|
url: "https://unpkg.com/htmx.org@latest",
|
|
306
315
|
mimeType: "application/javascript"
|
|
307
316
|
},
|
|
308
|
-
{
|
|
309
|
-
name: "hyperscript",
|
|
310
|
-
url: "https://unpkg.com/hyperscript.org@latest",
|
|
311
|
-
mimeType: "application/javascript"
|
|
312
|
-
},
|
|
313
317
|
{
|
|
314
318
|
name: "tailwindcss",
|
|
315
319
|
url: "https://cdn.tailwindcss.com",
|
|
@@ -319,16 +323,6 @@ var init_cdn_cache = __esm({
|
|
|
319
323
|
name: "alpinejs",
|
|
320
324
|
url: "https://unpkg.com/alpinejs@latest/dist/cdn.min.js",
|
|
321
325
|
mimeType: "application/javascript"
|
|
322
|
-
},
|
|
323
|
-
{
|
|
324
|
-
name: "idiomorph",
|
|
325
|
-
url: "https://unpkg.com/idiomorph@0.7.4/dist/idiomorph-ext.min.js",
|
|
326
|
-
mimeType: "application/javascript"
|
|
327
|
-
},
|
|
328
|
-
{
|
|
329
|
-
name: "sortablejs",
|
|
330
|
-
url: "https://unpkg.com/sortablejs@latest/Sortable.min.js",
|
|
331
|
-
mimeType: "application/javascript"
|
|
332
326
|
}
|
|
333
327
|
];
|
|
334
328
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -553,8 +547,8 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
553
547
|
/* @__PURE__ */ jsx("div", { children: customRenderer({
|
|
554
548
|
field,
|
|
555
549
|
value: parsedValue,
|
|
556
|
-
initialData,
|
|
557
|
-
|
|
550
|
+
item: initialData,
|
|
551
|
+
name: field.name
|
|
558
552
|
}) }),
|
|
559
553
|
field.description && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: field.description })
|
|
560
554
|
]
|
|
@@ -629,7 +623,7 @@ function renderFormField(field, initialData, formFieldRenderers) {
|
|
|
629
623
|
name: field.name,
|
|
630
624
|
required: field.required,
|
|
631
625
|
placeholder: field.placeholder || (isJsonString(value) ? "JSON \u683C\u5F0F\u6570\u636E" : ""),
|
|
632
|
-
rows: isJsonString(value) ? 10 :
|
|
626
|
+
rows: isJsonString(value) ? Math.max(10, value.split("\n").length) : Math.max(5, Math.ceil(value.length / 100)),
|
|
633
627
|
className: "w-full px-4 py-2.5 border border-gray-300 rounded-lg shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 resize-y font-mono text-sm",
|
|
634
628
|
"data-testid": `input-${field.name}`,
|
|
635
629
|
children: isJsonString(value) ? formatJsonString(value) : value
|
|
@@ -2807,286 +2801,6 @@ var DefaultListFeature = class extends BaseFeature {
|
|
|
2807
2801
|
}
|
|
2808
2802
|
};
|
|
2809
2803
|
|
|
2810
|
-
// src/component-system/store.ts
|
|
2811
|
-
var STATE_EXPIRATION_TIME = 864e5;
|
|
2812
|
-
var StateStore = class _StateStore {
|
|
2813
|
-
static instance;
|
|
2814
|
-
state;
|
|
2815
|
-
constructor() {
|
|
2816
|
-
this.state = /* @__PURE__ */ new Map();
|
|
2817
|
-
setInterval(() => {
|
|
2818
|
-
this.state.forEach((state) => {
|
|
2819
|
-
if (state.lastUpdated < Date.now() - STATE_EXPIRATION_TIME) {
|
|
2820
|
-
this.state.delete(state.instanceId);
|
|
2821
|
-
}
|
|
2822
|
-
});
|
|
2823
|
-
}, 3e4);
|
|
2824
|
-
}
|
|
2825
|
-
static get() {
|
|
2826
|
-
if (!_StateStore.instance) {
|
|
2827
|
-
_StateStore.instance = new _StateStore();
|
|
2828
|
-
}
|
|
2829
|
-
return _StateStore.instance;
|
|
2830
|
-
}
|
|
2831
|
-
/** 获取实例状态 */
|
|
2832
|
-
getState(instanceId) {
|
|
2833
|
-
const state = this.state.get(instanceId);
|
|
2834
|
-
if (state) {
|
|
2835
|
-
return state;
|
|
2836
|
-
}
|
|
2837
|
-
const newState = {
|
|
2838
|
-
instanceId,
|
|
2839
|
-
data: {
|
|
2840
|
-
props: {},
|
|
2841
|
-
state: {}
|
|
2842
|
-
},
|
|
2843
|
-
lastUpdated: Date.now()
|
|
2844
|
-
};
|
|
2845
|
-
this.state.set(instanceId, newState);
|
|
2846
|
-
return newState;
|
|
2847
|
-
}
|
|
2848
|
-
/** 设置实例状态 */
|
|
2849
|
-
setState(instanceId, state) {
|
|
2850
|
-
const instanceState = this.getState(instanceId);
|
|
2851
|
-
instanceState.data = Object.assign(instanceState.data.state, state);
|
|
2852
|
-
instanceState.lastUpdated = Date.now();
|
|
2853
|
-
}
|
|
2854
|
-
};
|
|
2855
|
-
|
|
2856
|
-
// src/component-system/utils.ts
|
|
2857
|
-
var globalIdCounter = 0;
|
|
2858
|
-
function generateUniqueId() {
|
|
2859
|
-
return `htmx-cid-${globalIdCounter++}`;
|
|
2860
|
-
}
|
|
2861
|
-
var HTMX_COMPONENT_PREFIX = "/_htmx_components";
|
|
2862
|
-
|
|
2863
|
-
// src/component-system/context.tsx
|
|
2864
|
-
var RenderContext = class {
|
|
2865
|
-
constructor(prefix, instanceId, componentName) {
|
|
2866
|
-
this.prefix = prefix;
|
|
2867
|
-
this.instanceId = instanceId;
|
|
2868
|
-
this.componentName = componentName;
|
|
2869
|
-
}
|
|
2870
|
-
// 生成唯一 ID(使用全局共享计数器,避免冲突)
|
|
2871
|
-
$id() {
|
|
2872
|
-
return generateUniqueId();
|
|
2873
|
-
}
|
|
2874
|
-
setState(state) {
|
|
2875
|
-
StateStore.get().setState(this.instanceId, state);
|
|
2876
|
-
}
|
|
2877
|
-
get state() {
|
|
2878
|
-
return StateStore.get().getState(this.instanceId).data.state;
|
|
2879
|
-
}
|
|
2880
|
-
get props() {
|
|
2881
|
-
return StateStore.get().getState(this.instanceId).data.props;
|
|
2882
|
-
}
|
|
2883
|
-
// 生成方法 URL(使用当前 instanceId)
|
|
2884
|
-
url(methodName, params) {
|
|
2885
|
-
const baseUrl = `${this.prefix}/${HTMX_COMPONENT_PREFIX}/${this.componentName}/${this.instanceId}/${methodName}`;
|
|
2886
|
-
if (params && Object.keys(params).length > 0) {
|
|
2887
|
-
const queryString = new URLSearchParams(
|
|
2888
|
-
Object.entries(params).reduce(
|
|
2889
|
-
(acc, [key, value]) => {
|
|
2890
|
-
acc[key] = String(value);
|
|
2891
|
-
return acc;
|
|
2892
|
-
},
|
|
2893
|
-
{}
|
|
2894
|
-
)
|
|
2895
|
-
).toString();
|
|
2896
|
-
return `${baseUrl}?${queryString}`;
|
|
2897
|
-
}
|
|
2898
|
-
return baseUrl;
|
|
2899
|
-
}
|
|
2900
|
-
callMethod(methodName, params) {
|
|
2901
|
-
const selectors = Object.entries(params).map(([name, expression]) => `${name}:${expression}`).join(",");
|
|
2902
|
-
return {
|
|
2903
|
-
"hx-post": this.url(methodName),
|
|
2904
|
-
"hx-vals": `js:{_params_:{${selectors}}}`,
|
|
2905
|
-
"hx-params": "_state_,_params_,_this_value_"
|
|
2906
|
-
};
|
|
2907
|
-
}
|
|
2908
|
-
};
|
|
2909
|
-
var ComponentContext = class extends RenderContext {
|
|
2910
|
-
constructor(prefix, ctx, componentName) {
|
|
2911
|
-
const routeParams = ctx.req.param();
|
|
2912
|
-
const instanceId = String(routeParams.instanceId || "");
|
|
2913
|
-
super(prefix, instanceId, componentName);
|
|
2914
|
-
this.ctx = ctx;
|
|
2915
|
-
}
|
|
2916
|
-
// 获取所有参数(统一接口:聚合 query string 和 body)
|
|
2917
|
-
async params() {
|
|
2918
|
-
const params = {};
|
|
2919
|
-
const routeParams = this.ctx.req.param();
|
|
2920
|
-
Object.assign(params, routeParams);
|
|
2921
|
-
const url = new URL(this.ctx.req.url);
|
|
2922
|
-
for (const [key, value] of url.searchParams.entries()) {
|
|
2923
|
-
params[key] = value;
|
|
2924
|
-
}
|
|
2925
|
-
const contentType = this.ctx.req.header("Content-Type") || "";
|
|
2926
|
-
if (contentType.includes("application/json")) {
|
|
2927
|
-
try {
|
|
2928
|
-
const body = await this.ctx.req.json();
|
|
2929
|
-
Object.assign(params, body);
|
|
2930
|
-
} catch (e) {
|
|
2931
|
-
console.warn("[ComponentContext] Failed to parse JSON body:", e);
|
|
2932
|
-
}
|
|
2933
|
-
} else if (this.ctx.req.method === "POST" || this.ctx.req.method === "PUT" || this.ctx.req.method === "PATCH" || this.ctx.req.method === "DELETE") {
|
|
2934
|
-
try {
|
|
2935
|
-
const formData = await this.ctx.req.formData();
|
|
2936
|
-
for (const [key, value] of formData.entries()) {
|
|
2937
|
-
params[key] = value instanceof File ? value : value.toString();
|
|
2938
|
-
}
|
|
2939
|
-
} catch (e) {
|
|
2940
|
-
console.warn("[ComponentContext] Failed to parse form data:", e);
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
return params;
|
|
2944
|
-
}
|
|
2945
|
-
// 获取查询参数
|
|
2946
|
-
query() {
|
|
2947
|
-
const url = new URL(this.ctx.req.url);
|
|
2948
|
-
return Object.fromEntries(url.searchParams.entries());
|
|
2949
|
-
}
|
|
2950
|
-
// 获取请求体
|
|
2951
|
-
async body() {
|
|
2952
|
-
const contentType = this.ctx.req.header("Content-Type") || "";
|
|
2953
|
-
if (contentType.includes("application/json")) {
|
|
2954
|
-
try {
|
|
2955
|
-
return await this.ctx.req.json();
|
|
2956
|
-
} catch (e) {
|
|
2957
|
-
console.warn("[ComponentContext] Failed to parse JSON body:", e);
|
|
2958
|
-
return {};
|
|
2959
|
-
}
|
|
2960
|
-
}
|
|
2961
|
-
try {
|
|
2962
|
-
const formData = await this.ctx.req.formData();
|
|
2963
|
-
const body = {};
|
|
2964
|
-
for (const [key, value] of formData.entries()) {
|
|
2965
|
-
body[key] = value instanceof File ? value : value.toString();
|
|
2966
|
-
}
|
|
2967
|
-
return body;
|
|
2968
|
-
} catch (e) {
|
|
2969
|
-
console.warn("[ComponentContext] Failed to parse form data:", e);
|
|
2970
|
-
return {};
|
|
2971
|
-
}
|
|
2972
|
-
}
|
|
2973
|
-
};
|
|
2974
|
-
|
|
2975
|
-
// src/component-system/component.tsx
|
|
2976
|
-
var METHOD_METADATA_KEY = /* @__PURE__ */ Symbol("htmx:method");
|
|
2977
|
-
function Method(config) {
|
|
2978
|
-
return function(target, propertyKey, _descriptor) {
|
|
2979
|
-
if (!target[METHOD_METADATA_KEY]) {
|
|
2980
|
-
target[METHOD_METADATA_KEY] = /* @__PURE__ */ new Map();
|
|
2981
|
-
}
|
|
2982
|
-
target[METHOD_METADATA_KEY].set(propertyKey, {
|
|
2983
|
-
method: config?.method || "get",
|
|
2984
|
-
path: config?.path
|
|
2985
|
-
});
|
|
2986
|
-
};
|
|
2987
|
-
}
|
|
2988
|
-
var HtmxComponent = class {
|
|
2989
|
-
constructor(name) {
|
|
2990
|
-
this.name = name;
|
|
2991
|
-
}
|
|
2992
|
-
prefix;
|
|
2993
|
-
// 组件函数
|
|
2994
|
-
Component = (props) => {
|
|
2995
|
-
const instanceId = generateUniqueId();
|
|
2996
|
-
const state = StateStore.get().getState(instanceId).data;
|
|
2997
|
-
state.props = props;
|
|
2998
|
-
state.state = {};
|
|
2999
|
-
const renderCtx = new RenderContext(
|
|
3000
|
-
this.prefix,
|
|
3001
|
-
instanceId,
|
|
3002
|
-
this.name
|
|
3003
|
-
);
|
|
3004
|
-
return this.render(renderCtx, props);
|
|
3005
|
-
};
|
|
3006
|
-
// 返回 JSX script 元素
|
|
3007
|
-
// 获取所有标记为 @Method() 的方法
|
|
3008
|
-
// 注意:handler 不再绑定 this,因为方法会接收 ComponentContext 作为第一个参数
|
|
3009
|
-
static getMethods(component) {
|
|
3010
|
-
const methods = /* @__PURE__ */ new Map();
|
|
3011
|
-
const metadata = component[METHOD_METADATA_KEY];
|
|
3012
|
-
if (!metadata) return methods;
|
|
3013
|
-
for (const [methodName, config] of metadata.entries()) {
|
|
3014
|
-
const handler = component[methodName];
|
|
3015
|
-
methods.set(methodName, {
|
|
3016
|
-
method: config.method,
|
|
3017
|
-
path: config.path,
|
|
3018
|
-
handler
|
|
3019
|
-
});
|
|
3020
|
-
}
|
|
3021
|
-
return methods;
|
|
3022
|
-
}
|
|
3023
|
-
};
|
|
3024
|
-
var HtmxComponentHandler = class {
|
|
3025
|
-
constructor(hono, prefix, components) {
|
|
3026
|
-
this.hono = hono;
|
|
3027
|
-
this.prefix = prefix;
|
|
3028
|
-
this.components = components;
|
|
3029
|
-
for (const component of this.components) {
|
|
3030
|
-
component.prefix = this.prefix;
|
|
3031
|
-
this.registerHandler(component);
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
registerHandler(component) {
|
|
3035
|
-
const methods = HtmxComponent.getMethods(component);
|
|
3036
|
-
for (const [methodName, methodConfig] of methods) {
|
|
3037
|
-
const routePath = `${this.prefix}/${HTMX_COMPONENT_PREFIX}/${component.name}/:instanceId/${methodName}`;
|
|
3038
|
-
logger.info(
|
|
3039
|
-
`[HtmxComponent] Registering handler ${methodConfig.method} ${routePath}`
|
|
3040
|
-
);
|
|
3041
|
-
this.hono[methodConfig.method](routePath, async (ctx) => {
|
|
3042
|
-
return this.handleComponentMethod(
|
|
3043
|
-
ctx,
|
|
3044
|
-
component,
|
|
3045
|
-
methodConfig.handler.bind(component)
|
|
3046
|
-
);
|
|
3047
|
-
});
|
|
3048
|
-
}
|
|
3049
|
-
}
|
|
3050
|
-
async handleComponentMethod(ctx, component, handler) {
|
|
3051
|
-
const componentContext = new ComponentContext(
|
|
3052
|
-
this.prefix,
|
|
3053
|
-
ctx,
|
|
3054
|
-
component.name
|
|
3055
|
-
);
|
|
3056
|
-
const result = await handler(componentContext);
|
|
3057
|
-
if (result instanceof Object && ("target" in result || "swap" in result || "body" in result || "oobs" in result)) {
|
|
3058
|
-
const { target, swap, body, oobs, trigger } = result;
|
|
3059
|
-
const headers = {};
|
|
3060
|
-
let bodyContent = body;
|
|
3061
|
-
if (target) headers["HX-Retarget"] = target;
|
|
3062
|
-
if (swap) headers["HX-Reswap"] = swap;
|
|
3063
|
-
if (trigger) headers["HX-Trigger"] = trigger;
|
|
3064
|
-
if (oobs) {
|
|
3065
|
-
oobs.forEach((oob) => {
|
|
3066
|
-
oob.props["hx-swap-oob"] = "true";
|
|
3067
|
-
});
|
|
3068
|
-
if (!body) {
|
|
3069
|
-
headers["HX-Reswap"] = "delete";
|
|
3070
|
-
}
|
|
3071
|
-
bodyContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3072
|
-
body,
|
|
3073
|
-
oobs
|
|
3074
|
-
] });
|
|
3075
|
-
}
|
|
3076
|
-
return ctx.html(bodyContent, 200, headers);
|
|
3077
|
-
}
|
|
3078
|
-
if (result === null) {
|
|
3079
|
-
return ctx.html(/* @__PURE__ */ jsx("div", {}), 200, {
|
|
3080
|
-
"HX-Reswap": "none"
|
|
3081
|
-
});
|
|
3082
|
-
}
|
|
3083
|
-
if (result instanceof Response) {
|
|
3084
|
-
return result;
|
|
3085
|
-
}
|
|
3086
|
-
return ctx.html(result, 200);
|
|
3087
|
-
}
|
|
3088
|
-
};
|
|
3089
|
-
|
|
3090
2804
|
// src/utils/path.ts
|
|
3091
2805
|
function modelNameToPath(modelName) {
|
|
3092
2806
|
return `/${modelName.replace(/([A-Z])/g, "-$1").toLowerCase()}`;
|
|
@@ -3098,8 +2812,9 @@ function ErrorAlert(props) {
|
|
|
3098
2812
|
type = "error",
|
|
3099
2813
|
showClose = true,
|
|
3100
2814
|
className = "",
|
|
3101
|
-
autoClose = 5e3
|
|
2815
|
+
autoClose = 5e3,
|
|
3102
2816
|
// 默认 5 秒自动关闭
|
|
2817
|
+
"hx-swap-oob": hxSwapOob
|
|
3103
2818
|
} = props;
|
|
3104
2819
|
const typeClasses = {
|
|
3105
2820
|
error: "bg-red-50 border-red-200 text-red-800",
|
|
@@ -3188,12 +2903,20 @@ function ErrorAlert(props) {
|
|
|
3188
2903
|
const now = Date.now();
|
|
3189
2904
|
this.elapsedTime = now - this.startTime;
|
|
3190
2905
|
this.progress = Math.max(0, 100 - (this.elapsedTime / this.autoCloseDelay) * 100);
|
|
2906
|
+
// \u66F4\u65B0\u8FDB\u5EA6\u6761\u6837\u5F0F
|
|
2907
|
+
const progressBar = this.$el.querySelector('.progress-bar');
|
|
2908
|
+
if (progressBar) {
|
|
2909
|
+
progressBar.style.width = this.progress + '%';
|
|
2910
|
+
}
|
|
3191
2911
|
if (this.progress > 0 && this.visible) {
|
|
3192
2912
|
this.progressTimer = requestAnimationFrame(updateProgress);
|
|
3193
2913
|
}
|
|
3194
2914
|
};
|
|
3195
2915
|
this.progressTimer = requestAnimationFrame(updateProgress);
|
|
3196
2916
|
},
|
|
2917
|
+
getProgressStyle() {
|
|
2918
|
+
return { width: this.progress + '%' };
|
|
2919
|
+
},
|
|
3197
2920
|
pauseAutoClose() {
|
|
3198
2921
|
if (this.autoCloseTimer) {
|
|
3199
2922
|
clearTimeout(this.autoCloseTimer);
|
|
@@ -3222,6 +2945,9 @@ function ErrorAlert(props) {
|
|
|
3222
2945
|
cancelAnimationFrame(this.progressTimer);
|
|
3223
2946
|
this.progressTimer = null;
|
|
3224
2947
|
}
|
|
2948
|
+
// \u6DFB\u52A0\u6DE1\u51FA\u52A8\u753B
|
|
2949
|
+
this.$el.classList.add('error-alert-exit');
|
|
2950
|
+
// \u52A8\u753B\u7ED3\u675F\u540E\u5B8C\u5168\u79FB\u9664\u5143\u7D20\uFF0C\u4E0D\u7559\u7A7A div
|
|
3225
2951
|
setTimeout(() => {
|
|
3226
2952
|
if (this.$el && this.$el.parentNode) {
|
|
3227
2953
|
this.$el.parentNode.removeChild(this.$el);
|
|
@@ -3232,6 +2958,9 @@ function ErrorAlert(props) {
|
|
|
3232
2958
|
visible: true,
|
|
3233
2959
|
close() {
|
|
3234
2960
|
this.visible = false;
|
|
2961
|
+
// \u6DFB\u52A0\u6DE1\u51FA\u52A8\u753B
|
|
2962
|
+
this.$el.classList.add('error-alert-exit');
|
|
2963
|
+
// \u52A8\u753B\u7ED3\u675F\u540E\u5B8C\u5168\u79FB\u9664\u5143\u7D20\uFF0C\u4E0D\u7559\u7A7A div
|
|
3235
2964
|
setTimeout(() => {
|
|
3236
2965
|
if (this.$el && this.$el.parentNode) {
|
|
3237
2966
|
this.$el.parentNode.removeChild(this.$el);
|
|
@@ -3253,18 +2982,26 @@ function ErrorAlert(props) {
|
|
|
3253
2982
|
alpineProps["@mouseenter"] = "pauseAutoClose()";
|
|
3254
2983
|
alpineProps["@mouseleave"] = "resumeAutoClose()";
|
|
3255
2984
|
}
|
|
2985
|
+
const htmxProps = {};
|
|
2986
|
+
if (hxSwapOob) {
|
|
2987
|
+
htmxProps["hx-swap-oob"] = hxSwapOob;
|
|
2988
|
+
}
|
|
3256
2989
|
return /* @__PURE__ */ jsxs(
|
|
3257
2990
|
"div",
|
|
3258
2991
|
{
|
|
3259
2992
|
...alpineProps,
|
|
3260
|
-
|
|
2993
|
+
...htmxProps,
|
|
2994
|
+
className: `w-full border rounded-lg p-4 shadow-lg ${typeClasses[type]} ${className} relative overflow-hidden pointer-events-auto`,
|
|
3261
2995
|
role: "alert",
|
|
2996
|
+
style: {
|
|
2997
|
+
animation: "slideInRight 0.3s ease-out"
|
|
2998
|
+
},
|
|
3262
2999
|
children: [
|
|
3263
3000
|
autoClose > 0 && /* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 h-1 bg-gray-200", children: /* @__PURE__ */ jsx(
|
|
3264
3001
|
"div",
|
|
3265
3002
|
{
|
|
3266
|
-
className: `h-full ${progressBarColors[type]}`,
|
|
3267
|
-
...{ ":style": "
|
|
3003
|
+
className: `h-full ${progressBarColors[type]} progress-bar`,
|
|
3004
|
+
...{ "x-bind:style": "getProgressStyle()" }
|
|
3268
3005
|
}
|
|
3269
3006
|
) }),
|
|
3270
3007
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start", children: [
|
|
@@ -3383,6 +3120,9 @@ async function createFeatureContext(ctx, page, feature, user, options) {
|
|
|
3383
3120
|
};
|
|
3384
3121
|
return featureContext;
|
|
3385
3122
|
}
|
|
3123
|
+
function generateDialogId() {
|
|
3124
|
+
return `dialog-${Date.now()}}`;
|
|
3125
|
+
}
|
|
3386
3126
|
function Dialog(props) {
|
|
3387
3127
|
const {
|
|
3388
3128
|
title,
|
|
@@ -3394,6 +3134,7 @@ function Dialog(props) {
|
|
|
3394
3134
|
actions = [],
|
|
3395
3135
|
fixedContentHeight = false
|
|
3396
3136
|
} = props;
|
|
3137
|
+
const dialogId = generateDialogId();
|
|
3397
3138
|
const sizeClasses = {
|
|
3398
3139
|
sm: "max-w-md",
|
|
3399
3140
|
md: "max-w-lg",
|
|
@@ -3401,19 +3142,33 @@ function Dialog(props) {
|
|
|
3401
3142
|
xl: "max-w-4xl",
|
|
3402
3143
|
full: "max-w-7xl"
|
|
3403
3144
|
};
|
|
3404
|
-
const
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3145
|
+
const alpineData = `{
|
|
3146
|
+
closeDialog() {
|
|
3147
|
+
const backdrop = this.$el.closest('.dialog-backdrop');
|
|
3148
|
+
if (backdrop) {
|
|
3149
|
+
backdrop.classList.add('dialog-exit');
|
|
3150
|
+
const content = backdrop.querySelector('.dialog-content');
|
|
3151
|
+
if (content) {
|
|
3152
|
+
content.classList.add('dialog-content-exit');
|
|
3153
|
+
}
|
|
3154
|
+
setTimeout(() => {
|
|
3155
|
+
backdrop.remove();
|
|
3156
|
+
}, 200);
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
}`;
|
|
3409
3160
|
return /* @__PURE__ */ jsx(
|
|
3410
3161
|
"div",
|
|
3411
3162
|
{
|
|
3163
|
+
id: dialogId,
|
|
3412
3164
|
className: "fixed inset-0 bg-black bg-opacity-50 z-[100] flex items-center justify-center p-4 dialog-backdrop",
|
|
3413
3165
|
style: {
|
|
3414
3166
|
animation: "fadeIn 0.2s ease-out"
|
|
3415
3167
|
},
|
|
3416
|
-
|
|
3168
|
+
"x-data": alpineData,
|
|
3169
|
+
...closeOnBackdropClick && {
|
|
3170
|
+
"x-on:click": "if ($event.target === $el) closeDialog()"
|
|
3171
|
+
},
|
|
3417
3172
|
children: /* @__PURE__ */ jsxs(
|
|
3418
3173
|
"div",
|
|
3419
3174
|
{
|
|
@@ -3421,7 +3176,7 @@ function Dialog(props) {
|
|
|
3421
3176
|
style: {
|
|
3422
3177
|
animation: "slideIn 0.3s ease-out"
|
|
3423
3178
|
},
|
|
3424
|
-
|
|
3179
|
+
...{ "x-on:click.stop": "" },
|
|
3425
3180
|
children: [
|
|
3426
3181
|
(title || showClose) && /* @__PURE__ */ jsxs("div", { className: "px-6 py-4 border-b border-gray-200 bg-white flex items-center justify-between", children: [
|
|
3427
3182
|
title && /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: title }),
|
|
@@ -3429,7 +3184,7 @@ function Dialog(props) {
|
|
|
3429
3184
|
"button",
|
|
3430
3185
|
{
|
|
3431
3186
|
className: "text-gray-400 hover:text-gray-600 transition-colors",
|
|
3432
|
-
|
|
3187
|
+
"x-on:click": "closeDialog()",
|
|
3433
3188
|
children: /* @__PURE__ */ jsx(
|
|
3434
3189
|
"svg",
|
|
3435
3190
|
{
|
|
@@ -3526,11 +3281,26 @@ function PermissionDeniedContent(props) {
|
|
|
3526
3281
|
Button,
|
|
3527
3282
|
{
|
|
3528
3283
|
variant: "secondary",
|
|
3529
|
-
|
|
3284
|
+
"x-data": `{
|
|
3285
|
+
closeDialog() {
|
|
3286
|
+
const backdrop = this.$el.closest('.dialog-backdrop');
|
|
3287
|
+
if (backdrop) {
|
|
3288
|
+
backdrop.classList.add('dialog-exit');
|
|
3289
|
+
const content = backdrop.querySelector('.dialog-content');
|
|
3290
|
+
if (content) {
|
|
3291
|
+
content.classList.add('dialog-content-exit');
|
|
3292
|
+
}
|
|
3293
|
+
setTimeout(() => {
|
|
3294
|
+
backdrop.remove();
|
|
3295
|
+
}, 200);
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
}`,
|
|
3299
|
+
"x-on:click": "closeDialog()",
|
|
3530
3300
|
children: "\u5173\u95ED"
|
|
3531
3301
|
}
|
|
3532
3302
|
),
|
|
3533
|
-
!isDialog && userInfo && /* @__PURE__ */ jsx(Button, { variant: "secondary",
|
|
3303
|
+
!isDialog && userInfo && /* @__PURE__ */ jsx(Button, { variant: "secondary", onclick: "window.history.back()", children: "\u8FD4\u56DE" })
|
|
3534
3304
|
] })
|
|
3535
3305
|
] });
|
|
3536
3306
|
}
|
|
@@ -3551,13 +3321,8 @@ var getResourceUrl = (prefix, name) => {
|
|
|
3551
3321
|
function globalScripts(prefix) {
|
|
3552
3322
|
return html`
|
|
3553
3323
|
<script src=${getResourceUrl(prefix, "htmx")}></script>
|
|
3554
|
-
<script src=${getResourceUrl(prefix, "htmx-ext-form-json")}></script>
|
|
3555
|
-
<script src=${getResourceUrl(prefix, "hyperscript")}></script>
|
|
3556
3324
|
<script src=${getResourceUrl(prefix, "tailwindcss")}></script>
|
|
3557
3325
|
<script src=${getResourceUrl(prefix, "alpinejs")} defer></script>
|
|
3558
|
-
<script src=${getResourceUrl(prefix, "sortablejs")}></script>
|
|
3559
|
-
<script src=${getResourceUrl(prefix, "idiomorph")}></script>
|
|
3560
|
-
<script type="module" src=${getResourceUrl(prefix, "datastar")}></script>
|
|
3561
3326
|
`;
|
|
3562
3327
|
}
|
|
3563
3328
|
function globalStyles() {
|
|
@@ -3687,36 +3452,6 @@ function globalStyles() {
|
|
|
3687
3452
|
}
|
|
3688
3453
|
</style>`;
|
|
3689
3454
|
}
|
|
3690
|
-
function sortableScript() {
|
|
3691
|
-
html`<script>
|
|
3692
|
-
if (typeof htmx !== "undefined" && typeof Sortable !== "undefined") {
|
|
3693
|
-
htmx.onLoad(function (content) {
|
|
3694
|
-
var sortables = content.querySelectorAll(".sortable");
|
|
3695
|
-
for (var i = 0; i < sortables.length; i++) {
|
|
3696
|
-
var sortable = sortables[i];
|
|
3697
|
-
// 检查是否已经初始化
|
|
3698
|
-
if (sortable.sortableInstance) {
|
|
3699
|
-
continue;
|
|
3700
|
-
}
|
|
3701
|
-
var sortableInstance = new Sortable(sortable, {
|
|
3702
|
-
animation: 150,
|
|
3703
|
-
ghostClass: "sortable-ghost",
|
|
3704
|
-
filter: ".htmx-indicator",
|
|
3705
|
-
onMove: function (evt) {
|
|
3706
|
-
return evt.related.className.indexOf("htmx-indicator") === -1;
|
|
3707
|
-
},
|
|
3708
|
-
});
|
|
3709
|
-
sortable.sortableInstance = sortableInstance;
|
|
3710
|
-
sortable.addEventListener("htmx:afterSwap", function () {
|
|
3711
|
-
if (sortable.sortableInstance) {
|
|
3712
|
-
sortable.sortableInstance.option("disabled", false);
|
|
3713
|
-
}
|
|
3714
|
-
});
|
|
3715
|
-
}
|
|
3716
|
-
});
|
|
3717
|
-
}
|
|
3718
|
-
</script>`;
|
|
3719
|
-
}
|
|
3720
3455
|
function Breadcrumb(props) {
|
|
3721
3456
|
const { items } = props;
|
|
3722
3457
|
if (items.length === 0) {
|
|
@@ -4072,7 +3807,7 @@ function SortableList(props) {
|
|
|
4072
3807
|
function StringArrayEditor(props) {
|
|
4073
3808
|
const {
|
|
4074
3809
|
value,
|
|
4075
|
-
|
|
3810
|
+
name,
|
|
4076
3811
|
placeholder = "\u8BF7\u8F93\u5165\u5185\u5BB9",
|
|
4077
3812
|
allowEmpty = false,
|
|
4078
3813
|
rows = 1
|
|
@@ -4080,185 +3815,174 @@ function StringArrayEditor(props) {
|
|
|
4080
3815
|
const initialItems = value || [];
|
|
4081
3816
|
const initialDataJson = JSON.stringify({
|
|
4082
3817
|
items: initialItems.map((item) => item || ""),
|
|
4083
|
-
fieldName,
|
|
3818
|
+
fieldName: name,
|
|
4084
3819
|
placeholder,
|
|
4085
3820
|
allowEmpty,
|
|
4086
3821
|
rows
|
|
4087
3822
|
});
|
|
4088
|
-
return /* @__PURE__ */ jsxs(
|
|
4089
|
-
"div",
|
|
4090
|
-
|
|
4091
|
-
|
|
4092
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
"button",
|
|
4096
|
-
{
|
|
4097
|
-
type: "button",
|
|
4098
|
-
...{
|
|
4099
|
-
"x-on:click": `
|
|
3823
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-3", "x-data": initialDataJson, children: [
|
|
3824
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-end", children: /* @__PURE__ */ jsxs(
|
|
3825
|
+
"button",
|
|
3826
|
+
{
|
|
3827
|
+
type: "button",
|
|
3828
|
+
...{
|
|
3829
|
+
"x-on:click": `
|
|
4100
3830
|
items.push('');
|
|
4101
3831
|
`
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
3832
|
+
},
|
|
3833
|
+
className: "px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium flex items-center gap-2",
|
|
3834
|
+
"data-testid": `${name}-add-button`,
|
|
3835
|
+
children: [
|
|
3836
|
+
/* @__PURE__ */ jsx(
|
|
3837
|
+
"svg",
|
|
3838
|
+
{
|
|
3839
|
+
className: "w-4 h-4",
|
|
3840
|
+
fill: "none",
|
|
3841
|
+
stroke: "currentColor",
|
|
3842
|
+
viewBox: "0 0 24 24",
|
|
3843
|
+
children: /* @__PURE__ */ jsx(
|
|
3844
|
+
"path",
|
|
4108
3845
|
{
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
children: /* @__PURE__ */ jsx(
|
|
4114
|
-
"path",
|
|
4115
|
-
{
|
|
4116
|
-
strokeLinecap: "round",
|
|
4117
|
-
strokeLinejoin: "round",
|
|
4118
|
-
strokeWidth: "2",
|
|
4119
|
-
d: "M12 4v16m8-8H4"
|
|
4120
|
-
}
|
|
4121
|
-
)
|
|
3846
|
+
strokeLinecap: "round",
|
|
3847
|
+
strokeLinejoin: "round",
|
|
3848
|
+
strokeWidth: "2",
|
|
3849
|
+
d: "M12 4v16m8-8H4"
|
|
4122
3850
|
}
|
|
4123
|
-
)
|
|
4124
|
-
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
|
|
3851
|
+
)
|
|
3852
|
+
}
|
|
3853
|
+
),
|
|
3854
|
+
"\u6DFB\u52A0\u9879"
|
|
3855
|
+
]
|
|
3856
|
+
}
|
|
3857
|
+
) }),
|
|
3858
|
+
/* @__PURE__ */ jsx(
|
|
3859
|
+
"div",
|
|
3860
|
+
{
|
|
3861
|
+
"x-show": "items.length > 0",
|
|
3862
|
+
"data-testid": `${name}-list-container`,
|
|
3863
|
+
...{
|
|
3864
|
+
"@sortable:change.stop": `
|
|
4135
3865
|
(function() {
|
|
4136
3866
|
const { oldIndex, newIndex } = $event.detail;
|
|
4137
3867
|
[items[oldIndex], items[newIndex]] = [items[newIndex], items[oldIndex]];
|
|
4138
3868
|
})();
|
|
4139
3869
|
`
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
|
|
4145
|
-
|
|
4146
|
-
|
|
4147
|
-
|
|
4148
|
-
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
}
|
|
4155
|
-
);
|
|
3870
|
+
},
|
|
3871
|
+
children: /* @__PURE__ */ jsx(SortableList, { className: "space-y-2", handle: "[data-drag-handle]", children: /* @__PURE__ */ jsx("template", { "x-for": "(item, index) in items", "x-bind:key": "index", children: /* @__PURE__ */ jsx(ArrayItem, { fieldName: name, rows }) }) })
|
|
3872
|
+
}
|
|
3873
|
+
),
|
|
3874
|
+
/* @__PURE__ */ jsx(
|
|
3875
|
+
"div",
|
|
3876
|
+
{
|
|
3877
|
+
className: "empty-state text-center py-8 text-gray-400 text-sm border border-dashed border-gray-300 rounded-lg",
|
|
3878
|
+
"x-show": "items.length === 0",
|
|
3879
|
+
"data-testid": `${name}-empty-state`,
|
|
3880
|
+
children: '\u6682\u65E0\u9879\uFF0C\u70B9\u51FB"\u6DFB\u52A0\u9879"\u6309\u94AE\u6DFB\u52A0'
|
|
3881
|
+
}
|
|
3882
|
+
)
|
|
3883
|
+
] });
|
|
4156
3884
|
}
|
|
4157
|
-
function ArrayItem({
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
3885
|
+
function ArrayItem({
|
|
3886
|
+
fieldName,
|
|
3887
|
+
rows = 1
|
|
3888
|
+
}) {
|
|
3889
|
+
return /* @__PURE__ */ jsxs("div", { "data-array-item": true, className: "flex items-center gap-2 group", children: [
|
|
3890
|
+
/* @__PURE__ */ jsx(
|
|
3891
|
+
"div",
|
|
3892
|
+
{
|
|
3893
|
+
className: "flex-shrink-0 cursor-move text-gray-400 hover:text-gray-600 transition-colors p-1",
|
|
3894
|
+
"data-drag-handle": true,
|
|
3895
|
+
"data-testid": `${fieldName}-drag-handle`,
|
|
3896
|
+
title: "\u62D6\u62FD\u6392\u5E8F",
|
|
3897
|
+
children: /* @__PURE__ */ jsx(
|
|
3898
|
+
"svg",
|
|
4166
3899
|
{
|
|
4167
|
-
className: "
|
|
4168
|
-
"
|
|
4169
|
-
"
|
|
4170
|
-
|
|
3900
|
+
className: "w-5 h-5",
|
|
3901
|
+
fill: "none",
|
|
3902
|
+
stroke: "currentColor",
|
|
3903
|
+
viewBox: "0 0 24 24",
|
|
4171
3904
|
children: /* @__PURE__ */ jsx(
|
|
4172
|
-
"
|
|
3905
|
+
"path",
|
|
4173
3906
|
{
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
children: /* @__PURE__ */ jsx(
|
|
4179
|
-
"path",
|
|
4180
|
-
{
|
|
4181
|
-
strokeLinecap: "round",
|
|
4182
|
-
strokeLinejoin: "round",
|
|
4183
|
-
strokeWidth: "2",
|
|
4184
|
-
d: "M4 8h16M4 16h16"
|
|
4185
|
-
}
|
|
4186
|
-
)
|
|
3907
|
+
strokeLinecap: "round",
|
|
3908
|
+
strokeLinejoin: "round",
|
|
3909
|
+
strokeWidth: "2",
|
|
3910
|
+
d: "M4 8h16M4 16h16"
|
|
4187
3911
|
}
|
|
4188
3912
|
)
|
|
4189
3913
|
}
|
|
4190
|
-
)
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
3914
|
+
)
|
|
3915
|
+
}
|
|
3916
|
+
),
|
|
3917
|
+
rows === 1 ? /* @__PURE__ */ jsx(
|
|
3918
|
+
"input",
|
|
3919
|
+
{
|
|
3920
|
+
type: "text",
|
|
3921
|
+
"x-model": "items[index]",
|
|
3922
|
+
"x-bind:placeholder": "placeholder + ' ' + (index + 1)",
|
|
3923
|
+
className: "flex-1 px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",
|
|
3924
|
+
"data-testid": `${fieldName}-input`,
|
|
3925
|
+
"x-bind:required": "!allowEmpty"
|
|
3926
|
+
}
|
|
3927
|
+
) : /* @__PURE__ */ jsx(
|
|
3928
|
+
"textarea",
|
|
3929
|
+
{
|
|
3930
|
+
"x-model": "items[index]",
|
|
3931
|
+
"x-bind:placeholder": "placeholder + ' ' + (index + 1)",
|
|
3932
|
+
rows,
|
|
3933
|
+
className: "flex-1 px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-y",
|
|
3934
|
+
"data-testid": `${fieldName}-input`,
|
|
3935
|
+
"x-bind:required": "!allowEmpty"
|
|
3936
|
+
}
|
|
3937
|
+
),
|
|
3938
|
+
/* @__PURE__ */ jsx(
|
|
3939
|
+
"input",
|
|
3940
|
+
{
|
|
3941
|
+
type: "hidden",
|
|
3942
|
+
"x-bind:name": "fieldName + '[' + index + ']'",
|
|
3943
|
+
"x-bind:value": "item"
|
|
3944
|
+
}
|
|
3945
|
+
),
|
|
3946
|
+
/* @__PURE__ */ jsx(
|
|
3947
|
+
"button",
|
|
3948
|
+
{
|
|
3949
|
+
type: "button",
|
|
3950
|
+
...{
|
|
3951
|
+
"x-on:click": `
|
|
4226
3952
|
items.splice(index, 1);
|
|
4227
3953
|
`
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
3954
|
+
},
|
|
3955
|
+
className: "flex-shrink-0 px-3 py-2 text-sm text-red-600 hover:bg-red-50 rounded-lg transition-colors",
|
|
3956
|
+
"data-testid": `${fieldName}-remove-button`,
|
|
3957
|
+
title: "\u5220\u9664\u6B64\u9879",
|
|
3958
|
+
children: /* @__PURE__ */ jsx(
|
|
3959
|
+
"svg",
|
|
3960
|
+
{
|
|
3961
|
+
className: "w-5 h-5",
|
|
3962
|
+
fill: "none",
|
|
3963
|
+
stroke: "currentColor",
|
|
3964
|
+
viewBox: "0 0 24 24",
|
|
4232
3965
|
children: /* @__PURE__ */ jsx(
|
|
4233
|
-
"
|
|
3966
|
+
"path",
|
|
4234
3967
|
{
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
children: /* @__PURE__ */ jsx(
|
|
4240
|
-
"path",
|
|
4241
|
-
{
|
|
4242
|
-
strokeLinecap: "round",
|
|
4243
|
-
strokeLinejoin: "round",
|
|
4244
|
-
strokeWidth: "2",
|
|
4245
|
-
d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
4246
|
-
}
|
|
4247
|
-
)
|
|
3968
|
+
strokeLinecap: "round",
|
|
3969
|
+
strokeLinejoin: "round",
|
|
3970
|
+
strokeWidth: "2",
|
|
3971
|
+
d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
|
|
4248
3972
|
}
|
|
4249
3973
|
)
|
|
4250
3974
|
}
|
|
4251
3975
|
)
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
);
|
|
3976
|
+
}
|
|
3977
|
+
)
|
|
3978
|
+
] });
|
|
4255
3979
|
}
|
|
4256
3980
|
function TagsEditor(props) {
|
|
4257
|
-
const { value,
|
|
3981
|
+
const { value, name, placeholder = "\u8F93\u5165\u6807\u7B7E\u540E\u6309\u56DE\u8F66\u6DFB\u52A0" } = props;
|
|
4258
3982
|
const initialTags = value || [];
|
|
4259
3983
|
const initialDataJson = JSON.stringify({
|
|
4260
3984
|
tags: initialTags.map((tag) => tag || ""),
|
|
4261
|
-
fieldName,
|
|
3985
|
+
fieldName: name,
|
|
4262
3986
|
newTag: "",
|
|
4263
3987
|
editingIndex: null,
|
|
4264
3988
|
editingValue: "",
|
|
@@ -4285,7 +4009,7 @@ function TagsEditor(props) {
|
|
|
4285
4009
|
placeholder,
|
|
4286
4010
|
autocomplete: "off",
|
|
4287
4011
|
className: "w-full px-3 py-1.5 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",
|
|
4288
|
-
"data-testid": `${
|
|
4012
|
+
"data-testid": `${name}-input`
|
|
4289
4013
|
}
|
|
4290
4014
|
),
|
|
4291
4015
|
/* @__PURE__ */ jsx(
|
|
@@ -4294,7 +4018,7 @@ function TagsEditor(props) {
|
|
|
4294
4018
|
"x-show": "error && editingIndex === null",
|
|
4295
4019
|
"x-text": "error",
|
|
4296
4020
|
className: "text-red-600 text-sm p-2",
|
|
4297
|
-
id: `${
|
|
4021
|
+
id: `${name}-error`
|
|
4298
4022
|
}
|
|
4299
4023
|
)
|
|
4300
4024
|
] }),
|
|
@@ -4302,7 +4026,7 @@ function TagsEditor(props) {
|
|
|
4302
4026
|
"div",
|
|
4303
4027
|
{
|
|
4304
4028
|
"x-show": "tags.length > 0",
|
|
4305
|
-
"data-testid": `${
|
|
4029
|
+
"data-testid": `${name}-tags-container`,
|
|
4306
4030
|
...{
|
|
4307
4031
|
"@sortable:change.stop": `
|
|
4308
4032
|
(function() {
|
|
@@ -4325,8 +4049,8 @@ function TagsEditor(props) {
|
|
|
4325
4049
|
"x-bind:value": "editingIndex === index ? editingValue : tag"
|
|
4326
4050
|
}
|
|
4327
4051
|
),
|
|
4328
|
-
/* @__PURE__ */ jsx(TagItem, { fieldName }),
|
|
4329
|
-
/* @__PURE__ */ jsx(TagItemEdit, { fieldName })
|
|
4052
|
+
/* @__PURE__ */ jsx(TagItem, { fieldName: name }),
|
|
4053
|
+
/* @__PURE__ */ jsx(TagItemEdit, { fieldName: name })
|
|
4330
4054
|
] }) })
|
|
4331
4055
|
}
|
|
4332
4056
|
)
|
|
@@ -4337,7 +4061,7 @@ function TagsEditor(props) {
|
|
|
4337
4061
|
{
|
|
4338
4062
|
className: "empty-state text-center py-4 text-gray-400 text-sm border border-dashed border-gray-300 rounded-md",
|
|
4339
4063
|
"x-show": "tags.length === 0",
|
|
4340
|
-
"data-testid": `${
|
|
4064
|
+
"data-testid": `${name}-empty-state`,
|
|
4341
4065
|
children: "\u6682\u65E0\u6807\u7B7E\uFF0C\u5728\u4E0A\u65B9\u8F93\u5165\u6846\u4E2D\u8F93\u5165\u6807\u7B7E\u540E\u6309\u56DE\u8F66\u6DFB\u52A0"
|
|
4342
4066
|
}
|
|
4343
4067
|
)
|
|
@@ -4518,7 +4242,7 @@ function TagItemEdit({ fieldName }) {
|
|
|
4518
4242
|
);
|
|
4519
4243
|
}
|
|
4520
4244
|
function ObjectEditor(props) {
|
|
4521
|
-
const { value,
|
|
4245
|
+
const { value, name, objectSchema } = props;
|
|
4522
4246
|
if (!objectSchema) {
|
|
4523
4247
|
return /* @__PURE__ */ jsx("div", { className: "p-4 border border-yellow-300 rounded-lg bg-yellow-50 text-yellow-800 text-sm", children: "\u8BF7\u63D0\u4F9B objectSchema \u53C2\u6570\u4EE5\u4F7F\u7528\u5BF9\u8C61\u7F16\u8F91\u5668" });
|
|
4524
4248
|
}
|
|
@@ -4538,7 +4262,7 @@ function ObjectEditor(props) {
|
|
|
4538
4262
|
const initialValueJson = JSON.stringify(initialObject);
|
|
4539
4263
|
JSON.stringify(fields.map((f) => f.name));
|
|
4540
4264
|
const generateField = (field) => {
|
|
4541
|
-
const fieldId = `${
|
|
4265
|
+
const fieldId = `${name}-${field.name}`;
|
|
4542
4266
|
const fieldValue = initialObject[field.name];
|
|
4543
4267
|
const fieldValueStr = fieldValue === void 0 || fieldValue === null ? "" : typeof fieldValue === "object" ? JSON.stringify(fieldValue) : String(fieldValue);
|
|
4544
4268
|
const requiredAttr = field.required ? "required" : "";
|
|
@@ -4548,11 +4272,11 @@ function ObjectEditor(props) {
|
|
|
4548
4272
|
<input
|
|
4549
4273
|
type="text"
|
|
4550
4274
|
id="${fieldId}"
|
|
4551
|
-
name="${
|
|
4275
|
+
name="${name}.${field.name}"
|
|
4552
4276
|
value="${fieldValueStr}"
|
|
4553
4277
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
4554
|
-
data-testid="${
|
|
4555
|
-
oninput="updateObjectField('${
|
|
4278
|
+
data-testid="${name}-input-${field.name}"
|
|
4279
|
+
oninput="updateObjectField('${name}', '${field.name}', this.value, 'text', ${field.required})"
|
|
4556
4280
|
${requiredAttr}
|
|
4557
4281
|
/>
|
|
4558
4282
|
`;
|
|
@@ -4560,11 +4284,11 @@ function ObjectEditor(props) {
|
|
|
4560
4284
|
inputElement = html`
|
|
4561
4285
|
<textarea
|
|
4562
4286
|
id="${fieldId}"
|
|
4563
|
-
name="${
|
|
4287
|
+
name="${name}.${field.name}"
|
|
4564
4288
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent resize-y"
|
|
4565
4289
|
rows="4"
|
|
4566
|
-
data-testid="${
|
|
4567
|
-
oninput="updateObjectField('${
|
|
4290
|
+
data-testid="${name}-input-${field.name}"
|
|
4291
|
+
oninput="updateObjectField('${name}', '${field.name}', this.value, 'text', ${field.required})"
|
|
4568
4292
|
${requiredAttr}
|
|
4569
4293
|
>${fieldValueStr}</textarea>
|
|
4570
4294
|
`;
|
|
@@ -4574,12 +4298,12 @@ function ObjectEditor(props) {
|
|
|
4574
4298
|
<input
|
|
4575
4299
|
type="number"
|
|
4576
4300
|
id="${fieldId}"
|
|
4577
|
-
name="${
|
|
4301
|
+
name="${name}.${field.name}"
|
|
4578
4302
|
value="${fieldValueStr}"
|
|
4579
4303
|
step="${step}"
|
|
4580
4304
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
4581
|
-
data-testid="${
|
|
4582
|
-
oninput="updateObjectField('${
|
|
4305
|
+
data-testid="${name}-input-${field.name}"
|
|
4306
|
+
oninput="updateObjectField('${name}', '${field.name}', this.value, 'number', ${field.required})"
|
|
4583
4307
|
${requiredAttr}
|
|
4584
4308
|
/>
|
|
4585
4309
|
`;
|
|
@@ -4588,11 +4312,11 @@ function ObjectEditor(props) {
|
|
|
4588
4312
|
<input
|
|
4589
4313
|
type="date"
|
|
4590
4314
|
id="${fieldId}"
|
|
4591
|
-
name="${
|
|
4315
|
+
name="${name}.${field.name}"
|
|
4592
4316
|
value="${fieldValueStr}"
|
|
4593
4317
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
4594
|
-
data-testid="${
|
|
4595
|
-
oninput="updateObjectField('${
|
|
4318
|
+
data-testid="${name}-input-${field.name}"
|
|
4319
|
+
oninput="updateObjectField('${name}', '${field.name}', this.value, 'date', ${field.required})"
|
|
4596
4320
|
${requiredAttr}
|
|
4597
4321
|
/>
|
|
4598
4322
|
`;
|
|
@@ -4601,11 +4325,11 @@ function ObjectEditor(props) {
|
|
|
4601
4325
|
<input
|
|
4602
4326
|
type="email"
|
|
4603
4327
|
id="${fieldId}"
|
|
4604
|
-
name="${
|
|
4328
|
+
name="${name}.${field.name}"
|
|
4605
4329
|
value="${fieldValueStr}"
|
|
4606
4330
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent"
|
|
4607
|
-
data-testid="${
|
|
4608
|
-
oninput="updateObjectField('${
|
|
4331
|
+
data-testid="${name}-input-${field.name}"
|
|
4332
|
+
oninput="updateObjectField('${name}', '${field.name}', this.value, 'text', ${field.required})"
|
|
4609
4333
|
${requiredAttr}
|
|
4610
4334
|
/>
|
|
4611
4335
|
`;
|
|
@@ -4613,10 +4337,10 @@ function ObjectEditor(props) {
|
|
|
4613
4337
|
inputElement = html`
|
|
4614
4338
|
<select
|
|
4615
4339
|
id="${fieldId}"
|
|
4616
|
-
name="${
|
|
4340
|
+
name="${name}.${field.name}"
|
|
4617
4341
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white"
|
|
4618
|
-
data-testid="${
|
|
4619
|
-
onchange="updateObjectField('${
|
|
4342
|
+
data-testid="${name}-select-${field.name}"
|
|
4343
|
+
onchange="updateObjectField('${name}', '${field.name}', this.value, 'text', ${field.required})"
|
|
4620
4344
|
${requiredAttr}
|
|
4621
4345
|
>
|
|
4622
4346
|
${!field.required ? html`<option value="">请选择</option>` : ""}
|
|
@@ -4639,11 +4363,11 @@ function ObjectEditor(props) {
|
|
|
4639
4363
|
<input
|
|
4640
4364
|
type="checkbox"
|
|
4641
4365
|
id="${fieldId}"
|
|
4642
|
-
name="${
|
|
4366
|
+
name="${name}.${field.name}"
|
|
4643
4367
|
${checked ? "checked" : ""}
|
|
4644
4368
|
class="w-4 h-4 text-blue-600 border-gray-300 rounded focus:ring-blue-500"
|
|
4645
|
-
data-testid="${
|
|
4646
|
-
onchange="updateObjectField('${
|
|
4369
|
+
data-testid="${name}-checkbox-${field.name}"
|
|
4370
|
+
onchange="updateObjectField('${name}', '${field.name}', this.checked, 'checkbox', ${field.required}')"
|
|
4647
4371
|
/>
|
|
4648
4372
|
<label for="${fieldId}" class="ml-2 text-sm text-gray-700">
|
|
4649
4373
|
${field.label}
|
|
@@ -4652,12 +4376,12 @@ function ObjectEditor(props) {
|
|
|
4652
4376
|
`;
|
|
4653
4377
|
}
|
|
4654
4378
|
return html`
|
|
4655
|
-
<div class="space-y-2" data-testid="${
|
|
4379
|
+
<div class="space-y-2" data-testid="${name}-field-${field.name}">
|
|
4656
4380
|
${field.type !== "checkbox" ? html`
|
|
4657
4381
|
<label
|
|
4658
4382
|
for="${fieldId}"
|
|
4659
4383
|
class="block text-sm font-semibold text-gray-700"
|
|
4660
|
-
data-testid="${
|
|
4384
|
+
data-testid="${name}-label-${field.name}"
|
|
4661
4385
|
>
|
|
4662
4386
|
${field.label}
|
|
4663
4387
|
${field.required ? html`<span class="text-red-500 ml-1">*</span>` : ""}
|
|
@@ -4669,15 +4393,15 @@ function ObjectEditor(props) {
|
|
|
4669
4393
|
};
|
|
4670
4394
|
return html`
|
|
4671
4395
|
<div
|
|
4672
|
-
id="object-editor-${
|
|
4396
|
+
id="object-editor-${name}"
|
|
4673
4397
|
class="space-y-4"
|
|
4674
4398
|
data-initial-value="${initialValueJson}"
|
|
4675
4399
|
>
|
|
4676
4400
|
<input
|
|
4677
4401
|
type="hidden"
|
|
4678
|
-
name="${
|
|
4402
|
+
name="${name}"
|
|
4679
4403
|
value="${initialValueJson}"
|
|
4680
|
-
data-testid="hidden-${
|
|
4404
|
+
data-testid="hidden-${name}"
|
|
4681
4405
|
/>
|
|
4682
4406
|
<div class="space-y-4">
|
|
4683
4407
|
${fields.map((field) => generateField(field))}
|
|
@@ -4739,14 +4463,13 @@ function BaseLayout(props) {
|
|
|
4739
4463
|
<meta name="description" content="${props.description || ""}" />
|
|
4740
4464
|
${globalScripts(props.prefix)} ${globalStyles()}
|
|
4741
4465
|
</head>
|
|
4742
|
-
<body
|
|
4466
|
+
<body className="bg-gray-50" hx-indicator="#loading-bar">
|
|
4743
4467
|
${LoadingBar()} ${props.children}
|
|
4744
4468
|
<div
|
|
4745
|
-
id="
|
|
4746
|
-
|
|
4469
|
+
id="notification-container"
|
|
4470
|
+
style="position: fixed; top: 1rem; right: 1rem; z-index: 200; display: flex; flex-direction: column; gap: 0.5rem; pointer-events: none; width: 100%; max-width: 28rem; padding-left: 1rem; padding-right: 1rem;"
|
|
4747
4471
|
></div>
|
|
4748
4472
|
<div id="dialog-container"></div>
|
|
4749
|
-
${sortableScript()}
|
|
4750
4473
|
</body>
|
|
4751
4474
|
</html>
|
|
4752
4475
|
`;
|
|
@@ -4998,7 +4721,7 @@ async function handlePermissionDenied(ctx, result, options) {
|
|
|
4998
4721
|
if (isHtmxRequest) {
|
|
4999
4722
|
const headers = {
|
|
5000
4723
|
"HX-Retarget": "#dialog-container",
|
|
5001
|
-
"HX-Reswap": "
|
|
4724
|
+
"HX-Reswap": "beforeend",
|
|
5002
4725
|
"X-Permission-Denied": "true"
|
|
5003
4726
|
};
|
|
5004
4727
|
return ctx.html(
|
|
@@ -5043,22 +4766,15 @@ function buildNotificationFragments(notifications) {
|
|
|
5043
4766
|
if (notifications.length === 0) {
|
|
5044
4767
|
return null;
|
|
5045
4768
|
}
|
|
5046
|
-
return notifications.map((notification, index) => /* @__PURE__ */ jsx(
|
|
5047
|
-
|
|
4769
|
+
return notifications.map((notification, index) => /* @__PURE__ */ jsx("div", { id: "notification-container", "hx-swap-oob": "beforeend", children: /* @__PURE__ */ jsx(
|
|
4770
|
+
ErrorAlert,
|
|
5048
4771
|
{
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
ErrorAlert,
|
|
5053
|
-
{
|
|
5054
|
-
type: notification.type,
|
|
5055
|
-
title: notification.title,
|
|
5056
|
-
message: notification.message
|
|
5057
|
-
}
|
|
5058
|
-
)
|
|
4772
|
+
type: notification.type,
|
|
4773
|
+
title: notification.title,
|
|
4774
|
+
message: notification.message
|
|
5059
4775
|
},
|
|
5060
4776
|
`notification-${index}`
|
|
5061
|
-
));
|
|
4777
|
+
) }));
|
|
5062
4778
|
}
|
|
5063
4779
|
function isEmptyContent(result) {
|
|
5064
4780
|
if (result === null || result === void 0) return true;
|
|
@@ -5152,7 +4868,6 @@ async function renderResult(ctx, context, result, renderOptions) {
|
|
|
5152
4868
|
if (context.isDialog) {
|
|
5153
4869
|
return ctx.html(
|
|
5154
4870
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5155
|
-
/* @__PURE__ */ jsx("div", { id: "dialog-container", "hx-swap-oob": "innerHTML" }),
|
|
5156
4871
|
notificationFragments,
|
|
5157
4872
|
/* @__PURE__ */ jsx("title", { children: metadata.title })
|
|
5158
4873
|
] }),
|
|
@@ -5208,7 +4923,7 @@ async function renderResult(ctx, context, result, renderOptions) {
|
|
|
5208
4923
|
);
|
|
5209
4924
|
}
|
|
5210
4925
|
const target = context.isDialog ? "#dialog-container" : "#main-content";
|
|
5211
|
-
const swap = context.isDialog ? "
|
|
4926
|
+
const swap = context.isDialog ? "beforeend" : "outerHTML";
|
|
5212
4927
|
const headers = {
|
|
5213
4928
|
"HX-Retarget": target,
|
|
5214
4929
|
"HX-Reswap": swap
|
|
@@ -5271,7 +4986,6 @@ async function renderResult(ctx, context, result, renderOptions) {
|
|
|
5271
4986
|
useAdminLayout,
|
|
5272
4987
|
currentPath,
|
|
5273
4988
|
userInfo: user,
|
|
5274
|
-
componentRegistry: renderOptions.componentRegistry,
|
|
5275
4989
|
breadcrumbs,
|
|
5276
4990
|
actions,
|
|
5277
4991
|
children: result
|
|
@@ -5307,7 +5021,6 @@ async function renderResult(ctx, context, result, renderOptions) {
|
|
|
5307
5021
|
prefix: options.prefix,
|
|
5308
5022
|
title: dynamicMetadata.title,
|
|
5309
5023
|
description: dynamicMetadata.description,
|
|
5310
|
-
componentRegistry: renderOptions.componentRegistry,
|
|
5311
5024
|
children: /* @__PURE__ */ jsx(
|
|
5312
5025
|
AdminLayout,
|
|
5313
5026
|
{
|
|
@@ -5319,7 +5032,6 @@ async function renderResult(ctx, context, result, renderOptions) {
|
|
|
5319
5032
|
userInfo: user,
|
|
5320
5033
|
breadcrumbs,
|
|
5321
5034
|
actions,
|
|
5322
|
-
componentRegistry: renderOptions.componentRegistry,
|
|
5323
5035
|
children: result
|
|
5324
5036
|
}
|
|
5325
5037
|
)
|
|
@@ -5334,7 +5046,6 @@ async function renderResult(ctx, context, result, renderOptions) {
|
|
|
5334
5046
|
prefix: options.prefix,
|
|
5335
5047
|
title: dynamicMetadata.title,
|
|
5336
5048
|
description: dynamicMetadata.description,
|
|
5337
|
-
componentRegistry: renderOptions.componentRegistry,
|
|
5338
5049
|
children: /* @__PURE__ */ jsx(NoLayout, { children: result })
|
|
5339
5050
|
}
|
|
5340
5051
|
)
|
|
@@ -5423,14 +5134,15 @@ async function handleRequest(ctx, page, feature, handlerOptions) {
|
|
|
5423
5134
|
if (isHtmxRequest) {
|
|
5424
5135
|
return ctx.html(
|
|
5425
5136
|
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5426
|
-
/* @__PURE__ */ jsx(
|
|
5137
|
+
/* @__PURE__ */ jsx(
|
|
5427
5138
|
ErrorAlert,
|
|
5428
5139
|
{
|
|
5140
|
+
"hx-swap-oob": "beforeend:#notification-container",
|
|
5429
5141
|
type: "error",
|
|
5430
5142
|
title: "\u8BF7\u6C42\u5931\u8D25",
|
|
5431
5143
|
message: "Feature has no handler or render method"
|
|
5432
5144
|
}
|
|
5433
|
-
)
|
|
5145
|
+
),
|
|
5434
5146
|
/* @__PURE__ */ jsx("title", { children: "\u9519\u8BEF" })
|
|
5435
5147
|
] }),
|
|
5436
5148
|
500,
|
|
@@ -5447,10 +5159,15 @@ async function handleRequest(ctx, page, feature, handlerOptions) {
|
|
|
5447
5159
|
if (isHtmxRequest) {
|
|
5448
5160
|
const errorMessage = error instanceof Error ? error.message : "Internal server error";
|
|
5449
5161
|
return ctx.html(
|
|
5450
|
-
/* @__PURE__ */
|
|
5451
|
-
|
|
5452
|
-
|
|
5453
|
-
|
|
5162
|
+
/* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
|
|
5163
|
+
ErrorAlert,
|
|
5164
|
+
{
|
|
5165
|
+
"hx-swap-oob": "beforeend:#notification-container",
|
|
5166
|
+
type: "error",
|
|
5167
|
+
title: "\u8BF7\u6C42\u5931\u8D25",
|
|
5168
|
+
message: errorMessage
|
|
5169
|
+
}
|
|
5170
|
+
) }),
|
|
5454
5171
|
500,
|
|
5455
5172
|
{
|
|
5456
5173
|
"HX-Reswap": "none"
|
|
@@ -5553,7 +5270,6 @@ var HtmxAdminPlugin = class {
|
|
|
5553
5270
|
options;
|
|
5554
5271
|
serviceName = "";
|
|
5555
5272
|
pages = /* @__PURE__ */ new Map();
|
|
5556
|
-
componentHandler;
|
|
5557
5273
|
constructor(options) {
|
|
5558
5274
|
this.options = {
|
|
5559
5275
|
title: options?.title || "\u7BA1\u7406\u540E\u53F0",
|
|
@@ -5562,8 +5278,7 @@ var HtmxAdminPlugin = class {
|
|
|
5562
5278
|
homePath: options?.homePath || "",
|
|
5563
5279
|
navigation: options?.navigation ?? [],
|
|
5564
5280
|
authProvider: options?.authProvider,
|
|
5565
|
-
pages: options?.pages ?? []
|
|
5566
|
-
components: options?.components ?? []
|
|
5281
|
+
pages: options?.pages ?? []
|
|
5567
5282
|
};
|
|
5568
5283
|
this.initPages();
|
|
5569
5284
|
}
|
|
@@ -5595,11 +5310,6 @@ var HtmxAdminPlugin = class {
|
|
|
5595
5310
|
logger.info(
|
|
5596
5311
|
`HtmxAdminPlugin initialized${this.serviceName ? ` (service: ${this.serviceName})` : ""}`
|
|
5597
5312
|
);
|
|
5598
|
-
this.componentHandler = new HtmxComponentHandler(
|
|
5599
|
-
this.hono,
|
|
5600
|
-
this.options.prefix,
|
|
5601
|
-
this.options.components
|
|
5602
|
-
);
|
|
5603
5313
|
initializeCdnCache().catch((error) => {
|
|
5604
5314
|
logger.error("[HtmxAdminPlugin] CDN \u7F13\u5B58\u521D\u59CB\u5316\u5931\u8D25", error);
|
|
5605
5315
|
});
|
|
@@ -5621,4 +5331,4 @@ var HtmxAdminPlugin = class {
|
|
|
5621
5331
|
}
|
|
5622
5332
|
};
|
|
5623
5333
|
|
|
5624
|
-
export { BaseFeature,
|
|
5334
|
+
export { BaseFeature, CustomFeature, DefaultCreateFeature, DefaultDeleteFeature, DefaultDetailFeature, DefaultEditFeature, DefaultListFeature, Dialog, ErrorAlert, HtmxAdminPlugin, LoadingBar, ObjectEditor, PageModel, SortableList, StringArrayEditor, TagsEditor, checkUserPermission, getUserInfo, modelNameToPath, parseListParams };
|