@hoardodile/ui 0.1.7 → 0.1.9
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/chunk-2BVZEYNW.js +97 -0
- package/dist/chunk-2BVZEYNW.js.map +1 -0
- package/dist/chunk-2DTR6CD5.js +47 -0
- package/dist/chunk-2DTR6CD5.js.map +1 -0
- package/dist/chunk-2HWSCY4T.js +20 -0
- package/dist/chunk-2HWSCY4T.js.map +1 -0
- package/dist/chunk-363CCKQ7.js +75 -0
- package/dist/chunk-363CCKQ7.js.map +1 -0
- package/dist/chunk-3ZQJWBVB.js +30 -0
- package/dist/chunk-3ZQJWBVB.js.map +1 -0
- package/dist/chunk-4D36OO5W.js +277 -0
- package/dist/chunk-4D36OO5W.js.map +1 -0
- package/dist/chunk-4UITFLIN.js +31 -0
- package/dist/chunk-4UITFLIN.js.map +1 -0
- package/dist/chunk-6HAIUXNZ.js +11 -0
- package/dist/chunk-6HAIUXNZ.js.map +1 -0
- package/dist/chunk-7JMMFY67.js +62 -0
- package/dist/chunk-7JMMFY67.js.map +1 -0
- package/dist/chunk-7MWWHI6T.js +1149 -0
- package/dist/chunk-7MWWHI6T.js.map +1 -0
- package/dist/chunk-AEHTAUAQ.js +65 -0
- package/dist/chunk-AEHTAUAQ.js.map +1 -0
- package/dist/chunk-ASRGQ5BD.js +130 -0
- package/dist/chunk-ASRGQ5BD.js.map +1 -0
- package/dist/chunk-BFGOE5AI.js +187 -0
- package/dist/chunk-BFGOE5AI.js.map +1 -0
- package/dist/chunk-BRT25IDQ.js +46 -0
- package/dist/chunk-BRT25IDQ.js.map +1 -0
- package/dist/chunk-BU5DQOPM.js +29 -0
- package/dist/chunk-BU5DQOPM.js.map +1 -0
- package/dist/chunk-BWASOT5X.js +266 -0
- package/dist/chunk-BWASOT5X.js.map +1 -0
- package/dist/chunk-F32V4Z7Q.js +26 -0
- package/dist/chunk-F32V4Z7Q.js.map +1 -0
- package/dist/chunk-F7RHDRRJ.js +24 -0
- package/dist/chunk-F7RHDRRJ.js.map +1 -0
- package/dist/chunk-FH5RNCFR.js +21 -0
- package/dist/chunk-FH5RNCFR.js.map +1 -0
- package/dist/chunk-GKSX5ULZ.js +513 -0
- package/dist/chunk-GKSX5ULZ.js.map +1 -0
- package/dist/chunk-JPFDNRCA.js +26 -0
- package/dist/chunk-JPFDNRCA.js.map +1 -0
- package/dist/chunk-KNPRUZ4H.js +13 -0
- package/dist/chunk-KNPRUZ4H.js.map +1 -0
- package/dist/chunk-KOFWEPPB.js +254 -0
- package/dist/chunk-KOFWEPPB.js.map +1 -0
- package/dist/chunk-M5OJN54O.js +10 -0
- package/dist/chunk-M5OJN54O.js.map +1 -0
- package/dist/chunk-OEVALKQ5.js +51 -0
- package/dist/chunk-OEVALKQ5.js.map +1 -0
- package/dist/chunk-OW5FWLPH.js +33 -0
- package/dist/chunk-OW5FWLPH.js.map +1 -0
- package/dist/chunk-POX7TXBH.js +41 -0
- package/dist/chunk-POX7TXBH.js.map +1 -0
- package/dist/chunk-PWJBHUM2.js +58 -0
- package/dist/chunk-PWJBHUM2.js.map +1 -0
- package/dist/chunk-QGMDWGJT.js +23 -0
- package/dist/chunk-QGMDWGJT.js.map +1 -0
- package/dist/chunk-QGTQQNUL.js +36 -0
- package/dist/chunk-QGTQQNUL.js.map +1 -0
- package/dist/chunk-SAY52ZKI.js +152 -0
- package/dist/chunk-SAY52ZKI.js.map +1 -0
- package/dist/chunk-SKDPGSRL.js +166 -0
- package/dist/chunk-SKDPGSRL.js.map +1 -0
- package/dist/chunk-T56ARCUK.js +38 -0
- package/dist/chunk-T56ARCUK.js.map +1 -0
- package/dist/chunk-TDDHQZ62.js +227 -0
- package/dist/chunk-TDDHQZ62.js.map +1 -0
- package/dist/chunk-TMQ5OMBK.js +29 -0
- package/dist/chunk-TMQ5OMBK.js.map +1 -0
- package/dist/chunk-UEVND7AS.js +23 -0
- package/dist/chunk-UEVND7AS.js.map +1 -0
- package/dist/chunk-UPWHCG4S.js +40 -0
- package/dist/chunk-UPWHCG4S.js.map +1 -0
- package/dist/chunk-VWUNF7VX.js +3 -0
- package/dist/chunk-VWUNF7VX.js.map +1 -0
- package/dist/chunk-WI6O7GZK.js +45 -0
- package/dist/chunk-WI6O7GZK.js.map +1 -0
- package/dist/chunk-WVEK3WCX.js +21 -0
- package/dist/chunk-WVEK3WCX.js.map +1 -0
- package/dist/chunk-XBPQEZES.js +48 -0
- package/dist/chunk-XBPQEZES.js.map +1 -0
- package/dist/chunk-ZYAGKKR7.js +142 -0
- package/dist/chunk-ZYAGKKR7.js.map +1 -0
- package/dist/components/alert.js +2 -21
- package/dist/components/alert.js.map +1 -1
- package/dist/components/app-dialog.js +10 -654
- package/dist/components/app-dialog.js.map +1 -1
- package/dist/components/badge.js +2 -23
- package/dist/components/badge.js.map +1 -1
- package/dist/components/breadcrumb.js +5 -504
- package/dist/components/breadcrumb.js.map +1 -1
- package/dist/components/button.js +3 -76
- package/dist/components/button.js.map +1 -1
- package/dist/components/caption-bar.js +7 -521
- package/dist/components/caption-bar.js.map +1 -1
- package/dist/components/checkbox.js +4 -74
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip-button.js +4 -85
- package/dist/components/chip-button.js.map +1 -1
- package/dist/components/close-confirm-dialog.js +12 -662
- package/dist/components/close-confirm-dialog.js.map +1 -1
- package/dist/components/color-picker.js +7 -533
- package/dist/components/color-picker.js.map +1 -1
- package/dist/components/combobox.js +15 -937
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-by-typing-dialog.js +12 -669
- package/dist/components/confirm-by-typing-dialog.js.map +1 -1
- package/dist/components/confirm-dialog.js +11 -637
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/count-badge.js +2 -21
- package/dist/components/count-badge.js.map +1 -1
- package/dist/components/dialog.js +8 -569
- package/dist/components/dialog.js.map +1 -1
- package/dist/components/dropdown-menu.js +9 -1007
- package/dist/components/dropdown-menu.js.map +1 -1
- package/dist/components/dropdown-select.js +9 -883
- package/dist/components/dropdown-select.js.map +1 -1
- package/dist/components/empty.js +2 -21
- package/dist/components/empty.js.map +1 -1
- package/dist/components/filter-rail.js +7 -145
- package/dist/components/filter-rail.js.map +1 -1
- package/dist/components/fixed-action-bar.js +2 -21
- package/dist/components/fixed-action-bar.js.map +1 -1
- package/dist/components/font-picker.js +11 -589
- package/dist/components/font-picker.js.map +1 -1
- package/dist/components/form.js +9 -66
- package/dist/components/form.js.map +1 -1
- package/dist/components/icon-tile.js +3 -43
- package/dist/components/icon-tile.js.map +1 -1
- package/dist/components/icon-toggle.js +3 -43
- package/dist/components/icon-toggle.js.map +1 -1
- package/dist/components/icon.js +3 -47
- package/dist/components/icon.js.map +1 -1
- package/dist/components/image-crop-panel.js +19 -775
- package/dist/components/image-crop-panel.js.map +1 -1
- package/dist/components/image-cropper.js +1 -164
- package/dist/components/image-cropper.js.map +1 -1
- package/dist/components/input-group.js +6 -268
- package/dist/components/input-group.js.map +1 -1
- package/dist/components/input.js +3 -58
- package/dist/components/input.js.map +1 -1
- package/dist/components/label.js +3 -38
- package/dist/components/label.js.map +1 -1
- package/dist/components/list-empty-row.js +2 -21
- package/dist/components/list-empty-row.js.map +1 -1
- package/dist/components/management-empty.js +2 -21
- package/dist/components/management-empty.js.map +1 -1
- package/dist/components/management-skeleton.js +4 -59
- package/dist/components/management-skeleton.js.map +1 -1
- package/dist/components/meta-chip.js +2 -21
- package/dist/components/meta-chip.js.map +1 -1
- package/dist/components/mobile-drawer.js +7 -268
- package/dist/components/mobile-drawer.js.map +1 -1
- package/dist/components/page-header.js +3 -42
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/page-scaffold.js +5 -76
- package/dist/components/page-scaffold.js.map +1 -1
- package/dist/components/pagination-bar.js +13 -617
- package/dist/components/pagination-bar.js.map +1 -1
- package/dist/components/pagination.js +6 -684
- package/dist/components/pagination.js.map +1 -1
- package/dist/components/panel-toolbar.js +11 -716
- package/dist/components/panel-toolbar.js.map +1 -1
- package/dist/components/pill-tabs.js +2 -21
- package/dist/components/pill-tabs.js.map +1 -1
- package/dist/components/plugin-download-consent.js +13 -663
- package/dist/components/plugin-download-consent.js.map +1 -1
- package/dist/components/popover.js +5 -242
- package/dist/components/popover.js.map +1 -1
- package/dist/components/preview-card.js +2 -21
- package/dist/components/preview-card.js.map +1 -1
- package/dist/components/progress.js +2 -20
- package/dist/components/progress.js.map +1 -1
- package/dist/components/radio-group.js +2 -21
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/scroll-area.js +2 -21
- package/dist/components/scroll-area.js.map +1 -1
- package/dist/components/search-field.js +6 -590
- package/dist/components/search-field.js.map +1 -1
- package/dist/components/secondary-stat.js +3 -40
- package/dist/components/secondary-stat.js.map +1 -1
- package/dist/components/section-header.js +3 -43
- package/dist/components/section-header.js.map +1 -1
- package/dist/components/section-label.js +3 -44
- package/dist/components/section-label.js.map +1 -1
- package/dist/components/section-tabs.js +2 -21
- package/dist/components/section-tabs.js.map +1 -1
- package/dist/components/separator.js +3 -47
- package/dist/components/separator.js.map +1 -1
- package/dist/components/sheet.js +8 -467
- package/dist/components/sheet.js.map +1 -1
- package/dist/components/sidebar.js +24 -1047
- package/dist/components/sidebar.js.map +1 -1
- package/dist/components/skeleton.js +3 -39
- package/dist/components/skeleton.js.map +1 -1
- package/dist/components/slider.js +2 -21
- package/dist/components/slider.js.map +1 -1
- package/dist/components/sortable-chip-list.js +2 -21
- package/dist/components/sortable-chip-list.js.map +1 -1
- package/dist/components/special-tag-surface.js +3 -531
- package/dist/components/special-tag-surface.js.map +1 -1
- package/dist/components/spinner.js +3 -63
- package/dist/components/spinner.js.map +1 -1
- package/dist/components/surface.js +3 -49
- package/dist/components/surface.js.map +1 -1
- package/dist/components/switch.js +3 -51
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.js +2 -20
- package/dist/components/table.js.map +1 -1
- package/dist/components/tag-chip.js +6 -617
- package/dist/components/tag-chip.js.map +1 -1
- package/dist/components/textarea.js +3 -56
- package/dist/components/textarea.js.map +1 -1
- package/dist/components/toast.js +8 -809
- package/dist/components/toast.js.map +1 -1
- package/dist/components/toggle.js +2 -20
- package/dist/components/toggle.js.map +1 -1
- package/dist/components/tooltip.js +3 -80
- package/dist/components/tooltip.js.map +1 -1
- package/dist/hooks/use-dialog-footer-actions.js +1 -9
- package/dist/hooks/use-dialog-footer-actions.js.map +1 -1
- package/dist/hooks/use-form-field.js +1 -34
- package/dist/hooks/use-form-field.js.map +1 -1
- package/dist/hooks/use-mobile.js +2 -27
- package/dist/hooks/use-mobile.js.map +1 -1
- package/dist/hooks/useMobileBackToClose.js +3 -232
- package/dist/hooks/useMobileBackToClose.js.map +1 -1
- package/dist/icons/actions.js +4 -524
- package/dist/icons/actions.js.map +1 -1
- package/dist/icons/icon-style.js +1 -49
- package/dist/icons/icon-style.js.map +1 -1
- package/dist/icons/marks.js +1 -46
- package/dist/icons/marks.js.map +1 -1
- package/dist/icons/registry.js +2 -1194
- package/dist/icons/registry.js.map +1 -1
- package/dist/index.js +10 -651
- package/dist/index.js.map +1 -1
- package/dist/lib/colors.js +1 -63
- package/dist/lib/colors.js.map +1 -1
- package/dist/lib/merge-config.js +1 -18
- package/dist/lib/merge-config.js.map +1 -1
- package/dist/lib/pagination.js +1 -24
- package/dist/lib/pagination.js.map +1 -1
- package/dist/lib/tag-surface.js +5 -613
- package/dist/lib/tag-surface.js.map +1 -1
- package/dist/lib/utils.js +2 -24
- package/dist/lib/utils.js.map +1 -1
- package/dist/res-card-template/format.js +1 -21
- package/dist/res-card-template/format.js.map +1 -1
- package/dist/res-card-template/icon.js +1 -39
- package/dist/res-card-template/icon.js.map +1 -1
- package/dist/res-card-template/index.js +3 -329
- package/dist/res-card-template/index.js.map +1 -1
- package/dist/res-card-template/template.js +3 -331
- package/dist/res-card-template/template.js.map +1 -1
- package/dist/viewport.js +1 -11
- package/dist/viewport.js.map +1 -1
- package/package.json +3 -3
- package/src/components/image-crop-panel.dist.test.tsx +54 -0
|
@@ -1,333 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
// src/res-card-template/template.ts
|
|
5
|
-
function formatBytes(bytes) {
|
|
6
|
-
if (bytes === void 0) return "";
|
|
7
|
-
if (!Number.isFinite(bytes) || bytes <= 0) return "0 B";
|
|
8
|
-
return prettyBytes(bytes, { binary: true }).replaceAll("iB", "B");
|
|
9
|
-
}
|
|
10
|
-
function formatClockDuration(ms) {
|
|
11
|
-
if (!Number.isFinite(ms) || ms < 0) return "";
|
|
12
|
-
const totalSeconds = Math.floor(ms / 1e3);
|
|
13
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
14
|
-
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
15
|
-
const seconds = totalSeconds % 60;
|
|
16
|
-
if (hours > 0) {
|
|
17
|
-
return `${hours}:${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
|
|
18
|
-
}
|
|
19
|
-
return `${minutes}:${String(seconds).padStart(2, "0")}`;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// src/res-card-template/icon.ts
|
|
23
|
-
var LEGACY_ICON_ALIASES = {
|
|
24
|
-
Files: "file",
|
|
25
|
-
Film: "video-frame",
|
|
26
|
-
Image: "gallery",
|
|
27
|
-
Info: "info-circle",
|
|
28
|
-
Music: "music-notes",
|
|
29
|
-
Search: "magnifier",
|
|
30
|
-
Sparkle: "star",
|
|
31
|
-
Video: "video-frame"
|
|
32
|
-
};
|
|
33
|
-
function normalizeSolarGlyphName(raw) {
|
|
34
|
-
const trimmed = raw.trim();
|
|
35
|
-
if (trimmed.length === 0) return void 0;
|
|
36
|
-
const aliased = LEGACY_ICON_ALIASES[trimmed];
|
|
37
|
-
if (aliased !== void 0) return aliased;
|
|
38
|
-
if (/^[a-z][a-z0-9-]*$/.test(trimmed)) return trimmed;
|
|
39
|
-
if (/^[A-Za-z][A-Za-z0-9]*$/.test(trimmed)) {
|
|
40
|
-
return trimmed.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
|
|
41
|
-
}
|
|
42
|
-
return void 0;
|
|
43
|
-
}
|
|
44
|
-
function parseIconRef(raw, pluginId, buildAssetUrl) {
|
|
45
|
-
const trimmed = raw.trim();
|
|
46
|
-
if (trimmed.length === 0) return void 0;
|
|
47
|
-
if (trimmed.startsWith("http://") || trimmed.startsWith("https://") || trimmed.startsWith("data:")) {
|
|
48
|
-
return void 0;
|
|
49
|
-
}
|
|
50
|
-
if (trimmed.includes(".") || trimmed.includes("/") || trimmed.includes("\\")) {
|
|
51
|
-
const rel = trimmed.replace(/^\.[\\/]/, "");
|
|
52
|
-
if (rel.length === 0 || rel.split("/").includes("..")) return void 0;
|
|
53
|
-
return { kind: "asset", url: buildAssetUrl(pluginId, rel) };
|
|
54
|
-
}
|
|
55
|
-
const name = normalizeSolarGlyphName(trimmed);
|
|
56
|
-
if (name === void 0) return void 0;
|
|
57
|
-
return { kind: "icon", name };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// src/res-card-template/template.ts
|
|
61
|
-
function resolvePath(segments, scope) {
|
|
62
|
-
const [namespace, ...rest] = segments;
|
|
63
|
-
const root = namespace === "file" ? scope.file : namespace === "searchMeta" ? scope.searchMeta : namespace === "data" ? scope.data : namespace === "coverMeta" ? scope.coverMeta : scope.source;
|
|
64
|
-
if (root === void 0 || root === null) return void 0;
|
|
65
|
-
let current = root;
|
|
66
|
-
for (const key of rest) {
|
|
67
|
-
if (typeof current !== "object" || current === null) return void 0;
|
|
68
|
-
current = current[key];
|
|
69
|
-
}
|
|
70
|
-
return current;
|
|
71
|
-
}
|
|
72
|
-
function resolveLocaleString(value, locale) {
|
|
73
|
-
if (typeof value === "string") return value;
|
|
74
|
-
const exact = value[locale];
|
|
75
|
-
if (exact !== void 0) return exact;
|
|
76
|
-
const base = locale.split("-")[0] ?? locale;
|
|
77
|
-
const partial = value[base];
|
|
78
|
-
if (partial !== void 0) return partial;
|
|
79
|
-
const first = Object.values(value)[0];
|
|
80
|
-
return first ?? "";
|
|
81
|
-
}
|
|
82
|
-
function evaluateExpression(expr, scope, ctx) {
|
|
83
|
-
if (expr.kind === "path") {
|
|
84
|
-
const value = resolvePath(expr.segments, scope);
|
|
85
|
-
if (value === void 0 || value === null) return "";
|
|
86
|
-
return String(value);
|
|
87
|
-
}
|
|
88
|
-
return evaluateCall(expr.name, expr.args, scope, ctx);
|
|
89
|
-
}
|
|
90
|
-
function evaluateCall(name, args, scope, ctx) {
|
|
91
|
-
switch (name) {
|
|
92
|
-
case "bytes":
|
|
93
|
-
return callPipe(
|
|
94
|
-
args,
|
|
95
|
-
scope,
|
|
96
|
-
ctx,
|
|
97
|
-
(value) => typeof value === "number" ? formatBytes(value) : ""
|
|
98
|
-
);
|
|
99
|
-
case "duration":
|
|
100
|
-
return callPipe(
|
|
101
|
-
args,
|
|
102
|
-
scope,
|
|
103
|
-
ctx,
|
|
104
|
-
(value) => typeof value === "number" ? formatClockDuration(value) : ""
|
|
105
|
-
);
|
|
106
|
-
case "number":
|
|
107
|
-
return callPipe(
|
|
108
|
-
args,
|
|
109
|
-
scope,
|
|
110
|
-
ctx,
|
|
111
|
-
(value) => typeof value === "number" && Number.isFinite(value) ? value.toLocaleString() : ""
|
|
112
|
-
);
|
|
113
|
-
case "inc":
|
|
114
|
-
return callPipe(
|
|
115
|
-
args,
|
|
116
|
-
scope,
|
|
117
|
-
ctx,
|
|
118
|
-
(value) => typeof value === "number" && Number.isFinite(value) ? String(value + 1) : ""
|
|
119
|
-
);
|
|
120
|
-
case "eq":
|
|
121
|
-
return compareCall(args, scope, ctx, (a, b) => a === b);
|
|
122
|
-
case "ne":
|
|
123
|
-
return compareCall(args, scope, ctx, (a, b) => a !== b);
|
|
124
|
-
case "gt":
|
|
125
|
-
return compareCall(args, scope, ctx, (a, b) => {
|
|
126
|
-
if (typeof a !== "number" || typeof b !== "number") return false;
|
|
127
|
-
return a > b;
|
|
128
|
-
});
|
|
129
|
-
case "lt":
|
|
130
|
-
return compareCall(args, scope, ctx, (a, b) => {
|
|
131
|
-
if (typeof a !== "number" || typeof b !== "number") return false;
|
|
132
|
-
return a < b;
|
|
133
|
-
});
|
|
134
|
-
case "gte":
|
|
135
|
-
return compareCall(args, scope, ctx, (a, b) => {
|
|
136
|
-
if (typeof a !== "number" || typeof b !== "number") return false;
|
|
137
|
-
return a >= b;
|
|
138
|
-
});
|
|
139
|
-
case "lte":
|
|
140
|
-
return compareCall(args, scope, ctx, (a, b) => {
|
|
141
|
-
if (typeof a !== "number" || typeof b !== "number") return false;
|
|
142
|
-
return a <= b;
|
|
143
|
-
});
|
|
144
|
-
case "if":
|
|
145
|
-
return callIf(args, scope, ctx);
|
|
146
|
-
case "t":
|
|
147
|
-
return callT(args, ctx);
|
|
148
|
-
case "icon":
|
|
149
|
-
return callIcon(args, ctx);
|
|
150
|
-
case "asset":
|
|
151
|
-
return callAsset(args, ctx);
|
|
152
|
-
case "kind":
|
|
153
|
-
return callKind(args, scope, ctx);
|
|
154
|
-
case "searchKindIcons":
|
|
155
|
-
return callSearchKindIcons(scope, ctx);
|
|
156
|
-
case "join":
|
|
157
|
-
return callJoin(args, scope, ctx);
|
|
158
|
-
default:
|
|
159
|
-
return "";
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
function callPipe(args, scope, ctx, pipeFn) {
|
|
163
|
-
const value = evaluateArgAsPrimitive(args[0], scope, ctx);
|
|
164
|
-
return pipeFn(value);
|
|
165
|
-
}
|
|
166
|
-
function callT(args, ctx) {
|
|
167
|
-
const key = evaluateArgAsString(args[0]);
|
|
168
|
-
if (key.length === 0) return "";
|
|
169
|
-
const map = ctx.manifest.i18n;
|
|
170
|
-
if (map === void 0) return "";
|
|
171
|
-
const value = map[key];
|
|
172
|
-
if (value === void 0) return "";
|
|
173
|
-
return resolveLocaleString(value, ctx.locale);
|
|
174
|
-
}
|
|
175
|
-
function callIcon(args, ctx) {
|
|
176
|
-
const name = evaluateArgAsString(args[0]);
|
|
177
|
-
if (name.length === 0) return null;
|
|
178
|
-
return ctx.renderIcon({ kind: "icon", name }, ctx.iconClassName);
|
|
179
|
-
}
|
|
180
|
-
function callAsset(args, ctx) {
|
|
181
|
-
const path = evaluateArgAsString(args[0]);
|
|
182
|
-
if (path.length === 0) return null;
|
|
183
|
-
const ref = parseIconRef(path, ctx.pluginId, ctx.buildAssetUrl);
|
|
184
|
-
if (ref === void 0) return null;
|
|
185
|
-
return ctx.renderIcon(ref, ctx.iconClassName);
|
|
186
|
-
}
|
|
187
|
-
function callKind(args, scope, ctx) {
|
|
188
|
-
const key = evaluateArgAsString(args[0]);
|
|
189
|
-
if (key.length === 0) return null;
|
|
190
|
-
const kinds = ctx.manifest.ui?.search?.kinds;
|
|
191
|
-
if (kinds === void 0) return null;
|
|
192
|
-
const match = kinds.find((k) => k.key === key);
|
|
193
|
-
if (match === void 0 || match.icon === void 0) return null;
|
|
194
|
-
const rendered = renderCardTemplate(match.icon, scope, ctx);
|
|
195
|
-
if (rendered === null || rendered === void 0 || rendered === "")
|
|
196
|
-
return null;
|
|
197
|
-
return rendered;
|
|
198
|
-
}
|
|
199
|
-
function callSearchKindIcons(scope, ctx) {
|
|
200
|
-
if (scope.searchMeta === void 0 || scope.searchMeta === null || typeof scope.searchMeta !== "object")
|
|
201
|
-
return [];
|
|
202
|
-
const facets = scope.searchMeta.facets;
|
|
203
|
-
if (facets === void 0 || typeof facets !== "object" || facets === null)
|
|
204
|
-
return [];
|
|
205
|
-
const kinds = ctx.manifest.ui?.search?.kinds;
|
|
206
|
-
if (kinds === void 0) return [];
|
|
207
|
-
const results = [];
|
|
208
|
-
for (const kind of kinds) {
|
|
209
|
-
if (kind.icon === void 0) continue;
|
|
210
|
-
const active = facets[kind.key];
|
|
211
|
-
if (active !== true) continue;
|
|
212
|
-
const rendered = renderCardTemplate(kind.icon, scope, ctx);
|
|
213
|
-
if (rendered === null || rendered === void 0 || rendered === "") continue;
|
|
214
|
-
results.push(rendered);
|
|
215
|
-
}
|
|
216
|
-
return results;
|
|
217
|
-
}
|
|
218
|
-
function callJoin(args, scope, ctx) {
|
|
219
|
-
if (args.length === 0) return "";
|
|
220
|
-
const separator = evaluateArgAsString(args[0]);
|
|
221
|
-
const items = [];
|
|
222
|
-
for (let i = 1; i < args.length; i++) {
|
|
223
|
-
const val = evaluateArg(args[i], scope, ctx);
|
|
224
|
-
if (Array.isArray(val)) {
|
|
225
|
-
for (const item of val) {
|
|
226
|
-
if (item !== null && item !== void 0 && item !== "") {
|
|
227
|
-
items.push(item);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
continue;
|
|
231
|
-
}
|
|
232
|
-
if (val !== null && val !== void 0 && val !== "") {
|
|
233
|
-
items.push(val);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
if (items.length === 0) return "";
|
|
237
|
-
if (items.every((item) => typeof item === "string")) {
|
|
238
|
-
return items.join(separator);
|
|
239
|
-
}
|
|
240
|
-
if (separator.length === 0) return items;
|
|
241
|
-
const interleaved = [];
|
|
242
|
-
for (let i = 0; i < items.length; i++) {
|
|
243
|
-
if (i > 0) interleaved.push(separator);
|
|
244
|
-
interleaved.push(items[i]);
|
|
245
|
-
}
|
|
246
|
-
return interleaved;
|
|
247
|
-
}
|
|
248
|
-
function evaluateArgAsPrimitive(arg, scope, ctx) {
|
|
249
|
-
if (arg === void 0) return void 0;
|
|
250
|
-
if (arg.kind === "string") return arg.value;
|
|
251
|
-
if (arg.expr.kind === "path") {
|
|
252
|
-
const segments = arg.expr.segments;
|
|
253
|
-
if (segments.length === 1) {
|
|
254
|
-
const seg = segments[0];
|
|
255
|
-
const num = Number(seg);
|
|
256
|
-
if (!Number.isNaN(num)) return num;
|
|
257
|
-
}
|
|
258
|
-
return resolvePath(segments, scope);
|
|
259
|
-
}
|
|
260
|
-
if (arg.expr.kind === "call") {
|
|
261
|
-
const result = evaluateCall(arg.expr.name, arg.expr.args, scope, ctx);
|
|
262
|
-
if (typeof result === "string" || typeof result === "number") return result;
|
|
263
|
-
if (Array.isArray(result)) return result;
|
|
264
|
-
return void 0;
|
|
265
|
-
}
|
|
266
|
-
return void 0;
|
|
267
|
-
}
|
|
268
|
-
function evaluateArg(arg, scope, ctx) {
|
|
269
|
-
if (arg === void 0) return void 0;
|
|
270
|
-
if (arg.kind === "string") return arg.value;
|
|
271
|
-
return evaluateExpression(arg.expr, scope, ctx);
|
|
272
|
-
}
|
|
273
|
-
function compareCall(args, scope, ctx, cmp) {
|
|
274
|
-
const a = evaluateArgAsPrimitive(args[0], scope, ctx);
|
|
275
|
-
const b = evaluateArgAsPrimitive(args[1], scope, ctx);
|
|
276
|
-
return cmp(a, b) ? "true" : "";
|
|
277
|
-
}
|
|
278
|
-
function callIf(args, scope, ctx) {
|
|
279
|
-
const cond = evaluateArgAsPrimitive(args[0], scope, ctx);
|
|
280
|
-
const truthy = cond !== void 0 && cond !== null && cond !== "" && cond !== false && cond !== 0;
|
|
281
|
-
if (truthy) {
|
|
282
|
-
const raw = evaluateArgAsPrimitive(args[1], scope, ctx);
|
|
283
|
-
if (raw !== void 0) return raw;
|
|
284
|
-
return evaluateArg(args[1], scope, ctx);
|
|
285
|
-
}
|
|
286
|
-
if (args.length > 2) {
|
|
287
|
-
const raw = evaluateArgAsPrimitive(args[2], scope, ctx);
|
|
288
|
-
if (raw !== void 0) return raw;
|
|
289
|
-
return evaluateArg(args[2], scope, ctx);
|
|
290
|
-
}
|
|
291
|
-
return "";
|
|
292
|
-
}
|
|
293
|
-
function evaluateArgAsString(arg) {
|
|
294
|
-
if (arg === void 0) return "";
|
|
295
|
-
if (arg.kind === "string") return arg.value;
|
|
296
|
-
return "";
|
|
297
|
-
}
|
|
298
|
-
function renderCardTemplate(template, scope, ctx) {
|
|
299
|
-
if (template.length === 0) return "";
|
|
300
|
-
const fragments = parseTemplateFragments(template);
|
|
301
|
-
if (fragments.length === 0) return "";
|
|
302
|
-
const results = [];
|
|
303
|
-
for (const frag of fragments) {
|
|
304
|
-
if (frag.kind === "text") {
|
|
305
|
-
results.push(frag.value);
|
|
306
|
-
continue;
|
|
307
|
-
}
|
|
308
|
-
const expr = parseTemplateExpression(frag.source);
|
|
309
|
-
if (expr === void 0) {
|
|
310
|
-
continue;
|
|
311
|
-
}
|
|
312
|
-
const value = evaluateExpression(expr, scope, ctx);
|
|
313
|
-
if (value !== null && value !== void 0 && value !== "") {
|
|
314
|
-
results.push(value);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
if (results.length === 0) return null;
|
|
318
|
-
if (results.length === 1) return results[0];
|
|
319
|
-
const allStrings = results.every((r) => typeof r === "string");
|
|
320
|
-
if (allStrings) return results.join("");
|
|
321
|
-
return results;
|
|
322
|
-
}
|
|
323
|
-
function renderSlotBadges(slotValues, scope, ctx) {
|
|
324
|
-
return slotValues.map((template) => renderCardTemplate(template, scope, ctx)).filter((n) => {
|
|
325
|
-
if (n === null || n === void 0 || n === "") return false;
|
|
326
|
-
if (Array.isArray(n) && n.length === 0) return false;
|
|
327
|
-
return true;
|
|
328
|
-
});
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
export { renderCardTemplate, renderSlotBadges, resolveLocaleString };
|
|
1
|
+
export { renderCardTemplate, renderSlotBadges, resolveLocaleString } from '../chunk-4D36OO5W.js';
|
|
2
|
+
import '../chunk-POX7TXBH.js';
|
|
3
|
+
import '../chunk-UEVND7AS.js';
|
|
332
4
|
//# sourceMappingURL=template.js.map
|
|
333
5
|
//# sourceMappingURL=template.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/res-card-template/format.ts","../../src/res-card-template/icon.ts","../../src/res-card-template/template.ts"],"names":[],"mappings":"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","file":"template.js","sourcesContent":["import prettyBytes from \"pretty-bytes\"\n\n/**\n * Format a non-negative byte count as a short human-readable string\n * via {@link prettyBytes} with binary conversion (base 1024) and JEDEC\n * labels (`4.5 KB`, `1.2 MB`, `930 GB`) — IEC `KiB`/`MiB`/`GiB` mapped\n * to `KB`/`MB`/`GB`. Matches how Windows and most disk tools report\n * sizes, without switching to decimal (base 1000) units.\n *\n * Returns the empty string for `undefined` so callers can splat the value\n * into a template without conditional checks. Negative or non-finite\n * inputs are clamped to `0 B`.\n */\nexport function formatBytes(bytes: number | undefined): string {\n\tif (bytes === undefined) return \"\"\n\tif (!Number.isFinite(bytes) || bytes <= 0) return \"0 B\"\n\treturn prettyBytes(bytes, { binary: true }).replaceAll(\"iB\", \"B\")\n}\n\n/**\n * Format a duration in milliseconds as a media clock — `m:ss`, or\n * `h:mm:ss` past the hour. Used by the plugin card templates\n * (`{{duration(...)}}`) and the card's inline audio player, so both\n * read the same way.\n */\nexport function formatClockDuration(ms: number): string {\n\tif (!Number.isFinite(ms) || ms < 0) return \"\"\n\tconst totalSeconds = Math.floor(ms / 1000)\n\tconst hours = Math.floor(totalSeconds / 3600)\n\tconst minutes = Math.floor((totalSeconds % 3600) / 60)\n\tconst seconds = totalSeconds % 60\n\tif (hours > 0) {\n\t\treturn `${hours}:${String(minutes).padStart(2, \"0\")}:${String(seconds).padStart(2, \"0\")}`\n\t}\n\treturn `${minutes}:${String(seconds).padStart(2, \"0\")}`\n}\n","import type { ReactNode } from \"react\"\n\n/**\n * A resolved template-icon reference: a Solar glyph name, or an\n * asset image URL derived from a manifest-relative path.\n */\nexport type IconRef =\n\t| { readonly kind: \"icon\"; readonly name: string }\n\t| { readonly kind: \"asset\"; readonly url: string }\n\n/**\n * Legacy whitelist name → Solar kebab glyph. Derived names are handled by\n * the PascalCase conversion; only these diverge.\n */\nconst LEGACY_ICON_ALIASES: Readonly<Record<string, string>> = {\n\tFiles: \"file\",\n\tFilm: \"video-frame\",\n\tImage: \"gallery\",\n\tInfo: \"info-circle\",\n\tMusic: \"music-notes\",\n\tSearch: \"magnifier\",\n\tSparkle: \"star\",\n\tVideo: \"video-frame\",\n}\n\n/**\n * Normalize a raw icon name to Solar kebab-case, or `undefined` when the\n * string cannot name a glyph at all (schemes, separators, punctuation).\n * This is syntax only — membership in the Solar glyph index is left to\n * the renderer that consumes the name.\n */\nexport function normalizeSolarGlyphName(raw: string): string | undefined {\n\tconst trimmed = raw.trim()\n\tif (trimmed.length === 0) return undefined\n\tconst aliased = LEGACY_ICON_ALIASES[trimmed]\n\tif (aliased !== undefined) return aliased\n\tif (/^[a-z][a-z0-9-]*$/.test(trimmed)) return trimmed\n\tif (/^[A-Za-z][A-Za-z0-9]*$/.test(trimmed)) {\n\t\treturn trimmed.replace(/([a-z0-9])([A-Z])/g, \"$1-$2\").toLowerCase()\n\t}\n\treturn undefined\n}\n\n/**\n * Parse a manifest-level icon string into a render-ready ref.\n *\n * `<SolarGlyph>` — Solar glyph name (manifest/template icons are\n * Solar-only; PascalCase and the legacy whitelist\n * names normalize to the kebab glyph)\n * `<relative/path>` — resolved through `buildAssetUrl(pluginId, path)`\n * (leading `./` stripped)\n *\n * Empty inputs, schemes (`http(s)`, `data:`), `..`-shaped paths and any\n * string that cannot name a glyph return `undefined`. The renderer treats\n * that as \"nothing\" — icon resolution never throws.\n */\nexport function parseIconRef(\n\traw: string,\n\tpluginId: string,\n\tbuildAssetUrl: (pluginId: string, path: string) => string,\n): IconRef | undefined {\n\tconst trimmed = raw.trim()\n\tif (trimmed.length === 0) return undefined\n\tif (\n\t\ttrimmed.startsWith(\"http://\") ||\n\t\ttrimmed.startsWith(\"https://\") ||\n\t\ttrimmed.startsWith(\"data:\")\n\t) {\n\t\treturn undefined\n\t}\n\tif (\n\t\ttrimmed.includes(\".\") ||\n\t\ttrimmed.includes(\"/\") ||\n\t\ttrimmed.includes(\"\\\\\")\n\t) {\n\t\tconst rel = trimmed.replace(/^\\.[\\\\/]/, \"\")\n\t\tif (rel.length === 0 || rel.split(\"/\").includes(\"..\")) return undefined\n\t\treturn { kind: \"asset\", url: buildAssetUrl(pluginId, rel) }\n\t}\n\tconst name = normalizeSolarGlyphName(trimmed)\n\tif (name === undefined) return undefined\n\treturn { kind: \"icon\", name }\n}\n\n/** How a parsed {@link IconRef} is drawn inside a rendered badge/template. */\nexport type RenderIcon = (ref: IconRef, className?: string) => ReactNode\n","import {\n\ttype TemplateArg as Arg,\n\ttype TemplateExpr as Expr,\n\tparseTemplateExpression,\n\tparseTemplateFragments,\n} from \"@hoardodile/sdk-types/template\"\nimport type { ReactNode } from \"react\"\nimport { formatBytes, formatClockDuration } from \"./format.ts\"\nimport { parseIconRef, type RenderIcon } from \"./icon.ts\"\n\n// The template grammar (fragment splitting, tokenising, parsing) lives\n// in @hoardodile/sdk-types/template — shared verbatim with the CLI's\n// build-time template lint so the two can never drift. This module only\n// evaluates the AST. The parser is lenient: unparseable expressions\n// render as the empty string.\n\n// ── Evaluation context ───────────────────────────────────────────────────────\n\n/** How a referenced icon is drawn; the caller owns the SVG/image resolution. */\nexport type TemplateContext = {\n\treadonly locale: string\n\treadonly pluginId: string\n\treadonly manifest: {\n\t\treadonly i18n?: Record<string, string | Record<string, string>>\n\t\treadonly ui?: {\n\t\t\treadonly search?: {\n\t\t\t\treadonly kinds?: readonly {\n\t\t\t\t\treadonly key: string\n\t\t\t\t\treadonly icon?: string\n\t\t\t\t}[]\n\t\t\t}\n\t\t}\n\t}\n\treadonly iconClassName?: string\n\t/** Renders a parsed {@link IconRef} (glyph or asset) inside the template. */\n\treadonly renderIcon: RenderIcon\n\t/** Resolves a manifest-relative `asset('path')` reference to a URL. */\n\treadonly buildAssetUrl: (pluginId: string, path: string) => string\n}\n\ntype EvalValue = string | ReactNode\n\ntype TemplateScope = {\n\treadonly file: unknown\n\treadonly source: unknown\n\treadonly searchMeta?: unknown\n\treadonly data?: unknown\n\treadonly coverMeta?: unknown\n}\n\n// ── Scope resolution (paths) ─────────────────────────────────────────────────\n\nfunction resolvePath(\n\tsegments: readonly string[],\n\tscope: TemplateScope,\n): unknown {\n\tconst [namespace, ...rest] = segments\n\tconst root =\n\t\tnamespace === \"file\"\n\t\t\t? scope.file\n\t\t\t: namespace === \"searchMeta\"\n\t\t\t\t? scope.searchMeta\n\t\t\t\t: namespace === \"data\"\n\t\t\t\t\t? scope.data\n\t\t\t\t\t: namespace === \"coverMeta\"\n\t\t\t\t\t\t? scope.coverMeta\n\t\t\t\t\t\t: scope.source\n\tif (root === undefined || root === null) return undefined\n\tlet current: unknown = root\n\tfor (const key of rest) {\n\t\tif (typeof current !== \"object\" || current === null) return undefined\n\t\tcurrent = (current as Record<string, unknown>)[key]\n\t}\n\treturn current\n}\n\n// ── Locale resolution ────────────────────────────────────────────────────────\n\n/**\n * Resolve a locale-aware template value: if the value is a plain string,\n * return it directly; if it is a `Record<locale, string>`, pick the best\n * match for the current language. Falls back to the first available key\n * when nothing matches.\n */\nexport function resolveLocaleString(\n\tvalue: string | Record<string, string>,\n\tlocale: string,\n): string {\n\tif (typeof value === \"string\") return value\n\tconst exact = value[locale]\n\tif (exact !== undefined) return exact\n\tconst base = locale.split(\"-\")[0] ?? locale\n\tconst partial = value[base]\n\tif (partial !== undefined) return partial\n\tconst first = Object.values(value)[0]\n\treturn first ?? \"\"\n}\n\n// ── Expression evaluation ────────────────────────────────────────────────────\n\nfunction evaluateExpression(\n\texpr: Expr,\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): EvalValue {\n\tif (expr.kind === \"path\") {\n\t\tconst value = resolvePath(expr.segments, scope)\n\t\tif (value === undefined || value === null) return \"\"\n\t\treturn String(value)\n\t}\n\treturn evaluateCall(expr.name, expr.args, scope, ctx)\n}\n\nfunction evaluateCall(\n\tname: string,\n\targs: readonly Arg[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): EvalValue {\n\tswitch (name) {\n\t\tcase \"bytes\":\n\t\t\treturn callPipe(args, scope, ctx, (value) =>\n\t\t\t\ttypeof value === \"number\" ? formatBytes(value) : \"\",\n\t\t\t)\n\t\tcase \"duration\":\n\t\t\treturn callPipe(args, scope, ctx, (value) =>\n\t\t\t\ttypeof value === \"number\" ? formatClockDuration(value) : \"\",\n\t\t\t)\n\t\tcase \"number\":\n\t\t\treturn callPipe(args, scope, ctx, (value) =>\n\t\t\t\ttypeof value === \"number\" && Number.isFinite(value)\n\t\t\t\t\t? value.toLocaleString()\n\t\t\t\t\t: \"\",\n\t\t\t)\n\t\tcase \"inc\":\n\t\t\treturn callPipe(args, scope, ctx, (value) =>\n\t\t\t\ttypeof value === \"number\" && Number.isFinite(value)\n\t\t\t\t\t? String(value + 1)\n\t\t\t\t\t: \"\",\n\t\t\t)\n\t\tcase \"eq\":\n\t\t\treturn compareCall(args, scope, ctx, (a, b) => a === b)\n\t\tcase \"ne\":\n\t\t\treturn compareCall(args, scope, ctx, (a, b) => a !== b)\n\t\tcase \"gt\":\n\t\t\treturn compareCall(args, scope, ctx, (a, b) => {\n\t\t\t\tif (typeof a !== \"number\" || typeof b !== \"number\") return false\n\t\t\t\treturn a > b\n\t\t\t})\n\t\tcase \"lt\":\n\t\t\treturn compareCall(args, scope, ctx, (a, b) => {\n\t\t\t\tif (typeof a !== \"number\" || typeof b !== \"number\") return false\n\t\t\t\treturn a < b\n\t\t\t})\n\t\tcase \"gte\":\n\t\t\treturn compareCall(args, scope, ctx, (a, b) => {\n\t\t\t\tif (typeof a !== \"number\" || typeof b !== \"number\") return false\n\t\t\t\treturn a >= b\n\t\t\t})\n\t\tcase \"lte\":\n\t\t\treturn compareCall(args, scope, ctx, (a, b) => {\n\t\t\t\tif (typeof a !== \"number\" || typeof b !== \"number\") return false\n\t\t\t\treturn a <= b\n\t\t\t})\n\t\tcase \"if\":\n\t\t\treturn callIf(args, scope, ctx)\n\t\tcase \"t\":\n\t\t\treturn callT(args, ctx)\n\t\tcase \"icon\":\n\t\t\treturn callIcon(args, ctx)\n\t\tcase \"asset\":\n\t\t\treturn callAsset(args, ctx)\n\t\tcase \"kind\":\n\t\t\treturn callKind(args, scope, ctx)\n\t\tcase \"searchKindIcons\":\n\t\t\treturn callSearchKindIcons(scope, ctx)\n\t\tcase \"join\":\n\t\t\treturn callJoin(args, scope, ctx)\n\t\tdefault:\n\t\t\treturn \"\"\n\t}\n}\n\nfunction callPipe(\n\targs: readonly Arg[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n\tpipeFn: (value: unknown) => string,\n): string {\n\tconst value = evaluateArgAsPrimitive(args[0], scope, ctx)\n\treturn pipeFn(value)\n}\n\nfunction callT(args: readonly Arg[], ctx: TemplateContext): string {\n\tconst key = evaluateArgAsString(args[0])\n\tif (key.length === 0) return \"\"\n\tconst map = ctx.manifest.i18n\n\tif (map === undefined) return \"\"\n\tconst value = map[key]\n\tif (value === undefined) return \"\"\n\treturn resolveLocaleString(value, ctx.locale)\n}\n\nfunction callIcon(args: readonly Arg[], ctx: TemplateContext): ReactNode {\n\tconst name = evaluateArgAsString(args[0])\n\tif (name.length === 0) return null\n\treturn ctx.renderIcon({ kind: \"icon\", name }, ctx.iconClassName)\n}\n\nfunction callAsset(args: readonly Arg[], ctx: TemplateContext): ReactNode {\n\tconst path = evaluateArgAsString(args[0])\n\tif (path.length === 0) return null\n\tconst ref = parseIconRef(path, ctx.pluginId, ctx.buildAssetUrl)\n\tif (ref === undefined) return null\n\treturn ctx.renderIcon(ref, ctx.iconClassName)\n}\n\nfunction callKind(\n\targs: readonly Arg[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): ReactNode {\n\tconst key = evaluateArgAsString(args[0])\n\tif (key.length === 0) return null\n\tconst kinds = ctx.manifest.ui?.search?.kinds\n\tif (kinds === undefined) return null\n\tconst match = kinds.find((k) => k.key === key)\n\tif (match === undefined || match.icon === undefined) return null\n\tconst rendered = renderCardTemplate(match.icon, scope, ctx)\n\tif (rendered === null || rendered === undefined || rendered === \"\")\n\t\treturn null\n\treturn rendered\n}\n\nfunction callSearchKindIcons(\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): readonly ReactNode[] {\n\tif (\n\t\tscope.searchMeta === undefined ||\n\t\tscope.searchMeta === null ||\n\t\ttypeof scope.searchMeta !== \"object\"\n\t)\n\t\treturn []\n\tconst facets = (scope.searchMeta as Record<string, unknown>).facets\n\tif (facets === undefined || typeof facets !== \"object\" || facets === null)\n\t\treturn []\n\tconst kinds = ctx.manifest.ui?.search?.kinds\n\tif (kinds === undefined) return []\n\tconst results: ReactNode[] = []\n\tfor (const kind of kinds) {\n\t\tif (kind.icon === undefined) continue\n\t\tconst active = (facets as Record<string, boolean>)[kind.key]\n\t\tif (active !== true) continue\n\t\tconst rendered = renderCardTemplate(kind.icon, scope, ctx)\n\t\tif (rendered === null || rendered === undefined || rendered === \"\") continue\n\t\tresults.push(rendered)\n\t}\n\treturn results\n}\n\nfunction callJoin(\n\targs: readonly Arg[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): string | readonly ReactNode[] {\n\tif (args.length === 0) return \"\"\n\n\tconst separator = evaluateArgAsString(args[0])\n\tconst items: ReactNode[] = []\n\tfor (let i = 1; i < args.length; i++) {\n\t\tconst val = evaluateArg(args[i], scope, ctx)\n\t\tif (Array.isArray(val)) {\n\t\t\tfor (const item of val) {\n\t\t\t\tif (item !== null && item !== undefined && item !== \"\") {\n\t\t\t\t\titems.push(item)\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif (val !== null && val !== undefined && val !== \"\") {\n\t\t\titems.push(val)\n\t\t}\n\t}\n\tif (items.length === 0) return \"\"\n\tif (items.every((item) => typeof item === \"string\")) {\n\t\treturn (items as readonly string[]).join(separator)\n\t}\n\tif (separator.length === 0) return items\n\tconst interleaved: ReactNode[] = []\n\tfor (let i = 0; i < items.length; i++) {\n\t\tif (i > 0) interleaved.push(separator)\n\t\tinterleaved.push(items[i])\n\t}\n\treturn interleaved\n}\n\n// ── Argument helpers ─────────────────────────────────────────────────────────\n\nfunction evaluateArgAsPrimitive(\n\targ: Arg | undefined,\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): unknown {\n\tif (arg === undefined) return undefined\n\tif (arg.kind === \"string\") return arg.value\n\tif (arg.expr.kind === \"path\") {\n\t\tconst segments = arg.expr.segments\n\t\tif (segments.length === 1) {\n\t\t\tconst seg = segments[0]!\n\t\t\tconst num = Number(seg)\n\t\t\tif (!Number.isNaN(num)) return num\n\t\t}\n\t\treturn resolvePath(segments, scope)\n\t}\n\tif (arg.expr.kind === \"call\") {\n\t\tconst result = evaluateCall(arg.expr.name, arg.expr.args, scope, ctx)\n\t\tif (typeof result === \"string\" || typeof result === \"number\") return result\n\t\tif (Array.isArray(result)) return result\n\t\treturn undefined\n\t}\n\treturn undefined\n}\n\nfunction evaluateArg(\n\targ: Arg | undefined,\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): EvalValue {\n\tif (arg === undefined) return undefined\n\tif (arg.kind === \"string\") return arg.value\n\treturn evaluateExpression(arg.expr, scope, ctx)\n}\n\nfunction compareCall(\n\targs: readonly Arg[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n\tcmp: (a: unknown, b: unknown) => boolean,\n): string {\n\tconst a = evaluateArgAsPrimitive(args[0], scope, ctx)\n\tconst b = evaluateArgAsPrimitive(args[1], scope, ctx)\n\treturn cmp(a, b) ? \"true\" : \"\"\n}\n\nfunction callIf(\n\targs: readonly Arg[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): EvalValue {\n\tconst cond = evaluateArgAsPrimitive(args[0], scope, ctx)\n\tconst truthy =\n\t\tcond !== undefined &&\n\t\tcond !== null &&\n\t\tcond !== \"\" &&\n\t\tcond !== false &&\n\t\tcond !== 0\n\tif (truthy) {\n\t\tconst raw = evaluateArgAsPrimitive(args[1], scope, ctx)\n\t\tif (raw !== undefined) return raw as EvalValue\n\t\treturn evaluateArg(args[1], scope, ctx)\n\t}\n\tif (args.length > 2) {\n\t\tconst raw = evaluateArgAsPrimitive(args[2], scope, ctx)\n\t\tif (raw !== undefined) return raw as EvalValue\n\t\treturn evaluateArg(args[2], scope, ctx)\n\t}\n\treturn \"\"\n}\n\nfunction evaluateArgAsString(arg: Arg | undefined): string {\n\tif (arg === undefined) return \"\"\n\tif (arg.kind === \"string\") return arg.value\n\treturn \"\"\n}\n\n// ── Public API ───────────────────────────────────────────────────────────────\n\n/**\n * Render one res-card template string. Returns a ReactNode so that\n * icon-producing functions (`icon`, `asset`, `kind`) can inject\n * components inline with text.\n */\nexport function renderCardTemplate(\n\ttemplate: string,\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): ReactNode {\n\tif (template.length === 0) return \"\"\n\tconst fragments = parseTemplateFragments(template)\n\tif (fragments.length === 0) return \"\"\n\n\tconst results: ReactNode[] = []\n\tfor (const frag of fragments) {\n\t\tif (frag.kind === \"text\") {\n\t\t\tresults.push(frag.value)\n\t\t\tcontinue\n\t\t}\n\t\tconst expr = parseTemplateExpression(frag.source)\n\t\tif (expr === undefined) {\n\t\t\tcontinue\n\t\t}\n\t\tconst value = evaluateExpression(expr, scope, ctx)\n\t\tif (value !== null && value !== undefined && value !== \"\") {\n\t\t\tresults.push(value)\n\t\t}\n\t}\n\n\tif (results.length === 0) return null\n\tif (results.length === 1) return results[0]\n\tconst allStrings = results.every((r) => typeof r === \"string\")\n\tif (allStrings) return results.join(\"\")\n\treturn results\n}\n\n/** Render every badge in a {@link CoverKindUi} slot array. */\nexport function renderSlotBadges(\n\tslotValues: readonly string[],\n\tscope: TemplateScope,\n\tctx: TemplateContext,\n): readonly ReactNode[] {\n\treturn slotValues\n\t\t.map((template) => renderCardTemplate(template, scope, ctx))\n\t\t.filter((n): n is Exclude<typeof n, null | undefined | \"\"> => {\n\t\t\tif (n === null || n === undefined || n === \"\") return false\n\t\t\tif (Array.isArray(n) && n.length === 0) return false\n\t\t\treturn true\n\t\t})\n}\n"]}
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"template.js"}
|
package/dist/viewport.js
CHANGED
|
@@ -1,13 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
var MOBILE_INITIAL_SCALE = 0.8;
|
|
3
|
-
var MOBILE_BREAKPOINT_PX = 768;
|
|
4
|
-
var MOBILE_BREAKPOINT_REM = MOBILE_BREAKPOINT_PX / 16;
|
|
5
|
-
var MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT_PX - 1}px)`;
|
|
6
|
-
var SIDEBAR_BREAKPOINT_PX = 1150;
|
|
7
|
-
var SIDEBAR_QUERY = `(max-width: ${SIDEBAR_BREAKPOINT_PX - 1}px)`;
|
|
8
|
-
var PANEL_BREAKPOINT_PX = 1440;
|
|
9
|
-
var PANEL_QUERY = `(max-width: ${PANEL_BREAKPOINT_PX - 1}px)`;
|
|
10
|
-
|
|
11
|
-
export { MOBILE_BREAKPOINT_PX, MOBILE_BREAKPOINT_REM, MOBILE_INITIAL_SCALE, MOBILE_QUERY, PANEL_BREAKPOINT_PX, PANEL_QUERY, SIDEBAR_BREAKPOINT_PX, SIDEBAR_QUERY };
|
|
1
|
+
export { MOBILE_BREAKPOINT_PX, MOBILE_BREAKPOINT_REM, MOBILE_INITIAL_SCALE, MOBILE_QUERY, PANEL_BREAKPOINT_PX, PANEL_QUERY, SIDEBAR_BREAKPOINT_PX, SIDEBAR_QUERY } from './chunk-KNPRUZ4H.js';
|
|
12
2
|
//# sourceMappingURL=viewport.js.map
|
|
13
3
|
//# sourceMappingURL=viewport.js.map
|
package/dist/viewport.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"viewport.js"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hoardodile/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "shadcn/ui component library for hoardodile plugin iframes.",
|
|
6
6
|
"keywords": [
|
|
@@ -83,8 +83,8 @@
|
|
|
83
83
|
"react-image-crop": "^11.1.2",
|
|
84
84
|
"react-use": "^17.6.1",
|
|
85
85
|
"tailwind-merge": "^3.6.0",
|
|
86
|
-
"@hoardodile/
|
|
87
|
-
"@hoardodile/
|
|
86
|
+
"@hoardodile/sdk-types": "0.1.9",
|
|
87
|
+
"@hoardodile/i18n": "0.1.9"
|
|
88
88
|
},
|
|
89
89
|
"peerDependencies": {
|
|
90
90
|
"i18next": "^26.4.0",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { resolve } from "node:path"
|
|
3
|
+
import { screen, within } from "@testing-library/react"
|
|
4
|
+
import { describe, expect, it, vi } from "vitest"
|
|
5
|
+
import { renderWithI18n } from "../test/i18n"
|
|
6
|
+
|
|
7
|
+
const TALL_IMAGE_SRC =
|
|
8
|
+
"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='1000' height='2000'%3E%3Crect width='100%25' height='100%25' fill='red'/%3E%3C/svg%3E"
|
|
9
|
+
|
|
10
|
+
// This suite exercises the PUBLISHED bundle (`dist/`), not `src/`. The
|
|
11
|
+
// `DialogFooterActions` routing relies on a single React context shared by
|
|
12
|
+
// `AppDialog` (the provider) and `ImageCropPanel` (the consumer). With
|
|
13
|
+
// `splitting: false` (see tsup.config.ts) tsup inlines that shared module into
|
|
14
|
+
// every entry, so the dist carries TWO copies of the context and production
|
|
15
|
+
// bundles give the provider and consumer different instances — the crop action
|
|
16
|
+
// then falls back to an inline row instead of the dialog footer. When the
|
|
17
|
+
// package has not been built there is no dist to test, so skip gracefully.
|
|
18
|
+
const distAppDialog = resolve(process.cwd(), "dist/components/app-dialog.js")
|
|
19
|
+
const built = existsSync(distAppDialog)
|
|
20
|
+
|
|
21
|
+
describe.skipIf(!built)("ImageCropPanel (production dist)", () => {
|
|
22
|
+
it("lands the crop action on the same dialog footer row as cancel", async () => {
|
|
23
|
+
const { AppDialog } = await import("../../dist/components/app-dialog")
|
|
24
|
+
const { ImageCropPanel } = await import("../../dist/components/image-crop-panel")
|
|
25
|
+
|
|
26
|
+
renderWithI18n(
|
|
27
|
+
<AppDialog
|
|
28
|
+
open
|
|
29
|
+
title="Cover"
|
|
30
|
+
onOpenChange={() => {}}
|
|
31
|
+
footer={
|
|
32
|
+
<button type="button" data-testid="dialog-cancel">
|
|
33
|
+
Cancel
|
|
34
|
+
</button>
|
|
35
|
+
}
|
|
36
|
+
>
|
|
37
|
+
<ImageCropPanel initialSrc={TALL_IMAGE_SRC} onSave={vi.fn()} />
|
|
38
|
+
</AppDialog>,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
await screen.findByRole("img")
|
|
42
|
+
const footer = document.querySelector('[data-slot="dialog-footer"]')
|
|
43
|
+
expect(footer).not.toBeNull()
|
|
44
|
+
// The crop action must be contributed into the SAME footer row as
|
|
45
|
+
// cancel — this is what breaks when the dist duplicates the
|
|
46
|
+
// `DialogFooterActionsContext` across entries.
|
|
47
|
+
expect(
|
|
48
|
+
within(footer as HTMLElement).getByTestId("image-crop-save"),
|
|
49
|
+
).toBeInTheDocument()
|
|
50
|
+
expect(
|
|
51
|
+
within(footer as HTMLElement).getByTestId("dialog-cancel"),
|
|
52
|
+
).toBeInTheDocument()
|
|
53
|
+
})
|
|
54
|
+
})
|