@tekki-forge/compiler 0.0.0-stage → 0.1.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.
Files changed (47) hide show
  1. package/README.md +4 -2
  2. package/dist/compile.d.ts +17 -0
  3. package/dist/compile.js +691 -0
  4. package/dist/compile.js.map +1 -0
  5. package/dist/dashboard.d.ts +7 -0
  6. package/dist/dashboard.js +103 -0
  7. package/dist/dashboard.js.map +1 -0
  8. package/dist/features.d.ts +13 -0
  9. package/dist/features.js +247 -0
  10. package/dist/features.js.map +1 -0
  11. package/dist/files.d.ts +34 -0
  12. package/dist/files.js +32 -0
  13. package/dist/files.js.map +1 -0
  14. package/dist/i18n.d.ts +24 -0
  15. package/dist/i18n.js +168 -0
  16. package/dist/i18n.js.map +1 -0
  17. package/dist/index.d.ts +11 -0
  18. package/dist/index.js +12 -0
  19. package/dist/index.js.map +1 -0
  20. package/dist/indexes.d.ts +13 -0
  21. package/dist/indexes.js +71 -0
  22. package/dist/indexes.js.map +1 -0
  23. package/dist/ir.d.ts +413 -0
  24. package/dist/ir.js +27 -0
  25. package/dist/ir.js.map +1 -0
  26. package/dist/landing.d.ts +5 -0
  27. package/dist/landing.js +73 -0
  28. package/dist/landing.js.map +1 -0
  29. package/dist/load.d.ts +12 -0
  30. package/dist/load.js +38 -0
  31. package/dist/load.js.map +1 -0
  32. package/dist/naming.d.ts +11 -0
  33. package/dist/naming.js +58 -0
  34. package/dist/naming.js.map +1 -0
  35. package/dist/notifications.d.ts +5 -0
  36. package/dist/notifications.js +80 -0
  37. package/dist/notifications.js.map +1 -0
  38. package/dist/rules.d.ts +4 -0
  39. package/dist/rules.js +43 -0
  40. package/dist/rules.js.map +1 -0
  41. package/dist/theme.d.ts +69 -0
  42. package/dist/theme.js +257 -0
  43. package/dist/theme.js.map +1 -0
  44. package/dist/ui.d.ts +83 -0
  45. package/dist/ui.js +102 -0
  46. package/dist/ui.js.map +1 -0
  47. package/package.json +41 -3
@@ -0,0 +1,80 @@
1
+ const ACTIONS = ["created", "updated", "deleted", "restored", "transitioned", "action"];
2
+ /** Placeholders like {number} or {customer} in notification texts. */
3
+ export function placeholders(text) {
4
+ return [...text.matchAll(/\{([A-Za-z_][A-Za-z0-9_]*)\}/g)].map((m) => m[1]);
5
+ }
6
+ export function compileNotifications(rules, entities, roles, issue) {
7
+ const out = [];
8
+ for (const [i, rule] of (rules ?? []).entries()) {
9
+ const at = `notifications[${i}]`;
10
+ const m = /^([A-Z][A-Za-z0-9]*)\.([a-z]+)(?::([A-Za-z0-9_]+))?$/.exec(rule.on ?? "");
11
+ if (!m) {
12
+ issue(`${at}.on`, `use "<Entity>.<action>" or "<Entity>.<action>:<name>", e.g. "Invoice.transitioned:send"`);
13
+ continue;
14
+ }
15
+ const [, entityName, action, name] = m;
16
+ const entity = entities.find((e) => e.name === entityName);
17
+ if (!entity) {
18
+ issue(`${at}.on`, `unknown entity "${entityName}"`);
19
+ continue;
20
+ }
21
+ if (!ACTIONS.includes(action))
22
+ issue(`${at}.on`, `unknown action "${action}" (${ACTIONS.join(", ")})`);
23
+ if (name) {
24
+ const known = action === "transitioned" ? entity.workflow?.transitions.map((t) => t.name) : action === "action" ? entity.actions.map((a) => a.name) : undefined;
25
+ if (!known)
26
+ issue(`${at}.on`, `":${name}" only applies to transitioned or action events`);
27
+ else if (!known.includes(name))
28
+ issue(`${at}.on`, `${entity.name} has no ${action === "action" ? "action" : "transition"} "${name}"`);
29
+ }
30
+ const to = [];
31
+ for (const target of typeof rule.to === "string" ? [rule.to] : [...(rule.to ?? [])]) {
32
+ if (target === "owner") {
33
+ if (!entity.ownerField)
34
+ issue(`${at}.to`, `${entity.name} has no owner relation`);
35
+ to.push({ kind: "owner" });
36
+ }
37
+ else if (target.startsWith("role:")) {
38
+ const role = target.slice(5);
39
+ if (!roles.includes(role))
40
+ issue(`${at}.to`, `unknown role "${role}"`);
41
+ to.push({ kind: "role", role });
42
+ }
43
+ else {
44
+ const f = entity.fields.find((x) => x.name === target);
45
+ if (!f || f.relation?.entity !== "User")
46
+ issue(`${at}.to`, `"${target}" must be "owner", "role:<role>" or a User relation of ${entity.name}`);
47
+ to.push({ kind: "field", field: target });
48
+ }
49
+ }
50
+ if (to.length === 0)
51
+ issue(`${at}.to`, "name at least one recipient");
52
+ if (!rule.title?.trim())
53
+ issue(`${at}.title`, "required");
54
+ const known = new Set(["actor", "entity", "id", ...entity.fields.map((f) => f.name)]);
55
+ for (const key of ["title", "body", "link"]) {
56
+ for (const p of placeholders(rule[key] ?? ""))
57
+ if (!known.has(p))
58
+ issue(`${at}.${key}`, `unknown placeholder {${p}} — use a field of ${entity.name}, {actor} or {entity}`);
59
+ }
60
+ if (rule.when?.changed) {
61
+ if (action !== "updated")
62
+ issue(`${at}.when`, `"changed" only applies to updated events`);
63
+ if (!entity.fields.some((f) => f.name === rule.when.changed))
64
+ issue(`${at}.when.changed`, `unknown field "${rule.when.changed}"`);
65
+ }
66
+ out.push({
67
+ entity: entity.name,
68
+ action: action,
69
+ ...(name ? { name } : {}),
70
+ to,
71
+ title: rule.title,
72
+ ...(rule.body ? { body: rule.body } : {}),
73
+ link: rule.link ?? `/${entity.path}/{id}`,
74
+ email: !!rule.email,
75
+ ...(rule.when?.changed ? { changed: rule.when.changed } : {}),
76
+ });
77
+ }
78
+ return out;
79
+ }
80
+ //# sourceMappingURL=notifications.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,GAAG,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,CAAU,CAAC;AAEjG,sEAAsE;AACtE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,+BAA+B,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,KAA8C,EAAE,QAAoB,EAAE,KAAe,EAAE,KAA8C;IACxK,MAAM,GAAG,GAAyB,EAAE,CAAC;IACrC,KAAK,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC;QAChD,MAAM,EAAE,GAAG,iBAAiB,CAAC,GAAG,CAAC;QACjC,MAAM,CAAC,GAAG,sDAAsD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACrF,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,yFAAyF,CAAC,CAAC;YAC7G,SAAS;QACX,CAAC;QACD,MAAM,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAC3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,mBAAmB,UAAU,GAAG,CAAC,CAAC;YACpD,SAAS;QACX,CAAC;QACD,IAAI,CAAE,OAA6B,CAAC,QAAQ,CAAC,MAAO,CAAC;YAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,mBAAmB,MAAM,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/H,IAAI,IAAI,EAAE,CAAC;YACT,MAAM,KAAK,GAAG,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAChK,IAAI,CAAC,KAAK;gBAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,IAAI,iDAAiD,CAAC,CAAC;iBACrF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,WAAW,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,GAAG,CAAC,CAAC;QACxI,CAAC;QACD,MAAM,EAAE,GAA6B,EAAE,CAAC;QACxC,KAAK,MAAM,MAAM,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;YACpF,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;gBACvB,IAAI,CAAC,MAAM,CAAC,UAAU;oBAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,wBAAwB,CAAC,CAAC;gBAClF,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC7B,CAAC;iBAAM,IAAI,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC7B,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC;oBAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,iBAAiB,IAAI,GAAG,CAAC,CAAC;gBACvE,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;gBACvD,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM;oBAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,MAAM,0DAA0D,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC9I,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QACD,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,6BAA6B,CAAC,CAAC;QACtE,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;YAAE,KAAK,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtF,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAU,EAAE,CAAC;YACrD,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;gBAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;oBAAE,KAAK,CAAC,GAAG,EAAE,IAAI,GAAG,EAAE,EAAE,wBAAwB,CAAC,sBAAsB,MAAM,CAAC,IAAI,uBAAuB,CAAC,CAAC;QAC7K,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,CAAC;YACvB,IAAI,MAAM,KAAK,SAAS;gBAAE,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,0CAA0C,CAAC,CAAC;YAC1F,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAK,CAAC,OAAO,CAAC;gBAAE,KAAK,CAAC,GAAG,EAAE,eAAe,EAAE,kBAAkB,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;QACrI,CAAC;QACD,GAAG,CAAC,IAAI,CAAC;YACP,MAAM,EAAE,MAAM,CAAC,IAAI;YACnB,MAAM,EAAE,MAAsC;YAC9C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzB,EAAE;YACF,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI,OAAO;YACzC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;YACnB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { PermissionRule } from "@tekki-forge/core";
2
+ import type { Operation, PermissionIR } from "./ir.js";
3
+ export declare const allowAll: () => PermissionIR;
4
+ export declare function compileRule(rule: PermissionRule, at: string, op: Operation, roles: string[], hasOwner: boolean, issue: (p: string, m: string) => void, hasTeam?: boolean): PermissionIR;
package/dist/rules.js ADDED
@@ -0,0 +1,43 @@
1
+ import { isCamelCase } from "./naming.js";
2
+ export const allowAll = () => ({ roles: [], owner: false, authenticated: false, public: true, policies: [] });
3
+ export function compileRule(rule, at, op, roles, hasOwner, issue, hasTeam = false) {
4
+ const out = { roles: [], owner: false, authenticated: false, public: false, policies: [] };
5
+ if (!Array.isArray(rule)) {
6
+ issue(at, "must be an array of roles or tokens");
7
+ return out;
8
+ }
9
+ for (const token of rule) {
10
+ if (token === "owner") {
11
+ if (!hasOwner)
12
+ issue(at, `"owner" requires a relation to User named "owner" or marked { owner: true }`);
13
+ if (op === "create")
14
+ issue(at, `"owner" cannot be used for create — the record does not exist yet`);
15
+ out.owner = true;
16
+ }
17
+ else if (token === "team") {
18
+ // On create, "team" means: the new record is assigned to one of the caller's teams.
19
+ if (!hasTeam)
20
+ issue(at, `"team" requires features: { teams: true } on the entity`);
21
+ out.team = true;
22
+ }
23
+ else if (token === "authenticated")
24
+ out.authenticated = true;
25
+ else if (token === "public") {
26
+ if (op !== "read")
27
+ issue(at, `"public" is only allowed for read`);
28
+ out.public = true;
29
+ }
30
+ else if (token.startsWith("policy:")) {
31
+ const name = token.slice("policy:".length);
32
+ if (!isCamelCase(name))
33
+ issue(at, `policy name "${name}" must be camelCase`);
34
+ out.policies.push(name);
35
+ }
36
+ else if (roles.includes(token))
37
+ out.roles.push(token);
38
+ else
39
+ issue(at, `unknown role "${token}" — declare it in roles: [...] or use owner, team, authenticated, public, policy:<name>`);
40
+ }
41
+ return out;
42
+ }
43
+ //# sourceMappingURL=rules.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../src/rules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAiB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;AAE5H,MAAM,UAAU,WAAW,CACzB,IAAoB,EACpB,EAAU,EACV,EAAa,EACb,KAAe,EACf,QAAiB,EACjB,KAAqC,EACrC,OAAO,GAAG,KAAK;IAEf,MAAM,GAAG,GAAiB,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IACzG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,EAAE,EAAE,qCAAqC,CAAC,CAAC;QACjD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC,QAAQ;gBAAE,KAAK,CAAC,EAAE,EAAE,6EAA6E,CAAC,CAAC;YACxG,IAAI,EAAE,KAAK,QAAQ;gBAAE,KAAK,CAAC,EAAE,EAAE,mEAAmE,CAAC,CAAC;YACpG,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC;QACnB,CAAC;aAAM,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;YAC5B,oFAAoF;YACpF,IAAI,CAAC,OAAO;gBAAE,KAAK,CAAC,EAAE,EAAE,yDAAyD,CAAC,CAAC;YACnF,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAClB,CAAC;aAAM,IAAI,KAAK,KAAK,eAAe;YAAE,GAAG,CAAC,aAAa,GAAG,IAAI,CAAC;aAC1D,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC5B,IAAI,EAAE,KAAK,MAAM;gBAAE,KAAK,CAAC,EAAE,EAAE,mCAAmC,CAAC,CAAC;YAClE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC;QACpB,CAAC;aAAM,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YAC3C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,EAAE,EAAE,gBAAgB,IAAI,qBAAqB,CAAC,CAAC;YAC7E,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;aAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;;YACnD,KAAK,CAAC,EAAE,EAAE,iBAAiB,KAAK,yFAAyF,CAAC,CAAC;IAClI,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { ThemeConfig } from "@tekki-forge/core";
2
+ import type { ThemeFontName, ThemeIR, ThemePresetName, ThemeStyleName } from "./ir.js";
3
+ export declare const UI_STYLES: readonly ["simple", "shadow", "neumorphism", "glassmorphism", "skeuomorphism", "material", "brutalist", "editorial", "aurora", "terminal", "clay"];
4
+ export declare const THEME_MODES: readonly ["light", "dark", "system"];
5
+ export declare const RADII: readonly ["none", "small", "medium", "large", "full"];
6
+ export declare const THEME_LAYOUTS: readonly ["sidebar", "topbar", "compact"];
7
+ export declare const THEME_DENSITIES: readonly ["comfortable", "compact"];
8
+ export declare const THEME_FONT_NAMES: readonly ["inter", "geist", "plex", "grotesk", "serif", "rounded", "mono", "system"];
9
+ export declare const THEME_PRESET_NAMES: readonly ["midnight", "sandstone", "ocean", "forest", "sunset", "graphite", "candy", "paper", "phosphor"];
10
+ export interface ThemeFontDefinition {
11
+ label: string;
12
+ hint: string;
13
+ /** CSS font stacks, each ending with system fallbacks. */
14
+ display: string;
15
+ body: string;
16
+ /** Google Fonts css2 `family=` values (empty: nothing to load). */
17
+ families: readonly string[];
18
+ }
19
+ /** Typeface pairings: display (headings, metrics) + body. */
20
+ export declare const THEME_FONTS: Record<ThemeFontName, ThemeFontDefinition>;
21
+ /** Google Fonts stylesheet for a font pairing (null when nothing needs loading). */
22
+ export declare function fontStylesheet(font: ThemeFontName): string | null;
23
+ export interface ThemePresetDefinition {
24
+ label: string;
25
+ description: string;
26
+ style: ThemeStyleName;
27
+ primary: string;
28
+ accent: string;
29
+ mode: ThemeIR["mode"];
30
+ radius: ThemeIR["radius"];
31
+ font: ThemeFontName;
32
+ layout: ThemeIR["layout"];
33
+ density: ThemeIR["density"];
34
+ }
35
+ /** Curated looks. Explicit theme keys override any of these values. */
36
+ export declare const THEME_PRESETS: Record<ThemePresetName, ThemePresetDefinition>;
37
+ /** What a style brings along when the theme doesn't say otherwise. */
38
+ export declare const STYLE_DEFAULTS: Partial<Record<ThemeStyleName, {
39
+ font?: ThemeFontName;
40
+ mode?: ThemeIR["mode"];
41
+ }>>;
42
+ export interface ThemeBase {
43
+ style: ThemeStyleName;
44
+ primary: string;
45
+ accent: string;
46
+ mode: ThemeIR["mode"];
47
+ radius: ThemeIR["radius"];
48
+ font: ThemeFontName;
49
+ layout: ThemeIR["layout"];
50
+ density: ThemeIR["density"];
51
+ }
52
+ /**
53
+ * The values a theme gets for every key it doesn't set: Forge defaults, then the preset, then (when the style
54
+ * isn't the preset's own) the style's companions such as terminal → mono font, dark mode.
55
+ */
56
+ export declare function themeBase(preset?: ThemePresetName | null, style?: ThemeStyleName): ThemeBase;
57
+ export declare function resolvePreset(input: string): ThemePresetName | undefined;
58
+ /**
59
+ * A logo reference as served by the web app: absolute http(s) URLs pass through; file paths are taken
60
+ * relative to apps/web/public ("logo.svg", "public/logo.svg", "apps/web/public/logo.svg" → "/logo.svg").
61
+ */
62
+ export declare function normalizeLogo(input: string): string | undefined;
63
+ export declare const DEFAULT_THEME: ThemeIR;
64
+ export declare function normalizeHex(input: string): string | undefined;
65
+ export declare function contrast(a: string, b: string): number;
66
+ /** White or near-black, whichever reads better on `hex`. */
67
+ export declare function readableOn(hex: string): string;
68
+ export declare function resolveStyle(input: string): ThemeIR["style"] | undefined;
69
+ export declare function compileTheme(theme: ThemeConfig | undefined, issue: (path: string, message: string) => void): ThemeIR;
package/dist/theme.js ADDED
@@ -0,0 +1,257 @@
1
+ export const UI_STYLES = ["simple", "shadow", "neumorphism", "glassmorphism", "skeuomorphism", "material", "brutalist", "editorial", "aurora", "terminal", "clay"];
2
+ export const THEME_MODES = ["light", "dark", "system"];
3
+ export const RADII = ["none", "small", "medium", "large", "full"];
4
+ export const THEME_LAYOUTS = ["sidebar", "topbar", "compact"];
5
+ export const THEME_DENSITIES = ["comfortable", "compact"];
6
+ export const THEME_FONT_NAMES = ["inter", "geist", "plex", "grotesk", "serif", "rounded", "mono", "system"];
7
+ export const THEME_PRESET_NAMES = ["midnight", "sandstone", "ocean", "forest", "sunset", "graphite", "candy", "paper", "phosphor"];
8
+ const SANS = `ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif`;
9
+ const SERIF = `ui-serif, Georgia, Cambria, "Times New Roman", serif`;
10
+ const MONO = `ui-monospace, SFMono-Regular, Menlo, Consolas, monospace`;
11
+ /** Typeface pairings: display (headings, metrics) + body. */
12
+ export const THEME_FONTS = {
13
+ inter: { label: "Inter", hint: "neutral and very legible", display: `"Inter", ${SANS}`, body: `"Inter", ${SANS}`, families: ["Inter:wght@400;500;600;700"] },
14
+ geist: { label: "Geist", hint: "crisp, technical sans", display: `"Geist", ${SANS}`, body: `"Geist", ${SANS}`, families: ["Geist:wght@400;500;600;700"] },
15
+ plex: { label: "IBM Plex", hint: "engineered, friendly corporate", display: `"IBM Plex Sans", ${SANS}`, body: `"IBM Plex Sans", ${SANS}`, families: ["IBM+Plex+Sans:wght@400;500;600;700"] },
16
+ grotesk: { label: "Space Grotesk + Inter", hint: "quirky geometric headings", display: `"Space Grotesk", ${SANS}`, body: `"Inter", ${SANS}`, families: ["Space+Grotesk:wght@500;600;700", "Inter:wght@400;500;600;700"] },
17
+ serif: { label: "Fraunces + Inter", hint: "editorial serif headings", display: `"Fraunces", ${SERIF}`, body: `"Inter", ${SANS}`, families: ["Fraunces:opsz,wght@9..144,500..700", "Inter:wght@400;500;600;700"] },
18
+ rounded: { label: "Nunito", hint: "soft, rounded and warm", display: `"Nunito", ${SANS}`, body: `"Nunito", ${SANS}`, families: ["Nunito:wght@400;500;600;700;800"] },
19
+ mono: { label: "JetBrains Mono", hint: "monospace everywhere", display: `"JetBrains Mono", ${MONO}`, body: `"JetBrains Mono", ${MONO}`, families: ["JetBrains+Mono:wght@400;500;600;700"] },
20
+ system: { label: "System", hint: "the device's own font, nothing to load", display: SANS, body: SANS, families: [] },
21
+ };
22
+ /** Google Fonts stylesheet for a font pairing (null when nothing needs loading). */
23
+ export function fontStylesheet(font) {
24
+ const families = THEME_FONTS[font].families;
25
+ return families.length ? `https://fonts.googleapis.com/css2?${families.map((f) => `family=${f}`).join("&")}&display=swap` : null;
26
+ }
27
+ /** Curated looks. Explicit theme keys override any of these values. */
28
+ export const THEME_PRESETS = {
29
+ midnight: { label: "Midnight", description: "deep indigo aurora, glassy cards, Geist", style: "aurora", primary: "#4f46e5", accent: "#22d3ee", mode: "dark", radius: "large", font: "geist", layout: "sidebar", density: "comfortable" },
30
+ sandstone: { label: "Sandstone", description: "warm terracotta, soft extruded surfaces", style: "neumorphism", primary: "#c2410c", accent: "#0d9488", mode: "light", radius: "large", font: "plex", layout: "sidebar", density: "comfortable" },
31
+ ocean: { label: "Ocean", description: "frosted glass over sea blues", style: "glassmorphism", primary: "#0369a1", accent: "#14b8a6", mode: "system", radius: "large", font: "inter", layout: "sidebar", density: "comfortable" },
32
+ forest: { label: "Forest", description: "evergreen and gold, serif headings, top bar", style: "shadow", primary: "#15803d", accent: "#ca8a04", mode: "light", radius: "medium", font: "serif", layout: "topbar", density: "comfortable" },
33
+ sunset: { label: "Sunset", description: "puffy clay in rose and orange", style: "clay", primary: "#e11d48", accent: "#f97316", mode: "light", radius: "large", font: "rounded", layout: "sidebar", density: "comfortable" },
34
+ graphite: { label: "Graphite", description: "dense, neutral, icon rail — for power users", style: "simple", primary: "#52525b", accent: "#84cc16", mode: "system", radius: "small", font: "grotesk", layout: "compact", density: "compact" },
35
+ candy: { label: "Candy", description: "neo-brutalist pink and yellow", style: "brutalist", primary: "#db2777", accent: "#facc15", mode: "light", radius: "none", font: "grotesk", layout: "topbar", density: "comfortable" },
36
+ paper: { label: "Paper", description: "ink on paper, editorial serif", style: "editorial", primary: "#1c1917", accent: "#b91c1c", mode: "light", radius: "none", font: "serif", layout: "topbar", density: "comfortable" },
37
+ phosphor: { label: "Phosphor", description: "green-on-black terminal, monospace", style: "terminal", primary: "#16a34a", accent: "#f59e0b", mode: "dark", radius: "small", font: "mono", layout: "compact", density: "compact" },
38
+ };
39
+ /** What a style brings along when the theme doesn't say otherwise. */
40
+ export const STYLE_DEFAULTS = {
41
+ brutalist: { font: "grotesk" },
42
+ editorial: { font: "serif" },
43
+ terminal: { font: "mono", mode: "dark" },
44
+ clay: { font: "rounded" },
45
+ };
46
+ /**
47
+ * The values a theme gets for every key it doesn't set: Forge defaults, then the preset, then (when the style
48
+ * isn't the preset's own) the style's companions such as terminal → mono font, dark mode.
49
+ */
50
+ export function themeBase(preset, style) {
51
+ const p = preset ? THEME_PRESETS[preset] : undefined;
52
+ const base = p
53
+ ? { style: p.style, primary: p.primary, accent: p.accent, mode: p.mode, radius: p.radius, font: p.font, layout: p.layout, density: p.density }
54
+ : { style: DEFAULT_THEME.style, primary: DEFAULT_THEME.colors.primary, accent: DEFAULT_THEME.colors.accent, mode: DEFAULT_THEME.mode, radius: DEFAULT_THEME.radius, font: "system", layout: "sidebar", density: "comfortable" };
55
+ const finalStyle = style ?? base.style;
56
+ if (!p || finalStyle !== p.style)
57
+ Object.assign(base, STYLE_DEFAULTS[finalStyle] ?? {});
58
+ base.style = finalStyle;
59
+ return base;
60
+ }
61
+ export function resolvePreset(input) {
62
+ const k = input.trim().toLowerCase();
63
+ return THEME_PRESET_NAMES.includes(k) ? k : undefined;
64
+ }
65
+ const LOGO_FILE = /^\/[\w@.\/-]+\.(svg|png|jpe?g|webp|gif|ico|avif)$/i;
66
+ /**
67
+ * A logo reference as served by the web app: absolute http(s) URLs pass through; file paths are taken
68
+ * relative to apps/web/public ("logo.svg", "public/logo.svg", "apps/web/public/logo.svg" → "/logo.svg").
69
+ */
70
+ export function normalizeLogo(input) {
71
+ const v = input.trim();
72
+ if (/^https?:\/\//i.test(v)) {
73
+ if (/\s/.test(v))
74
+ return undefined;
75
+ try {
76
+ const url = new URL(v);
77
+ return url.hostname ? url.toString() : undefined;
78
+ }
79
+ catch {
80
+ return undefined;
81
+ }
82
+ }
83
+ let path = v.replace(/^\.\//, "").replace(/^(apps\/web\/)?public\//, "");
84
+ if (!path.startsWith("/"))
85
+ path = `/${path}`;
86
+ if (path.startsWith("//") || path.split("/").includes("..") || !LOGO_FILE.test(path))
87
+ return undefined;
88
+ return path;
89
+ }
90
+ /** Common spellings people use for the styles. */
91
+ const STYLE_ALIASES = {
92
+ flat: "simple",
93
+ shadowy: "shadow",
94
+ shadows: "shadow",
95
+ neomorphism: "neumorphism",
96
+ neumorphic: "neumorphism",
97
+ glass: "glassmorphism",
98
+ glassmorphic: "glassmorphism",
99
+ skeumorphism: "skeuomorphism",
100
+ skeuomorphic: "skeuomorphism",
101
+ skeumorphim: "skeuomorphism",
102
+ "material-design": "material",
103
+ md3: "material",
104
+ brutal: "brutalist",
105
+ brutalism: "brutalist",
106
+ neobrutalism: "brutalist",
107
+ "neo-brutalism": "brutalist",
108
+ "neo-brutalist": "brutalist",
109
+ magazine: "editorial",
110
+ print: "editorial",
111
+ gradient: "aurora",
112
+ mesh: "aurora",
113
+ console: "terminal",
114
+ hacker: "terminal",
115
+ cli: "terminal",
116
+ crt: "terminal",
117
+ claymorphism: "clay",
118
+ claymorphic: "clay",
119
+ };
120
+ export const DEFAULT_THEME = {
121
+ preset: null,
122
+ style: "simple",
123
+ mode: "light",
124
+ radius: "medium",
125
+ colors: {
126
+ primary: "#4f46e5",
127
+ primaryForeground: "#ffffff",
128
+ accent: "#f59e0b",
129
+ accentForeground: "#111827",
130
+ danger: "#dc2626",
131
+ dangerForeground: "#ffffff",
132
+ },
133
+ font: "system",
134
+ fonts: { body: SANS, display: SANS, stylesheet: null },
135
+ layout: "sidebar",
136
+ density: "comfortable",
137
+ logo: null,
138
+ tagline: null,
139
+ };
140
+ export function normalizeHex(input) {
141
+ const m = /^#?([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(input.trim());
142
+ if (!m)
143
+ return undefined;
144
+ const h = m[1].length === 3 ? [...m[1]].map((c) => c + c).join("") : m[1];
145
+ return `#${h.toLowerCase()}`;
146
+ }
147
+ function luminance(hex) {
148
+ const [r, g, b] = [1, 3, 5].map((i) => {
149
+ const c = parseInt(hex.slice(i, i + 2), 16) / 255;
150
+ return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
151
+ });
152
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
153
+ }
154
+ export function contrast(a, b) {
155
+ const [l1, l2] = [luminance(a), luminance(b)].sort((x, y) => y - x);
156
+ return (l1 + 0.05) / (l2 + 0.05);
157
+ }
158
+ /** White or near-black, whichever reads better on `hex`. */
159
+ export function readableOn(hex) {
160
+ return contrast(hex, "#ffffff") >= contrast(hex, "#111827") ? "#ffffff" : "#111827";
161
+ }
162
+ export function resolveStyle(input) {
163
+ const k = input.trim().toLowerCase();
164
+ return UI_STYLES.includes(k) ? k : STYLE_ALIASES[k];
165
+ }
166
+ const TAGLINE_MAX = 160;
167
+ export function compileTheme(theme, issue) {
168
+ const t = theme ?? {};
169
+ const oneOf = (key, value, allowed, fallback, noun) => {
170
+ if (value === undefined)
171
+ return fallback;
172
+ if (typeof value === "string" && allowed.includes(value))
173
+ return value;
174
+ issue(`theme.${key}`, `unknown ${noun} "${String(value)}" (choose ${allowed.join(", ")})`);
175
+ return fallback;
176
+ };
177
+ let preset = null;
178
+ if (t.preset !== undefined) {
179
+ const resolved = typeof t.preset === "string" ? resolvePreset(t.preset) : undefined;
180
+ if (resolved)
181
+ preset = resolved;
182
+ else
183
+ issue("theme.preset", `unknown preset "${String(t.preset)}" (choose ${THEME_PRESET_NAMES.join(", ")})`);
184
+ }
185
+ let explicitStyle;
186
+ if (t.style !== undefined) {
187
+ const resolved = typeof t.style === "string" ? resolveStyle(t.style) : undefined;
188
+ if (resolved)
189
+ explicitStyle = resolved;
190
+ else
191
+ issue("theme.style", `unknown style "${String(t.style)}" (choose ${UI_STYLES.join(", ")})`);
192
+ }
193
+ const base = themeBase(preset, explicitStyle);
194
+ const mode = t.mode ?? base.mode;
195
+ if (!THEME_MODES.includes(mode))
196
+ issue("theme.mode", `must be one of ${THEME_MODES.join(", ")}`);
197
+ const radius = t.radius ?? base.radius;
198
+ if (!RADII.includes(radius))
199
+ issue("theme.radius", `must be one of ${RADII.join(", ")}`);
200
+ const font = oneOf("font", t.font, THEME_FONT_NAMES, base.font, "font");
201
+ const layout = oneOf("layout", t.layout, THEME_LAYOUTS, base.layout, "layout");
202
+ const density = oneOf("density", t.density, THEME_DENSITIES, base.density, "density");
203
+ const color = (key) => {
204
+ const raw = t.colors?.[key];
205
+ const fallback = key === "danger" ? DEFAULT_THEME.colors.danger : base[key];
206
+ if (raw === undefined)
207
+ return fallback;
208
+ const hex = typeof raw === "string" ? normalizeHex(raw) : undefined;
209
+ if (!hex) {
210
+ issue(`theme.colors.${key}`, `"${String(raw)}" is not a hex colour like #4f46e5`);
211
+ return fallback;
212
+ }
213
+ return hex;
214
+ };
215
+ const primary = color("primary");
216
+ const accent = color("accent");
217
+ const danger = color("danger");
218
+ let logo = null;
219
+ if (t.logo !== undefined) {
220
+ const normalized = typeof t.logo === "string" ? normalizeLogo(t.logo) : undefined;
221
+ if (normalized)
222
+ logo = normalized;
223
+ else
224
+ issue("theme.logo", `"${String(t.logo)}" is not a logo URL (https://…) or an image in apps/web/public such as "/logo.svg" (svg, png, jpg, webp, gif, ico, avif)`);
225
+ }
226
+ let tagline = null;
227
+ if (t.tagline !== undefined) {
228
+ if (typeof t.tagline !== "string" || !t.tagline.trim())
229
+ issue("theme.tagline", "must be a non-empty string");
230
+ else if (t.tagline.trim().length > TAGLINE_MAX)
231
+ issue("theme.tagline", `must be at most ${TAGLINE_MAX} characters`);
232
+ else
233
+ tagline = t.tagline.trim();
234
+ }
235
+ const typeface = THEME_FONTS[font];
236
+ return {
237
+ preset,
238
+ style: base.style,
239
+ mode,
240
+ radius,
241
+ colors: {
242
+ primary,
243
+ primaryForeground: readableOn(primary),
244
+ accent,
245
+ accentForeground: readableOn(accent),
246
+ danger,
247
+ dangerForeground: readableOn(danger),
248
+ },
249
+ font,
250
+ fonts: { body: typeface.body, display: typeface.display, stylesheet: fontStylesheet(font) },
251
+ layout,
252
+ density,
253
+ logo,
254
+ tagline,
255
+ };
256
+ }
257
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../src/theme.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,aAAa,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAU,CAAC;AAC5K,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AAChE,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAC3E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAC;AACvE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,aAAa,EAAE,SAAS,CAAU,CAAC;AACnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAU,CAAC;AACrH,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,CAAU,CAAC;AAE5I,MAAM,IAAI,GAAG,yEAAyE,CAAC;AACvF,MAAM,KAAK,GAAG,sDAAsD,CAAC;AACrE,MAAM,IAAI,GAAG,0DAA0D,CAAC;AAYxE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,WAAW,GAA+C;IACrE,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,0BAA0B,EAAE,OAAO,EAAE,YAAY,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,4BAA4B,CAAC,EAAE;IAC5J,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,YAAY,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,4BAA4B,CAAC,EAAE;IACzJ,IAAI,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,gCAAgC,EAAE,OAAO,EAAE,oBAAoB,IAAI,EAAE,EAAE,IAAI,EAAE,oBAAoB,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,oCAAoC,CAAC,EAAE;IAC5L,OAAO,EAAE,EAAE,KAAK,EAAE,uBAAuB,EAAE,IAAI,EAAE,2BAA2B,EAAE,OAAO,EAAE,oBAAoB,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,gCAAgC,EAAE,4BAA4B,CAAC,EAAE;IACzN,KAAK,EAAE,EAAE,KAAK,EAAE,kBAAkB,EAAE,IAAI,EAAE,0BAA0B,EAAE,OAAO,EAAE,eAAe,KAAK,EAAE,EAAE,IAAI,EAAE,YAAY,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,oCAAoC,EAAE,4BAA4B,CAAC,EAAE;IACjN,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,aAAa,IAAI,EAAE,EAAE,IAAI,EAAE,aAAa,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,iCAAiC,CAAC,EAAE;IACpK,IAAI,EAAE,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,sBAAsB,EAAE,OAAO,EAAE,qBAAqB,IAAI,EAAE,EAAE,IAAI,EAAE,qBAAqB,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,qCAAqC,CAAC,EAAE;IAC3L,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,wCAAwC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;CACrH,CAAC;AAEF,oFAAoF;AACpF,MAAM,UAAU,cAAc,CAAC,IAAmB;IAChD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;IAC5C,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,qCAAqC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;AACnI,CAAC;AAeD,uEAAuE;AACvE,MAAM,CAAC,MAAM,aAAa,GAAmD;IAC3E,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,yCAAyC,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE;IACxO,SAAS,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,yCAAyC,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE;IAC/O,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,8BAA8B,EAAE,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE;IAChO,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,6CAA6C,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;IACzO,MAAM,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,+BAA+B,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE;IAC3N,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,6CAA6C,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE;IAC5O,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,+BAA+B,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;IAC5N,KAAK,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,+BAA+B,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,EAAE;IAC1N,QAAQ,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,oCAAoC,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE;CACjO,CAAC;AAEF,sEAAsE;AACtE,MAAM,CAAC,MAAM,cAAc,GAAsF;IAC/G,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;IAC9B,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;IAC5B,QAAQ,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACxC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;CAC1B,CAAC;AAaF;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAA+B,EAAE,KAAsB;IAC/E,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACrD,MAAM,IAAI,GAAc,CAAC;QACvB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;QAC9I,CAAC,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;IAClO,MAAM,UAAU,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC;IACvC,IAAI,CAAC,CAAC,IAAI,UAAU,KAAK,CAAC,CAAC,KAAK;QAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;IACxF,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC;IACxB,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAQ,kBAAwC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAqB,CAAC,CAAC,CAAC,SAAS,CAAC;AACpG,CAAC;AAED,MAAM,SAAS,GAAG,oDAAoD,CAAC;AAEvE;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACnC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;YACvB,OAAO,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;QACnD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,IAAI,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;IACzE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;IAC7C,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACvG,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kDAAkD;AAClD,MAAM,aAAa,GAAqC;IACtD,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,QAAQ;IACjB,OAAO,EAAE,QAAQ;IACjB,WAAW,EAAE,aAAa;IAC1B,UAAU,EAAE,aAAa;IACzB,KAAK,EAAE,eAAe;IACtB,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,YAAY,EAAE,eAAe;IAC7B,WAAW,EAAE,eAAe;IAC5B,iBAAiB,EAAE,UAAU;IAC7B,GAAG,EAAE,UAAU;IACf,MAAM,EAAE,WAAW;IACnB,SAAS,EAAE,WAAW;IACtB,YAAY,EAAE,WAAW;IACzB,eAAe,EAAE,WAAW;IAC5B,eAAe,EAAE,WAAW;IAC5B,QAAQ,EAAE,WAAW;IACrB,KAAK,EAAE,WAAW;IAClB,QAAQ,EAAE,QAAQ;IAClB,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,UAAU;IACnB,MAAM,EAAE,UAAU;IAClB,GAAG,EAAE,UAAU;IACf,GAAG,EAAE,UAAU;IACf,YAAY,EAAE,MAAM;IACpB,WAAW,EAAE,MAAM;CACpB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAY;IACpC,MAAM,EAAE,IAAI;IACZ,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,OAAO;IACb,MAAM,EAAE,QAAQ;IAChB,MAAM,EAAE;QACN,OAAO,EAAE,SAAS;QAClB,iBAAiB,EAAE,SAAS;QAC5B,MAAM,EAAE,SAAS;QACjB,gBAAgB,EAAE,SAAS;QAC3B,MAAM,EAAE,SAAS;QACjB,gBAAgB,EAAE,SAAS;KAC5B;IACD,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE;IACtD,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,CAAC,GAAG,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9D,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC;IAC7E,OAAO,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;AAC/B,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACpC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC;QAClD,OAAO,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,CAAC;IACjE,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,GAAG,CAAE,GAAG,MAAM,GAAG,CAAE,GAAG,MAAM,GAAG,CAAE,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,CAAS,EAAE,CAAS;IAC3C,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,EAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAG,GAAG,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACrC,OAAQ,SAA+B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAE,CAAsB,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACnG,CAAC;AAED,MAAM,WAAW,GAAG,GAAG,CAAC;AAExB,MAAM,UAAU,YAAY,CAAC,KAA8B,EAAE,KAA8C;IACzG,MAAM,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;IACtB,MAAM,KAAK,GAAG,CAAmB,GAAW,EAAE,KAAc,EAAE,OAAqB,EAAE,QAAW,EAAE,IAAY,EAAK,EAAE;QACnH,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAK,OAA6B,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,KAAU,CAAC;QACnG,KAAK,CAAC,SAAS,GAAG,EAAE,EAAE,WAAW,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3F,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IAEF,IAAI,MAAM,GAA2B,IAAI,CAAC;IAC1C,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpF,IAAI,QAAQ;YAAE,MAAM,GAAG,QAAQ,CAAC;;YAC3B,KAAK,CAAC,cAAc,EAAE,mBAAmB,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/G,CAAC;IACD,IAAI,aAAyC,CAAC;IAC9C,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjF,IAAI,QAAQ;YAAE,aAAa,GAAG,QAAQ,CAAC;;YAClC,KAAK,CAAC,aAAa,EAAE,kBAAkB,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACnG,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC;IACjC,IAAI,CAAE,WAAiC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,YAAY,EAAE,kBAAkB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACxH,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC;IACvC,IAAI,CAAE,KAA2B,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,KAAK,CAAC,cAAc,EAAE,kBAAkB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChH,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxE,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC/E,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IAEtF,MAAM,KAAK,GAAG,CAAC,GAAoC,EAAE,EAAE;QACrD,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5E,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QACvC,MAAM,GAAG,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpE,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,KAAK,CAAC,gBAAgB,GAAG,EAAE,EAAE,IAAI,MAAM,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAClF,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE/B,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACzB,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAClF,IAAI,UAAU;YAAE,IAAI,GAAG,UAAU,CAAC;;YAC7B,KAAK,CAAC,YAAY,EAAE,IAAI,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,0HAA0H,CAAC,CAAC;IACzK,CAAC;IACD,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE;YAAE,KAAK,CAAC,eAAe,EAAE,4BAA4B,CAAC,CAAC;aACxG,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,WAAW;YAAE,KAAK,CAAC,eAAe,EAAE,mBAAmB,WAAW,aAAa,CAAC,CAAC;;YAC/G,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO;QACL,MAAM;QACN,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI;QACJ,MAAM;QACN,MAAM,EAAE;YACN,OAAO;YACP,iBAAiB,EAAE,UAAU,CAAC,OAAO,CAAC;YACtC,MAAM;YACN,gBAAgB,EAAE,UAAU,CAAC,MAAM,CAAC;YACpC,MAAM;YACN,gBAAgB,EAAE,UAAU,CAAC,MAAM,CAAC;SACrC;QACD,IAAI;QACJ,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE;QAC3F,MAAM;QACN,OAAO;QACP,IAAI;QACJ,OAAO;KACR,CAAC;AACJ,CAAC"}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,83 @@
1
+ import type { AppIR, EntityIR, FieldIR } from "./ir.js";
2
+ /** UI metadata consumed by the generic admin renderer (`<ResourceList>`, `<ResourceForm>`). */
3
+ export interface ResourceMeta {
4
+ name: string;
5
+ path: string;
6
+ label: string;
7
+ pluralLabel: string;
8
+ icon: string;
9
+ nav: boolean;
10
+ display: string;
11
+ searchable: boolean;
12
+ searchPlaceholder: string;
13
+ list: {
14
+ columns: ColumnMeta[];
15
+ filters: FilterMeta[];
16
+ defaultSort: string;
17
+ pageSize: number;
18
+ };
19
+ form: {
20
+ fields: FormFieldMeta[];
21
+ };
22
+ detail: {
23
+ fields: string[];
24
+ related: RelatedMeta[];
25
+ };
26
+ features: EntityIR["features"];
27
+ actions: EntityIR["actions"];
28
+ workflow?: EntityIR["workflow"];
29
+ views: EntityIR["views"];
30
+ }
31
+ export interface ColumnMeta {
32
+ key: string;
33
+ label: string;
34
+ kind: FieldIR["kind"] | "system";
35
+ sortable: boolean;
36
+ /** Display renderer: text, badge, boolean, money, percentage, date, datetime, relation, color, email, url */
37
+ cell: string;
38
+ }
39
+ export interface FilterMeta {
40
+ key: string;
41
+ label: string;
42
+ type: "select" | "relation" | "boolean" | "range";
43
+ options?: {
44
+ value: string;
45
+ label: string;
46
+ }[];
47
+ relationPath?: string;
48
+ }
49
+ export interface FormFieldMeta {
50
+ name: string;
51
+ apiName: string;
52
+ label: string;
53
+ component: string;
54
+ required: boolean;
55
+ description?: string;
56
+ placeholder?: string;
57
+ options?: {
58
+ value: string;
59
+ label: string;
60
+ }[];
61
+ relation?: {
62
+ entity: string;
63
+ lookupPath: string;
64
+ many: boolean;
65
+ };
66
+ file?: {
67
+ image: boolean;
68
+ accept: string[];
69
+ maxSize: number;
70
+ };
71
+ currency?: string;
72
+ validation: FieldIR["validation"];
73
+ defaultValue?: unknown;
74
+ }
75
+ export interface RelatedMeta {
76
+ name: string;
77
+ label: string;
78
+ resourcePath: string;
79
+ filterKey: string;
80
+ }
81
+ /** Path segment used to look up records of a relation target. */
82
+ export declare function lookupPath(ir: AppIR, entity: string): string;
83
+ export declare function deriveResources(ir: AppIR): ResourceMeta[];