release: add ErrorPopup component and export

This commit is contained in:
ci
2026-04-23 12:26:40 +00:00
commit b597ace25c
29 changed files with 620 additions and 0 deletions

2
dist/App.vue.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
export default _default;

BIN
dist/assets/limelight_logo.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
dist/assets/preview.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

11
dist/components/ErrorPopup.vue.d.ts vendored Normal file
View File

@@ -0,0 +1,11 @@
type __VLS_Props = {
message: string | null;
show: boolean;
title?: string;
};
declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
close: () => any;
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
onClose?: (() => any) | undefined;
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
export default _default;

View File

@@ -0,0 +1,21 @@
type __VLS_Props = {
variant?: 'primary' | 'outline' | 'ghost' | 'danger';
disabled?: boolean;
};
declare function __VLS_template(): {
attrs: Partial<{}>;
slots: {
default?(_: {}): any;
};
refs: {};
rootEl: HTMLButtonElement;
};
type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
declare const __VLS_component: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLButtonElement>;
declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
export default _default;
type __VLS_WithTemplateSlots<T, S> = T & {
new (): {
$slots: S;
};
};

2
dist/env.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
/// <reference path="./utils/filemaker.d.ts" />
/// <reference types="vite/client" />

1
dist/index.css vendored Normal file
View File

@@ -0,0 +1 @@
/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */.btn[data-v-e0bc8f43]{height:calc(var(--spacing,.25rem) * 10);font-size:var(--text-sm,.875rem);line-height:var(--tw-leading,var(--text-sm--line-height,calc(1.25 / .875)));letter-spacing:.06em;text-transform:uppercase;cursor:pointer;clip-path:polygon(8px 0%,100% 0%,calc(100% - 8px) 100%,0% 100%);-webkit-user-select:none;user-select:none;border:none;padding:0 1.5rem;font-family:Barlow,sans-serif;font-weight:700;transition:background .15s,color .15s,border-color .15s,transform .1s}.btn--primary[data-v-e0bc8f43]{background:var(--color-primary);color:var(--color-black)}.btn--primary[data-v-e0bc8f43]:hover{background:var(--color-primary-light);transform:scaleX(1.03)}.btn--outline[data-v-e0bc8f43]{color:var(--color-primary);border:1.5px solid var(--color-primary);background:0 0}.btn--outline[data-v-e0bc8f43]:hover{background:var(--color-primary-dark);transform:scaleX(1.03)}.btn--ghost[data-v-e0bc8f43]{color:var(--color-secondary-light);border:1px solid var(--color-secondary-light);background:0 0}.btn--ghost[data-v-e0bc8f43]:hover{color:var(--color-primary);border-color:var(--color-primary);transform:scaleX(1.03)}.btn--danger[data-v-e0bc8f43]{background:var(--color-red);color:#fff}.btn--danger[data-v-e0bc8f43]:hover{filter:brightness(1.2);transform:scaleX(1.03)}.btn[data-v-e0bc8f43]:active{transform:scale(.97)}.btn--disabled[data-v-e0bc8f43]{opacity:.5;cursor:not-allowed}.btn--disabled[data-v-e0bc8f43]:hover{transform:scale(1)!important}

3
dist/index.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
export { default as LimelightButton } from './components/LimelightButton.vue';
export { default as ErrorPopup } from './components/ErrorPopup.vue';
export * from './utils/webviewer';

114
dist/index.js vendored Normal file
View File

@@ -0,0 +1,114 @@
import { defineComponent as d, openBlock as c, createElementBlock as f, normalizeClass as m, renderSlot as p, createElementVNode as r, toDisplayString as a, createVNode as b, withCtx as k, createTextVNode as v, createCommentVNode as g } from "vue";
const h = ["disabled"], w = /* @__PURE__ */ d({
__name: "LimelightButton",
props: {
variant: {},
disabled: { type: Boolean }
},
setup(e) {
return (i, n) => (c(), f("button", {
type: "button",
class: m(["btn", [e.variant && `btn--${e.variant}`, { "btn--disabled": e.disabled }]]),
disabled: e.disabled
}, [
p(i.$slots, "default", {}, void 0, !0)
], 10, h));
}
}), x = (e, i) => {
const n = e.__vccOpts || e;
for (const [t, s] of i)
n[t] = s;
return n;
}, y = /* @__PURE__ */ x(w, [["__scopeId", "data-v-e0bc8f43"]]), M = {
key: 0,
class: "fixed inset-0 z-50 flex items-center justify-center"
}, F = { class: "relative bg-secondary border border-red-500/40 rounded-2xl p-5 max-w-sm w-[90%] shadow-xl" }, _ = { class: "flex items-center gap-3 mb-3" }, C = { class: "text-white font-semibold" }, S = { class: "text-white/80 text-sm whitespace-pre-line" }, P = /* @__PURE__ */ d({
__name: "ErrorPopup",
props: {
message: {},
show: { type: Boolean },
title: {}
},
emits: ["close"],
setup(e, { emit: i }) {
return (n, t) => e.show && e.message ? (c(), f("div", M, [
r("div", {
class: "absolute inset-0 bg-black/60",
onClick: t[0] || (t[0] = (s) => n.$emit("close"))
}),
r("div", F, [
r("div", _, [
t[2] || (t[2] = r("div", { class: "w-10 h-10 rounded-full bg-red/15 flex items-center justify-center" }, [
r("svg", {
class: "w-5 h-5 text-red",
fill: "none",
stroke: "currentColor",
viewBox: "0 0 24 24"
}, [
r("path", {
"stroke-linecap": "round",
"stroke-linejoin": "round",
"stroke-width": "2",
d: "M12 9v2m0 4h.01M10.29 3.86l-8.2 14A1.5 1.5 0 003.3 20h16.4a1.5 1.5 0 001.21-2.14l-8.2-14a1.5 1.5 0 00-2.42 0z"
})
])
], -1)),
r("p", C, a(e.title ?? "Verbindungsfehler"), 1)
]),
r("p", S, a(e.message), 1),
b(y, {
variant: "danger",
class: "mt-4 w-full",
onClick: t[1] || (t[1] = (s) => n.$emit("close"))
}, {
default: k(() => [...t[3] || (t[3] = [
v(" OK ", -1)
])]),
_: 1
})
])
])) : g("", !0);
}
});
function O(e, i) {
return typeof FileMaker > "u" ? !1 : (FileMaker.PerformScript(e, i), !0);
}
function V(e, i, n) {
return typeof FileMaker > "u" ? !1 : (FileMaker.PerformScriptWithOption(e, i, n), !0);
}
const o = /* @__PURE__ */ new Map();
let $ = 1;
function T(e, i = "", n) {
return new Promise((t, s) => {
if (typeof FileMaker > "u") {
s({ callbackId: -1, message: "FileMaker runtime not available" });
return;
}
const l = $++;
o.set(l, { resolve: t, reject: s });
const u = { callbackId: l, parameter: i };
FileMaker.PerformScript(e, JSON.stringify(u)), n !== void 0 && setTimeout(() => {
o.has(l) && (o.delete(l), s({ callbackId: l, message: `Timed out after ${n}ms` }));
}, n);
});
}
function z(e, i = "", n) {
const t = parseInt(e), s = o.get(t);
s && (o.delete(t), n ? s.reject({ callbackId: t, message: i }) : s.resolve(i));
}
function B(e, i, n = 10, t = 0) {
I() ? e() : t >= n ? i == null || i() : setTimeout(() => B(e, i, n, t + 1), 100);
}
function I() {
return typeof FileMaker < "u";
}
export {
P as ErrorPopup,
y as LimelightButton,
T as callFileMakerScript,
I as isFileMakerEnvironment,
O as performScript,
V as performScriptWithOption,
z as resolveFileMakerCallback,
B as waitForFileMaker
};

1
dist/index.umd.cjs vendored Normal file
View File

@@ -0,0 +1 @@
(function(o,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(o=typeof globalThis<"u"?globalThis:o||self,e(o.LimelightCommonWebComponents={},o.Vue))})(this,(function(o,e){"use strict";const m=["disabled"],d=((t,i)=>{const l=t.__vccOpts||t;for(const[n,r]of i)l[n]=r;return l})(e.defineComponent({__name:"LimelightButton",props:{variant:{},disabled:{type:Boolean}},setup(t){return(i,l)=>(e.openBlock(),e.createElementBlock("button",{type:"button",class:e.normalizeClass(["btn",[t.variant&&`btn--${t.variant}`,{"btn--disabled":t.disabled}]]),disabled:t.disabled},[e.renderSlot(i.$slots,"default",{},void 0,!0)],10,m))}}),[["__scopeId","data-v-e0bc8f43"]]),p={key:0,class:"fixed inset-0 z-50 flex items-center justify-center"},u={class:"relative bg-secondary border border-red-500/40 rounded-2xl p-5 max-w-sm w-[90%] shadow-xl"},k={class:"flex items-center gap-3 mb-3"},b={class:"text-white font-semibold"},g={class:"text-white/80 text-sm whitespace-pre-line"},h=e.defineComponent({__name:"ErrorPopup",props:{message:{},show:{type:Boolean},title:{}},emits:["close"],setup(t,{emit:i}){return(l,n)=>t.show&&t.message?(e.openBlock(),e.createElementBlock("div",p,[e.createElementVNode("div",{class:"absolute inset-0 bg-black/60",onClick:n[0]||(n[0]=r=>l.$emit("close"))}),e.createElementVNode("div",u,[e.createElementVNode("div",k,[n[2]||(n[2]=e.createElementVNode("div",{class:"w-10 h-10 rounded-full bg-red/15 flex items-center justify-center"},[e.createElementVNode("svg",{class:"w-5 h-5 text-red",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24"},[e.createElementVNode("path",{"stroke-linecap":"round","stroke-linejoin":"round","stroke-width":"2",d:"M12 9v2m0 4h.01M10.29 3.86l-8.2 14A1.5 1.5 0 003.3 20h16.4a1.5 1.5 0 001.21-2.14l-8.2-14a1.5 1.5 0 00-2.42 0z"})])],-1)),e.createElementVNode("p",b,e.toDisplayString(t.title??"Verbindungsfehler"),1)]),e.createElementVNode("p",g,e.toDisplayString(t.message),1),e.createVNode(d,{variant:"danger",class:"mt-4 w-full",onClick:n[1]||(n[1]=r=>l.$emit("close"))},{default:e.withCtx(()=>[...n[3]||(n[3]=[e.createTextVNode(" OK ",-1)])]),_:1})])])):e.createCommentVNode("",!0)}});function y(t,i){return typeof FileMaker>"u"?!1:(FileMaker.PerformScript(t,i),!0)}function M(t,i,l){return typeof FileMaker>"u"?!1:(FileMaker.PerformScriptWithOption(t,i,l),!0)}const s=new Map;let w=1;function F(t,i="",l){return new Promise((n,r)=>{if(typeof FileMaker>"u"){r({callbackId:-1,message:"FileMaker runtime not available"});return}const a=w++;s.set(a,{resolve:n,reject:r});const S={callbackId:a,parameter:i};FileMaker.PerformScript(t,JSON.stringify(S)),l!==void 0&&setTimeout(()=>{s.has(a)&&(s.delete(a),r({callbackId:a,message:`Timed out after ${l}ms`}))},l)})}function _(t,i="",l){const n=parseInt(t),r=s.get(n);r&&(s.delete(n),l?r.reject({callbackId:n,message:i}):r.resolve(i))}function c(t,i,l=10,n=0){f()?t():n>=l?i==null||i():setTimeout(()=>c(t,i,l,n+1),100)}function f(){return typeof FileMaker<"u"}o.ErrorPopup=h,o.LimelightButton=d,o.callFileMakerScript=F,o.isFileMakerEnvironment=f,o.performScript=y,o.performScriptWithOption=M,o.resolveFileMakerCallback=_,o.waitForFileMaker=c,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})}));

0
dist/main.d.ts vendored Normal file
View File

106
dist/utils/webviewer.d.ts vendored Normal file
View File

@@ -0,0 +1,106 @@
/** The FileMaker object injected by the runtime into web viewers. */
export interface FileMakerAPI {
PerformScript(script: string, parameter?: string): void;
PerformScriptWithOption(script: string, parameter?: string, option?: ScriptOption): void;
}
declare global {
/** Available only inside a FileMaker web viewer. Always guard with `typeof FileMaker !== 'undefined'`. */
const FileMaker: FileMakerAPI | undefined;
interface Window {
resolveFileMakerCallback: typeof resolveFileMakerCallback;
}
}
/**
* Controls how a currently running FileMaker script is handled when a new
* script is started via `FileMaker.PerformScriptWithOption`.
*
* | Value | Behaviour |
* |-------|------------------------------------------------------------------|
* | "0" | Pause the current script, run the new one, then resume |
* | "1" | Abort the current script and run the new one |
* | "2" | Exit the current script and run the new one |
* | "3" | Run the new script concurrently (default async behaviour) |
* | "4" | Trigger script (same as 3 but fires as a script trigger would) |
* | "5" | Suspend the current script; resume it after the new one exits |
*/
export type ScriptOption = '0' | '1' | '2' | '3' | '4' | '5';
/**
* Type-safe wrapper that calls `FileMaker.PerformScript` only when the
* runtime is available (i.e. the page is running inside a web viewer).
*
* @returns `true` if the script was dispatched, `false` otherwise.
*
* @example
* performScript("Delete Record", String(recordId));
*/
export declare function performScript(script: string, parameter?: string): boolean;
/**
* Type-safe wrapper around `FileMaker.PerformScriptWithOption`.
*
* @returns `true` if the script was dispatched, `false` otherwise.
*/
export declare function performScriptWithOption(script: string, parameter?: string, option?: ScriptOption): boolean;
/** Error thrown when a FileMaker script signals failure. */
export interface FileMakerScriptError {
/** The callback ID that was active when the error occurred. */
callbackId: number;
/** Optional error message forwarded from the FileMaker script. */
message?: string;
}
/**
* Invokes a FileMaker script and returns a `Promise` that resolves when
* FileMaker calls back into JavaScript via {@link resolveFileMakerCallback}.
*
* **FileMaker side:** the script must eventually call
* *Perform JavaScript in Web Viewer* targeting `resolveFileMakerCallback`
* and pass back the same `callbackId` together with the result data.
*
* ```
* // FileMaker script (pseudocode)
* Set Variable [$payload ; Value: Get(ScriptParameter)]
* Set Variable [$id ; Value: JSONGetElement($payload; "callbackId")]
* Set Variable [$result ; Value: \* … your work … *\]
* Perform JavaScript in Web Viewer [
* Object Name: "MyWebViewer"
* Function: "resolveFileMakerCallback"
* Parameters: $id, $result
* ]
* ```
*
* @param script - FileMaker script name.
* @param parameter - Arbitrary string payload for the script.
* @param timeout - Optional ms before the promise is rejected automatically
* (defaults to no timeout).
*
* @example
* const json = await callFileMakerScript("Get Customer", String(customerId));
* const customer = JSON.parse(json);
*/
export declare function callFileMakerScript(script: string, parameter?: string, timeout?: number): Promise<string>;
/**
* Must be exposed as a global function so that FileMaker's
* *Perform JavaScript in Web Viewer* script step can invoke it.
*
* Call this from your FileMaker script to resolve a promise created by
* {@link callFileMakerScript}.
*
* @param callbackId - The numeric ID forwarded from the script parameter.
* @param result - The string result to hand back to JavaScript.
* @param isError - When truthy, the promise is rejected instead.
*
* @example
* // Expose globally so FileMaker can reach it
* (window as any).resolveFileMakerCallback = resolveFileMakerCallback;
*/
export declare function resolveFileMakerCallback(callbackId: string, result?: string, isError?: boolean): void;
export declare function waitForFileMaker(callback: () => void, onError?: () => void, maxAttempts?: number, // 1 Sekunde bei 100ms Intervall
attempt?: number): void;
/**
* Returns `true` when the page is running inside a FileMaker web viewer.
*
* @example
* if (isFileMakerEnvironment()) {
* FileMaker!.PerformScript("On Load");
* }
*/
export declare function isFileMakerEnvironment(): boolean;