@brickflow/ui 0.0.33 → 0.0.35

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/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  },
5
5
  "configKey": "brickflowUi",
6
6
  "name": "@brickflow/ui",
7
- "version": "0.0.33",
7
+ "version": "0.0.35",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.3",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,9 +1,9 @@
1
- import { defineNuxtModule, createResolver, resolvePath, addTemplate, updateTemplates, addImportsDir, addComponentsDir } from '@nuxt/kit';
1
+ import { defineNuxtModule, createResolver, resolvePath, addTypeTemplate, addTemplate, updateTemplates, addImportsDir, addComponentsDir } from '@nuxt/kit';
2
2
  import tailwindcss from '@tailwindcss/vite';
3
3
  import { createJiti } from 'jiti';
4
4
  import { readdir, mkdir, readFile, writeFile } from 'node:fs/promises';
5
- import { join, resolve, basename, extname, dirname, relative } from 'node:path';
6
- import { defineBrickflowUiConfig } from '../dist/runtime/tailwind.js';
5
+ import { join, basename, extname, dirname, resolve, relative } from 'node:path';
6
+ import { isBrickflowUiStyleReference, getBrickflowUiStyleReferencePath, defineBrickflowUi } from '../dist/runtime/tailwind.js';
7
7
  import { generateFonts, FontAssetType, OtherAssetType } from 'fantasticon';
8
8
 
9
9
  const ICON_FILE_PATTERN = /\.svg$/i;
@@ -85,6 +85,8 @@ ${CUSTOM_DARK_VARIANT}${code.slice(index)}`,
85
85
  });
86
86
 
87
87
  const UI_STYLE_PATTERN = /\bUI_STYLE((?:\.[A-Za-z_$][\w$]*)+)/g;
88
+ const UI_CONFIG_PATTERN = /\bUI_CONFIG((?:\.[A-Za-z_$][\w$]*)+)/g;
89
+ const UI_CONFIG_MACRO = "defineUiConfig";
88
90
  const SCRIPT_FILE_PATTERN = /\.(?:[cm]?[jt]sx?|vue)(?:\?.*)?$/;
89
91
  const TYPE_INDENT = " ";
90
92
  const refreshUiStyleModules = (server) => {
@@ -109,7 +111,7 @@ const resolveUiStyleConfigPath = (id, path) => {
109
111
  return path;
110
112
  }
111
113
  const componentName = basename(cleanId, extname(cleanId));
112
- const configName = componentName === "index" ? basename(dirname(cleanId)) : componentName;
114
+ const configName = componentName === "index" || componentName.endsWith(".demo") ? basename(dirname(cleanId)) : componentName;
113
115
  return [toCamelCase(configName), ...path];
114
116
  };
115
117
  const resolveStyleValue = (styles, id, path) => {
@@ -123,6 +125,73 @@ const resolveStyleValue = (styles, id, path) => {
123
125
  }
124
126
  return configPathValue ?? globalValue;
125
127
  };
128
+ const resolveUiConfigValue = (config, id, path) => {
129
+ const configPathValue = readPath(config, resolveUiStyleConfigPath(id, path));
130
+ return configPathValue ?? readPath(config, path);
131
+ };
132
+ const resolveUiConfigStyleReferences = (value, styles, id) => {
133
+ if (isBrickflowUiStyleReference(value)) {
134
+ const stylePath = getBrickflowUiStyleReferencePath(value);
135
+ const styleValue = resolveStyleValue(styles, id, [...stylePath]);
136
+ if (typeof styleValue !== "string") {
137
+ throw new TypeError(`UI_STYLE.${stylePath.join(".")} does not resolve to a string in ${id}.`);
138
+ }
139
+ return styleValue;
140
+ }
141
+ if (typeof value === "string") {
142
+ return value;
143
+ }
144
+ return Object.fromEntries(
145
+ Object.entries(value).map(([key, childValue]) => [
146
+ key,
147
+ resolveUiConfigStyleReferences(childValue, styles, id)
148
+ ])
149
+ );
150
+ };
151
+ const replaceUiConfigMacros = (code, config, styles, id, error) => {
152
+ let result = "";
153
+ let cursor = 0;
154
+ while (cursor < code.length) {
155
+ const start = code.indexOf(UI_CONFIG_MACRO, cursor);
156
+ if (start === -1) {
157
+ return result + code.slice(cursor);
158
+ }
159
+ const genericStart = start + UI_CONFIG_MACRO.length;
160
+ let callStart = genericStart;
161
+ if (code[genericStart] === "<") {
162
+ let depth = 0;
163
+ let index = genericStart;
164
+ for (; index < code.length; index += 1) {
165
+ if (code[index] === "<") {
166
+ depth += 1;
167
+ }
168
+ if (code[index] === ">") {
169
+ depth -= 1;
170
+ }
171
+ if (depth === 0) {
172
+ break;
173
+ }
174
+ }
175
+ callStart = index + 1;
176
+ }
177
+ while (/\s/u.test(code[callStart] ?? "")) {
178
+ callStart += 1;
179
+ }
180
+ if (code.slice(callStart, callStart + 2) !== "()") {
181
+ result += code.slice(cursor, callStart);
182
+ cursor = callStart;
183
+ continue;
184
+ }
185
+ const value = resolveUiConfigValue(config, id, []);
186
+ if (value === void 0) {
187
+ error(`defineUiConfig() in ${id} has no matching uiConfig entry.`);
188
+ }
189
+ result += code.slice(cursor, start);
190
+ result += JSON.stringify(resolveUiConfigStyleReferences(value, styles, id));
191
+ cursor = callStart + 2;
192
+ }
193
+ return result;
194
+ };
126
195
  const createUiStylePathTree = () => ({
127
196
  children: /* @__PURE__ */ new Map()
128
197
  });
@@ -134,16 +203,18 @@ const addPathToTree = (tree, path) => {
134
203
  currentTree = childTree;
135
204
  }
136
205
  };
137
- const renderTypeTree = (tree, level, objectType) => {
206
+ const renderTypeTree = (tree, level, objectType, leafType = "string", path = []) => {
138
207
  const lines = [];
139
208
  const indent = TYPE_INDENT.repeat(level);
140
209
  for (const [key, childTree] of [...tree.children.entries()].sort(([a], [b]) => a.localeCompare(b))) {
141
210
  if (childTree.children.size === 0) {
142
- lines.push(`${indent}readonly ${key}: string`);
211
+ const childPath = [...path, key];
212
+ const childLeafType = typeof leafType === "function" ? leafType(childPath) : leafType;
213
+ lines.push(`${indent}readonly ${key}: ${childLeafType}`);
143
214
  continue;
144
215
  }
145
216
  lines.push(objectType ? `${indent}readonly ${key}: ${objectType} & {` : `${indent}readonly ${key}: {`);
146
- lines.push(...renderTypeTree(childTree, level + 1, objectType));
217
+ lines.push(...renderTypeTree(childTree, level + 1, objectType, leafType, [...path, key]));
147
218
  lines.push(`${indent}}`);
148
219
  }
149
220
  return lines;
@@ -156,18 +227,111 @@ const collectUiStylePathsFromCode = (code) => {
156
227
  return paths.filter((path) => path.length > 0);
157
228
  };
158
229
  const collectUiStyleConfigPathsFromCode = (code, id) => collectUiStylePathsFromCode(code).map((path) => resolveUiStyleConfigPath(id, path));
159
- const renderInterfaceDeclaration = (name, paths, objectType) => {
230
+ const collectUiConfigValuePaths = (value, prefix) => {
231
+ if (typeof value === "string" || isBrickflowUiStyleReference(value)) {
232
+ return [prefix];
233
+ }
234
+ return Object.entries(value).flatMap(
235
+ ([key, childValue]) => collectUiConfigValuePaths(childValue, [...prefix, key])
236
+ );
237
+ };
238
+ const collectUiConfigPathsFromCode = (code, id, config) => {
239
+ const paths = [];
240
+ for (const match of code.matchAll(UI_CONFIG_PATTERN)) {
241
+ const path = match[1]?.slice(1).split(".") ?? [];
242
+ const value = resolveUiConfigValue(config, id, path);
243
+ paths.push(...value === void 0 ? [path] : collectUiConfigValuePaths(value, path));
244
+ }
245
+ return paths.filter((path) => path.length > 0);
246
+ };
247
+ const collectUiConfigComponentPathsFromCode = (code, id, config) => {
248
+ const paths = [];
249
+ for (const match of code.matchAll(UI_CONFIG_PATTERN)) {
250
+ const path = match[1]?.slice(1).split(".") ?? [];
251
+ const componentPath = resolveUiStyleConfigPath(id, path);
252
+ const value = readPath(config, componentPath);
253
+ paths.push(
254
+ ...value === void 0 ? [componentPath] : collectUiConfigValuePaths(value, componentPath)
255
+ );
256
+ }
257
+ if (code.includes(UI_CONFIG_MACRO)) {
258
+ const componentPath = resolveUiStyleConfigPath(id, []);
259
+ const value = readPath(config, componentPath);
260
+ if (value !== void 0) {
261
+ paths.push(...collectUiConfigValuePaths(value, componentPath));
262
+ }
263
+ }
264
+ return paths.filter((path) => path.length > 0);
265
+ };
266
+ const collectUiConfigSchemaEntriesFromCode = (code, id) => {
267
+ const entries = [];
268
+ let cursor = 0;
269
+ while (cursor < code.length) {
270
+ const start = code.indexOf(UI_CONFIG_MACRO, cursor);
271
+ if (start === -1) {
272
+ return entries;
273
+ }
274
+ const genericStart = start + UI_CONFIG_MACRO.length;
275
+ if (code[genericStart] !== "<") {
276
+ cursor = genericStart;
277
+ continue;
278
+ }
279
+ let depth = 0;
280
+ let genericEnd = genericStart;
281
+ for (; genericEnd < code.length; genericEnd += 1) {
282
+ if (code[genericEnd] === "<") {
283
+ depth += 1;
284
+ }
285
+ if (code[genericEnd] === ">") {
286
+ depth -= 1;
287
+ }
288
+ if (depth === 0) {
289
+ break;
290
+ }
291
+ }
292
+ let callStart = genericEnd + 1;
293
+ while (/\s/u.test(code[callStart] ?? "")) {
294
+ callStart += 1;
295
+ }
296
+ if (code.slice(callStart, callStart + 2) !== "()") {
297
+ cursor = callStart;
298
+ continue;
299
+ }
300
+ const schema = code.slice(genericStart + 1, genericEnd).trim();
301
+ const path = resolveUiStyleConfigPath(id, []);
302
+ if (schema.startsWith("{") && path.length > 0) {
303
+ entries.push({ path, schema });
304
+ }
305
+ cursor = callStart + 2;
306
+ }
307
+ return entries;
308
+ };
309
+ const collectUiConfigStyleReferencePathsFromValue = (value, componentPath) => {
310
+ if (isBrickflowUiStyleReference(value)) {
311
+ return [[...componentPath, ...getBrickflowUiStyleReferencePath(value)]];
312
+ }
313
+ if (typeof value === "string") {
314
+ return [];
315
+ }
316
+ return Object.values(value).flatMap(
317
+ (childValue) => collectUiConfigStyleReferencePathsFromValue(childValue, componentPath)
318
+ );
319
+ };
320
+ const collectUiConfigStyleReferencePaths = (config) => Object.entries(config).flatMap(([key, value]) => collectUiConfigStyleReferencePathsFromValue(value, [key]));
321
+ const renderInterfaceDeclaration = (name, paths, objectType, leafType = "string") => {
160
322
  const tree = createUiStylePathTree();
161
323
  for (const path of paths) {
162
324
  addPathToTree(tree, path);
163
325
  }
164
- return [` interface ${name} {`, ...renderTypeTree(tree, 2, objectType), " }"];
326
+ return [` interface ${name} {`, ...renderTypeTree(tree, 2, objectType, leafType), " }"];
165
327
  };
166
328
  const createUiStyleTypeDeclaration = (options) => {
167
329
  return [
168
330
  "declare global {",
169
331
  ...renderInterfaceDeclaration("BrickflowUiConfigStylePaths", options.configPaths),
170
332
  "",
333
+ ...renderInterfaceDeclaration("BrickflowUiConfigPaths", options.uiConfigPaths),
334
+ "",
171
335
  ...renderInterfaceDeclaration("BrickflowUiStylePaths", options.paths, "BrickflowUiStyleValue"),
172
336
  "}",
173
337
  "",
@@ -175,6 +339,39 @@ const createUiStyleTypeDeclaration = (options) => {
175
339
  ""
176
340
  ].join("\n");
177
341
  };
342
+ const createUiConfigLiteralTypeDeclaration = (paths, config) => [
343
+ "declare global {",
344
+ ...renderInterfaceDeclaration("BrickflowUiConfigLiteralPaths", paths, void 0, (path) => {
345
+ const value = config ? readPath(config, path) : void 0;
346
+ return typeof value === "string" ? toStringLiteral(value) : "string";
347
+ }),
348
+ "}",
349
+ "",
350
+ "export {}",
351
+ ""
352
+ ].join("\n");
353
+ const createUiConfigSchemaTypeDeclaration = (entries) => {
354
+ const schemasByPath = /* @__PURE__ */ new Map();
355
+ for (const { path, schema } of entries) {
356
+ const pathKey = path.join(".");
357
+ const schemas = schemasByPath.get(pathKey) ?? [];
358
+ schemas.push(schema);
359
+ schemasByPath.set(pathKey, schemas);
360
+ }
361
+ return [
362
+ "declare global {",
363
+ " interface BrickflowUiConfigSchema {",
364
+ ...[...schemasByPath.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([path, schemas]) => {
365
+ const [componentName] = path.split(".");
366
+ return ` readonly ${componentName}: ${schemas.map((schema) => `(${schema})`).join(" & ")}`;
367
+ }),
368
+ " }",
369
+ "}",
370
+ "",
371
+ "export {}",
372
+ ""
373
+ ].join("\n");
374
+ };
178
375
  const brickflowUiStylePlugin = (options) => ({
179
376
  buildStart: {
180
377
  handler() {
@@ -197,13 +394,42 @@ const brickflowUiStylePlugin = (options) => ({
197
394
  },
198
395
  name: "brickflow-ui-style",
199
396
  async transform(code, id) {
200
- if (!SCRIPT_FILE_PATTERN.test(id) || !code.includes("UI_STYLE.")) {
397
+ const cleanId = id.split("?")[0] ?? id;
398
+ const isVirtualModule = cleanId.startsWith("\0") || cleanId.startsWith("virtual:");
399
+ const isVueSubmodule = cleanId.endsWith(".vue") && id.includes("?vue");
400
+ if (isVirtualModule || isVueSubmodule && !code.includes(UI_CONFIG_MACRO) || !SCRIPT_FILE_PATTERN.test(id) || !code.includes("UI_STYLE.") && !code.includes("UI_CONFIG.") && !code.includes(UI_CONFIG_MACRO)) {
201
401
  return null;
202
402
  }
203
403
  this.addWatchFile?.(options.configPath);
204
404
  const styles = await options.getStyles();
405
+ const config = await options.getConfig();
406
+ const isConfigFile = normalizePath(cleanId) === normalizePath(options.configPath);
407
+ const hasUiConfigMacro = cleanId.endsWith(".vue") && code.includes(UI_CONFIG_MACRO);
205
408
  let changed = false;
206
- const transformedCode = code.replace(UI_STYLE_PATTERN, (match, rawPath) => {
409
+ const codeWithUiConfigMacros = hasUiConfigMacro ? replaceUiConfigMacros(code, config, styles, id, this.error.bind(this)) : code;
410
+ if (codeWithUiConfigMacros !== code) {
411
+ changed = true;
412
+ }
413
+ const transformedCode = codeWithUiConfigMacros.replace(UI_CONFIG_PATTERN, (match, rawPath) => {
414
+ if (hasUiConfigMacro) {
415
+ return match;
416
+ }
417
+ const path = rawPath.slice(1).split(".");
418
+ const value = resolveUiConfigValue(config, id, path);
419
+ changed = true;
420
+ if (value === void 0) {
421
+ return "undefined";
422
+ }
423
+ try {
424
+ const resolvedValue = resolveUiConfigStyleReferences(value, styles, id);
425
+ return typeof resolvedValue === "string" ? toStringLiteral(resolvedValue) : JSON.stringify(resolvedValue);
426
+ } catch (error) {
427
+ this.error(error instanceof Error ? error.message : String(error));
428
+ }
429
+ }).replace(UI_STYLE_PATTERN, (match, rawPath) => {
430
+ if (isConfigFile) {
431
+ return match;
432
+ }
207
433
  const path = rawPath.slice(1).split(".");
208
434
  const value = resolveStyleValue(styles, id, path);
209
435
  if (typeof value === "string") {
@@ -453,14 +679,13 @@ const module$1 = defineNuxtModule({
453
679
  );
454
680
  };
455
681
  const loadUiConfig = async () => {
456
- const validateConfig = defineBrickflowUiConfig;
682
+ const validateConfig = defineBrickflowUi;
457
683
  return validateConfig(
458
684
  await loadConfig.import(resolvedConfigPath).catch(() => ({}))
459
685
  );
460
686
  };
461
687
  await loadUiConfig();
462
- const uiStyleTypePath = resolve(nuxt.options.buildDir, "types/brickflow-ui-style.d.ts");
463
- const generateUiStyleTypes = async () => {
688
+ const getUiStyleTypeContents = async () => {
464
689
  const files = await scanUiStyleFiles(runtimePath);
465
690
  const fileContents = await Promise.all(
466
691
  files.map(async (file) => ({
@@ -468,19 +693,55 @@ const module$1 = defineNuxtModule({
468
693
  file
469
694
  }))
470
695
  );
471
- const paths = fileContents.flatMap(({ content }) => collectUiStylePathsFromCode(content));
696
+ const uiConfig = (await loadUiConfig()).uiConfig;
697
+ const uiConfigStyleReferencePaths = collectUiConfigStyleReferencePaths(uiConfig);
698
+ const paths = [
699
+ ...fileContents.flatMap(({ content }) => collectUiStylePathsFromCode(content)),
700
+ ...uiConfigStyleReferencePaths.map((path) => path.slice(1))
701
+ ];
472
702
  const configPaths = fileContents.flatMap(
473
703
  ({ content, file }) => collectUiStyleConfigPathsFromCode(content, file)
474
704
  );
475
- await mkdir(resolve(nuxt.options.buildDir, "types"), { recursive: true });
476
- await writeFile(
477
- uiStyleTypePath,
478
- createUiStyleTypeDeclaration({
479
- configPaths,
480
- paths
481
- })
705
+ configPaths.push(...uiConfigStyleReferencePaths);
706
+ const uiConfigPaths = fileContents.flatMap(
707
+ ({ content, file }) => collectUiConfigPathsFromCode(content, file, uiConfig)
482
708
  );
709
+ return createUiStyleTypeDeclaration({
710
+ configPaths,
711
+ paths,
712
+ uiConfigPaths
713
+ });
483
714
  };
715
+ const uiStyleTypeTemplate = addTypeTemplate({
716
+ filename: "types/brickflow-ui-style.d.ts",
717
+ getContents: getUiStyleTypeContents
718
+ });
719
+ const uiConfigLiteralTypeTemplate = addTypeTemplate({
720
+ filename: "types/brickflow-ui-config-literals.d.ts",
721
+ getContents: async () => {
722
+ const files = await scanUiStyleFiles(runtimePath);
723
+ const uiConfig = (await loadUiConfig()).uiConfig;
724
+ const paths = await Promise.all(
725
+ files.map(
726
+ async (file) => collectUiConfigComponentPathsFromCode(await readFile(file, "utf8"), file, uiConfig)
727
+ )
728
+ );
729
+ return createUiConfigLiteralTypeDeclaration(paths.flat(), uiConfig);
730
+ }
731
+ });
732
+ const uiConfigSchemaTypeTemplate = addTypeTemplate({
733
+ filename: "types/brickflow-ui-config-contract.d.ts",
734
+ getContents: async () => {
735
+ const files = await scanUiStyleFiles(componentsDirectory);
736
+ const entries = await Promise.all(
737
+ files.map(async (file) => collectUiConfigSchemaEntriesFromCode(await readFile(file, "utf8"), file))
738
+ );
739
+ return createUiConfigSchemaTypeDeclaration(entries.flat());
740
+ }
741
+ });
742
+ nuxt.hook("prepare:types", ({ references }) => {
743
+ references.push({ path: resolver.resolve("./runtime/config.d.ts") });
744
+ });
484
745
  const iconFontTemplate = addTemplate({
485
746
  filename: "brickflow/brickflow-ui-icons.mjs",
486
747
  getContents: async () => {
@@ -495,12 +756,14 @@ const module$1 = defineNuxtModule({
495
756
  const uiConfigTemplate = addTemplate({
496
757
  filename: "brickflow/brickflow-ui-config.mjs",
497
758
  getContents: () => [
759
+ `import { defineBrickflowUi } from ${JSON.stringify(resolver.resolve("./runtime/tailwind").replaceAll("\\", "/"))}`,
498
760
  `import rawConfig from ${JSON.stringify(resolvedConfigPath.replaceAll("\\", "/"))}`,
499
- `import { defineBrickflowUiConfig } from ${JSON.stringify(resolver.resolve("./runtime/tailwind").replaceAll("\\", "/"))}`,
500
761
  "",
501
- "const config = defineBrickflowUiConfig(rawConfig)",
762
+ "const config = defineBrickflowUi(rawConfig)",
502
763
  "",
503
764
  "export const UI_STYLE = config.uiStyles",
765
+ "export const UI_CONFIG = config.uiConfig",
766
+ "export const uiConfig = config.uiConfig",
504
767
  "export const uiStyles = config.uiStyles",
505
768
  "export default config",
506
769
  ""
@@ -615,17 +878,14 @@ const module$1 = defineNuxtModule({
615
878
  path: "/ui"
616
879
  });
617
880
  });
618
- await generateUiStyleTypes();
619
- nuxt.hook("prepare:types", async ({ references }) => {
620
- await generateUiStyleTypes();
621
- references.push({ path: uiStyleTypePath });
622
- });
623
881
  nuxt.hook("builder:watch", async (_event, path) => {
624
882
  const absolutePath = resolve(nuxt.options.srcDir, path);
625
883
  if (relative(runtimePath, absolutePath).startsWith("..") || !UI_STYLE_FILE_PATTERN.test(path)) {
626
884
  return;
627
885
  }
628
- await generateUiStyleTypes();
886
+ await updateTemplates({
887
+ filter: (template) => template.filename === uiStyleTypeTemplate.filename || template.filename === uiConfigLiteralTypeTemplate.filename || template.filename === uiConfigSchemaTypeTemplate.filename
888
+ });
629
889
  if (!relative(componentsDirectory, absolutePath).startsWith("..") && (UI_COMPONENT_FILE_PATTERN.test(path) || UI_DEMO_FILE_PATTERN.test(path))) {
630
890
  await updateTemplates({ filter: (template) => template.filename === uiCatalogTemplate.filename });
631
891
  }
@@ -644,6 +904,7 @@ const module$1 = defineNuxtModule({
644
904
  viteConfig.plugins.push(
645
905
  brickflowUiStylePlugin({
646
906
  configPath: resolvedConfigPath,
907
+ getConfig: async () => (await loadUiConfig()).uiConfig,
647
908
  getStyles: async () => (await loadUiConfig()).uiStyles
648
909
  })
649
910
  );
@@ -1,42 +1,48 @@
1
1
  import type { RouteLocationRaw } from 'vue-router';
2
- type __VLS_Props = {
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
4
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
3
5
  block?: boolean;
4
- color?: ButtonColor;
6
+ color?: string;
5
7
  disabled?: boolean;
6
8
  icon?: string;
7
9
  loading?: boolean;
8
10
  rounded?: boolean;
9
- size?: ButtonSize;
11
+ size?: string;
10
12
  square?: boolean;
11
13
  to?: RouteLocationRaw;
12
14
  trailingIcon?: string;
13
- type?: 'button' | 'reset' | 'submit';
14
- variant?: ButtonVariant;
15
- };
16
- type ButtonColor = 'alt' | 'danger' | 'info' | 'main' | 'plain' | 'warn' | 'win';
17
- type ButtonSize = 'lg' | 'md' | 'sm' | 'xl' | 'xs';
18
- type ButtonVariant = 'ghost' | 'mist' | 'soft' | 'solid' | 'subtle';
19
- declare var __VLS_10: {}, __VLS_22: {}, __VLS_24: {};
20
- type __VLS_Slots = {} & {
21
- leading?: (props: typeof __VLS_10) => any;
22
- } & {
23
- default?: (props: typeof __VLS_22) => any;
24
- } & {
25
- trailing?: (props: typeof __VLS_24) => any;
26
- };
27
- declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
28
- size: ButtonSize;
15
+ type?: "button" | "reset" | "submit";
16
+ variant?: string;
17
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
18
+ block?: boolean;
19
+ color?: string;
20
+ disabled?: boolean;
21
+ icon?: string;
22
+ loading?: boolean;
23
+ rounded?: boolean;
24
+ size?: string;
25
+ square?: boolean;
26
+ to?: RouteLocationRaw;
27
+ trailingIcon?: string;
28
+ type?: "button" | "reset" | "submit";
29
+ variant?: string;
30
+ }> & Readonly<{}>, {
31
+ size: string;
29
32
  type: "button" | "reset" | "submit";
30
- color: ButtonColor;
33
+ color: string;
31
34
  to: RouteLocationRaw;
32
35
  icon: string;
33
36
  rounded: boolean;
34
37
  trailingIcon: string;
35
- variant: ButtonVariant;
36
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
37
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
38
- declare const _default: typeof __VLS_export;
39
- export default _default;
38
+ variant: string;
39
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
40
+ leading?: (props: {}) => any;
41
+ } & {
42
+ default?: (props: {}) => any;
43
+ } & {
44
+ trailing?: (props: {}) => any;
45
+ }>;
40
46
  type __VLS_WithSlots<T, S> = T & {
41
47
  new (): {
42
48
  $slots: S;
@@ -1,28 +1,27 @@
1
+ <script>
2
+ const UI_CONFIG = defineUiConfig();
3
+ </script>
4
+
1
5
  <script setup>
2
6
  import { computed, shallowRef } from "vue";
3
7
  import Icon from "../Icon/index.vue";
4
8
  import BaseLink from "../Link/index.vue";
5
9
  const props = defineProps({
6
10
  block: { type: Boolean, required: false },
7
- color: { type: String, required: false, default: "main" },
11
+ color: { type: String, required: false, default: UI_CONFIG.colorDefault },
8
12
  disabled: { type: Boolean, required: false },
9
13
  icon: { type: String, required: false, default: void 0 },
10
14
  loading: { type: Boolean, required: false },
11
15
  rounded: { type: Boolean, required: false, default: false },
12
- size: { type: String, required: false, default: "md" },
16
+ size: { type: String, required: false, default: UI_CONFIG.sizeDefault },
13
17
  square: { type: Boolean, required: false },
14
18
  to: { type: null, required: false, default: void 0 },
15
19
  trailingIcon: { type: String, required: false, default: void 0 },
16
20
  type: { type: String, required: false, default: "button" },
17
- variant: { type: String, required: false, default: "solid" }
21
+ variant: { type: String, required: false, default: UI_CONFIG.variantDefault }
18
22
  });
19
- const sizeClasses = {
20
- lg: UI_STYLE.size.lg,
21
- md: UI_STYLE.size.md,
22
- sm: UI_STYLE.size.sm,
23
- xl: UI_STYLE.size.xl,
24
- xs: UI_STYLE.size.xs
25
- };
23
+ const colorClasses = UI_CONFIG.colorClasses;
24
+ const sizeClasses = UI_CONFIG.sizeClasses;
26
25
  const sizeIconClasses = {
27
26
  lg: UI_STYLE.size.lgIcon,
28
27
  md: UI_STYLE.size.mdIcon,
@@ -30,57 +29,6 @@ const sizeIconClasses = {
30
29
  xl: UI_STYLE.size.xlIcon,
31
30
  xs: UI_STYLE.size.xsIcon
32
31
  };
33
- const colorClasses = {
34
- alt: {
35
- ghost: UI_STYLE.color.alt.ghost,
36
- mist: UI_STYLE.color.alt.mist,
37
- soft: UI_STYLE.color.alt.soft,
38
- solid: UI_STYLE.color.alt.solid,
39
- subtle: UI_STYLE.color.alt.subtle
40
- },
41
- danger: {
42
- ghost: UI_STYLE.color.danger.ghost,
43
- mist: UI_STYLE.color.danger.mist,
44
- soft: UI_STYLE.color.danger.soft,
45
- solid: UI_STYLE.color.danger.solid,
46
- subtle: UI_STYLE.color.danger.subtle
47
- },
48
- info: {
49
- ghost: UI_STYLE.color.info.ghost,
50
- mist: UI_STYLE.color.info.mist,
51
- soft: UI_STYLE.color.info.soft,
52
- solid: UI_STYLE.color.info.solid,
53
- subtle: UI_STYLE.color.info.subtle
54
- },
55
- main: {
56
- ghost: UI_STYLE.color.main.ghost,
57
- mist: UI_STYLE.color.main.mist,
58
- soft: UI_STYLE.color.main.soft,
59
- solid: UI_STYLE.color.main.solid,
60
- subtle: UI_STYLE.color.main.subtle
61
- },
62
- plain: {
63
- ghost: UI_STYLE.color.plain.ghost,
64
- mist: UI_STYLE.color.plain.mist,
65
- soft: UI_STYLE.color.plain.soft,
66
- solid: UI_STYLE.color.plain.solid,
67
- subtle: UI_STYLE.color.plain.subtle
68
- },
69
- warn: {
70
- ghost: UI_STYLE.color.warn.ghost,
71
- mist: UI_STYLE.color.warn.mist,
72
- soft: UI_STYLE.color.warn.soft,
73
- solid: UI_STYLE.color.warn.solid,
74
- subtle: UI_STYLE.color.warn.subtle
75
- },
76
- win: {
77
- ghost: UI_STYLE.color.win.ghost,
78
- mist: UI_STYLE.color.win.mist,
79
- soft: UI_STYLE.color.win.soft,
80
- solid: UI_STYLE.color.win.solid,
81
- subtle: UI_STYLE.color.win.subtle
82
- }
83
- };
84
32
  const component = computed(() => props.to === void 0 ? "button" : BaseLink);
85
33
  const disabled = computed(() => props.disabled || props.loading);
86
34
  const isButton = computed(() => props.to === void 0);
@@ -126,7 +74,7 @@ function handleTap() {
126
74
  <slot name="leading">
127
75
  <Icon
128
76
  v-if="props.loading"
129
- :name="UI_STYLE.state.loadingIconName"
77
+ :name="UI_CONFIG.loadingIconName"
130
78
  :class="UI_STYLE.state.loading"
131
79
  aria-hidden="true"
132
80
  />
@@ -1,42 +1,48 @@
1
1
  import type { RouteLocationRaw } from 'vue-router';
2
- type __VLS_Props = {
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
4
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
3
5
  block?: boolean;
4
- color?: ButtonColor;
6
+ color?: string;
5
7
  disabled?: boolean;
6
8
  icon?: string;
7
9
  loading?: boolean;
8
10
  rounded?: boolean;
9
- size?: ButtonSize;
11
+ size?: string;
10
12
  square?: boolean;
11
13
  to?: RouteLocationRaw;
12
14
  trailingIcon?: string;
13
- type?: 'button' | 'reset' | 'submit';
14
- variant?: ButtonVariant;
15
- };
16
- type ButtonColor = 'alt' | 'danger' | 'info' | 'main' | 'plain' | 'warn' | 'win';
17
- type ButtonSize = 'lg' | 'md' | 'sm' | 'xl' | 'xs';
18
- type ButtonVariant = 'ghost' | 'mist' | 'soft' | 'solid' | 'subtle';
19
- declare var __VLS_10: {}, __VLS_22: {}, __VLS_24: {};
20
- type __VLS_Slots = {} & {
21
- leading?: (props: typeof __VLS_10) => any;
22
- } & {
23
- default?: (props: typeof __VLS_22) => any;
24
- } & {
25
- trailing?: (props: typeof __VLS_24) => any;
26
- };
27
- declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
28
- size: ButtonSize;
15
+ type?: "button" | "reset" | "submit";
16
+ variant?: string;
17
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
18
+ block?: boolean;
19
+ color?: string;
20
+ disabled?: boolean;
21
+ icon?: string;
22
+ loading?: boolean;
23
+ rounded?: boolean;
24
+ size?: string;
25
+ square?: boolean;
26
+ to?: RouteLocationRaw;
27
+ trailingIcon?: string;
28
+ type?: "button" | "reset" | "submit";
29
+ variant?: string;
30
+ }> & Readonly<{}>, {
31
+ size: string;
29
32
  type: "button" | "reset" | "submit";
30
- color: ButtonColor;
33
+ color: string;
31
34
  to: RouteLocationRaw;
32
35
  icon: string;
33
36
  rounded: boolean;
34
37
  trailingIcon: string;
35
- variant: ButtonVariant;
36
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
37
- declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
38
- declare const _default: typeof __VLS_export;
39
- export default _default;
38
+ variant: string;
39
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
40
+ leading?: (props: {}) => any;
41
+ } & {
42
+ default?: (props: {}) => any;
43
+ } & {
44
+ trailing?: (props: {}) => any;
45
+ }>;
40
46
  type __VLS_WithSlots<T, S> = T & {
41
47
  new (): {
42
48
  $slots: S;
@@ -6,199 +6,43 @@ export const uiDemo = {
6
6
 
7
7
  <script setup>
8
8
  import Button from "./index.vue";
9
+ const UI_CONFIG = defineUiConfig();
10
+ const colors = Object.entries(UI_CONFIG.colorClasses).map(([name, classes]) => ({
11
+ name,
12
+ variants: Object.keys(classes)
13
+ }));
14
+ const variants = colors[0]?.variants ?? [];
9
15
  </script>
10
16
 
11
17
  <template>
12
- <div class="relative flex w-fit flex-col flex-wrap items-start gap-3 pl-13">
18
+ <div class="relative flex w-fit flex-col items-start gap-3 pl-13">
13
19
  <div class="absolute top-0 left-0 z-0 size-full object-cover pt-7 pl-13">
14
20
  <img
15
- src="https://picsum.photos/1000/1000"
21
+ src="https://images.unsplash.com/photo-1545346315-f4c47e3e1b55?ixid=M3w4MjcwNjd8MHwxfHNlYXJjaHwyfHxzdHJvbmclMjBtYW58ZW58MHx8fHwxNzg4MjIyNTU1fDA&ixlib=rb-4.1.0&w=1000&h=1000&fit=max&q=80"
16
22
  class="top-0 z-0 size-full rounded-xl object-cover opacity-50"
17
23
  />
18
24
  </div>
19
25
  <div class="flex w-full flex-wrap items-center justify-around gap-3 text-xs text-slate-600">
20
- <span>solid</span>
21
- <span>ghost</span>
22
- <span>mist</span>
23
- <span>soft</span>
24
- <span>subtle</span>
26
+ <span
27
+ v-for="variant in variants"
28
+ :key="variant"
29
+ >
30
+ {{ variant }}
31
+ </span>
25
32
  </div>
26
33
  <div
27
- class="absolute top-0 left-0 flex h-full flex-col items-center justify-around gap-3 pt-7 text-xs text-slate-600"
34
+ v-for="color in colors"
35
+ :key="color.name"
36
+ class="relative flex w-full flex-wrap items-center gap-3 p-2"
28
37
  >
29
- <span>main</span>
30
- <span>plain</span>
31
- <span>alt</span>
32
- <span>danger</span>
33
- <span>info</span>
34
- <span>warn</span>
35
- <span>win</span>
36
- </div>
37
- <div class="flex flex-wrap items-center gap-3 p-2">
38
- <Button>Button</Button>
39
- <Button variant="ghost">Button</Button>
40
- <Button variant="mist">Button</Button>
41
- <Button variant="soft">Button</Button>
42
- <Button variant="subtle">Button</Button>
43
- </div>
44
- <div class="flex flex-wrap items-center gap-3 p-2">
45
- <Button color="plain">Button</Button>
46
- <Button
47
- color="plain"
48
- variant="ghost"
49
- >
50
- Button
51
- </Button>
52
- <Button
53
- color="plain"
54
- variant="mist"
55
- >
56
- Button
57
- </Button>
58
- <Button
59
- color="plain"
60
- variant="soft"
61
- >
62
- Button
63
- </Button>
64
- <Button
65
- color="plain"
66
- variant="subtle"
67
- >
68
- Button
69
- </Button>
70
- </div>
71
- <div class="flex flex-wrap items-center gap-3 p-2">
72
- <Button color="alt">Button</Button>
73
- <Button
74
- color="alt"
75
- variant="ghost"
76
- >
77
- Button
78
- </Button>
79
- <Button
80
- color="alt"
81
- variant="mist"
82
- >
83
- Button
84
- </Button>
85
- <Button
86
- color="alt"
87
- variant="soft"
88
- >
89
- Button
90
- </Button>
91
- <Button
92
- color="alt"
93
- variant="subtle"
94
- >
95
- Button
96
- </Button>
97
- </div>
98
- <div class="flex flex-wrap items-center gap-3 p-2">
99
- <Button color="danger">Button</Button>
100
- <Button
101
- color="danger"
102
- variant="ghost"
103
- >
104
- Button
105
- </Button>
106
- <Button
107
- color="danger"
108
- variant="mist"
109
- >
110
- Button
111
- </Button>
112
- <Button
113
- color="danger"
114
- variant="soft"
115
- >
116
- Button
117
- </Button>
118
- <Button
119
- color="danger"
120
- variant="subtle"
121
- >
122
- Button
123
- </Button>
124
- </div>
125
- <div class="flex flex-wrap items-center gap-3 p-2">
126
- <Button color="info">Button</Button>
127
- <Button
128
- color="info"
129
- variant="ghost"
130
- >
131
- Button
132
- </Button>
133
- <Button
134
- color="info"
135
- variant="mist"
136
- >
137
- Button
138
- </Button>
139
- <Button
140
- color="info"
141
- variant="soft"
142
- >
143
- Button
144
- </Button>
145
- <Button
146
- color="info"
147
- variant="subtle"
148
- >
149
- Button
150
- </Button>
151
- </div>
152
- <div class="flex flex-wrap items-center gap-3 p-2">
153
- <Button color="warn">Button</Button>
154
- <Button
155
- color="warn"
156
- variant="ghost"
157
- >
158
- Button
159
- </Button>
160
- <Button
161
- color="warn"
162
- variant="mist"
163
- >
164
- Button
165
- </Button>
166
- <Button
167
- color="warn"
168
- variant="soft"
169
- >
170
- Button
171
- </Button>
172
- <Button
173
- color="warn"
174
- variant="subtle"
175
- >
176
- Button
177
- </Button>
178
- </div>
179
- <div class="flex flex-wrap items-center gap-3 p-2">
180
- <Button color="win">Button</Button>
181
- <Button
182
- color="win"
183
- variant="ghost"
184
- >
185
- Button
186
- </Button>
187
- <Button
188
- color="win"
189
- variant="mist"
190
- >
191
- Button
192
- </Button>
193
- <Button
194
- color="win"
195
- variant="soft"
196
- >
197
- Button
198
- </Button>
199
- <Button
200
- color="win"
201
- variant="subtle"
38
+ <span class="absolute top-1/2 right-full mr-3 -translate-y-1/2 text-xs text-slate-600">
39
+ {{ color.name }}
40
+ </span>
41
+ <Button
42
+ v-for="variant in color.variants"
43
+ :key="variant"
44
+ :color="color.name"
45
+ :variant="variant"
202
46
  >
203
47
  Button
204
48
  </Button>
@@ -3,7 +3,9 @@ export {}
3
3
  declare module '#brickflow-ui-config' {
4
4
  import type { BrickflowUiConfig } from './tailwind'
5
5
 
6
- export const UI_STYLE: BrickflowUiConfig['uiStyles']
6
+ export const UI_CONFIG: BrickflowUiConfigType
7
+ export const UI_STYLE: BrickflowUiStyleType
8
+ export const uiConfig: BrickflowUiConfig['uiConfig']
7
9
  export const uiStyles: BrickflowUiConfig['uiStyles']
8
10
 
9
11
  const config: BrickflowUiConfig
@@ -12,6 +14,22 @@ declare module '#brickflow-ui-config' {
12
14
  }
13
15
 
14
16
  declare global {
17
+ type BrickflowUiConfigFor<TExpected extends BrickflowUiConfigObject> = {
18
+ [TKey in keyof BrickflowUiConfigLiteralPaths]: BrickflowUiConfigLiteralPaths[TKey] extends TExpected
19
+ ? BrickflowUiConfigLiteralPaths[TKey]
20
+ : never
21
+ }[keyof BrickflowUiConfigLiteralPaths] extends infer TMatched
22
+ ? [TMatched] extends [never]
23
+ ? TExpected
24
+ : TMatched
25
+ : never
26
+
27
+ interface BrickflowUiConfigLiteralPaths {}
28
+
29
+ interface BrickflowUiConfigPaths {}
30
+
31
+ type BrickflowUiConfigType = BrickflowUiConfigPaths & Record<string, unknown>
32
+
15
33
  interface BrickflowUiStylePaths {}
16
34
 
17
35
  type BrickflowUiStyleType = BrickflowUiStylePaths & BrickflowUiStyleValue
@@ -21,10 +39,15 @@ declare global {
21
39
  }
22
40
 
23
41
  const UI_STYLE: BrickflowUiStyleType
42
+
43
+ const UI_CONFIG: BrickflowUiConfigType
44
+
45
+ function defineUiConfig<TConfig extends BrickflowUiConfigObject>(): BrickflowUiConfigFor<TConfig>
24
46
  }
25
47
 
26
48
  declare module '@vue/runtime-core' {
27
49
  interface ComponentCustomProperties {
50
+ readonly UI_CONFIG: BrickflowUiConfigType
28
51
  readonly UI_STYLE: BrickflowUiStyleType
29
52
  }
30
53
  }
@@ -1,14 +1,29 @@
1
- export interface BrickflowUiConfig<TStyles = BrickflowUiStyles> {
1
+ declare const UI_STYLE_REFERENCE: unique symbol;
2
+ export interface BrickflowUiConfig<TStyles = BrickflowUiStyles, TConfig = BrickflowUiConfigObject> {
3
+ uiConfig: TConfig;
2
4
  uiStyles: TStyles;
3
5
  }
6
+ export type BrickflowUiConfigObject = {
7
+ readonly [key: string]: BrickflowUiConfigValue;
8
+ };
9
+ export type BrickflowUiConfigValue = BrickflowUiConfigObject | BrickflowUiStyleReference | string;
10
+ export interface BrickflowUiStyleReference {
11
+ readonly [UI_STYLE_REFERENCE]: readonly string[];
12
+ }
13
+ /** A chainable compile-time reference to a string in `uiStyles`. */
14
+ export type BrickflowUiStyleReferenceValue = string & {
15
+ readonly [key: string]: any;
16
+ };
4
17
  declare global {
18
+ interface BrickflowUiConfigSchema {
19
+ }
5
20
  interface BrickflowUiConfigStylePaths {
6
21
  }
7
22
  type BrickflowUiStyleObject = {
8
23
  readonly [key: string]: BrickflowUiStyleObject | string;
9
24
  };
10
25
  }
11
- export type BrickflowUiConfigInput<TStyles extends BrickflowUiStyleObject = BrickflowUiStyles> = {
26
+ export type BrickflowUiConfigInput<TStyles extends BrickflowUiStyleObject = BrickflowUiStyles, TConfig extends BrickflowUiConfigObject = BrickflowUiConfigObject> = BrickflowUiConfigInputConfig<TConfig> & {
12
27
  readonly uiStyles?: TStyles;
13
28
  };
14
29
  export type BrickflowUiNoExtraKeys<TValue, TShape> = TValue extends string ? TShape extends string ? TValue : never : TShape extends string ? never : {
@@ -16,10 +31,27 @@ export type BrickflowUiNoExtraKeys<TValue, TShape> = TValue extends string ? TSh
16
31
  };
17
32
  export type BrickflowUiStrictStyles<TStyles extends BrickflowUiConfigStylePaths> = BrickflowUiNoExtraKeys<TStyles, BrickflowUiConfigStylePaths> & TStyles;
18
33
  export type BrickflowUiStyles = BrickflowUiStyleObject;
34
+ type BrickflowUiConfigContext = keyof BrickflowUiConfigSchema extends never ? unknown : {
35
+ readonly uiConfig: BrickflowUiConfigSchema;
36
+ };
37
+ type BrickflowUiConfigInputConfig<TConfig extends BrickflowUiConfigObject> = keyof BrickflowUiConfigSchema extends never ? {
38
+ readonly uiConfig?: TConfig;
39
+ } : {
40
+ readonly uiConfig: TConfig;
41
+ };
42
+ type BrickflowUiConfigValidation<TConfig extends BrickflowUiConfigObject> = keyof BrickflowUiConfigSchema extends never ? unknown : TConfig extends BrickflowUiConfigSchema ? unknown : {
43
+ readonly __brickflowUiConfigError: 'uiConfig does not satisfy a component config schema';
44
+ };
19
45
  export declare const emptyUiStyles: {};
20
- export declare const emptyBrickflowUiConfig: BrickflowUiConfig<typeof emptyUiStyles>;
21
- export declare function defineBrickflowUiConfig(): BrickflowUiConfig<typeof emptyUiStyles>;
22
- export declare function defineBrickflowUiConfig<const TStyles extends BrickflowUiConfigStylePaths>(config: BrickflowUiConfigInput<BrickflowUiStrictStyles<TStyles>>): BrickflowUiConfig<TStyles>;
46
+ export declare const emptyUiConfig: {};
47
+ export declare const emptyBrickflowUiConfig: BrickflowUiConfig<typeof emptyUiStyles, typeof emptyUiConfig>;
48
+ export declare function defineBrickflowUi(): BrickflowUiConfig<typeof emptyUiStyles, typeof emptyUiConfig>;
49
+ export declare function defineBrickflowUi<const TStyles extends BrickflowUiConfigStylePaths, const TConfig extends BrickflowUiConfigObject>(config: BrickflowUiConfigContext & BrickflowUiConfigInput<BrickflowUiStrictStyles<TStyles>, TConfig> & BrickflowUiConfigValidation<TConfig>): BrickflowUiConfig<TStyles, TConfig>;
23
50
  export declare const uiStyles: {};
51
+ export declare const uiConfig: {};
52
+ /** A compile-time reference to a value in `uiStyles`, for use inside `uiConfig`. */
53
+ export declare const UI_STYLE: BrickflowUiStyleReferenceValue;
54
+ export declare const isBrickflowUiStyleReference: (value: unknown) => value is BrickflowUiStyleReference;
55
+ export declare const getBrickflowUiStyleReferencePath: (value: BrickflowUiStyleReference) => readonly string[];
24
56
  export default emptyBrickflowUiConfig;
25
57
  //# sourceMappingURL=tailwind.d.ts.map
@@ -1,22 +1,68 @@
1
+ const UI_STYLE_REFERENCE = Symbol.for("@brickflow/ui/style-reference");
1
2
  export const emptyUiStyles = {};
3
+ export const emptyUiConfig = {};
2
4
  export const emptyBrickflowUiConfig = {
5
+ uiConfig: emptyUiConfig,
3
6
  uiStyles: emptyUiStyles
4
7
  };
5
- export function defineBrickflowUiConfig(config = {}) {
8
+ export function defineBrickflowUi(config = {}) {
9
+ const uiConfig2 = config.uiConfig ?? emptyUiConfig;
6
10
  const uiStyles2 = config.uiStyles ?? emptyUiStyles;
11
+ validateUiConfig(uiConfig2);
7
12
  validateUiStyles(uiStyles2);
8
13
  return {
14
+ uiConfig: uiConfig2,
9
15
  uiStyles: uiStyles2
10
16
  };
11
17
  }
12
18
  export const uiStyles = emptyBrickflowUiConfig.uiStyles;
19
+ export const uiConfig = emptyBrickflowUiConfig.uiConfig;
20
+ const createUiStyleReference = (path = []) => new Proxy(
21
+ { [UI_STYLE_REFERENCE]: path },
22
+ {
23
+ get(target, key) {
24
+ if (key === UI_STYLE_REFERENCE) {
25
+ return target[UI_STYLE_REFERENCE];
26
+ }
27
+ return typeof key === "string" ? createUiStyleReference([...path, key]) : void 0;
28
+ }
29
+ }
30
+ );
31
+ export const UI_STYLE = createUiStyleReference();
32
+ export const isBrickflowUiStyleReference = (value) => Boolean(value && typeof value === "object" && UI_STYLE_REFERENCE in value);
33
+ export const getBrickflowUiStyleReferencePath = (value) => value[UI_STYLE_REFERENCE];
34
+ if (!("UI_STYLE" in globalThis)) {
35
+ Object.defineProperty(globalThis, "UI_STYLE", {
36
+ configurable: true,
37
+ value: UI_STYLE
38
+ });
39
+ }
13
40
  const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
41
+ function validateUiConfig(value, path = "uiConfig") {
42
+ if (!isRecord(value)) {
43
+ throw new TypeError(`${path} must be an object.`);
44
+ }
45
+ for (const [key, childValue] of Object.entries(value)) {
46
+ const childPath = `${path}.${key}`;
47
+ if (typeof childValue === "string" || isBrickflowUiStyleReference(childValue)) {
48
+ continue;
49
+ }
50
+ if (isRecord(childValue)) {
51
+ validateUiConfig(childValue, childPath);
52
+ continue;
53
+ }
54
+ throw new TypeError(`${childPath} must be a string, UI_STYLE reference, or an object.`);
55
+ }
56
+ }
14
57
  function validateUiStyles(value, path = "uiStyles") {
15
58
  if (!isRecord(value)) {
16
59
  throw new TypeError(`${path} must be an object.`);
17
60
  }
18
61
  for (const [key, childValue] of Object.entries(value)) {
19
62
  const childPath = `${path}.${key}`;
63
+ if (isBrickflowUiStyleReference(childValue)) {
64
+ throw new TypeError(`${childPath} cannot reference UI_STYLE.`);
65
+ }
20
66
  if (typeof childValue === "string") {
21
67
  continue;
22
68
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickflow/ui",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "type": "module",
5
5
  "description": "brickflow UI Nuxt module.",
6
6
  "files": [