mnfst 0.5.229 → 0.5.231
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/lib/manifest.appwrite.data.js +1 -1
- package/lib/manifest.css +20 -2
- package/lib/manifest.data.js +1 -1
- package/lib/manifest.edit.css +7 -1
- package/lib/manifest.edit.js +137 -16
- package/lib/manifest.integrity.json +7 -7
- package/lib/manifest.min.css +1 -1
- package/lib/manifest.sw.js +1 -1
- package/lib/manifest.text.edit.css +13 -1
- package/lib/manifest.text.edit.js +251 -54
- package/lib/manifest.toasts.js +64 -28
- package/lib/manifest.tooltips.js +56 -40
- package/package.json +1 -1
package/lib/manifest.toasts.js
CHANGED
|
@@ -3,6 +3,57 @@
|
|
|
3
3
|
(function () {
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
// mnfst:expressions:start — synced by the build from scripts/snippets/manifest.expressions.js; edit there
|
|
7
|
+
// Directive values: any JS expression evaluates; text that isn't one stays verbatim.
|
|
8
|
+
|
|
9
|
+
const EXPR_BARE_IDENTIFIER = /^[\p{ID_Start}$_][\p{ID_Continue}$]*$/u;
|
|
10
|
+
// No name, string or template: numbers, dates, ratios ("24/7", "2026-10-13") stay text
|
|
11
|
+
const EXPR_HAS_TOKEN = /[\p{L}$_'"`]/u;
|
|
12
|
+
|
|
13
|
+
function exprParses(src) {
|
|
14
|
+
try { new Function('return (' + src + '\n)'); return true; } catch { return false; }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function exprInScope(el, name) {
|
|
18
|
+
try { return name in Alpine.$data(el); } catch { return false; }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Errors come back as values: unresolved names read as plain text
|
|
22
|
+
// ("Re-run", "Hello, world"); other errors warn against the authored expression
|
|
23
|
+
const exprGuarded = (src) =>
|
|
24
|
+
'(() => { try { return (' + src + '\n) } catch (e) { return { __exprError: e } } })()';
|
|
25
|
+
|
|
26
|
+
function exprUnwrap(v, el, src) {
|
|
27
|
+
const err = v && typeof v === 'object' && v.__exprError;
|
|
28
|
+
if (!(err instanceof Error)) return v;
|
|
29
|
+
if (err instanceof ReferenceError) return undefined;
|
|
30
|
+
console.warn(`Alpine Expression Error: ${err.message}\n\nExpression: "${src}"\n\n`, el);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// null for static text; else (cb) => cb(value, asText), asText meaning the
|
|
35
|
+
// authored text shows instead (unresolved name, undefined, NaN)
|
|
36
|
+
function expressionResolver(el, src, evaluateLater) {
|
|
37
|
+
if (src.startsWith('$x.')) {
|
|
38
|
+
const getValue = evaluateLater(src);
|
|
39
|
+
return (cb) => getValue(v => cb(v, false));
|
|
40
|
+
}
|
|
41
|
+
if (!EXPR_HAS_TOKEN.test(src) || !exprParses(src)) return null;
|
|
42
|
+
let getValue;
|
|
43
|
+
if (EXPR_BARE_IDENTIFIER.test(src)) {
|
|
44
|
+
// Single word: a scope value or magic, else text (never a global like Image or close)
|
|
45
|
+
const getWord = evaluateLater(exprGuarded(src));
|
|
46
|
+
getValue = (cb) => (src.startsWith('$') || exprInScope(el, src)) ? getWord(cb) : cb(undefined);
|
|
47
|
+
} else {
|
|
48
|
+
getValue = evaluateLater(exprGuarded(src));
|
|
49
|
+
}
|
|
50
|
+
return (cb) => getValue(raw => {
|
|
51
|
+
const v = exprUnwrap(raw, el, src);
|
|
52
|
+
cb(v, v === undefined || Number.isNaN(v));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// mnfst:expressions:end
|
|
56
|
+
|
|
6
57
|
const TOAST_DURATION = 3000; // Default duration in ms
|
|
7
58
|
|
|
8
59
|
function initializeToastPlugin() {
|
|
@@ -127,7 +178,7 @@ function initializeToastPlugin() {
|
|
|
127
178
|
};
|
|
128
179
|
|
|
129
180
|
// Add toast directive
|
|
130
|
-
Alpine.directive('toast', (el, { modifiers, expression }, {
|
|
181
|
+
Alpine.directive('toast', (el, { modifiers, expression }, { evaluateLater }) => {
|
|
131
182
|
// Parse options from modifiers
|
|
132
183
|
const options = {
|
|
133
184
|
type: modifiers.includes('brand') ? 'brand' :
|
|
@@ -146,32 +197,11 @@ function initializeToastPlugin() {
|
|
|
146
197
|
options.duration = modifiers.includes('long') ? TOAST_DURATION * 2 : TOAST_DURATION;
|
|
147
198
|
}
|
|
148
199
|
|
|
149
|
-
//
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
// Use evaluate for $x expressions to access collections
|
|
155
|
-
message = evaluate(expression);
|
|
156
|
-
} else if (expression.includes('<') && expression.includes('>')) {
|
|
157
|
-
// Treat as literal HTML string - preserve spaces and formatting
|
|
158
|
-
// Escape quotes to prevent syntax errors, but keep the HTML intact
|
|
159
|
-
const escapedExpression = expression.replace(/'/g, "\\'");
|
|
160
|
-
message = evaluate(`'${escapedExpression}'`);
|
|
161
|
-
} else if (expression.includes('+') || expression.includes('`') || expression.includes('${')) {
|
|
162
|
-
// Try to evaluate as a dynamic expression
|
|
163
|
-
message = evaluate(expression);
|
|
164
|
-
} else {
|
|
165
|
-
// Use as static string
|
|
166
|
-
message = expression;
|
|
167
|
-
}
|
|
168
|
-
} catch (e) {
|
|
169
|
-
// If evaluation fails, use the expression as a static string
|
|
170
|
-
message = expression;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Store the toast options on the element
|
|
174
|
-
el._toastOptions = { message, options };
|
|
200
|
+
// Static text (author HTML included) shows as written; expressions
|
|
201
|
+
// evaluate on every click. Empty results (null, false, '') show nothing.
|
|
202
|
+
const src = expression.trim();
|
|
203
|
+
const evaluate = expressionResolver(el, src, evaluateLater);
|
|
204
|
+
if (evaluate && src.startsWith('$x.')) evaluate(() => {}); // starts the source loading
|
|
175
205
|
|
|
176
206
|
// Add click handler that works with other handlers
|
|
177
207
|
const originalClick = el.onclick;
|
|
@@ -181,7 +211,13 @@ function initializeToastPlugin() {
|
|
|
181
211
|
originalClick.call(el, e);
|
|
182
212
|
}
|
|
183
213
|
// Show toast after original handler
|
|
184
|
-
showToast(
|
|
214
|
+
if (!evaluate) { showToast(expression, options); return; }
|
|
215
|
+
// After the element's other click listeners, so state they change shows
|
|
216
|
+
setTimeout(() => evaluate((v, asText) => {
|
|
217
|
+
if (asText) { showToast(expression, options); return; }
|
|
218
|
+
const message = v == null || v === false ? '' : String(v);
|
|
219
|
+
if (message !== '') showToast(message, options);
|
|
220
|
+
}));
|
|
185
221
|
};
|
|
186
222
|
});
|
|
187
223
|
|
package/lib/manifest.tooltips.js
CHANGED
|
@@ -3,6 +3,57 @@
|
|
|
3
3
|
(function () {
|
|
4
4
|
|
|
5
5
|
|
|
6
|
+
// mnfst:expressions:start — synced by the build from scripts/snippets/manifest.expressions.js; edit there
|
|
7
|
+
// Directive values: any JS expression evaluates; text that isn't one stays verbatim.
|
|
8
|
+
|
|
9
|
+
const EXPR_BARE_IDENTIFIER = /^[\p{ID_Start}$_][\p{ID_Continue}$]*$/u;
|
|
10
|
+
// No name, string or template: numbers, dates, ratios ("24/7", "2026-10-13") stay text
|
|
11
|
+
const EXPR_HAS_TOKEN = /[\p{L}$_'"`]/u;
|
|
12
|
+
|
|
13
|
+
function exprParses(src) {
|
|
14
|
+
try { new Function('return (' + src + '\n)'); return true; } catch { return false; }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function exprInScope(el, name) {
|
|
18
|
+
try { return name in Alpine.$data(el); } catch { return false; }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Errors come back as values: unresolved names read as plain text
|
|
22
|
+
// ("Re-run", "Hello, world"); other errors warn against the authored expression
|
|
23
|
+
const exprGuarded = (src) =>
|
|
24
|
+
'(() => { try { return (' + src + '\n) } catch (e) { return { __exprError: e } } })()';
|
|
25
|
+
|
|
26
|
+
function exprUnwrap(v, el, src) {
|
|
27
|
+
const err = v && typeof v === 'object' && v.__exprError;
|
|
28
|
+
if (!(err instanceof Error)) return v;
|
|
29
|
+
if (err instanceof ReferenceError) return undefined;
|
|
30
|
+
console.warn(`Alpine Expression Error: ${err.message}\n\nExpression: "${src}"\n\n`, el);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// null for static text; else (cb) => cb(value, asText), asText meaning the
|
|
35
|
+
// authored text shows instead (unresolved name, undefined, NaN)
|
|
36
|
+
function expressionResolver(el, src, evaluateLater) {
|
|
37
|
+
if (src.startsWith('$x.')) {
|
|
38
|
+
const getValue = evaluateLater(src);
|
|
39
|
+
return (cb) => getValue(v => cb(v, false));
|
|
40
|
+
}
|
|
41
|
+
if (!EXPR_HAS_TOKEN.test(src) || !exprParses(src)) return null;
|
|
42
|
+
let getValue;
|
|
43
|
+
if (EXPR_BARE_IDENTIFIER.test(src)) {
|
|
44
|
+
// Single word: a scope value or magic, else text (never a global like Image or close)
|
|
45
|
+
const getWord = evaluateLater(exprGuarded(src));
|
|
46
|
+
getValue = (cb) => (src.startsWith('$') || exprInScope(el, src)) ? getWord(cb) : cb(undefined);
|
|
47
|
+
} else {
|
|
48
|
+
getValue = evaluateLater(exprGuarded(src));
|
|
49
|
+
}
|
|
50
|
+
return (cb) => getValue(raw => {
|
|
51
|
+
const v = exprUnwrap(raw, el, src);
|
|
52
|
+
cb(v, v === undefined || Number.isNaN(v));
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
// mnfst:expressions:end
|
|
56
|
+
|
|
6
57
|
// Hover delay from CSS var (with time-unit parsing). Defaults to 500ms.
|
|
7
58
|
function getTooltipHoverDelay(element) {
|
|
8
59
|
let computedStyle = getComputedStyle(element);
|
|
@@ -157,33 +208,8 @@ function initializeTooltipPlugin() {
|
|
|
157
208
|
if (wasOpen) markTooltipHidden();
|
|
158
209
|
}
|
|
159
210
|
|
|
160
|
-
// ---- Content classification ----
|
|
161
|
-
// Any JS expression evaluates; text that isn't one renders verbatim.
|
|
162
|
-
|
|
163
|
-
const BARE_IDENTIFIER = /^[\p{ID_Start}$_][\p{ID_Continue}$]*$/u;
|
|
164
211
|
const looksLikeHtml = (s) => s.includes('<') && s.includes('>');
|
|
165
212
|
|
|
166
|
-
function parsesAsExpression(src) {
|
|
167
|
-
try { new Function('return (' + src + '\n)'); return true; } catch { return false; }
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function inScope(el, name) {
|
|
171
|
-
try { return name in Alpine.$data(el); } catch { return false; }
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// Errors come back as values: unresolved names read as plain text
|
|
175
|
-
// ("Re-run", "Hello, world"); other errors warn against the authored expression
|
|
176
|
-
const guarded = (src) =>
|
|
177
|
-
'(() => { try { return (' + src + '\n) } catch (e) { return { __tooltipError: e } } })()';
|
|
178
|
-
|
|
179
|
-
function unwrapError(v, el, src) {
|
|
180
|
-
const err = v && typeof v === 'object' && v.__tooltipError;
|
|
181
|
-
if (!(err instanceof Error)) return { value: v };
|
|
182
|
-
if (err instanceof ReferenceError) return { value: undefined };
|
|
183
|
-
console.warn(`Alpine Expression Error: ${err.message}\n\nExpression: "${src}"\n\n`, el);
|
|
184
|
-
return { value: null };
|
|
185
|
-
}
|
|
186
|
-
|
|
187
213
|
// ---- Directive ----
|
|
188
214
|
|
|
189
215
|
Alpine.directive('tooltip', (el, { modifiers, expression }, { effect, evaluateLater }) => {
|
|
@@ -193,25 +219,16 @@ function initializeTooltipPlugin() {
|
|
|
193
219
|
const htmlOptIn = modifiers.includes('html') || modifiers.includes('safe');
|
|
194
220
|
const literal = expression ? { text: expression, html: htmlOptIn || looksLikeHtml(expression) } : null;
|
|
195
221
|
const src = expression.trim();
|
|
196
|
-
|
|
197
|
-
let fallback = true;
|
|
222
|
+
const evaluate = expressionResolver(el, src, evaluateLater);
|
|
198
223
|
|
|
199
224
|
if (src.startsWith('$x.')) {
|
|
200
225
|
const [contentType] = src.substring(3).split('.');
|
|
201
|
-
evaluate = evaluateLater(src);
|
|
202
|
-
fallback = false;
|
|
203
226
|
effect(() => {
|
|
204
227
|
const store = Alpine.store('collections');
|
|
205
228
|
if (store && typeof store.loadCollection === 'function' && !store[contentType]) {
|
|
206
229
|
store.loadCollection(contentType);
|
|
207
230
|
}
|
|
208
231
|
});
|
|
209
|
-
} else if (BARE_IDENTIFIER.test(src)) {
|
|
210
|
-
// Single word: a scope value or magic, else text (never a global like Image or close)
|
|
211
|
-
const getValue = evaluateLater(guarded(src));
|
|
212
|
-
evaluate = (cb) => (src.startsWith('$') || inScope(el, src)) ? getValue(cb) : cb(undefined);
|
|
213
|
-
} else if (parsesAsExpression(src)) {
|
|
214
|
-
evaluate = evaluateLater(guarded(src));
|
|
215
232
|
}
|
|
216
233
|
|
|
217
234
|
// --- Positioning modifiers ---
|
|
@@ -222,11 +239,10 @@ function initializeTooltipPlugin() {
|
|
|
222
239
|
// Empty results (null, false, '') show nothing.
|
|
223
240
|
const resolveContent = (cb) => {
|
|
224
241
|
if (!evaluate) { cb(literal); return; }
|
|
225
|
-
evaluate(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
cb({ text: String(v), html: htmlOptIn });
|
|
242
|
+
evaluate((v, asText) => {
|
|
243
|
+
if (asText) { cb(literal); return; }
|
|
244
|
+
const text = v == null || v === false ? '' : String(v);
|
|
245
|
+
cb(text === '' ? null : { text, html: htmlOptIn });
|
|
230
246
|
});
|
|
231
247
|
};
|
|
232
248
|
|