nuance-ui 0.2.28 → 0.2.30

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 (64) hide show
  1. package/dist/module.d.mts +13 -0
  2. package/dist/module.d.ts +13 -0
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +87 -2
  5. package/dist/runtime/app-config.d.ts +22 -0
  6. package/dist/runtime/components/action-icon/action-icon-section.vue +4 -3
  7. package/dist/runtime/components/action-icon/action-icon.vue +4 -3
  8. package/dist/runtime/components/alert.vue +5 -4
  9. package/dist/runtime/components/avatar/avatar.d.vue.ts +1 -4
  10. package/dist/runtime/components/avatar/avatar.vue +7 -5
  11. package/dist/runtime/components/avatar/avatar.vue.d.ts +1 -4
  12. package/dist/runtime/components/badge.d.vue.ts +3 -1
  13. package/dist/runtime/components/badge.vue +12 -9
  14. package/dist/runtime/components/badge.vue.d.ts +3 -1
  15. package/dist/runtime/components/breadcrumbs.d.vue.ts +1 -4
  16. package/dist/runtime/components/breadcrumbs.vue +4 -2
  17. package/dist/runtime/components/breadcrumbs.vue.d.ts +1 -4
  18. package/dist/runtime/components/button/button.module.css +1 -1
  19. package/dist/runtime/components/button/button.vue +4 -3
  20. package/dist/runtime/components/calendar/ui/core/calendar-header.vue +9 -4
  21. package/dist/runtime/components/checkbox/checkbox-indicator.vue +4 -3
  22. package/dist/runtime/components/checkbox/checkbox.vue +4 -3
  23. package/dist/runtime/components/chip/chip.vue +8 -7
  24. package/dist/runtime/components/combobox/combobox-option.vue +6 -3
  25. package/dist/runtime/components/date-time-picker.vue +4 -3
  26. package/dist/runtime/components/dialog/ui/dialog-close-button.vue +6 -2
  27. package/dist/runtime/components/files/file-upload-button.vue +4 -1
  28. package/dist/runtime/components/files/file-upload-icon.vue +5 -2
  29. package/dist/runtime/components/index.d.ts +1 -0
  30. package/dist/runtime/components/input/date-picker.vue +4 -3
  31. package/dist/runtime/components/input/email-input.vue +6 -2
  32. package/dist/runtime/components/input/number-input.vue +4 -2
  33. package/dist/runtime/components/input/password-input.vue +3 -1
  34. package/dist/runtime/components/link/lib.d.ts +2 -2
  35. package/dist/runtime/components/modal/modal.module.css +1 -1
  36. package/dist/runtime/components/nav-link/nav-link.vue +4 -7
  37. package/dist/runtime/components/select.vue +3 -1
  38. package/dist/runtime/components/table/ui/table-sort-icon.vue +5 -3
  39. package/dist/runtime/components/tabs/tabs-root.d.vue.ts +1 -1
  40. package/dist/runtime/components/tabs/tabs-root.vue.d.ts +1 -1
  41. package/dist/runtime/components/theme-toggle.vue +3 -2
  42. package/dist/runtime/components/time-picker/time-picker.vue +4 -2
  43. package/dist/runtime/components/timeline.d.vue.ts +93 -0
  44. package/dist/runtime/components/timeline.vue +112 -0
  45. package/dist/runtime/components/timeline.vue.d.ts +93 -0
  46. package/dist/runtime/components/tree/_ui/tree-item.vue +9 -6
  47. package/dist/runtime/components/tree/_ui/tree-root.vue +5 -3
  48. package/dist/runtime/composables/index.d.ts +1 -0
  49. package/dist/runtime/composables/index.js +1 -0
  50. package/dist/runtime/composables/use-config.d.ts +6 -0
  51. package/dist/runtime/composables/use-config.js +12 -0
  52. package/dist/runtime/styles/colors.css +1 -1
  53. package/dist/runtime/types/icons.d.ts +51 -0
  54. package/dist/runtime/types/icons.js +0 -0
  55. package/dist/runtime/types/index.d.ts +17 -0
  56. package/dist/runtime/utils/icons/default-icons.d.ts +3 -0
  57. package/dist/runtime/utils/icons/default-icons.js +33 -0
  58. package/dist/runtime/utils/icons/index.d.ts +1 -0
  59. package/dist/runtime/utils/icons/index.js +1 -0
  60. package/dist/runtime/utils/index.d.ts +1 -0
  61. package/dist/runtime/utils/index.js +1 -0
  62. package/dist/runtime/utils/style/create-variant-color-resolver.d.ts +8 -8
  63. package/dist/runtime/utils/style/create-variant-color-resolver.js +2 -2
  64. package/package.json +1 -1
package/dist/module.d.mts CHANGED
@@ -1,4 +1,8 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
+ import { NuanceDefaultThemeColor, NuanceGradient, NuanceIcons } from '../dist/runtime/types/index.js';
3
+
4
+ /** Primary color: a theme palette name or an array of 10 shade values (0..9). */
5
+ type PrimaryColor = NuanceDefaultThemeColor | string[];
2
6
 
3
7
  interface ModuleOptions {
4
8
  /**
@@ -17,6 +21,15 @@ interface ModuleOptions {
17
21
  * @default 'light'
18
22
  */
19
23
  theme?: 'light' | 'dark' | 'auto';
24
+ /**
25
+ * Primary color: a theme palette name or an array of 10 shade values (0..9)
26
+ * @default 'blue'
27
+ */
28
+ primaryColor?: PrimaryColor;
29
+ /** Default gradient configuration */
30
+ gradient?: NuanceGradient;
31
+ /** Icon registry overrides */
32
+ icons?: Partial<NuanceIcons>;
20
33
  }
21
34
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
22
35
 
package/dist/module.d.ts CHANGED
@@ -1,4 +1,8 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
+ import { NuanceDefaultThemeColor, NuanceGradient, NuanceIcons } from '../dist/runtime/types/index.js';
3
+
4
+ /** Primary color: a theme palette name or an array of 10 shade values (0..9). */
5
+ type PrimaryColor = NuanceDefaultThemeColor | string[];
2
6
 
3
7
  interface ModuleOptions {
4
8
  /**
@@ -17,6 +21,15 @@ interface ModuleOptions {
17
21
  * @default 'light'
18
22
  */
19
23
  theme?: 'light' | 'dark' | 'auto';
24
+ /**
25
+ * Primary color: a theme palette name or an array of 10 shade values (0..9)
26
+ * @default 'blue'
27
+ */
28
+ primaryColor?: PrimaryColor;
29
+ /** Default gradient configuration */
30
+ gradient?: NuanceGradient;
31
+ /** Icon registry overrides */
32
+ icons?: Partial<NuanceIcons>;
20
33
  }
21
34
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
22
35
 
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^4.0.0"
6
6
  },
7
- "version": "0.2.28",
7
+ "version": "0.2.30",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,10 +1,80 @@
1
- import { defineNuxtModule, createResolver, addComponentsDir, addImportsDir } from '@nuxt/kit';
1
+ import { defineNuxtModule, createResolver, addTypeTemplate, addComponentsDir, addImportsDir, addTemplate } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
+ import { DEFAULT_GRADIENT } from '../dist/runtime/utils/color/const.js';
4
+ import { DEFAULT_ICONS } from '../dist/runtime/utils/icons/default-icons.js';
5
+
6
+ const SHADES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
7
+ function fromName(name) {
8
+ const base = SHADES.map((shade) => ` --color-primary-${shade}: var(--color-${name}-${shade});`).join("\n");
9
+ return `:root {
10
+ ${base}
11
+
12
+ --color-primary-filled: var(--color-${name}-filled);
13
+ --color-primary-filled-hover: var(--color-${name}-filled-hover);
14
+ --color-primary-light: alpha(var(--color-${name}-light), .15);
15
+ --color-primary-light-hover: var(--color-${name}-light-hover);
16
+ --color-primary-light-color: var(--color-${name}-light-color);
17
+ --color-primary-outline: var(--color-${name}-outline);
18
+ --color-primary-outline-hover: alpha(var(--color-${name}-outline), .1);
19
+ }
20
+ `;
21
+ }
22
+ function derivedTokens(scheme) {
23
+ if (scheme === "light") {
24
+ return ` --color-primary-filled: var(--color-primary-6);
25
+ --color-primary-filled-hover: var(--color-primary-7);
26
+ --color-primary-light: alpha(var(--color-primary-6), .1);
27
+ --color-primary-light-hover: alpha(var(--color-primary-6), .12);
28
+ --color-primary-light-color: var(--color-primary-6);
29
+ --color-primary-outline: var(--color-primary-6);
30
+ --color-primary-outline-hover: alpha(var(--color-primary-6), .05);`;
31
+ }
32
+ return ` --color-primary-filled: var(--color-primary-8);
33
+ --color-primary-filled-hover: var(--color-primary-9);
34
+ --color-primary-light: alpha(var(--color-primary-8), .15);
35
+ --color-primary-light-hover: alpha(var(--color-primary-8), .2);
36
+ --color-primary-light-color: var(--color-primary-0);
37
+ --color-primary-outline: var(--color-primary-4);
38
+ --color-primary-outline-hover: alpha(var(--color-primary-4), .05);`;
39
+ }
40
+ function fromArray(shades) {
41
+ const base = SHADES.map((shade) => ` --color-primary-${shade}: ${shades[shade]};`).join("\n");
42
+ return `:root {
43
+ ${base}
44
+ }
45
+
46
+ :root {
47
+ @mixin light-root {
48
+ ${derivedTokens("light")}
49
+ }
50
+ }
51
+
52
+ :root {
53
+ @mixin dark-root {
54
+ ${derivedTokens("dark")}
55
+ }
56
+ }
57
+ `;
58
+ }
59
+ function generatePrimaryCss(primaryColor) {
60
+ if (Array.isArray(primaryColor)) {
61
+ if (primaryColor.length !== 10) {
62
+ throw new Error(
63
+ `[@nuance-ui] "primaryColor" array must contain exactly 10 shades, got ${primaryColor.length}.`
64
+ );
65
+ }
66
+ return fromArray(primaryColor);
67
+ }
68
+ return fromName(primaryColor);
69
+ }
3
70
 
4
71
  const defaultConfig = {
5
72
  autoImport: true,
6
73
  theme: "light",
7
- prefix: "N"
74
+ prefix: "N",
75
+ primaryColor: "blue",
76
+ gradient: DEFAULT_GRADIENT,
77
+ icons: DEFAULT_ICONS
8
78
  };
9
79
  const module$1 = defineNuxtModule({
10
80
  meta: {
@@ -43,6 +113,14 @@ const module$1 = defineNuxtModule({
43
113
  for (const key in aliases) {
44
114
  nuxt.options.alias[`@nui/${key}`] = aliases[key];
45
115
  }
116
+ nuxt.options.appConfig.nui = defu(nuxt.options.appConfig.nui, {
117
+ gradient: options.gradient,
118
+ icons: options.icons
119
+ });
120
+ addTypeTemplate({
121
+ filename: "types/nui-app-config.d.ts",
122
+ src: resolve("./runtime/app-config.d.ts")
123
+ });
46
124
  nuxt.options.postcss = nuxt.options.postcss || {};
47
125
  nuxt.options.postcss.plugins = nuxt.options.postcss.plugins || {};
48
126
  nuxt.options.postcss.plugins = defu(nuxt.options.postcss.plugins, {
@@ -86,6 +164,13 @@ const module$1 = defineNuxtModule({
86
164
  addImportsDir(aliases.utils);
87
165
  }
88
166
  nuxt.options.css.push(resolve("./runtime/styles/global.css"));
167
+ const primaryCss = generatePrimaryCss(options.primaryColor ?? "blue");
168
+ const { dst } = addTemplate({
169
+ filename: "nui-primary-color.css",
170
+ getContents: () => primaryCss,
171
+ write: true
172
+ });
173
+ nuxt.options.css.push(dst);
89
174
  }
90
175
  });
91
176
 
@@ -0,0 +1,22 @@
1
+ import type { NuanceGradient, NuanceIcons } from './types'
2
+
3
+
4
+ declare module '@nuxt/schema' {
5
+ interface AppConfigInput {
6
+ nui?: {
7
+ /** Default gradient configuration */
8
+ gradient?: NuanceGradient
9
+ /** Icon registry overrides */
10
+ icons?: Partial<NuanceIcons>
11
+ }
12
+ }
13
+
14
+ interface AppConfig {
15
+ nui: {
16
+ gradient: NuanceGradient
17
+ icons: NuanceIcons
18
+ }
19
+ }
20
+ }
21
+
22
+ export {}
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
3
- import { createVariantColorResolver, getFontSize, getRadius, getSize } from "@nui/utils";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
+ import { getFontSize, getRadius, getSize } from "@nui/utils";
4
4
  import Box from "../box.vue";
5
5
  import css from "./action-icon.module.css";
6
6
  const {
@@ -21,8 +21,9 @@ const {
21
21
  is: { type: null, required: false },
22
22
  mod: { type: [Object, Array, null], required: false }
23
23
  });
24
+ const { variantResolver } = useConfig();
24
25
  const style = useVarsResolver((theme) => {
25
- const { background, border, text } = createVariantColorResolver({ variant, color, theme, gradient });
26
+ const { background, border, text } = variantResolver({ variant, color, theme, gradient });
26
27
  return {
27
28
  root: {
28
29
  "--section-height": getSize(size, "section-height"),
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
3
- import { createVariantColorResolver, getRadius, getSize } from "@nui/utils";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
+ import { getRadius, getSize } from "@nui/utils";
4
4
  import Box from "../box.vue";
5
5
  import Loader from "../loader/loader.vue";
6
6
  import css from "./action-icon.module.css";
@@ -27,13 +27,14 @@ const {
27
27
  variant: { type: String, required: false },
28
28
  classes: { type: Object, required: false }
29
29
  });
30
+ const { variantResolver } = useConfig();
30
31
  const style = useVarsResolver((theme) => {
31
32
  const {
32
33
  background,
33
34
  border,
34
35
  hover,
35
36
  text
36
- } = createVariantColorResolver({ variant, color, theme, gradient });
37
+ } = variantResolver({ variant, color, theme, gradient });
37
38
  return {
38
39
  root: {
39
40
  "--ai-size": getSize(size, "ai-size"),
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
3
- import { createVariantColorResolver, getRadius } from "@nui/utils";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
+ import { getRadius } from "@nui/utils";
4
4
  import { useId } from "vue";
5
5
  import ActionIcon from "./action-icon/action-icon.vue";
6
6
  import Box from "./box.vue";
@@ -28,8 +28,9 @@ const {
28
28
  });
29
29
  defineEmits(["close"]);
30
30
  const id = useId();
31
+ const { icons, variantResolver } = useConfig();
31
32
  const style = useVarsResolver((theme) => {
32
- const { background, border, text } = createVariantColorResolver({ variant, color, theme });
33
+ const { background, border, text } = variantResolver({ variant, color, theme });
33
34
  return {
34
35
  root: {
35
36
  "--alert-radius": radius === void 0 ? void 0 : getRadius(radius),
@@ -79,7 +80,7 @@ const style = useVarsResolver((theme) => {
79
80
  v-if='withCloseButton'
80
81
  :class='[$style.closeButton, classes?.closeButton]'
81
82
  variant='subtle'
82
- icon='gravity-ui:xmark'
83
+ :icon='icons.close'
83
84
  size='sm'
84
85
  :color
85
86
  @click='$emit("close")'
@@ -19,10 +19,7 @@ export interface AvatarProps extends BoxProps {
19
19
  name?: string;
20
20
  /** Palette of colors picked from for autogenerated initials. Defaults to all theme colors except gray and dark. */
21
21
  allowedInitialsColors?: NuanceColor[];
22
- /**
23
- * Icon rendered when no `src` and no `name` are provided
24
- * @default 'gravity-ui:person'
25
- */
22
+ /** Icon rendered when no `src` and no `name` are provided. Defaults to the configured `person` icon. */
26
23
  placeholder?: string;
27
24
  /** Visual variant */
28
25
  variant?: AvatarVariant;
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
3
- import { createVariantColorResolver, getRadius, getSize } from "@nui/utils";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
+ import { getRadius, getSize } from "@nui/utils";
4
4
  import { computed } from "vue";
5
5
  import Box from "../box.vue";
6
6
  import css from "./avatar.module.css";
@@ -10,7 +10,7 @@ import { getInitialsColor } from "./lib/get-initials-color";
10
10
  const {
11
11
  name,
12
12
  radius,
13
- placeholder = "gravity-ui:person",
13
+ placeholder,
14
14
  ...props
15
15
  } = defineProps({
16
16
  radius: { type: [String, Number, Object], required: false },
@@ -29,9 +29,11 @@ const {
29
29
  });
30
30
  const initials = computed(() => name && getInitials(name));
31
31
  const ctx = useAvatarGroupState();
32
+ const { icons, variantResolver } = useConfig();
33
+ const resolvedPlaceholder = computed(() => placeholder ?? icons.person);
32
34
  const style = useVarsResolver((theme) => {
33
35
  const color = props.color === "initials" && typeof name === "string" ? getInitialsColor(name, props.allowedInitialsColors) : props.color;
34
- const { background, text, border } = createVariantColorResolver({
36
+ const { background, text, border } = variantResolver({
35
37
  theme,
36
38
  gradient: props.gradient,
37
39
  color: color || "gray",
@@ -57,7 +59,7 @@ const style = useVarsResolver((theme) => {
57
59
  >
58
60
  <span v-if='!src' :class='[css.placeholder, classes?.placeholder]' :title='alt'>
59
61
  <slot>
60
- <Icon v-if='!src && !name' :name='placeholder' />
62
+ <Icon v-if='!src && !name' :name='resolvedPlaceholder' />
61
63
  {{ initials }}
62
64
  </slot>
63
65
  </span>
@@ -19,10 +19,7 @@ export interface AvatarProps extends BoxProps {
19
19
  name?: string;
20
20
  /** Palette of colors picked from for autogenerated initials. Defaults to all theme colors except gray and dark. */
21
21
  allowedInitialsColors?: NuanceColor[];
22
- /**
23
- * Icon rendered when no `src` and no `name` are provided
24
- * @default 'gravity-ui:person'
25
- */
22
+ /** Icon rendered when no `src` and no `name` are provided. Defaults to the configured `person` icon. */
26
23
  placeholder?: string;
27
24
  /** Visual variant */
28
25
  variant?: AvatarVariant;
@@ -1,7 +1,7 @@
1
1
  import type { AnyString, NuanceColor, NuanceGradient, NuanceRadius, NuanceSize } from '@nui/types';
2
2
  import type { CSSProperties } from 'vue';
3
3
  import type { BoxProps } from './box.vue.js';
4
- export type BadgeVariant = 'filled' | 'light' | 'outline' | 'dot' | 'default' | 'gradient';
4
+ export type BadgeVariant = 'filled' | 'light' | 'outline' | 'default' | 'gradient' | 'subtle';
5
5
  export interface BadgeVars {
6
6
  root: '--badge-height' | '--badge-padding-x' | '--badge-fz' | '--badge-fw' | '--badge-radius' | '--badge-bg' | '--badge-color' | '--badge-bd' | '--badge-dot-color';
7
7
  }
@@ -33,6 +33,8 @@ export interface BadgeProps extends BoxProps {
33
33
  variant?: BadgeVariant;
34
34
  /** Font weight */
35
35
  fw?: CSSProperties['font-weight'];
36
+ /** Adds a dot indicator before the label, inheriting the text color */
37
+ dotted?: boolean;
36
38
  }
37
39
  declare var __VLS_8: {}, __VLS_15: {}, __VLS_17: {};
38
40
  type __VLS_Slots = {} & {
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
3
- import { createVariantColorResolver, getRadius, getSize, getThemeColor } from "@nui/utils";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
+ import { getRadius, getSize, getThemeColor } from "@nui/utils";
4
4
  import Box from "./box.vue";
5
5
  const {
6
6
  variant = "filled",
@@ -10,7 +10,8 @@ const {
10
10
  fullWidth = false,
11
11
  circle,
12
12
  icon,
13
- fw
13
+ fw,
14
+ dotted
14
15
  } = defineProps({
15
16
  size: { type: [String, Object], required: false },
16
17
  circle: { type: Boolean, required: false },
@@ -21,13 +22,15 @@ const {
21
22
  icon: { type: String, required: false },
22
23
  variant: { type: String, required: false },
23
24
  fw: { type: void 0, required: false },
25
+ dotted: { type: Boolean, required: false },
24
26
  is: { type: null, required: false },
25
27
  mod: { type: [Object, Array, null], required: false }
26
28
  });
29
+ const { variantResolver } = useConfig();
27
30
  const style = useVarsResolver((theme) => {
28
- const { background, border, text } = createVariantColorResolver({
31
+ const { background, border, text } = variantResolver({
29
32
  theme,
30
- variant: variant === "dot" ? "default" : variant,
33
+ variant,
31
34
  color
32
35
  });
33
36
  return {
@@ -40,7 +43,7 @@ const style = useVarsResolver((theme) => {
40
43
  "--badge-bg": color || variant ? background : void 0,
41
44
  "--badge-color": color || variant ? text : void 0,
42
45
  "--badge-bd": color || variant ? border : void 0,
43
- "--badge-dot-color": variant === "dot" ? getThemeColor(color, theme) : void 0
46
+ "--badge-dot-color": dotted ? variant === "default" ? getThemeColor(color, theme) : text : void 0
44
47
  }
45
48
  };
46
49
  });
@@ -54,14 +57,14 @@ const style = useVarsResolver((theme) => {
54
57
  {
55
58
  "block": fullWidth,
56
59
  circle,
57
- variant,
60
+ dotted,
58
61
  "with-left-section": !!$slots.leftSection || !!icon,
59
62
  "with-right-section": !!$slots.rightSection
60
63
  },
61
64
  mod
62
65
  ]'
63
66
  >
64
- <span v-if='variant === "dot"' :class='$style.dot' />
67
+ <span v-if='dotted && !circle' :class='$style.dot' />
65
68
 
66
69
  <span v-else-if='$slots.leftSection || !!icon' :class='$style.section' data-position='left'>
67
70
  <slot name='leftSection'>
@@ -80,5 +83,5 @@ const style = useVarsResolver((theme) => {
80
83
  </template>
81
84
 
82
85
  <style module>
83
- .root{--badge-height-xs:rem(16px);--badge-height-sm:rem(18px);--badge-height-md:rem(20px);--badge-height-lg:rem(26px);--badge-height-xl:rem(32px);--badge-fz-xs:rem(8px);--badge-fz-sm:rem(10px);--badge-fz-md:rem(12px);--badge-fz-lg:rem(14px);--badge-fz-xl:rem(16px);--badge-fw:400;--badge-padding-x-xs:rem(6px);--badge-padding-x-sm:rem(8px);--badge-padding-x-md:rem(10px);--badge-padding-x-lg:rem(12px);--badge-padding-x-xl:rem(16px);--badge-height:var(--badge-height-md);--badge-fz:var(--badge-fz-md);--badge-padding-x:var(--badge-padding-x-md);--badge-radius:100%;--badge-lh:calc(var(--badge-height) - rem(2px));--badge-color:var(--color-white);--badge-bg:var(--color-primary-filled);--badge-border-width:1px;--badge-bd:var(--badge-border-width) solid transparent;align-items:center;background:var(--badge-bg);border:var(--badge-bd);border-radius:var(--badge-radius);color:var(--badge-color);cursor:default;display:inline-grid;font-size:var(--badge-fz);font-weight:var(--badge-fw);height:var(--badge-height);justify-content:center;letter-spacing:.25px;line-height:var(--badge-lh);overflow:hidden;padding:0 var(--badge-padding-x);text-decoration:none;text-overflow:ellipsis;text-transform:uppercase;width:-moz-fit-content;width:fit-content;-webkit-tap-highlight-color:transparent}.root:where([data-with-left-section],[data-variant=dot]){grid-template-columns:auto 1fr;padding-left:calc(var(--badge-padding-x) - var(--spacing-xs)/2)}.root:where([data-with-right-section]){grid-template-columns:1fr auto;padding-right:calc(var(--badge-padding-x) - var(--spacing-xs)/2)}.root:where([data-with-left-section][data-with-right-section],[data-variant=dot][data-with-right-section]){grid-template-columns:auto 1fr auto;padding:0 calc(var(--spacing-xs)/2)}.root:where([data-block]){display:flex;width:100%}.root:where([data-circle]){display:flex;padding-inline:2px;width:var(--badge-height)}.root:where([data-variant=dot]){@mixin where-light{--badge-color:var(--color-black)}@mixin where-dark{--badge-color:var(--color-white)}}.dot{--badge-dot-size:calc(var(--badge-height)/2.5);background-color:var(--badge-dot-color,var(--badge-color));border-radius:var(--badge-dot-size);display:block;height:var(--badge-dot-size);margin-inline-end:calc(var(--badge-dot-size)/2);width:var(--badge-dot-size)}.label{cursor:inherit;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}.section{--badge-section-margin:calc(var(--spacing-xs)/2);align-items:center;display:inline-flex;justify-content:center;max-height:calc(var(--badge-height) - var(--badge-border-width)*2)}.section:where([data-position=left]){margin-inline-end:var(--badge-section-margin)}.section:where([data-position=right]){margin-inline-start:var(--badge-section-margin)}
86
+ .root{--badge-height-xs:rem(16px);--badge-height-sm:rem(18px);--badge-height-md:rem(20px);--badge-height-lg:rem(26px);--badge-height-xl:rem(32px);--badge-fz-xs:rem(8px);--badge-fz-sm:rem(10px);--badge-fz-md:rem(12px);--badge-fz-lg:rem(14px);--badge-fz-xl:rem(16px);--badge-fw:600;--badge-padding-x-xs:rem(6px);--badge-padding-x-sm:rem(8px);--badge-padding-x-md:rem(10px);--badge-padding-x-lg:rem(12px);--badge-padding-x-xl:rem(16px);--badge-height:var(--badge-height-md);--badge-fz:var(--badge-fz-md);--badge-padding-x:var(--badge-padding-x-md);--badge-radius:100%;--badge-lh:calc(var(--badge-height) - rem(2px));--badge-color:var(--color-white);--badge-bg:var(--color-primary-filled);--badge-border-width:1px;--badge-bd:var(--badge-border-width) solid transparent;align-items:center;background:var(--badge-bg);border:var(--badge-bd);border-radius:var(--badge-radius);color:var(--badge-color);cursor:default;display:inline-grid;font-size:var(--badge-fz);font-weight:var(--badge-fw);height:var(--badge-height);justify-content:center;letter-spacing:.25px;line-height:var(--badge-lh);overflow:hidden;padding:0 var(--badge-padding-x);text-decoration:none;text-overflow:ellipsis;text-transform:uppercase;width:-moz-fit-content;width:fit-content;-webkit-tap-highlight-color:transparent}.root:where([data-with-left-section],[data-dotted]){grid-template-columns:auto 1fr;padding-left:calc(var(--badge-padding-x) - var(--spacing-xs)/2)}.root:where([data-with-right-section]){grid-template-columns:1fr auto;padding-right:calc(var(--badge-padding-x) - var(--spacing-xs)/2)}.root:where([data-with-left-section][data-with-right-section],[data-dotted][data-with-right-section]){grid-template-columns:auto 1fr auto;padding:0 calc(var(--spacing-xs)/2)}.root:where([data-block]){display:flex;width:100%}.root:where([data-circle]){display:flex;padding-inline:2px;width:var(--badge-height)}.dot{--badge-dot-size:calc(var(--badge-height)/2.5);background-color:var(--badge-dot-color,var(--badge-color));border-radius:var(--badge-dot-size);display:block;height:var(--badge-dot-size);margin-inline-end:calc(var(--badge-dot-size)/2);width:var(--badge-dot-size)}.label{cursor:inherit;overflow:hidden;text-align:center;text-overflow:ellipsis;white-space:nowrap}.section{--badge-section-margin:calc(var(--spacing-xs)/2);align-items:center;display:inline-flex;justify-content:center;max-height:calc(var(--badge-height) - var(--badge-border-width)*2)}.section:where([data-position=left]){margin-inline-end:var(--badge-section-margin)}.section:where([data-position=right]){margin-inline-start:var(--badge-section-margin)}
84
87
  </style>
@@ -1,7 +1,7 @@
1
1
  import type { AnyString, NuanceColor, NuanceGradient, NuanceRadius, NuanceSize } from '@nui/types';
2
2
  import type { CSSProperties } from 'vue';
3
3
  import type { BoxProps } from './box.vue.js';
4
- export type BadgeVariant = 'filled' | 'light' | 'outline' | 'dot' | 'default' | 'gradient';
4
+ export type BadgeVariant = 'filled' | 'light' | 'outline' | 'default' | 'gradient' | 'subtle';
5
5
  export interface BadgeVars {
6
6
  root: '--badge-height' | '--badge-padding-x' | '--badge-fz' | '--badge-fw' | '--badge-radius' | '--badge-bg' | '--badge-color' | '--badge-bd' | '--badge-dot-color';
7
7
  }
@@ -33,6 +33,8 @@ export interface BadgeProps extends BoxProps {
33
33
  variant?: BadgeVariant;
34
34
  /** Font weight */
35
35
  fw?: CSSProperties['font-weight'];
36
+ /** Adds a dot indicator before the label, inheriting the text color */
37
+ dotted?: boolean;
36
38
  }
37
39
  declare var __VLS_8: {}, __VLS_15: {}, __VLS_17: {};
38
40
  type __VLS_Slots = {} & {
@@ -18,10 +18,7 @@ export interface BreadcrumbsItem extends Omit<LinkProps, 'mod'> {
18
18
  export interface BreadcrumbsProps extends BoxProps {
19
19
  /** Items array */
20
20
  items?: MaybeRef<BreadcrumbsItem[]>;
21
- /**
22
- * Separator icon between items
23
- * @default `'gravity-ui:chevron-right'`
24
- */
21
+ /** Separator icon between items. Defaults to the configured `chevronRight` icon. */
25
22
  separator?: string;
26
23
  /** Spacing token */
27
24
  spacing?: NuanceSpacing;
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { useTheme } from "@nui/composables";
2
+ import { useConfig, useTheme } from "@nui/composables";
3
3
  import { getSpacing } from "@nui/utils";
4
4
  import { computed, unref } from "vue";
5
5
  import Box from "./box.vue";
@@ -8,7 +8,7 @@ const {
8
8
  is = "ol",
9
9
  mod,
10
10
  spacing,
11
- separator = "gravity-ui:chevron-right",
11
+ separator: _separator,
12
12
  color = "primary",
13
13
  variant = "subtle",
14
14
  size = "compact-sm",
@@ -24,6 +24,8 @@ const {
24
24
  mod: { type: [Object, Array, null], required: false }
25
25
  });
26
26
  defineEmits(["click"]);
27
+ const { icons } = useConfig();
28
+ const separator = computed(() => _separator ?? icons.chevronRight);
27
29
  const style = computed(() => ({
28
30
  "--bc-spacing": getSpacing(spacing)
29
31
  }));
@@ -18,10 +18,7 @@ export interface BreadcrumbsItem extends Omit<LinkProps, 'mod'> {
18
18
  export interface BreadcrumbsProps extends BoxProps {
19
19
  /** Items array */
20
20
  items?: MaybeRef<BreadcrumbsItem[]>;
21
- /**
22
- * Separator icon between items
23
- * @default `'gravity-ui:chevron-right'`
24
- */
21
+ /** Separator icon between items. Defaults to the configured `chevronRight` icon. */
25
22
  separator?: string;
26
23
  /** Spacing token */
27
24
  spacing?: NuanceSpacing;
@@ -1 +1 @@
1
- .root{--button-height-xs:rem(26px);--button-height-sm:rem(30px);--button-height-md:rem(36px);--button-height-lg:rem(42px);--button-height-xl:rem(50px);--button-height-compact-xs:rem(22px);--button-height-compact-sm:rem(26px);--button-height-compact-md:rem(30px);--button-height-compact-lg:rem(34px);--button-height-compact-xl:rem(40px);--button-padding-x-xs:rem(14px);--button-padding-x-sm:rem(18px);--button-padding-x-md:rem(22px);--button-padding-x-lg:rem(26px);--button-padding-x-xl:rem(32px);--button-padding-x-compact-xs:rem(7px);--button-padding-x-compact-sm:rem(8px);--button-padding-x-compact-md:rem(10px);--button-padding-x-compact-lg:rem(12px);--button-padding-x-compact-xl:rem(14px);--button-height:var(--button-height-sm);--button-padding-x:var(--button-padding-x-sm);--button-color:var(--color-white);--button-fz:var(--font-size-md);--button-bg:var(--color-primary-filled);--button-radius:var(--radius-default);--button-hover:var(--color-primary-filled-hover);--button-spacing:0;--button-justify:center;--button-section-size:calc(var(--button-height) - 0.25rem);background:var(--button-bg);border:var(--button-bd,rem(1px) solid transparent);border-radius:var(--button-radius);color:var(--button-color,var(--color-white));cursor:pointer;display:inline-block;font-size:var(--button-fz);font-weight:600;height:var(--button-height,var(--button-height-sm));line-height:1;overflow:hidden;padding-inline:var(--button-padding-x,var(--button-padding-x-sm));position:relative;text-align:center;transition:background-color .2s ease-in,color .2s ease-in;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:auto}.root:where([data-with-left-section]){padding-inline-start:0}.root:where([data-with-right-section]){padding-inline-end:0}.root:where([data-variant=gradient-outline]){background-clip:padding-box,border-box;background-origin:border-box}.root:where(:disabled:not([data-loading])){background:var(--color-disabled);border:1px solid transparent;color:var(--color-disabled-text);cursor:not-allowed;transform:none}.root:before{border-radius:var(--button-radius,var(--radius-default));content:"";filter:blur(12px);inset:-1px;opacity:0;pointer-events:none;position:absolute;transform:translateY(-100%);transition:transform .15s ease,opacity .1s ease;@mixin where-light{background:var(--color-gray-1);color:var(--color-gray-5)}@mixin where-dark{background:var(--color-dark-6);color:var(--color-dark-3)}}.root:where([data-loading]){cursor:not-allowed;transform:none}.root:where([data-loading]):before{opacity:1;transform:translateY(0)}.root:where([data-loading]) .inner{opacity:0;transform:translateY(100%)}.root:hover:where(:not([data-loading],:disabled)){background:var(--button-hover);color:var(--button-color)}.root:hover:where(:not([data-loading],:disabled)):where([data-variant=gradient-outline]){color:#fff}.inner{gap:var(--button-spacing);justify-content:center;overflow:visible;transition:transform .15s ease,opacity .1s ease;width:100%}.inner,.label{align-items:center;display:flex;height:100%}.label{flex:1;justify-content:var(--button-justify);opacity:1;overflow:hidden;white-space:nowrap}.label:where([data-loading]){opacity:.2}.section{--section-pointer-events:none;align-items:center;display:flex;height:100%;justify-content:center;pointer-events:var(--section-pointer-events);width:var(--button-section-size)}.loader{left:calc(50% - var(--loader-size)/2);position:absolute;top:calc(50% - var(--loader-size)/2)}.group{--group-border-width:1px;display:flex}.group>:where(*):focus{position:relative;z-index:1}.group[data-orientation=horizontal]{flex-direction:row}.group[data-orientation=horizontal]>:where(*):not(:only-child):first-child{border-end-end-radius:0;border-inline-end-width:calc(var(--group-border-width)/2);border-start-end-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):last-child{border-end-start-radius:0;border-inline-start-width:calc(var(--group-border-width)/2);border-start-start-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-inline-width:calc(var(--group-border-width)/2);border-radius:0}.group[data-orientation=vertical]{flex-direction:column}.group[data-orientation=vertical]>:where(*):not(:only-child):first-child{border-bottom-width:calc(var(--group-border-width)/2);border-end-end-radius:0;border-end-start-radius:0}.group[data-orientation=vertical]>:where(*):not(:only-child):last-child{border-start-end-radius:0;border-start-start-radius:0;border-top-width:calc(var(--group-border-width)/2)}.group[data-orientation=vertical]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-bottom-width:calc(var(--group-border-width)/2);border-radius:0;border-top-width:calc(var(--group-border-width)/2)}
1
+ .root{--button-height-xs:rem(26px);--button-height-sm:rem(30px);--button-height-md:rem(36px);--button-height-lg:rem(42px);--button-height-xl:rem(50px);--button-height-compact-xs:rem(22px);--button-height-compact-sm:rem(26px);--button-height-compact-md:rem(30px);--button-height-compact-lg:rem(34px);--button-height-compact-xl:rem(40px);--button-padding-x-xs:rem(14px);--button-padding-x-sm:rem(18px);--button-padding-x-md:rem(22px);--button-padding-x-lg:rem(26px);--button-padding-x-xl:rem(32px);--button-padding-x-compact-xs:rem(7px);--button-padding-x-compact-sm:rem(8px);--button-padding-x-compact-md:rem(10px);--button-padding-x-compact-lg:rem(12px);--button-padding-x-compact-xl:rem(14px);--button-height:var(--button-height-sm);--button-padding-x:var(--button-padding-x-sm);--button-color:var(--color-white);--button-fz:var(--font-size-md);--button-bg:var(--color-primary-filled);--button-radius:var(--radius-default);--button-hover:var(--color-primary-filled-hover);--button-spacing:0;--button-justify:center;--button-section-size:calc(var(--button-height) - 0.25rem);background:var(--button-bg);border:var(--button-bd,rem(1px) solid transparent);border-radius:var(--button-radius);color:var(--button-color,var(--color-white));cursor:pointer;display:inline-block;font-size:var(--button-fz);font-weight:500;height:var(--button-height,var(--button-height-sm));line-height:1;overflow:hidden;padding-inline:var(--button-padding-x,var(--button-padding-x-sm));position:relative;text-align:center;transition:background-color .2s ease-in,color .2s ease-in;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:auto}.root:where([data-with-left-section]){padding-inline-start:0}.root:where([data-with-right-section]){padding-inline-end:0}.root:where([data-variant=gradient-outline]){background-clip:padding-box,border-box;background-origin:border-box}.root:where(:disabled:not([data-loading])){background:var(--color-disabled);border:1px solid transparent;color:var(--color-disabled-text);cursor:not-allowed;transform:none}.root:before{border-radius:var(--button-radius,var(--radius-default));content:"";filter:blur(12px);inset:-1px;opacity:0;pointer-events:none;position:absolute;transform:translateY(-100%);transition:transform .15s ease,opacity .1s ease;@mixin where-light{background:var(--color-gray-1);color:var(--color-gray-5)}@mixin where-dark{background:var(--color-dark-6);color:var(--color-dark-3)}}.root:where([data-loading]){cursor:not-allowed;transform:none}.root:where([data-loading]):before{opacity:1;transform:translateY(0)}.root:where([data-loading]) .inner{opacity:0;transform:translateY(100%)}.root:hover:where(:not([data-loading],:disabled)),.root[data-active]{background:var(--button-hover);color:var(--button-color)}.root:hover:where(:not([data-loading],:disabled)):where([data-variant=gradient-outline]),.root[data-active]:where([data-variant=gradient-outline]){color:#fff}.inner{gap:var(--button-spacing);justify-content:center;overflow:visible;transition:transform .15s ease,opacity .1s ease;width:100%}.inner,.label{align-items:center;display:flex;height:100%}.label{flex:1;justify-content:var(--button-justify);opacity:1;overflow:hidden;white-space:nowrap}.label:where([data-loading]){opacity:.2}.section{--section-pointer-events:none;align-items:center;display:flex;height:100%;justify-content:center;pointer-events:var(--section-pointer-events);width:var(--button-section-size)}.loader{left:calc(50% - var(--loader-size)/2);position:absolute;top:calc(50% - var(--loader-size)/2)}.group{--group-border-width:1px;display:flex}.group>:where(*):focus{position:relative;z-index:1}.group[data-orientation=horizontal]{flex-direction:row}.group[data-orientation=horizontal]>:where(*):not(:only-child):first-child{border-end-end-radius:0;border-inline-end-width:calc(var(--group-border-width)/2);border-start-end-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):last-child{border-end-start-radius:0;border-inline-start-width:calc(var(--group-border-width)/2);border-start-start-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-inline-width:calc(var(--group-border-width)/2);border-radius:0}.group[data-orientation=vertical]{flex-direction:column}.group[data-orientation=vertical]>:where(*):not(:only-child):first-child{border-bottom-width:calc(var(--group-border-width)/2);border-end-end-radius:0;border-end-start-radius:0}.group[data-orientation=vertical]>:where(*):not(:only-child):last-child{border-start-end-radius:0;border-start-start-radius:0;border-top-width:calc(var(--group-border-width)/2)}.group[data-orientation=vertical]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-bottom-width:calc(var(--group-border-width)/2);border-radius:0;border-top-width:calc(var(--group-border-width)/2)}
@@ -1,6 +1,6 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
3
- import { createVariantColorResolver, getFontSize, getRadius, getSize, getSpacing } from "@nui/utils";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
+ import { getFontSize, getRadius, getSize, getSpacing } from "@nui/utils";
4
4
  import Box from "../box.vue";
5
5
  import Loader from "../loader/loader.vue";
6
6
  import css from "./button.module.css";
@@ -33,8 +33,9 @@ const {
33
33
  is: { type: null, required: false },
34
34
  mod: { type: [Object, Array, null], required: false }
35
35
  });
36
+ const { variantResolver } = useConfig();
36
37
  const style = useVarsResolver((theme) => {
37
- const { background, border, hover, text } = createVariantColorResolver({
38
+ const { background, border, hover, text } = variantResolver({
38
39
  theme,
39
40
  variant,
40
41
  color: props.color,
@@ -1,10 +1,12 @@
1
1
  <script setup>
2
+ import { useConfig } from "@nui/composables";
3
+ import { computed } from "vue";
2
4
  import Box from "../../../box.vue";
3
5
  import UnstyledButton from "../../../button/unstyled-button.vue";
4
6
  const {
5
7
  is = "header",
6
- prevIcon = "gravity-ui:chevron-left",
7
- nextIcon = "gravity-ui:chevron-right",
8
+ prevIcon,
9
+ nextIcon,
8
10
  withPrev = true,
9
11
  withNext = true,
10
12
  nextDisabled,
@@ -23,6 +25,9 @@ const {
23
25
  mod: { type: [Object, Array, null], required: false }
24
26
  });
25
27
  defineEmits(["prev", "level", "next"]);
28
+ const { icons } = useConfig();
29
+ const resolvedPrevIcon = computed(() => prevIcon ?? icons.chevronLeft);
30
+ const resolvedNextIcon = computed(() => nextIcon ?? icons.chevronRight);
26
31
  </script>
27
32
 
28
33
  <template>
@@ -34,7 +39,7 @@ defineEmits(["prev", "level", "next"]);
34
39
  :class='$style.control'
35
40
  @click='$emit("prev")'
36
41
  >
37
- <Icon :name='prevIcon' :class='$style.icon' />
42
+ <Icon :name='resolvedPrevIcon' :class='$style.icon' />
38
43
  </UnstyledButton>
39
44
 
40
45
  <UnstyledButton
@@ -52,7 +57,7 @@ defineEmits(["prev", "level", "next"]);
52
57
  :class='$style.control'
53
58
  @click='$emit("next")'
54
59
  >
55
- <Icon :name='nextIcon' :class='$style.icon' />
60
+ <Icon :name='resolvedNextIcon' :class='$style.icon' />
56
61
  </UnstyledButton>
57
62
  </Box>
58
63
  </template>
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
3
  import { getRadius, getSize, getThemeColor, parseThemeColor } from "@nui/utils";
4
4
  import { computed } from "vue";
5
5
  import Box from "../box.vue";
@@ -26,6 +26,7 @@ const checked = computed(() => {
26
26
  return ctx?.value.value;
27
27
  return modelValue.value;
28
28
  });
29
+ const { icons } = useConfig();
29
30
  const style = useVarsResolver((theme) => {
30
31
  const parsed = parseThemeColor({ color, theme });
31
32
  const outlineColor = parsed.isThemeColor && parsed.shade === void 0 ? `var(--color-${parsed.color}-outline)` : parsed.color;
@@ -43,8 +44,8 @@ const style = useVarsResolver((theme) => {
43
44
  <template>
44
45
  <Box :style='style.root' :class='$style.indicator' :mod='{ checked }'>
45
46
  <slot :indeterminate='indeterminate' :class='$style.icon' :mod='{ checked }'>
46
- <Icon v-if='!indeterminate' name='gravity-ui:check' :class='$style.icon' :mod='{ checked }' />
47
- <Icon v-else :class='$style.icon' name='gravity-ui:minus' :mod='{ checked }' />
47
+ <Icon v-if='!indeterminate' :name='icons.check' :class='$style.icon' :mod='{ checked }' />
48
+ <Icon v-else :class='$style.icon' :name='icons.minus' :mod='{ checked }' />
48
49
  </slot>
49
50
  </Box>
50
51
  </template>
@@ -1,5 +1,5 @@
1
1
  <script setup>
2
- import { useVarsResolver } from "@nui/composables";
2
+ import { useConfig, useVarsResolver } from "@nui/composables";
3
3
  import { getRadius, getSize, getThemeColor, parseThemeColor } from "@nui/utils";
4
4
  import { computed, useId } from "vue";
5
5
  import Box from "../box.vue";
@@ -35,6 +35,7 @@ const {
35
35
  });
36
36
  const modelValue = defineModel({ type: [Boolean, String] });
37
37
  const ctx = useCheckboxGroupState();
38
+ const { icons } = useConfig();
38
39
  const checked = computed({
39
40
  get: () => {
40
41
  if (ctx && value !== void 0)
@@ -94,10 +95,10 @@ const style = useVarsResolver((theme) => {
94
95
  >
95
96
  <Icon
96
97
  v-if='modelValue !== "indeterminate"'
97
- name='gravity-ui:check'
98
+ :name='icons.check'
98
99
  :class='$style.icon'
99
100
  />
100
- <Icon v-else name='gravity-ui:minus' :class='$style.icon' />
101
+ <Icon v-else :name='icons.minus' :class='$style.icon' />
101
102
  </slot>
102
103
  </Box>
103
104
  </InputInline>