@brickflow/ui 0.0.57 → 0.0.58

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 (31) hide show
  1. package/dist/module.d.mts +3 -2
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +33 -7
  4. package/dist/runtime/brickflow-ui.d.ts +1 -0
  5. package/dist/runtime/components/Button/index.vue +5 -3
  6. package/dist/runtime/components/Dialog/DemoContent.vue +33 -0
  7. package/dist/runtime/components/Dialog/DemoForm.vue +54 -0
  8. package/dist/runtime/components/Dialog/DemoSimple.vue +23 -0
  9. package/dist/runtime/components/Dialog/DemoStack.vue +41 -0
  10. package/dist/runtime/components/Dialog/Host.vue +654 -0
  11. package/dist/runtime/components/Dialog/basic.demo.vue +27 -0
  12. package/dist/runtime/components/Dialog/form.demo.vue +34 -0
  13. package/dist/runtime/components/Dialog/index.vue +53 -0
  14. package/dist/runtime/components/Dialog/scroll.demo.vue +27 -0
  15. package/dist/runtime/components/Dialog/stack.demo.vue +19 -0
  16. package/dist/runtime/components/Form/rules.demo.vue +108 -0
  17. package/dist/runtime/components/Icon/gallery.demo.vue +1 -1
  18. package/dist/runtime/components/Icon/index.vue +3 -1
  19. package/dist/runtime/components/Input/index.vue +7 -5
  20. package/dist/runtime/components/InputNumber/controls.demo.vue +145 -0
  21. package/dist/runtime/components/InputNumber/index.vue +4 -3
  22. package/dist/runtime/composables/useDialog.d.ts +38 -0
  23. package/dist/runtime/composables/useDialog.js +40 -0
  24. package/dist/runtime/composables/useScreen.d.ts +8 -0
  25. package/dist/runtime/plugins/dialog.d.ts +3 -0
  26. package/dist/runtime/plugins/dialog.js +22 -0
  27. package/dist/runtime/tailwind.d.ts +1 -1
  28. package/dist/runtime/tailwind.js +2 -2
  29. package/dist/types.d.mts +2 -0
  30. package/package.json +6 -6
  31. package/dist/runtime/icon-font.d.ts +0 -4
@@ -0,0 +1,34 @@
1
+ <script lang="ts">
2
+ export const uiDemo = {
3
+ description: 'Keep form state inside the dialog, require an explicit choice, and return the saved value.',
4
+ title: 'Form and explicit dismissal',
5
+ }
6
+ </script>
7
+
8
+ <script setup lang="ts">
9
+ import { defineAsyncComponent, ref } from 'vue'
10
+
11
+ import { useDialog } from '../../composables/useDialog'
12
+ import Button from '../Button/index.vue'
13
+
14
+ const dialog = useDialog()
15
+ const savedName = ref('')
16
+ const LazyDemoForm = defineAsyncComponent(() => import('./DemoForm.vue'))
17
+
18
+ function openForm(): void {
19
+ dialog.open(LazyDemoForm, { onSave: (name: string) => (savedName.value = name) }, { preventClose: true })
20
+ }
21
+ </script>
22
+
23
+ <template>
24
+ <div class="flex flex-wrap items-center gap-3">
25
+ <Button @click="openForm">Create project</Button>
26
+ <p
27
+ v-if="savedName"
28
+ class="text-sm text-zinc-300"
29
+ role="status"
30
+ >
31
+ Saved: {{ savedName }}
32
+ </p>
33
+ </div>
34
+ </template>
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ import type { IconName } from '#brickflow-ui'
3
+
4
+ import type { DialogPlacement } from '../../composables/useDialog'
5
+ import type { ScreenKey } from '../../composables/useScreen'
6
+
7
+ export const dialogConfig = defineUiConfig<{
8
+ elasticHeight?: boolean
9
+ loadingDelay: number
10
+ loadingIconName: IconName
11
+ loadingIconTransition: string
12
+ placement: Record<ScreenKey, DialogPlacement>
13
+ }>()
14
+ </script>
15
+
16
+ <script setup lang="ts">
17
+ defineProps<{
18
+ dragY?: number
19
+ elasticHeight: boolean
20
+ placement: 'bottom' | 'center' | 'fullscreen'
21
+ }>()
22
+
23
+ const placementClasses = {
24
+ bottom: UI_STYLE.panelPlacementClasses.bottom,
25
+ center: UI_STYLE.panelPlacementClasses.center,
26
+ fullscreen: UI_STYLE.panelPlacementClasses.fullscreen,
27
+ }
28
+ </script>
29
+
30
+ <template>
31
+ <div
32
+ :class="[UI_STYLE.panel, placementClasses[placement]]"
33
+ data-dialog-panel
34
+ role="dialog"
35
+ aria-modal="true"
36
+ tabindex="-1"
37
+ :style="{
38
+ '--dialog-elastic-height':
39
+ placement === 'bottom' && elasticHeight ? `${Math.max(0, -(dragY ?? 0))}px` : undefined,
40
+ transform: dragY && (!elasticHeight || dragY > 0) ? `translateY(${dragY}px)` : undefined,
41
+ }"
42
+ >
43
+ <div
44
+ v-if="placement === 'bottom'"
45
+ :class="UI_STYLE.dragHandle"
46
+ data-dialog-handle
47
+ aria-hidden="true"
48
+ >
49
+ <span :class="UI_STYLE.dragHandleIndicator" />
50
+ </div>
51
+ <slot />
52
+ </div>
53
+ </template>
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ export const uiDemo = {
3
+ description: 'The content component owns overflow. Scroll to an edge before dragging the sheet.',
4
+ title: 'Long content and scrolling',
5
+ }
6
+ </script>
7
+
8
+ <script setup lang="ts">
9
+ import { defineAsyncComponent } from 'vue'
10
+
11
+ import { useDialog } from '../../composables/useDialog'
12
+ import Button from '../Button/index.vue'
13
+
14
+ const dialog = useDialog()
15
+ const LazyDemoContent = defineAsyncComponent(() => import('./DemoContent.vue'))
16
+ </script>
17
+
18
+ <template>
19
+ <div class="flex flex-wrap gap-2">
20
+ <Button @click="dialog.open(LazyDemoContent, { text: 'Scrollable bottom sheet' }, { placement: 'bottom' })">
21
+ Scrollable sheet
22
+ </Button>
23
+ <Button @click="dialog.open(LazyDemoContent, { text: 'Scrollable centered dialog' }, { placement: 'center' })">
24
+ Scrollable center
25
+ </Button>
26
+ </div>
27
+ </template>
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ export const uiDemo = {
3
+ title: 'Stacked dialogs',
4
+ }
5
+ </script>
6
+
7
+ <script setup lang="ts">
8
+ import { defineAsyncComponent } from 'vue'
9
+
10
+ import { useDialog } from '../../composables/useDialog'
11
+ import Button from '../Button/index.vue'
12
+
13
+ const dialog = useDialog()
14
+ const LazyDemoStack = defineAsyncComponent(() => import('./DemoStack.vue'))
15
+ </script>
16
+
17
+ <template>
18
+ <Button @click="dialog.open(LazyDemoStack, { level: 1 })">Open stack</Button>
19
+ </template>
@@ -0,0 +1,108 @@
1
+ <script lang="ts">
2
+ export const uiDemo = {
3
+ description: 'Each field has one rule. Submit it to see that rule’s validation message.',
4
+ title: 'Basic rules',
5
+ }
6
+ </script>
7
+
8
+ <script setup lang="ts">
9
+ import { reactive } from 'vue'
10
+
11
+ import { rule, type Rule } from '../../utils/rules'
12
+ import Button from '../Button/index.vue'
13
+ import Input from '../Input/index.vue'
14
+ import Form from './index.vue'
15
+
16
+ const demos: { description: string; id: string; label: string; placeholder: string; rules: Rule<string>[] }[] = [
17
+ {
18
+ description: 'Leave empty, or enter only spaces.',
19
+ id: 'required',
20
+ label: 'Required',
21
+ placeholder: 'Enter any text',
22
+ rules: [rule.required()],
23
+ },
24
+ {
25
+ description: 'Try “hello”, then “hello@example.com”.',
26
+ id: 'email',
27
+ label: 'Email',
28
+ placeholder: 'hello@example.com',
29
+ rules: [rule.email()],
30
+ },
31
+ {
32
+ description: 'Enter exactly 5 characters.',
33
+ id: 'length',
34
+ label: 'Length (5)',
35
+ placeholder: 'abcde',
36
+ rules: [rule.length(5)],
37
+ },
38
+ {
39
+ description: 'Enter fewer than 5 characters, then 5 or more.',
40
+ id: 'minLength',
41
+ label: 'Minimum length (5)',
42
+ placeholder: 'At least 5 characters',
43
+ rules: [rule.minLength(5)],
44
+ },
45
+ {
46
+ description: 'Enter more than 5 characters.',
47
+ id: 'maxLength',
48
+ label: 'Maximum length (5)',
49
+ placeholder: 'Up to 5 characters',
50
+ rules: [rule.maxLength(5)],
51
+ },
52
+ {
53
+ description: 'Enter letters or numbers, then add a space or symbol.',
54
+ id: 'regex',
55
+ label: 'Regex (letters and numbers)',
56
+ placeholder: 'abc123',
57
+ rules: [rule.regex(/^[a-z0-9]+$/i, 'Use letters and numbers only')],
58
+ },
59
+ {
60
+ description: 'Try “example.com”, then “https://example.com”.',
61
+ id: 'url',
62
+ label: 'URL',
63
+ placeholder: 'https://example.com',
64
+ rules: [rule.url()],
65
+ },
66
+ ]
67
+
68
+ const values = reactive<Record<string, string>>({})
69
+ const submitted = reactive<Record<string, boolean>>({})
70
+
71
+ function updateValue(id: string, value: string): void {
72
+ values[id] = value
73
+ submitted[id] = false
74
+ }
75
+ </script>
76
+
77
+ <template>
78
+ <div class="grid gap-6">
79
+ <Form
80
+ v-for="demo in demos"
81
+ :key="demo.id"
82
+ class="rounded-lg"
83
+ @submit="submitted[demo.id] = true"
84
+ >
85
+ <Input
86
+ :value="values[demo.id] ?? ''"
87
+ :label="demo.label"
88
+ :description="demo.description"
89
+ :placeholder="demo.placeholder"
90
+ :rules="demo.rules"
91
+ @input="updateValue(demo.id, $event)"
92
+ />
93
+ <Button
94
+ class="self-start"
95
+ type="submit"
96
+ >
97
+ Test rule
98
+ </Button>
99
+ <p
100
+ v-if="submitted[demo.id]"
101
+ class="text-sm text-green-400"
102
+ role="status"
103
+ >
104
+ Passed
105
+ </p>
106
+ </Form>
107
+ </div>
108
+ </template>
@@ -20,7 +20,7 @@
20
20
  const filteredIconNames = computed(() => {
21
21
  const query = search.value.trim().toLocaleLowerCase()
22
22
 
23
- return query ? iconNames.filter((name) => name.toLocaleLowerCase().includes(query)) : iconNames
23
+ return query ? iconNames.filter((name: string) => name.toLocaleLowerCase().includes(query)) : iconNames
24
24
  })
25
25
 
26
26
  const copyIconName = async (name: string): Promise<void> => {
@@ -1,9 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from 'vue'
3
3
 
4
+ import type { IconName } from '#brickflow-ui'
5
+
4
6
  const props = withDefaults(
5
7
  defineProps<{
6
- name: string
8
+ name: IconName
7
9
  }>(),
8
10
  {},
9
11
  )
@@ -1,8 +1,10 @@
1
1
  <script lang="ts">
2
+ import type { IconName } from '#brickflow-ui'
3
+
2
4
  const UI_CONFIG = defineUiConfig<{
3
- hidePasswordIconName: string
4
- searchClearIconName: string
5
- showPasswordIconName: string
5
+ hidePasswordIconName: IconName
6
+ searchClearIconName: IconName
7
+ showPasswordIconName: IconName
6
8
  sizeClasses: Record<
7
9
  string,
8
10
  {
@@ -51,7 +53,7 @@
51
53
  autoWidth?: boolean
52
54
  description?: string
53
55
  disabled?: boolean
54
- icon?: string
56
+ icon?: IconName
55
57
  label?: string
56
58
  mask?: MaskInputOptions | MaskType
57
59
  onBlur?: (value: string, target: HTMLInputElement) => void
@@ -65,7 +67,7 @@
65
67
  readonly?: boolean
66
68
  rules?: Rule<string>[]
67
69
  size?: InputSize
68
- trailingIcon?: string
70
+ trailingIcon?: IconName
69
71
  type?: 'decimal' | 'email' | 'numeric' | 'password' | 'search' | 'tel' | 'text' | 'url'
70
72
  value?: null | string
71
73
  variant?: InputVariant
@@ -0,0 +1,145 @@
1
+ <script lang="ts">
2
+ export const uiDemo = {
3
+ description: 'Custom step buttons built with the leading and trailing slots.',
4
+ title: 'Custom controls',
5
+ }
6
+ </script>
7
+
8
+ <script lang="ts" setup>
9
+ import { ref } from 'vue'
10
+
11
+ import InputNumber from './index.vue'
12
+
13
+ const horizontalValue = ref(20)
14
+ const verticalValue = ref(100)
15
+
16
+ const horizontalMin = 0
17
+ const horizontalMax = 25
18
+ const verticalMin = 0
19
+ const verticalMax = 120
20
+ const verticalStep = 5
21
+
22
+ const horizontalControlClass =
23
+ 'inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg text-plain-500 transition-colors enabled:hover:bg-plain-800 enabled:hover:text-plain-100 disabled:cursor-not-allowed disabled:opacity-40'
24
+ const verticalControlClass =
25
+ 'flex min-h-5 flex-1 items-center justify-center text-plain-500 transition-colors enabled:hover:bg-plain-800 enabled:hover:text-plain-100 disabled:cursor-not-allowed disabled:opacity-40'
26
+
27
+ function stepHorizontal(direction: -1 | 1): void {
28
+ horizontalValue.value = Math.max(horizontalMin, Math.min(horizontalMax, horizontalValue.value + direction))
29
+ }
30
+
31
+ function stepVertical(direction: -1 | 1): void {
32
+ verticalValue.value = Math.max(
33
+ verticalMin,
34
+ Math.min(verticalMax, verticalValue.value + direction * verticalStep),
35
+ )
36
+ }
37
+ </script>
38
+
39
+ <template>
40
+ <div class="flex max-w-sm flex-col gap-6">
41
+ <InputNumber
42
+ :value="horizontalValue"
43
+ align="center"
44
+ label="Number *"
45
+ description="This is a hint text to help user."
46
+ :min="horizontalMin"
47
+ :max="horizontalMax"
48
+ @input="horizontalValue = $event"
49
+ >
50
+ <template #leading>
51
+ <button
52
+ type="button"
53
+ :disabled="horizontalValue <= horizontalMin"
54
+ aria-label="Decrease number"
55
+ :class="[horizontalControlClass, '-ml-2']"
56
+ @click="stepHorizontal(-1)"
57
+ >
58
+ <span
59
+ aria-hidden="true"
60
+ class="text-2xl leading-none font-light"
61
+ >
62
+ −
63
+ </span>
64
+ </button>
65
+ </template>
66
+ <template #trailing>
67
+ <button
68
+ type="button"
69
+ :disabled="horizontalValue >= horizontalMax"
70
+ aria-label="Increase number"
71
+ :class="[horizontalControlClass, '-mr-2']"
72
+ @click="stepHorizontal(1)"
73
+ >
74
+ <span
75
+ aria-hidden="true"
76
+ class="text-2xl leading-none font-light"
77
+ >
78
+ +
79
+ </span>
80
+ </button>
81
+ </template>
82
+ </InputNumber>
83
+
84
+ <InputNumber
85
+ :value="verticalValue"
86
+ label="Number *"
87
+ description="This is a hint text to help user."
88
+ :step="verticalStep"
89
+ :min="verticalMin"
90
+ :max="verticalMax"
91
+ @input="verticalValue = $event"
92
+ >
93
+ <template #trailing>
94
+ <span
95
+ class="-mr-3 flex w-12 shrink-0 flex-col self-stretch overflow-hidden rounded-r-xl border-l border-neutral-600/20"
96
+ >
97
+ <button
98
+ type="button"
99
+ :disabled="verticalValue >= verticalMax"
100
+ aria-label="Increase number"
101
+ :class="verticalControlClass"
102
+ @click="stepVertical(1)"
103
+ >
104
+ <svg
105
+ aria-hidden="true"
106
+ class="size-4"
107
+ viewBox="0 0 16 16"
108
+ fill="none"
109
+ >
110
+ <path
111
+ d="m3 10 5-5 5 5"
112
+ stroke="currentColor"
113
+ stroke-width="2"
114
+ stroke-linecap="round"
115
+ stroke-linejoin="round"
116
+ />
117
+ </svg>
118
+ </button>
119
+ <button
120
+ type="button"
121
+ :disabled="verticalValue <= verticalMin"
122
+ aria-label="Decrease number"
123
+ :class="[verticalControlClass, 'border-t border-neutral-600/20']"
124
+ @click="stepVertical(-1)"
125
+ >
126
+ <svg
127
+ aria-hidden="true"
128
+ class="size-4"
129
+ viewBox="0 0 16 16"
130
+ fill="none"
131
+ >
132
+ <path
133
+ d="m3 6 5 5 5-5"
134
+ stroke="currentColor"
135
+ stroke-width="2"
136
+ stroke-linecap="round"
137
+ stroke-linejoin="round"
138
+ />
139
+ </svg>
140
+ </button>
141
+ </span>
142
+ </template>
143
+ </InputNumber>
144
+ </div>
145
+ </template>
@@ -1,6 +1,8 @@
1
1
  <script setup lang="ts" generic="T extends boolean = false">
2
2
  import { computed, ref, shallowRef, watch } from 'vue'
3
3
 
4
+ import type { IconName } from '#brickflow-ui'
5
+
4
6
  import type { Rule } from '../../utils/rules'
5
7
 
6
8
  import { isEmpty } from '../../utils/checkup.js'
@@ -16,7 +18,7 @@
16
18
  denominator?: number
17
19
  description?: string
18
20
  disabled?: boolean
19
- icon?: string
21
+ icon?: IconName
20
22
  label?: string
21
23
  max?: number
22
24
  min?: number
@@ -33,7 +35,7 @@
33
35
  rules?: Rule<null | number>[]
34
36
  size?: InputProps['size']
35
37
  step?: number
36
- trailingIcon?: string
38
+ trailingIcon?: IconName
37
39
  value: true extends NoInfer<T> ? null | number : number
38
40
  variant?: InputProps['variant']
39
41
  }>(),
@@ -176,7 +178,6 @@
176
178
  if (!Number.isFinite(props.step) || props.step <= 0) {
177
179
  return
178
180
  }
179
-
180
181
  event.preventDefault()
181
182
  const parsedValue = Number(target.value)
182
183
  const currentValue = target.value !== '' && Number.isFinite(parsedValue) ? parsedValue : (props.value ?? 0)
@@ -0,0 +1,38 @@
1
+ import { type Component, type InjectionKey } from 'vue';
2
+ import type { ScreenKey } from './useScreen.js';
3
+ export interface DialogController {
4
+ close(id?: number): void;
5
+ closeAll(): void;
6
+ open<C extends Component>(component: C, props: DialogProps<C>, options?: DialogOptions): DialogHandle;
7
+ readonly stack: DialogEntry[];
8
+ }
9
+ export interface DialogEntry {
10
+ component: Component;
11
+ id: number;
12
+ options: Required<DialogOptions> & {
13
+ elasticHeight: boolean;
14
+ };
15
+ props: Record<string, unknown>;
16
+ }
17
+ export interface DialogHandle {
18
+ close: () => void;
19
+ id: number;
20
+ }
21
+ export interface DialogOptions {
22
+ /** Dialog position, optionally overridden for each screen range. Defaults to center. */
23
+ placement?: DialogPlacementConfig;
24
+ /** Prevent backdrop, Escape, and swipe dismissal. Defaults to false. */
25
+ preventClose?: boolean;
26
+ }
27
+ export type DialogPlacement = 'bottom' | 'center' | 'fullscreen';
28
+ export type DialogPlacementConfig = DialogPlacement | Record<ScreenKey, DialogPlacement>;
29
+ type DialogProps<C> = C extends new (...args: never[]) => {
30
+ $props: infer P;
31
+ } ? Omit<P, 'class' | 'key' | 'ref' | 'style'> : Record<string, unknown>;
32
+ export declare const dialogKey: InjectionKey<DialogController>;
33
+ export declare function createDialogController(defaultOptions?: DialogOptions & {
34
+ elasticHeight?: boolean;
35
+ }): DialogController;
36
+ export declare function useDialog(): DialogController;
37
+ export {};
38
+ //# sourceMappingURL=useDialog.d.ts.map
@@ -0,0 +1,40 @@
1
+ import { inject, markRaw, reactive } from "vue";
2
+ export const dialogKey = Symbol("brickflow-dialog");
3
+ export function createDialogController(defaultOptions = {}) {
4
+ const stack = reactive([]);
5
+ let nextId = 0;
6
+ return {
7
+ close(id) {
8
+ const index = id === void 0 ? stack.length - 1 : stack.findIndex((entry) => entry.id === id);
9
+ if (index !== -1) {
10
+ stack.splice(index, 1);
11
+ }
12
+ },
13
+ closeAll() {
14
+ stack.splice(0);
15
+ },
16
+ open(component, props, options = {}) {
17
+ nextId += 1;
18
+ const id = nextId;
19
+ stack.push({
20
+ component: markRaw(component),
21
+ id,
22
+ options: {
23
+ elasticHeight: defaultOptions.elasticHeight ?? true,
24
+ placement: options.placement ?? defaultOptions.placement ?? "center",
25
+ preventClose: options.preventClose ?? defaultOptions.preventClose ?? false
26
+ },
27
+ props: { ...props }
28
+ });
29
+ return { close: () => this.close(id), id };
30
+ },
31
+ stack
32
+ };
33
+ }
34
+ export function useDialog() {
35
+ const dialog = inject(dialogKey, void 0);
36
+ if (!dialog) {
37
+ throw new Error("useDialog() requires the @brickflow/ui Nuxt module");
38
+ }
39
+ return dialog;
40
+ }
@@ -1,3 +1,11 @@
1
+ export type ScreenKey = keyof ScreenState;
2
+ interface ScreenState {
3
+ dk: boolean;
4
+ lp: boolean;
5
+ mb: boolean;
6
+ ms: boolean;
7
+ tb: boolean;
8
+ }
1
9
  declare const screen: {
2
10
  readonly dk: boolean;
3
11
  readonly dkClass: "dkHidden";
@@ -0,0 +1,3 @@
1
+ declare const _default: import("nuxt/app").Plugin<Record<string, unknown>> & import("nuxt/app").ObjectPlugin<Record<string, unknown>>;
2
+ export default _default;
3
+ //# sourceMappingURL=dialog.d.ts.map
@@ -0,0 +1,22 @@
1
+ import { defineNuxtPlugin } from "nuxt/app";
2
+ import { createVNode, render } from "vue";
3
+ import { uiConfig } from "#brickflow-ui";
4
+ import DialogHost from "../components/Dialog/Host.vue";
5
+ import { createDialogController, dialogKey } from "../composables/useDialog.js";
6
+ export default defineNuxtPlugin((nuxtApp) => {
7
+ const dialog = createDialogController({
8
+ elasticHeight: uiConfig.dialog.elasticHeight,
9
+ placement: uiConfig.dialog.placement
10
+ });
11
+ nuxtApp.vueApp.provide(dialogKey, dialog);
12
+ if (import.meta.client) {
13
+ nuxtApp.hook("app:mounted", () => {
14
+ const mountPoint = document.createElement("div");
15
+ mountPoint.id = "brickflow-dialog-host";
16
+ document.body.appendChild(mountPoint);
17
+ const vnode = createVNode(DialogHost, { dialog });
18
+ vnode.appContext = nuxtApp.vueApp._context;
19
+ render(vnode, mountPoint);
20
+ });
21
+ }
22
+ });
@@ -6,7 +6,7 @@ export interface BrickflowUiConfig<TStyles = BrickflowUiStyles, TConfig = Brickf
6
6
  export type BrickflowUiConfigObject = {
7
7
  readonly [key: string]: BrickflowUiConfigValue;
8
8
  };
9
- export type BrickflowUiConfigValue = BrickflowUiConfigObject | BrickflowUiStyleReference | string;
9
+ export type BrickflowUiConfigValue = boolean | BrickflowUiConfigObject | BrickflowUiStyleReference | number | string;
10
10
  export interface BrickflowUiStyleReference {
11
11
  readonly [UI_STYLE_REFERENCE]: readonly string[];
12
12
  }
@@ -44,14 +44,14 @@ function validateUiConfig(value, path = "uiConfig") {
44
44
  }
45
45
  for (const [key, childValue] of Object.entries(value)) {
46
46
  const childPath = `${path}.${key}`;
47
- if (typeof childValue === "string" || isBrickflowUiStyleReference(childValue)) {
47
+ if (typeof childValue === "string" || typeof childValue === "boolean" || typeof childValue === "number" && Number.isFinite(childValue) || isBrickflowUiStyleReference(childValue)) {
48
48
  continue;
49
49
  }
50
50
  if (isRecord(childValue)) {
51
51
  validateUiConfig(childValue, childPath);
52
52
  continue;
53
53
  }
54
- throw new TypeError(`${childPath} must be a string, UI_STYLE reference, or an object.`);
54
+ throw new TypeError(`${childPath} must be a string, boolean, finite number, UI_STYLE reference, or an object.`);
55
55
  }
56
56
  }
57
57
  function validateUiStyles(value, path = "uiStyles") {
package/dist/types.d.mts CHANGED
@@ -1,5 +1,7 @@
1
1
  export { type BrickflowConfig } from '../dist/runtime/composables/useBrickflow.js'
2
2
 
3
+ export { type DialogController, type DialogHandle, type DialogOptions } from '../dist/runtime/composables/useDialog.js'
4
+
3
5
  export { type BrickflowI18n, type BrickflowRouteLocationParam } from '../dist/runtime/composables/useTranslate.js'
4
6
 
5
7
  export { type Rule, type RuleMessages, type rule } from '../dist/runtime/utils/rules.js'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickflow/ui",
3
- "version": "0.0.57",
3
+ "version": "0.0.58",
4
4
  "type": "module",
5
5
  "description": "brickflow UI Nuxt module.",
6
6
  "files": [
@@ -36,17 +36,17 @@
36
36
  "fantasticon": "4.1.0",
37
37
  "jiti": "2.7.0",
38
38
  "maska": "3.2.2",
39
- "tailwind-merge": "3.6.0",
39
+ "tailwind-merge": "3.7.0",
40
40
  "tailwindcss": "4.3.3"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@brickflow/lint": "workspace:*",
44
44
  "@brickflow/prettier": "workspace:*",
45
- "@nuxt/kit": "4.5.2",
45
+ "@nuxt/kit": "4.6.3",
46
46
  "@nuxt/module-builder": "1.0.3",
47
- "nuxt": "4.5.2",
48
- "vue": "3.5.42",
49
- "vue-tsc": "3.3.11"
47
+ "nuxt": "4.6.3",
48
+ "vue": "3.5.44",
49
+ "vue-tsc": "3.3.14"
50
50
  },
51
51
  "author": "",
52
52
  "license": "ISC"
@@ -1,4 +0,0 @@
1
- declare module '#brickflow-ui-icons' {
2
- export const firstIconName: string
3
- export const iconNames: readonly string[]
4
- }