@trebired/frontend 0.3.0 → 0.4.1

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 (102) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +87 -3
  3. package/dist/config/index.d.ts +54 -0
  4. package/dist/config/index.d.ts.map +1 -0
  5. package/dist/config/index.js +303 -0
  6. package/dist/config/index.js.map +1 -0
  7. package/dist/flash/dialogs.d.ts.map +1 -1
  8. package/dist/flash/dialogs.js +23 -14
  9. package/dist/flash/dialogs.js.map +1 -1
  10. package/dist/fullscreen/index.d.ts +15 -0
  11. package/dist/fullscreen/index.d.ts.map +1 -0
  12. package/dist/fullscreen/index.js +62 -0
  13. package/dist/fullscreen/index.js.map +1 -0
  14. package/dist/icons/index.d.ts +44 -0
  15. package/dist/icons/index.d.ts.map +1 -0
  16. package/dist/icons/index.js +180 -0
  17. package/dist/icons/index.js.map +1 -0
  18. package/dist/icons/middleware/index.d.ts +19 -0
  19. package/dist/icons/middleware/index.d.ts.map +1 -0
  20. package/dist/icons/middleware/index.js +46 -0
  21. package/dist/icons/middleware/index.js.map +1 -0
  22. package/dist/icons/react/index.d.ts +16 -0
  23. package/dist/icons/react/index.d.ts.map +1 -0
  24. package/dist/icons/react/index.js +70 -0
  25. package/dist/icons/react/index.js.map +1 -0
  26. package/dist/icons/server/index.d.ts +70 -0
  27. package/dist/icons/server/index.d.ts.map +1 -0
  28. package/dist/icons/server/index.js +310 -0
  29. package/dist/icons/server/index.js.map +1 -0
  30. package/dist/icons/server-context.d.ts +12 -0
  31. package/dist/icons/server-context.d.ts.map +1 -0
  32. package/dist/icons/server-context.js +25 -0
  33. package/dist/icons/server-context.js.map +1 -0
  34. package/dist/icons/shared.d.ts +29 -0
  35. package/dist/icons/shared.d.ts.map +1 -0
  36. package/dist/icons/shared.js +151 -0
  37. package/dist/icons/shared.js.map +1 -0
  38. package/dist/icons/styles/index.scss +76 -0
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +6 -0
  42. package/dist/index.js.map +1 -1
  43. package/dist/layer/index.d.ts.map +1 -1
  44. package/dist/layer/index.js +27 -2
  45. package/dist/layer/index.js.map +1 -1
  46. package/dist/modal/index.d.ts +1 -0
  47. package/dist/modal/index.d.ts.map +1 -1
  48. package/dist/modal/index.js +72 -7
  49. package/dist/modal/index.js.map +1 -1
  50. package/dist/src/config/index.d.ts +54 -0
  51. package/dist/src/config/index.d.ts.map +1 -0
  52. package/dist/src/config/index.js +303 -0
  53. package/dist/src/config/index.js.map +1 -0
  54. package/dist/src/flash/dialogs.d.ts.map +1 -1
  55. package/dist/src/flash/dialogs.js +23 -14
  56. package/dist/src/flash/dialogs.js.map +1 -1
  57. package/dist/src/fullscreen/index.d.ts +15 -0
  58. package/dist/src/fullscreen/index.d.ts.map +1 -0
  59. package/dist/src/fullscreen/index.js +62 -0
  60. package/dist/src/fullscreen/index.js.map +1 -0
  61. package/dist/src/icons/index.d.ts +44 -0
  62. package/dist/src/icons/index.d.ts.map +1 -0
  63. package/dist/src/icons/index.js +180 -0
  64. package/dist/src/icons/index.js.map +1 -0
  65. package/dist/src/icons/middleware/index.d.ts +19 -0
  66. package/dist/src/icons/middleware/index.d.ts.map +1 -0
  67. package/dist/src/icons/middleware/index.js +46 -0
  68. package/dist/src/icons/middleware/index.js.map +1 -0
  69. package/dist/src/icons/react/index.d.ts +16 -0
  70. package/dist/src/icons/react/index.d.ts.map +1 -0
  71. package/dist/src/icons/react/index.js +70 -0
  72. package/dist/src/icons/react/index.js.map +1 -0
  73. package/dist/src/icons/server/index.d.ts +70 -0
  74. package/dist/src/icons/server/index.d.ts.map +1 -0
  75. package/dist/src/icons/server/index.js +310 -0
  76. package/dist/src/icons/server/index.js.map +1 -0
  77. package/dist/src/icons/server-context.d.ts +12 -0
  78. package/dist/src/icons/server-context.d.ts.map +1 -0
  79. package/dist/src/icons/server-context.js +25 -0
  80. package/dist/src/icons/server-context.js.map +1 -0
  81. package/dist/src/icons/shared.d.ts +29 -0
  82. package/dist/src/icons/shared.d.ts.map +1 -0
  83. package/dist/src/icons/shared.js +151 -0
  84. package/dist/src/icons/shared.js.map +1 -0
  85. package/dist/src/index.d.ts +2 -0
  86. package/dist/src/index.d.ts.map +1 -1
  87. package/dist/src/index.js +6 -0
  88. package/dist/src/index.js.map +1 -1
  89. package/dist/src/layer/index.d.ts.map +1 -1
  90. package/dist/src/layer/index.js +27 -2
  91. package/dist/src/layer/index.js.map +1 -1
  92. package/dist/src/modal/index.d.ts +1 -0
  93. package/dist/src/modal/index.d.ts.map +1 -1
  94. package/dist/src/modal/index.js +72 -7
  95. package/dist/src/modal/index.js.map +1 -1
  96. package/dist/src/styles/index.d.ts.map +1 -1
  97. package/dist/src/styles/index.js +1 -0
  98. package/dist/src/styles/index.js.map +1 -1
  99. package/dist/styles/index.d.ts.map +1 -1
  100. package/dist/styles/index.js +1 -0
  101. package/dist/styles/index.js.map +1 -1
  102. package/package.json +44 -13
package/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `@trebired/frontend` will be documented here.
4
4
 
5
5
  This project follows semantic versioning once published.
6
6
 
7
+ ## 0.4.1
8
+
9
+ - Refreshed package dependency ranges and lockfile state with `bun update` after adopting the `.trebired/code-discipline` structure.
10
+
11
+ ## 0.4.0
12
+
13
+ - Added `.trebired/frontend/config.ts` support with `defineTrebiredFrontendConfig()`, validation, defaults, deterministic generated SCSS, and `.trebired/frontend/generated/styles.scss` output.
14
+ - Added first-class `remixicon` and `simple-icons` support with spec parsing, server HTML rendering, SVG response helpers, Express-compatible middleware, browser fetch/cache rendering, React `Icon`, simple-icons brand colors, explicit colors, source-color preservation, and shared icon SCSS.
15
+ - Added the fullscreen runtime and upgraded root runtime binding to include icons and fullscreen controls.
16
+ - Improved generic modal/layer behavior with focus restoration, scroll-lock gap handling, lifecycle events, fullscreen-aware layers, and safer dialog timer cleanup for flash prompts/confirms.
17
+ - Added config/icon/runtime verification and updated package exports, README examples, and pack coverage.
18
+
7
19
  ## 0.3.0
8
20
 
9
21
  - Added TSX markup component subpaths for actions, flash, progress, layers, tooltips, popovers, modals, inputs, theme, and live refresh.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Generic browser runtime systems for DOM binding, actions, overlays, theme state, live refresh, inputs, upload, and React rendering in the Trebired ecosystem.
4
4
 
5
- `@trebired/frontend` owns reusable browser behavior. Callers own product routes, product copy, storage keys, icon systems, persistence, navigation, logging, and backend response contracts beyond the documented generic JSON shape.
5
+ `@trebired/frontend` owns reusable browser behavior, generic icon rendering, and package-owned overlay/runtime primitives. Callers own product routes, product copy, storage keys, persistence, navigation, logging, domain icon maps, and backend response contracts beyond the documented generic JSON shape.
6
6
 
7
7
  ## Install
8
8
 
@@ -35,6 +35,7 @@ Load only the SCSS systems your product uses:
35
35
  ```scss
36
36
  @use "@trebired/frontend/styles/tokens" as *;
37
37
  @use "@trebired/frontend/styles/utils" as *;
38
+ @use "@trebired/frontend/icons/styles" as *;
38
39
  @use "@trebired/frontend/actions/styles" as *;
39
40
  @use "@trebired/frontend/flash/styles" as *;
40
41
  @use "@trebired/frontend/progress/styles" as *;
@@ -104,6 +105,41 @@ Upload markup includes hidden file and directory inputs, mixed file/folder butto
104
105
 
105
106
  ## Configuration
106
107
 
108
+ ### Project Config
109
+
110
+ Projects can define `.trebired/frontend/config.ts`:
111
+
112
+ ```ts
113
+ import { defineTrebiredFrontendConfig } from "@trebired/frontend/config";
114
+
115
+ export default defineTrebiredFrontendConfig({
116
+ prefix: "tbf",
117
+ icons: {
118
+ endpoint: "/__icons/svg",
119
+ packs: ["remixicon", "simple-icons"],
120
+ },
121
+ systems: {
122
+ actions: true,
123
+ flash: true,
124
+ fullscreen: true,
125
+ icons: true,
126
+ inputs: true,
127
+ layer: true,
128
+ modal: true,
129
+ popover: true,
130
+ progress: true,
131
+ theme: true,
132
+ tooltip: true,
133
+ },
134
+ theme: {
135
+ cssVariables: true,
136
+ tokens: {},
137
+ },
138
+ });
139
+ ```
140
+
141
+ `@trebired/frontend/config` exports `defineTrebiredFrontendConfig()`, `normalizeTrebiredFrontendConfig()`, `loadTrebiredFrontendConfig()`, `findTrebiredFrontendConfig()`, `generateTrebiredFrontendScss()`, and `writeGeneratedTrebiredFrontendScss()`. Missing config files use package defaults. Generated SCSS is written to `.trebired/frontend/generated/styles.scss`.
142
+
107
143
  ### Runtime Options
108
144
 
109
145
  `bindFrontendRuntime(root, options)` accepts:
@@ -130,7 +166,7 @@ Set `frontend_quiet: true`, `quiet: true`, `globalThis.frontend_quiet = true`, o
130
166
 
131
167
  ### Binding Order
132
168
 
133
- The canonical runtime binds theme, layer roots, progress, flash, inputs, uploads, tooltips, popovers, modals, actions, and live refresh in that order.
169
+ The canonical runtime binds theme, layer roots, icons, progress, flash, inputs, uploads, tooltips, popovers, modals, actions, fullscreen controls, and live refresh in that order.
134
170
 
135
171
  ### CSS
136
172
 
@@ -146,6 +182,7 @@ Base exports:
146
182
  System exports:
147
183
 
148
184
  - `@trebired/frontend/actions/styles`
185
+ - `@trebired/frontend/icons/styles`
149
186
  - `@trebired/frontend/flash/styles`
150
187
  - `@trebired/frontend/progress/styles`
151
188
  - `@trebired/frontend/layer/styles`
@@ -158,6 +195,46 @@ System exports:
158
195
 
159
196
  Upload crop uses `cropperjs` only through the upload crop path. The root runtime import and the normal `@trebired/frontend/inputs` import do not load cropper or TSX component modules until a crop session opens.
160
197
 
198
+ ### Icons
199
+
200
+ Canonical icon specs use `pack:name`:
201
+
202
+ - `remixicon:add-line`
203
+ - `remixicon:settings-3-line`
204
+ - `simple-icons:github`
205
+ - `simple-icons:cloudflare`
206
+
207
+ Browser runtime:
208
+
209
+ ```ts
210
+ import { bindIcons, renderIconElement } from "@trebired/frontend/icons";
211
+
212
+ bindIcons(document);
213
+ await renderIconElement(document.querySelector("[data-tbf-icon]")!, "remixicon:add-line");
214
+ ```
215
+
216
+ React:
217
+
218
+ ```tsx
219
+ import { Icon } from "@trebired/frontend/icons/react";
220
+
221
+ export function SaveIcon() {
222
+ return <Icon spec="remixicon:save-3-line" label="Save" />;
223
+ }
224
+ ```
225
+
226
+ Server:
227
+
228
+ ```ts
229
+ import { renderIconHtml } from "@trebired/frontend/icons/server";
230
+ import { createIconMiddleware } from "@trebired/frontend/icons/middleware";
231
+
232
+ const html = renderIconHtml("simple-icons:github", { label: "GitHub" });
233
+ const middleware = createIconMiddleware();
234
+ ```
235
+
236
+ The icon system supports explicit colors, simple-icons brand colors, source-color preservation, browser fetch/cache rendering, server HTML rendering, and an Express-compatible `/__icons/svg` middleware.
237
+
161
238
  ## Public API
162
239
 
163
240
  Entrypoints:
@@ -165,6 +242,12 @@ Entrypoints:
165
242
  - `@trebired/frontend`
166
243
  - `@trebired/frontend/dom`
167
244
  - `@trebired/frontend/http`
245
+ - `@trebired/frontend/config`
246
+ - `@trebired/frontend/fullscreen`
247
+ - `@trebired/frontend/icons`
248
+ - `@trebired/frontend/icons/react`
249
+ - `@trebired/frontend/icons/server`
250
+ - `@trebired/frontend/icons/middleware`
168
251
  - `@trebired/frontend/actions`
169
252
  - `@trebired/frontend/actions/components`
170
253
  - `@trebired/frontend/flash`
@@ -189,6 +272,7 @@ Entrypoints:
189
272
  - `@trebired/frontend/styles`
190
273
  - `@trebired/frontend/styles/tokens`
191
274
  - `@trebired/frontend/styles/utils`
275
+ - `@trebired/frontend/icons/styles`
192
276
  - `@trebired/frontend/actions/styles`
193
277
  - `@trebired/frontend/flash/styles`
194
278
  - `@trebired/frontend/progress/styles`
@@ -207,6 +291,6 @@ This package does not:
207
291
  - export markup components from the root entrypoint
208
292
  - ship an aggregate `styles.css`
209
293
  - own product routes, domains, copy, or storage keys
210
- - require a specific icon system
294
+ - own product-specific icon maps
211
295
  - migrate an existing application to consume the package
212
296
  - replace framework-specific component libraries
@@ -0,0 +1,54 @@
1
+ type TrebiredFrontendIconPack = "remixicon" | "simple-icons";
2
+ type TrebiredFrontendSystemKey = "actions" | "flash" | "fullscreen" | "icons" | "inputs" | "layer" | "modal" | "popover" | "progress" | "theme" | "tooltip";
3
+ type TrebiredFrontendThemeTokens = Record<string, unknown>;
4
+ type TrebiredFrontendConfig = {
5
+ prefix?: string;
6
+ icons?: {
7
+ endpoint?: string;
8
+ packs?: readonly TrebiredFrontendIconPack[];
9
+ };
10
+ systems?: Partial<Record<TrebiredFrontendSystemKey, boolean>>;
11
+ theme?: {
12
+ cssVariables?: boolean;
13
+ tokens?: TrebiredFrontendThemeTokens;
14
+ };
15
+ };
16
+ type NormalizedTrebiredFrontendConfig = {
17
+ prefix: string;
18
+ icons: {
19
+ endpoint: string;
20
+ packs: TrebiredFrontendIconPack[];
21
+ };
22
+ systems: Record<TrebiredFrontendSystemKey, boolean>;
23
+ theme: {
24
+ cssVariables: boolean;
25
+ tokens: TrebiredFrontendThemeTokens;
26
+ };
27
+ };
28
+ type LoadedTrebiredFrontendConfig = {
29
+ config: NormalizedTrebiredFrontendConfig;
30
+ configPath: string | null;
31
+ generatedScss: string;
32
+ generatedScssPath: string;
33
+ };
34
+ type LoadTrebiredFrontendConfigOptions = {
35
+ configPath?: string;
36
+ defaultIfMissing?: boolean;
37
+ searchFrom?: string;
38
+ };
39
+ declare const TREBIRED_FRONTEND_CONFIG_PATH = ".trebired/frontend/config.ts";
40
+ declare const TREBIRED_FRONTEND_GENERATED_DIR = ".trebired/frontend/generated";
41
+ declare const TREBIRED_FRONTEND_GENERATED_SCSS_PATH = ".trebired/frontend/generated/styles.scss";
42
+ declare const SUPPORTED_ICON_PACKS: TrebiredFrontendIconPack[];
43
+ declare const SYSTEM_ORDER: TrebiredFrontendSystemKey[];
44
+ declare const DEFAULT_TREBIRED_FRONTEND_CONFIG: NormalizedTrebiredFrontendConfig;
45
+ declare function defineTrebiredFrontendConfig<T extends TrebiredFrontendConfig>(config: T): T;
46
+ declare function normalizeTrebiredFrontendConfig(config?: unknown): NormalizedTrebiredFrontendConfig;
47
+ declare function generateTrebiredFrontendScss(configInput: TrebiredFrontendConfig | NormalizedTrebiredFrontendConfig): string;
48
+ declare function findTrebiredFrontendConfig(startDir?: string, boundaryDir?: string): Promise<string | null>;
49
+ declare function loadTrebiredFrontendConfig(projectRoot?: string, options?: LoadTrebiredFrontendConfigOptions): Promise<LoadedTrebiredFrontendConfig>;
50
+ declare function resolveTrebiredFrontendGeneratedScssPath(projectRoot?: string): string;
51
+ declare function writeGeneratedTrebiredFrontendScss(projectRoot: string, config: TrebiredFrontendConfig | NormalizedTrebiredFrontendConfig): Promise<string>;
52
+ export { DEFAULT_TREBIRED_FRONTEND_CONFIG, SUPPORTED_ICON_PACKS, SYSTEM_ORDER, TREBIRED_FRONTEND_CONFIG_PATH, TREBIRED_FRONTEND_GENERATED_DIR, TREBIRED_FRONTEND_GENERATED_SCSS_PATH, defineTrebiredFrontendConfig, findTrebiredFrontendConfig, generateTrebiredFrontendScss, loadTrebiredFrontendConfig, normalizeTrebiredFrontendConfig, resolveTrebiredFrontendGeneratedScssPath, writeGeneratedTrebiredFrontendScss, };
53
+ export type { LoadedTrebiredFrontendConfig, LoadTrebiredFrontendConfigOptions, NormalizedTrebiredFrontendConfig, TrebiredFrontendConfig, TrebiredFrontendIconPack, TrebiredFrontendSystemKey, TrebiredFrontendThemeTokens, };
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,303 @@
1
+ import crypto from "node:crypto";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+ const TREBIRED_FRONTEND_CONFIG_PATH = ".trebired/frontend/config.ts";
6
+ const TREBIRED_FRONTEND_GENERATED_DIR = ".trebired/frontend/generated";
7
+ const TREBIRED_FRONTEND_GENERATED_SCSS_PATH = `${TREBIRED_FRONTEND_GENERATED_DIR}/styles.scss`;
8
+ const SUPPORTED_ICON_PACKS = ["remixicon", "simple-icons"];
9
+ const SYSTEM_ORDER = [
10
+ "theme",
11
+ "layer",
12
+ "icons",
13
+ "progress",
14
+ "flash",
15
+ "tooltip",
16
+ "popover",
17
+ "modal",
18
+ "inputs",
19
+ "actions",
20
+ "fullscreen",
21
+ ];
22
+ const SYSTEM_STYLE_IMPORTS = {
23
+ actions: "@trebired/frontend/actions/styles",
24
+ flash: "@trebired/frontend/flash/styles",
25
+ icons: "@trebired/frontend/icons/styles",
26
+ inputs: "@trebired/frontend/inputs/styles",
27
+ layer: "@trebired/frontend/layer/styles",
28
+ modal: "@trebired/frontend/modal/styles",
29
+ popover: "@trebired/frontend/popover/styles",
30
+ progress: "@trebired/frontend/progress/styles",
31
+ tooltip: "@trebired/frontend/tooltip/styles",
32
+ };
33
+ const DEFAULT_TREBIRED_FRONTEND_CONFIG = Object.freeze({
34
+ prefix: "tbf",
35
+ icons: Object.freeze({
36
+ endpoint: "/__icons/svg",
37
+ packs: Object.freeze([...SUPPORTED_ICON_PACKS]),
38
+ }),
39
+ systems: Object.freeze(Object.fromEntries(SYSTEM_ORDER.map((key) => [key, true]))),
40
+ theme: Object.freeze({
41
+ cssVariables: true,
42
+ tokens: Object.freeze({}),
43
+ }),
44
+ });
45
+ function defineTrebiredFrontendConfig(config) {
46
+ return config;
47
+ }
48
+ function isPlainObject(value) {
49
+ return Boolean(value && typeof value === "object" && !Array.isArray(value));
50
+ }
51
+ function assertPlainObject(value, pathLabel) {
52
+ if (!isPlainObject(value)) {
53
+ throw new Error(`trebired-frontend-invalid-config :: ${pathLabel} must be an object`);
54
+ }
55
+ return value;
56
+ }
57
+ function normalizePrefix(value) {
58
+ const prefix = String(value || DEFAULT_TREBIRED_FRONTEND_CONFIG.prefix).trim();
59
+ if (!/^[a-z][a-z0-9_-]*$/iu.test(prefix)) {
60
+ throw new Error("trebired-frontend-invalid-config :: prefix must start with a letter and contain only letters, numbers, underscores, or hyphens");
61
+ }
62
+ return prefix;
63
+ }
64
+ function normalizeEndpoint(value) {
65
+ const endpoint = String(value || DEFAULT_TREBIRED_FRONTEND_CONFIG.icons.endpoint).trim();
66
+ if (!endpoint || /[\s"'<>]/u.test(endpoint)) {
67
+ throw new Error("trebired-frontend-invalid-config :: icons.endpoint must be a URL path without whitespace");
68
+ }
69
+ return endpoint;
70
+ }
71
+ function normalizeIconPacks(value) {
72
+ const raw = value === undefined ? DEFAULT_TREBIRED_FRONTEND_CONFIG.icons.packs : value;
73
+ if (!Array.isArray(raw)) {
74
+ throw new Error("trebired-frontend-invalid-config :: icons.packs must be an array");
75
+ }
76
+ const packs = [];
77
+ for (const item of raw) {
78
+ if (!SUPPORTED_ICON_PACKS.includes(item)) {
79
+ throw new Error(`trebired-frontend-invalid-config :: unsupported icon pack ${String(item)}`);
80
+ }
81
+ if (!packs.includes(item))
82
+ packs.push(item);
83
+ }
84
+ return packs;
85
+ }
86
+ function normalizeSystems(value) {
87
+ if (value === undefined)
88
+ return { ...DEFAULT_TREBIRED_FRONTEND_CONFIG.systems };
89
+ const source = assertPlainObject(value, "systems");
90
+ const systems = { ...DEFAULT_TREBIRED_FRONTEND_CONFIG.systems };
91
+ for (const [key, enabled] of Object.entries(source)) {
92
+ if (!SYSTEM_ORDER.includes(key)) {
93
+ throw new Error(`trebired-frontend-invalid-config :: unsupported system ${key}`);
94
+ }
95
+ if (typeof enabled !== "boolean") {
96
+ throw new Error(`trebired-frontend-invalid-config :: systems.${key} must be boolean`);
97
+ }
98
+ systems[key] = enabled;
99
+ }
100
+ return systems;
101
+ }
102
+ function normalizeThemeTokens(value, pathLabel = "theme.tokens") {
103
+ if (value === undefined)
104
+ return {};
105
+ const source = assertPlainObject(value, pathLabel);
106
+ const out = {};
107
+ for (const [key, item] of Object.entries(source).sort(([a], [b]) => a.localeCompare(b))) {
108
+ if (!/^[a-z0-9_-]+$/iu.test(key)) {
109
+ throw new Error(`trebired-frontend-invalid-config :: ${pathLabel}.${key} has an invalid token key`);
110
+ }
111
+ if (isPlainObject(item)) {
112
+ out[key] = normalizeThemeTokens(item, `${pathLabel}.${key}`);
113
+ continue;
114
+ }
115
+ if (typeof item !== "string" && typeof item !== "number") {
116
+ throw new Error(`trebired-frontend-invalid-config :: ${pathLabel}.${key} must be a string, number, or token object`);
117
+ }
118
+ out[key] = item;
119
+ }
120
+ return out;
121
+ }
122
+ function normalizeBoolean(value, defaultValue, pathLabel) {
123
+ if (value === undefined)
124
+ return defaultValue;
125
+ if (typeof value !== "boolean") {
126
+ throw new Error(`trebired-frontend-invalid-config :: ${pathLabel} must be boolean`);
127
+ }
128
+ return value;
129
+ }
130
+ function normalizeTrebiredFrontendConfig(config = {}) {
131
+ const source = assertPlainObject(config, "config");
132
+ const icons = source.icons === undefined ? {} : assertPlainObject(source.icons, "icons");
133
+ const theme = source.theme === undefined ? {} : assertPlainObject(source.theme, "theme");
134
+ return {
135
+ prefix: normalizePrefix(source.prefix),
136
+ icons: {
137
+ endpoint: normalizeEndpoint(icons.endpoint),
138
+ packs: normalizeIconPacks(icons.packs),
139
+ },
140
+ systems: normalizeSystems(source.systems),
141
+ theme: {
142
+ cssVariables: normalizeBoolean(theme.cssVariables, true, "theme.cssVariables"),
143
+ tokens: normalizeThemeTokens(theme.tokens),
144
+ },
145
+ };
146
+ }
147
+ function cssString(value) {
148
+ return JSON.stringify(String(value ?? ""));
149
+ }
150
+ function cssComment(value) {
151
+ return String(value || "").replace(/\*\//gu, "* /");
152
+ }
153
+ function flattenThemeTokens(tokens, prefix = []) {
154
+ const out = [];
155
+ for (const [key, value] of Object.entries(tokens).sort(([a], [b]) => a.localeCompare(b))) {
156
+ if (isPlainObject(value)) {
157
+ out.push(...flattenThemeTokens(value, [...prefix, key]));
158
+ continue;
159
+ }
160
+ if (typeof value === "string" || typeof value === "number") {
161
+ out.push([[...prefix, key].join("-"), value]);
162
+ }
163
+ }
164
+ return out;
165
+ }
166
+ function renderCssVariables(config) {
167
+ if (!config.theme.cssVariables)
168
+ return [];
169
+ const declarations = [
170
+ ` --${config.prefix}-config-prefix: ${cssString(config.prefix)};`,
171
+ ` --${config.prefix}-icon-endpoint: ${cssString(config.icons.endpoint)};`,
172
+ ...flattenThemeTokens(config.theme.tokens).map(([key, value]) => {
173
+ return ` --${config.prefix}-${key}: ${String(value)};`;
174
+ }),
175
+ ];
176
+ return [
177
+ ":root {",
178
+ ...declarations,
179
+ "}",
180
+ ];
181
+ }
182
+ function generateTrebiredFrontendScss(configInput) {
183
+ const config = normalizeTrebiredFrontendConfig(configInput);
184
+ const lines = [
185
+ "/* Generated by @trebired/frontend. Do not edit directly. */",
186
+ `/* prefix: ${cssComment(config.prefix)} */`,
187
+ '@use "@trebired/frontend/styles/tokens" as *;',
188
+ '@use "@trebired/frontend/styles/utils" as *;',
189
+ ];
190
+ for (const system of SYSTEM_ORDER) {
191
+ const importPath = SYSTEM_STYLE_IMPORTS[system];
192
+ if (importPath && config.systems[system]) {
193
+ lines.push(`@use ${cssString(importPath)} as *;`);
194
+ }
195
+ }
196
+ const variables = renderCssVariables(config);
197
+ if (variables.length) {
198
+ lines.push("", ...variables);
199
+ }
200
+ return `${lines.join("\n")}\n`;
201
+ }
202
+ async function pathExists(filePath) {
203
+ try {
204
+ await fs.access(filePath);
205
+ return true;
206
+ }
207
+ catch {
208
+ return false;
209
+ }
210
+ }
211
+ async function findTrebiredFrontendConfig(startDir = process.cwd(), boundaryDir) {
212
+ const boundary = path.resolve(boundaryDir || path.parse(path.resolve(startDir)).root);
213
+ let current = path.resolve(startDir);
214
+ for (;;) {
215
+ const candidate = path.join(current, TREBIRED_FRONTEND_CONFIG_PATH);
216
+ if (await pathExists(candidate))
217
+ return candidate;
218
+ if (current === boundary || current === path.dirname(current))
219
+ return null;
220
+ current = path.dirname(current);
221
+ }
222
+ }
223
+ function createConfigBuildHash(filePath, sourceText) {
224
+ return crypto.createHash("sha256")
225
+ .update(path.resolve(filePath))
226
+ .update("\0")
227
+ .update(sourceText)
228
+ .digest("hex")
229
+ .slice(0, 16);
230
+ }
231
+ async function buildConfigModuleToUrl(projectRoot, filePath) {
232
+ if (typeof Bun === "undefined" || typeof Bun.build !== "function") {
233
+ const url = pathToFileURL(filePath);
234
+ url.searchParams.set("mtime", String((await fs.stat(filePath)).mtimeMs));
235
+ return url.href;
236
+ }
237
+ const sourceText = await fs.readFile(filePath, "utf8");
238
+ const digest = createConfigBuildHash(filePath, sourceText);
239
+ const outputDir = path.join(projectRoot, "node_modules", ".cache", "trebired-frontend", "config", digest);
240
+ const basename = path.basename(filePath, path.extname(filePath)).replace(/[^\w.-]/gu, "_") || "config";
241
+ const outputPath = path.join(outputDir, `${basename}.js`);
242
+ if (!await pathExists(outputPath)) {
243
+ await fs.mkdir(outputDir, { recursive: true });
244
+ const result = await Bun.build({
245
+ entrypoints: [filePath],
246
+ external: ["@trebired/frontend", "@trebired/frontend/*"],
247
+ format: "esm",
248
+ naming: `${basename}.js`,
249
+ outdir: outputDir,
250
+ packages: "external",
251
+ target: "bun",
252
+ });
253
+ if (!result.success) {
254
+ const message = result.logs.map((log) => log.message).filter(Boolean).join("\n");
255
+ throw new Error(`trebired-frontend-invalid-config :: failed to compile ${filePath}${message ? `\n${message}` : ""}`);
256
+ }
257
+ }
258
+ return pathToFileURL(outputPath).href;
259
+ }
260
+ async function importConfigModule(projectRoot, filePath) {
261
+ const imported = await import(await buildConfigModuleToUrl(projectRoot, filePath));
262
+ return imported.default;
263
+ }
264
+ async function loadTrebiredFrontendConfig(projectRoot = process.cwd(), options = {}) {
265
+ const root = path.resolve(projectRoot);
266
+ const resolvedPath = options.configPath
267
+ ? path.resolve(root, options.configPath)
268
+ : await findTrebiredFrontendConfig(options.searchFrom || root);
269
+ if (!resolvedPath) {
270
+ if (options.defaultIfMissing === false) {
271
+ throw new Error(`trebired-frontend-config-not-found :: ${TREBIRED_FRONTEND_CONFIG_PATH}`);
272
+ }
273
+ const config = normalizeTrebiredFrontendConfig({});
274
+ return {
275
+ config,
276
+ configPath: null,
277
+ generatedScss: generateTrebiredFrontendScss(config),
278
+ generatedScssPath: resolveTrebiredFrontendGeneratedScssPath(root),
279
+ };
280
+ }
281
+ if (!await pathExists(resolvedPath)) {
282
+ throw new Error(`trebired-frontend-config-not-found :: ${resolvedPath}`);
283
+ }
284
+ const config = normalizeTrebiredFrontendConfig(await importConfigModule(root, resolvedPath));
285
+ return {
286
+ config,
287
+ configPath: resolvedPath,
288
+ generatedScss: generateTrebiredFrontendScss(config),
289
+ generatedScssPath: resolveTrebiredFrontendGeneratedScssPath(root),
290
+ };
291
+ }
292
+ function resolveTrebiredFrontendGeneratedScssPath(projectRoot = process.cwd()) {
293
+ return path.resolve(projectRoot, TREBIRED_FRONTEND_GENERATED_SCSS_PATH);
294
+ }
295
+ async function writeGeneratedTrebiredFrontendScss(projectRoot, config) {
296
+ const filePath = resolveTrebiredFrontendGeneratedScssPath(projectRoot);
297
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
298
+ const scss = generateTrebiredFrontendScss(config);
299
+ await fs.writeFile(filePath, scss, "utf8");
300
+ return filePath;
301
+ }
302
+ export { DEFAULT_TREBIRED_FRONTEND_CONFIG, SUPPORTED_ICON_PACKS, SYSTEM_ORDER, TREBIRED_FRONTEND_CONFIG_PATH, TREBIRED_FRONTEND_GENERATED_DIR, TREBIRED_FRONTEND_GENERATED_SCSS_PATH, defineTrebiredFrontendConfig, findTrebiredFrontendConfig, generateTrebiredFrontendScss, loadTrebiredFrontendConfig, normalizeTrebiredFrontendConfig, resolveTrebiredFrontendGeneratedScssPath, writeGeneratedTrebiredFrontendScss, };
303
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"dialogs.d.ts","sourceRoot":"","sources":["../../../src/flash/dialogs.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAYhE,iBAAS,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,SAAK,EAAE,OAAO,GAAE,cAAmB,oBAmBhF;AAiCD,iBAAS,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,SAAK,EAAE,OAAO,GAAE,aAAkB,gBAY9E;AAoDD,iBAAS,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,cAAc,GAAE,OAAO,GAAG,IAAW,oBAWpF;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"dialogs.d.ts","sourceRoot":"","sources":["../../../src/flash/dialogs.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgBhE,iBAAS,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,SAAK,EAAE,OAAO,GAAE,cAAmB,oBAqBhF;AAgCD,iBAAS,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,SAAK,EAAE,OAAO,GAAE,aAAkB,gBAc9E;AAkDD,iBAAS,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,EAAE,cAAc,GAAE,OAAO,GAAG,IAAW,oBAWpF;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC"}
@@ -1,7 +1,12 @@
1
1
  import { FLASH_CONFIRM_TIMEOUT_MS, FLASH_PROMPT_TIMEOUT_MS, normalizeFlashType, } from "./duration.js";
2
2
  import { createDialogFlash, makeButton } from "./elements.js";
3
3
  import { ensureFlashStack, hideFlashElement, layoutFlashStack } from "./stack.js";
4
- function finishDialog(stack, element, resolve, value) {
4
+ function finishDialog(stack, element, resolve, value, timeoutId) {
5
+ if (element.hasAttribute("data-tbf-dialog-resolved"))
6
+ return;
7
+ element.setAttribute("data-tbf-dialog-resolved", "true");
8
+ if (timeoutId !== undefined)
9
+ window.clearTimeout(timeoutId);
5
10
  hideFlashElement(stack, element);
6
11
  resolve(value);
7
12
  }
@@ -22,18 +27,20 @@ function confirm(message, description = "", options = {}) {
22
27
  actions.append(cancel, ok);
23
28
  body?.appendChild(actions);
24
29
  stack.appendChild(controls.element);
25
- bindConfirmControls(stack, controls.element, resolve, cancel, ok, controls.close);
26
- window.setTimeout(() => finishDialog(stack, controls.element, resolve, false), FLASH_CONFIRM_TIMEOUT_MS);
30
+ let timeoutId;
31
+ const finish = (value) => finishDialog(stack, controls.element, resolve, value, timeoutId);
32
+ bindConfirmControls(controls.element, finish, cancel, ok, controls.close);
33
+ timeoutId = window.setTimeout(() => finish(false), FLASH_CONFIRM_TIMEOUT_MS);
27
34
  revealDialog(stack, controls.element, input);
28
35
  });
29
36
  }
30
- function bindConfirmControls(stack, element, resolve, cancel, ok, close) {
31
- close.addEventListener("click", () => finishDialog(stack, element, resolve, false));
32
- cancel.addEventListener("click", () => finishDialog(stack, element, resolve, false));
33
- ok.addEventListener("click", () => finishDialog(stack, element, resolve, true));
37
+ function bindConfirmControls(element, finish, cancel, ok, close) {
38
+ close.addEventListener("click", () => finish(false));
39
+ cancel.addEventListener("click", () => finish(false));
40
+ ok.addEventListener("click", () => finish(true));
34
41
  element.addEventListener("keydown", (event) => {
35
42
  if (event.key === "Escape")
36
- finishDialog(stack, element, resolve, false);
43
+ finish(false);
37
44
  });
38
45
  }
39
46
  function createConfirmInput(options, ok) {
@@ -60,8 +67,10 @@ function prompt(message, description = "", options = {}) {
60
67
  const form = createPromptForm(options);
61
68
  controls.element.querySelector(".tbf-flash__body")?.appendChild(form);
62
69
  stack.appendChild(controls.element);
63
- bindPromptControls(stack, controls.element, resolve, form, controls.close);
64
- window.setTimeout(() => finishDialog(stack, controls.element, resolve, null), FLASH_PROMPT_TIMEOUT_MS);
70
+ let timeoutId;
71
+ const finish = (value) => finishDialog(stack, controls.element, resolve, value, timeoutId);
72
+ bindPromptControls(form, controls.close, finish);
73
+ timeoutId = window.setTimeout(() => finish(null), FLASH_PROMPT_TIMEOUT_MS);
65
74
  revealDialog(stack, controls.element, form.querySelector("input"));
66
75
  });
67
76
  }
@@ -84,15 +93,15 @@ function submitButton(label) {
84
93
  button.type = "submit";
85
94
  return button;
86
95
  }
87
- function bindPromptControls(stack, element, resolve, form, close) {
96
+ function bindPromptControls(form, close, finish) {
88
97
  const input = form.querySelector("input");
89
98
  const cancel = form.querySelector(".tbf-button:not(.tbf-button--strong)");
90
99
  form.addEventListener("submit", (event) => {
91
100
  event.preventDefault();
92
- finishDialog(stack, element, resolve, input?.value.trim() || null);
101
+ finish(input?.value.trim() || null);
93
102
  });
94
- cancel?.addEventListener("click", () => finishDialog(stack, element, resolve, null));
95
- close.addEventListener("click", () => finishDialog(stack, element, resolve, null));
103
+ cancel?.addEventListener("click", () => finish(null));
104
+ close.addEventListener("click", () => finish(null));
96
105
  }
97
106
  function revealDialog(stack, element, focusTarget) {
98
107
  window.requestAnimationFrame(() => {