nuance-ui 0.1.8 → 0.1.9

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 (43) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/action-icon/action-icon.d.vue.ts +1 -0
  3. package/dist/runtime/components/action-icon/action-icon.vue.d.ts +1 -0
  4. package/dist/runtime/components/alert.d.vue.ts +48 -0
  5. package/dist/runtime/components/alert.vue +178 -0
  6. package/dist/runtime/components/alert.vue.d.ts +48 -0
  7. package/dist/runtime/components/app-shell/app-shell-main.vue +1 -0
  8. package/dist/runtime/components/button/button.d.vue.ts +1 -0
  9. package/dist/runtime/components/button/button.vue.d.ts +1 -0
  10. package/dist/runtime/components/index.d.ts +1 -0
  11. package/dist/runtime/components/index.js +1 -0
  12. package/dist/runtime/components/input/number-input.vue +12 -16
  13. package/dist/runtime/components/input/ui/input-base.d.vue.ts +3 -3
  14. package/dist/runtime/components/input/ui/input-base.vue +2 -2
  15. package/dist/runtime/components/input/ui/input-base.vue.d.ts +3 -3
  16. package/dist/runtime/components/nav-link/nav-link.vue +10 -10
  17. package/dist/runtime/components/progress/index.d.ts +3 -0
  18. package/dist/runtime/components/progress/index.js +0 -0
  19. package/dist/runtime/components/progress/progress-label.d.vue.ts +14 -0
  20. package/dist/runtime/components/progress/progress-label.vue +14 -0
  21. package/dist/runtime/components/progress/progress-label.vue.d.ts +14 -0
  22. package/dist/runtime/components/progress/progress-root.d.vue.ts +25 -0
  23. package/dist/runtime/components/progress/progress-root.vue +31 -0
  24. package/dist/runtime/components/progress/progress-root.vue.d.ts +25 -0
  25. package/dist/runtime/components/progress/progress-section.d.vue.ts +25 -0
  26. package/dist/runtime/components/progress/progress-section.vue +42 -0
  27. package/dist/runtime/components/progress/progress-section.vue.d.ts +25 -0
  28. package/dist/runtime/components/progress/progress.d.vue.ts +16 -0
  29. package/dist/runtime/components/progress/progress.module.css +1 -0
  30. package/dist/runtime/components/progress/progress.vue +39 -0
  31. package/dist/runtime/components/progress/progress.vue.d.ts +16 -0
  32. package/dist/runtime/components/tree/_ui/tree-item.vue +8 -7
  33. package/dist/runtime/components/tree/_ui/tree-root.d.vue.ts +11 -5
  34. package/dist/runtime/components/tree/_ui/tree-root.vue +15 -5
  35. package/dist/runtime/components/tree/_ui/tree-root.vue.d.ts +11 -5
  36. package/dist/runtime/components/tree/lib/context.d.ts +9 -1
  37. package/dist/runtime/components/tree/lib/context.js +16 -15
  38. package/dist/runtime/components/tree/tree.vue +15 -5
  39. package/dist/runtime/styles/colors.css +1 -1
  40. package/dist/runtime/styles/light-theme.css +1 -1
  41. package/dist/runtime/utils/tree.d.ts +19 -0
  42. package/dist/runtime/utils/tree.js +16 -16
  43. package/package.json +1 -1
@@ -0,0 +1,25 @@
1
+ import type { BoxProps } from '@nui/components';
2
+ import type { NuanceColor } from '@nui/types';
3
+ export interface ProgressSectionProps extends BoxProps {
4
+ /** Determines whether `aria-*` props should be added to the root element @default `true` */
5
+ withAria?: boolean;
6
+ /** Key of `theme.colors` or any valid CSS value @default `theme.primaryColor` */
7
+ color?: NuanceColor;
8
+ /** If set, the section has stripes @default `false` */
9
+ striped?: boolean;
10
+ /** If set, the sections stripes are animated, `striped` prop is ignored @default `false` */
11
+ animated?: boolean;
12
+ }
13
+ type __VLS_Props = ProgressSectionProps;
14
+ type __VLS_ModelProps = {
15
+ /** Value of the section in 0–100 range */
16
+ modelValue: number;
17
+ };
18
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
19
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
20
+ "update:modelValue": (value: number) => any;
21
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
22
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
23
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const _default: typeof __VLS_export;
25
+ export default _default;
@@ -0,0 +1,42 @@
1
+ <script setup>
2
+ import { useStyleResolver } from "@nui/composals";
3
+ import { getThemeColor } from "@nui/utils";
4
+ import { computed } from "vue";
5
+ import Box from "../box.vue";
6
+ import css from "./progress.module.css";
7
+ const {
8
+ withAria,
9
+ animated,
10
+ striped,
11
+ color,
12
+ mod
13
+ } = defineProps({
14
+ withAria: { type: Boolean, required: false },
15
+ color: { type: null, required: false },
16
+ striped: { type: Boolean, required: false },
17
+ animated: { type: Boolean, required: false },
18
+ is: { type: null, required: false },
19
+ mod: { type: [Object, Array, null], required: false }
20
+ });
21
+ const value = defineModel({ type: Number, ...{ required: true } });
22
+ const ariaAttributes = computed(() => withAria ? {
23
+ "role": "progressbar",
24
+ "aria-valuemax": 100,
25
+ "aria-valuemin": 0,
26
+ "aria-valuenow": value.value,
27
+ "aria-valuetext": `${value.value}%`
28
+ } : {});
29
+ const style = computed(() => useStyleResolver((theme) => ({
30
+ "--progress-section-size": `${value.value}%`,
31
+ "--progress-section-color": getThemeColor(color, theme)
32
+ })));
33
+ </script>
34
+
35
+ <template>
36
+ <Box
37
+ :style
38
+ v-bind='ariaAttributes'
39
+ :class='css.section'
40
+ :mod='[{ striped: striped || animated, animated }, mod]'
41
+ />
42
+ </template>
@@ -0,0 +1,25 @@
1
+ import type { BoxProps } from '@nui/components';
2
+ import type { NuanceColor } from '@nui/types';
3
+ export interface ProgressSectionProps extends BoxProps {
4
+ /** Determines whether `aria-*` props should be added to the root element @default `true` */
5
+ withAria?: boolean;
6
+ /** Key of `theme.colors` or any valid CSS value @default `theme.primaryColor` */
7
+ color?: NuanceColor;
8
+ /** If set, the section has stripes @default `false` */
9
+ striped?: boolean;
10
+ /** If set, the sections stripes are animated, `striped` prop is ignored @default `false` */
11
+ animated?: boolean;
12
+ }
13
+ type __VLS_Props = ProgressSectionProps;
14
+ type __VLS_ModelProps = {
15
+ /** Value of the section in 0–100 range */
16
+ modelValue: number;
17
+ };
18
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
19
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
20
+ "update:modelValue": (value: number) => any;
21
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
22
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
23
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
24
+ declare const _default: typeof __VLS_export;
25
+ export default _default;
@@ -0,0 +1,16 @@
1
+ import type { ProgressRootProps } from './progress-root.vue.js';
2
+ import type { ProgressSectionProps } from './progress-section.vue.js';
3
+ export interface ProgressProps extends ProgressRootProps, ProgressSectionProps {
4
+ }
5
+ type __VLS_Props = ProgressProps;
6
+ type __VLS_ModelProps = {
7
+ modelValue: number;
8
+ };
9
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ "update:modelValue": (value: number) => any;
12
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
13
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
14
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
@@ -0,0 +1 @@
1
+ .root{--progress-radius:var(--radius-default);--progress-size:var(--progress-size-md);--progress-size-xs:rem(8px);--progress-size-sm:rem(12px);--progress-size-md:rem(16px);--progress-size-lg:rem(20px);--progress-size-xl:rem(24px);border-radius:var(--progress-radius);display:flex;height:var(--progress-size);overflow:hidden;position:relative;@mixin where-light{background-color:var(--color-gray-2)}@mixin where-dark{background-color:var(--color-dark-4)}}.root:where([data-orientation=vertical]){flex-direction:column-reverse;height:auto;width:var(--progress-size)}.section{--progress-section-size:var(--progress-size-sm);--progress-section-color:var(--color-primary-4);--progress-transition-duration:100ms;align-items:center;background-color:var(--progress-section-color);background-size:20px 20px;display:flex;height:100%;justify-content:center;overflow:hidden;transition:width var(--progress-transition-duration) ease;width:var(--progress-section-size)}.section:where([data-striped]){background-image:linear-gradient(45deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.section:where([data-animated]){animation:stripes-animation 1s linear infinite}.section:where(:last-of-type){border-radius:0;border-end-end-radius:var(--progress-radius);border-start-end-radius:var(--progress-radius)}.section:where(:first-of-type){border-radius:0;border-end-start-radius:var(--progress-radius);border-start-start-radius:var(--progress-radius)}.root:where([data-orientation=vertical]) .section{height:var(--progress-section-size);transition:height var(--progress-transition-duration,.1s) ease;width:100%}.root:where([data-orientation=vertical]) .section:where([data-striped]){background-image:linear-gradient(135deg,hsla(0,0%,100%,.15) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.15) 0,hsla(0,0%,100%,.15) 75%,transparent 0,transparent)}.root:where([data-orientation=vertical]) .section:where([data-animated]){animation:stripes-animation-vertical 1s linear infinite}.root:where([data-orientation=vertical]) .section:where(:last-of-type){border-radius:0;border-start-end-radius:var(--progress-radius);border-start-start-radius:var(--progress-radius)}.root:where([data-orientation=vertical]) .section:where(:first-of-type){border-radius:0;border-end-end-radius:var(--progress-radius);border-end-start-radius:var(--progress-radius)}.label{--progress-label-color:var(--color-white);color:var(--progress-label-color);font-size:min(calc(var(--progress-size)*.65));font-weight:700;line-height:1;overflow:hidden;padding-inline:4px;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;user-select:none;white-space:nowrap}.root:where([data-orientation=vertical]) .label{writing-mode:vertical-rl}@keyframes stripes-animation{0%{background-position:0 0}to{background-position:40px 0}}@keyframes stripes-animation-vertical{0%{background-position:0 0}to{background-position:0 40px}}
@@ -0,0 +1,39 @@
1
+ <script setup>
2
+ import ProgressRoot from "./progress-root.vue";
3
+ import ProgressSection from "./progress-section.vue";
4
+ const {
5
+ mod,
6
+ size,
7
+ color,
8
+ radius,
9
+ striped,
10
+ animated,
11
+ withAria,
12
+ orientation,
13
+ transitionDuration
14
+ } = defineProps({
15
+ size: { type: String, required: false },
16
+ radius: { type: [String, Number], required: false },
17
+ transitionDuration: { type: Number, required: false },
18
+ orientation: { type: String, required: false },
19
+ is: { type: null, required: false },
20
+ mod: { type: [Object, Array, null], required: false },
21
+ withAria: { type: Boolean, required: false },
22
+ color: { type: null, required: false },
23
+ striped: { type: Boolean, required: false },
24
+ animated: { type: Boolean, required: false }
25
+ });
26
+ const value = defineModel({ type: Number, ...{ required: true } });
27
+ </script>
28
+
29
+ <template>
30
+ <ProgressRoot :size :radius :orientation :transition-duration :mod>
31
+ <ProgressSection
32
+ v-model='value'
33
+ :striped
34
+ :animated
35
+ :color
36
+ :with-aria
37
+ />
38
+ </ProgressRoot>
39
+ </template>
@@ -0,0 +1,16 @@
1
+ import type { ProgressRootProps } from './progress-root.vue.js';
2
+ import type { ProgressSectionProps } from './progress-section.vue.js';
3
+ export interface ProgressProps extends ProgressRootProps, ProgressSectionProps {
4
+ }
5
+ type __VLS_Props = ProgressProps;
6
+ type __VLS_ModelProps = {
7
+ modelValue: number;
8
+ };
9
+ type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
10
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
11
+ "update:modelValue": (value: number) => any;
12
+ }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
13
+ "onUpdate:modelValue"?: ((value: number) => any) | undefined;
14
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
@@ -56,9 +56,10 @@ function handleKeyDown(event) {
56
56
  break;
57
57
  }
58
58
  // Enter/Space - выбор элемента
59
- case "Enter":
59
+ case "Enter": {
60
60
  ctx.on("select", value);
61
61
  return ctx.setActive(value);
62
+ }
62
63
  case " ": {
63
64
  event.preventDefault();
64
65
  if (event.shiftKey)
@@ -75,8 +76,10 @@ function handleKeyDown(event) {
75
76
  <li :class='$style.root' role='presentation'>
76
77
  <RovingFocusItem>
77
78
  <Button
78
- variant='subtle'
79
- size='compact-md'
79
+ :size='ctx.size'
80
+ :color='ctx.color'
81
+ :variant='ctx.variant'
82
+ :disabled
80
83
  role='treeitem'
81
84
  :classes='{
82
85
  root: $style.button,
@@ -84,10 +87,9 @@ function handleKeyDown(event) {
84
87
  inner: $style.inner,
85
88
  section: $style.section
86
89
  }'
87
- :mod='{ active, selected, level }'
88
- :aria-selected='selected'
89
90
  :aria-level='level'
90
- :disabled
91
+ :aria-selected='selected'
92
+ :mod='{ active, selected, level }'
91
93
  @click.prevent='handleClick'
92
94
  @keydown.prevent='handleKeyDown'
93
95
  >
@@ -135,7 +137,6 @@ function handleKeyDown(event) {
135
137
  color: var(--color-text);
136
138
 
137
139
  .label {
138
- font-size: var(--font-size-sm);
139
140
  font-weight: 500;
140
141
  }
141
142
  }
@@ -1,28 +1,34 @@
1
- import type { NuanceSize } from '@nui/types';
1
+ import type { ButtonProps } from '@nui/components';
2
2
  import type { RovingFocusProps } from '../../roving-focus/roving-focus.vue.js';
3
3
  import type { TreeIconResolver, TreeModels } from '../model.js';
4
4
  export type TreeRootProps<T extends string = string> = RovingFocusProps & {
5
- size?: NuanceSize | string;
6
5
  iconResolver?: TreeIconResolver<T>;
7
6
  removable?: boolean;
7
+ selectable?: boolean;
8
+ variant?: ButtonProps['variant'];
9
+ color?: ButtonProps['color'];
10
+ size?: ButtonProps['size'];
8
11
  };
9
12
  declare const __VLS_export: <T extends string = string>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
10
13
  props: __VLS_PrettifyLocal<(RovingFocusProps & {
11
- size?: NuanceSize | string;
12
14
  iconResolver?: TreeIconResolver<T> | undefined;
13
15
  removable?: boolean;
16
+ selectable?: boolean;
17
+ variant?: ButtonProps["variant"];
18
+ color?: ButtonProps["color"];
19
+ size?: ButtonProps["size"];
14
20
  } & {
15
21
  tree: TreeModels<T>["tree"];
16
22
  active?: TreeModels<T>["active"];
17
23
  selected?: TreeModels<T>["selected"];
18
24
  expanded?: TreeModels<T>["expanded"];
19
- }) & __VLS_EmitsToProps<__VLS_NormalizeEmits<((evt: "update:tree", value: import("..").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void)>>> & import("vue").PublicProps;
25
+ }) & __VLS_EmitsToProps<__VLS_NormalizeEmits<((evt: "update:tree", value: import("@nui/components").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void)>>> & import("vue").PublicProps;
20
26
  expose: (exposed: {}) => void;
21
27
  attrs: any;
22
28
  slots: {
23
29
  default?: (props: {}) => any;
24
30
  };
25
- emit: ((evt: "update:tree", value: import("..").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void);
31
+ emit: ((evt: "update:tree", value: import("@nui/components").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void);
26
32
  }>) => import("vue").VNode & {
27
33
  __ctx?: Awaited<typeof __VLS_setup>;
28
34
  };
@@ -7,19 +7,25 @@ import Box from "../../box.vue";
7
7
  import RovingFocus from "../../roving-focus/roving-focus.vue";
8
8
  import { useProvideTreeState } from "../lib/context";
9
9
  const {
10
- size,
10
+ color,
11
11
  attr,
12
12
  loop,
13
13
  orientation,
14
+ variant = "subtle",
15
+ size = "compact-sm",
14
16
  iconResolver = () => ({ icon: "gravity-ui:file" }),
15
- removable = false
17
+ removable = false,
18
+ selectable = false
16
19
  } = defineProps({
17
20
  loop: { type: Boolean, required: false },
18
21
  orientation: { type: String, required: false },
19
22
  attr: { type: String, required: false },
20
- size: { type: String, required: false },
21
23
  iconResolver: { type: Function, required: false },
22
- removable: { type: Boolean, required: false }
24
+ removable: { type: Boolean, required: false },
25
+ selectable: { type: Boolean, required: false },
26
+ variant: { type: String, required: false },
27
+ color: { type: null, required: false },
28
+ size: { type: null, required: false }
23
29
  });
24
30
  const tree = defineModel("tree", { type: Array, ...{ required: true } });
25
31
  const active = defineModel("active", { type: null, ...{ default: null } });
@@ -35,7 +41,11 @@ useProvideTreeState({
35
41
  active,
36
42
  selected,
37
43
  expanded,
38
- iconResolver
44
+ iconResolver,
45
+ size,
46
+ color,
47
+ variant,
48
+ selectable
39
49
  });
40
50
  if (removable) {
41
51
  useEventListener(root, "keydown", (event) => {
@@ -1,28 +1,34 @@
1
- import type { NuanceSize } from '@nui/types';
1
+ import type { ButtonProps } from '@nui/components';
2
2
  import type { RovingFocusProps } from '../../roving-focus/roving-focus.vue.js';
3
3
  import type { TreeIconResolver, TreeModels } from '../model.js';
4
4
  export type TreeRootProps<T extends string = string> = RovingFocusProps & {
5
- size?: NuanceSize | string;
6
5
  iconResolver?: TreeIconResolver<T>;
7
6
  removable?: boolean;
7
+ selectable?: boolean;
8
+ variant?: ButtonProps['variant'];
9
+ color?: ButtonProps['color'];
10
+ size?: ButtonProps['size'];
8
11
  };
9
12
  declare const __VLS_export: <T extends string = string>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_expose?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
10
13
  props: __VLS_PrettifyLocal<(RovingFocusProps & {
11
- size?: NuanceSize | string;
12
14
  iconResolver?: TreeIconResolver<T> | undefined;
13
15
  removable?: boolean;
16
+ selectable?: boolean;
17
+ variant?: ButtonProps["variant"];
18
+ color?: ButtonProps["color"];
19
+ size?: ButtonProps["size"];
14
20
  } & {
15
21
  tree: TreeModels<T>["tree"];
16
22
  active?: TreeModels<T>["active"];
17
23
  selected?: TreeModels<T>["selected"];
18
24
  expanded?: TreeModels<T>["expanded"];
19
- }) & __VLS_EmitsToProps<__VLS_NormalizeEmits<((evt: "update:tree", value: import("..").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void)>>> & import("vue").PublicProps;
25
+ }) & __VLS_EmitsToProps<__VLS_NormalizeEmits<((evt: "update:tree", value: import("@nui/components").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void)>>> & import("vue").PublicProps;
20
26
  expose: (exposed: {}) => void;
21
27
  attrs: any;
22
28
  slots: {
23
29
  default?: (props: {}) => any;
24
30
  };
25
- emit: ((evt: "update:tree", value: import("..").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void);
31
+ emit: ((evt: "update:tree", value: import("@nui/components").TreeItem<T>[]) => void) & ((evt: "update:active", value: T | null) => void) & ((evt: "update:selected", value: T[]) => void) & ((evt: "update:expanded", value: T[]) => void);
26
32
  }>) => import("vue").VNode & {
27
33
  __ctx?: Awaited<typeof __VLS_setup>;
28
34
  };
@@ -1,4 +1,4 @@
1
- import type { TreeIconResolver, TreeItem } from '@nui/components';
1
+ import type { ButtonProps, TreeIconResolver, TreeItem } from '@nui/components';
2
2
  import type { ModelRef } from 'vue';
3
3
  type EventType = 'select' | 'expand';
4
4
  type SelectMode = 'single' | 'multiple' | 'range';
@@ -8,6 +8,10 @@ export interface TreeContext<T extends string = string> {
8
8
  selected: ModelRef<T[]>;
9
9
  expanded: ModelRef<T[]>;
10
10
  iconResolver: TreeIconResolver<T>;
11
+ selectable: boolean;
12
+ variant: ButtonProps['variant'];
13
+ color: ButtonProps['color'];
14
+ size: ButtonProps['size'];
11
15
  }
12
16
  export interface TreeState<T extends string = string> {
13
17
  active: ModelRef<T | null>;
@@ -18,6 +22,10 @@ export interface TreeState<T extends string = string> {
18
22
  on: ((type: 'expand', value: T) => void) & ((type: 'select', value: T, mode?: SelectMode) => void);
19
23
  off: (type: EventType, value: T) => void;
20
24
  setActive: (value: T | null) => void;
25
+ selectable: boolean;
26
+ variant: ButtonProps['variant'];
27
+ color: ButtonProps['color'];
28
+ size: ButtonProps['size'];
21
29
  }
22
30
  export declare function useProvideTreeState<T extends string = string>(ctx: TreeContext<T>): TreeState<T>;
23
31
  export declare function useTreeState<T extends string = string>(): TreeState<T>;
@@ -6,12 +6,16 @@ const [useProvide, useState] = createStrictInjection(({
6
6
  active,
7
7
  selected,
8
8
  expanded,
9
- iconResolver
9
+ iconResolver,
10
+ selectable,
11
+ ...rest
10
12
  }) => {
11
13
  const setActive = (value) => active.value = value;
12
14
  function on(type, value, mode) {
13
15
  if (type === "select") {
14
16
  setActive(value);
17
+ if (!selectable)
18
+ return;
15
19
  switch (mode) {
16
20
  case "single":
17
21
  return selected.value = [value];
@@ -48,8 +52,8 @@ const [useProvide, useState] = createStrictInjection(({
48
52
  return;
49
53
  }
50
54
  case "expand": {
51
- const children = getBranchChildren(tree.value, value);
52
- return expanded.value = expanded.value.filter((v) => !children.includes(v)).filter((v) => v !== value);
55
+ const children = new Set(getBranchChildren(tree.value, value));
56
+ return expanded.value = expanded.value.filter((v) => v !== value && !children.has(v));
53
57
  }
54
58
  default:
55
59
  return console.warn(`Unknown target type in NuiTree: ${type}`);
@@ -61,34 +65,31 @@ const [useProvide, useState] = createStrictInjection(({
61
65
  const isSelected = selected.value.includes(value);
62
66
  if (mode === "single")
63
67
  return on(type, value, mode);
64
- if (mode === "multiple") {
65
- if (isSelected)
66
- return off(type, value);
67
- return on(type, value, mode);
68
- }
68
+ if (mode === "multiple")
69
+ return isSelected ? off(type, value) : on(type, value, mode);
69
70
  if (mode === "range")
70
71
  return on(type, value, mode);
71
72
  return;
72
73
  }
73
74
  case "expand": {
74
75
  const isExpanded = expanded.value.includes(value);
75
- if (isExpanded)
76
- return off(type, value);
77
- return on(type, value);
76
+ return isExpanded ? off(type, value) : on(type, value);
78
77
  }
79
78
  default:
80
79
  console.warn(`Unknown target type in NuiTree: ${type}`);
81
80
  }
82
81
  };
83
82
  return {
83
+ on,
84
+ off,
85
+ toggle,
86
+ setActive,
84
87
  active,
85
88
  selected,
86
89
  expanded,
87
90
  iconResolver,
88
- toggle,
89
- on,
90
- off,
91
- setActive
91
+ selectable,
92
+ ...rest
92
93
  };
93
94
  }, {
94
95
  injectionKey,
@@ -1,15 +1,22 @@
1
1
  <script setup>
2
- import { unref } from "vue";
3
2
  import UTreeItem from "./_ui/tree-item.vue";
4
3
  import TreeRoot from "./_ui/tree-root.vue";
5
4
  import { getExpandedItems } from "./lib/get-default";
6
- const props = defineProps({
5
+ const {
6
+ color,
7
+ variant = "subtle",
8
+ size = "compact-sm",
9
+ ...props
10
+ } = defineProps({
7
11
  loop: { type: Boolean, required: false },
8
12
  orientation: { type: String, required: false },
9
13
  attr: { type: String, required: false },
10
- size: { type: String, required: false },
11
14
  iconResolver: { type: Function, required: false },
12
- removable: { type: Boolean, required: false }
15
+ removable: { type: Boolean, required: false },
16
+ selectable: { type: Boolean, required: false },
17
+ variant: { type: String, required: false },
18
+ color: { type: null, required: false },
19
+ size: { type: null, required: false }
13
20
  });
14
21
  const tree = defineModel("tree", { type: Array, ...{ required: true } });
15
22
  const active = defineModel("active", { type: null, ...{ default: null } });
@@ -25,9 +32,12 @@ expanded.value = getExpandedItems(tree.value);
25
32
  v-model:active='active'
26
33
  v-model:selected='selected'
27
34
  v-model:expanded='expanded'
35
+ :size
36
+ :color
37
+ :variant
28
38
  >
29
39
  <UTreeItem
30
- v-for='item in unref(tree)'
40
+ v-for='item in tree'
31
41
  :key='item.value'
32
42
  :item
33
43
  :level='1'
@@ -1 +1 @@
1
- :root{--color-white:#fff;--color-black:#000;--color-primary-0:var(--color-blue-0);--color-primary-1:var(--color-blue-1);--color-primary-2:var(--color-blue-2);--color-primary-3:var(--color-blue-3);--color-primary-4:var(--color-blue-4);--color-primary-5:var(--color-blue-5);--color-primary-6:var(--color-blue-6);--color-primary-7:var(--color-blue-7);--color-primary-8:var(--color-blue-8);--color-primary-9:var(--color-blue-9);--color-primary-filled:var(--color-blue-filled);--color-primary-filled-hover:var(--color-blue-filled-hover);--color-primary-light:alpha(var(--color-blue-light),.15);--color-primary-light-hover:var(--color-blue-light-hover);--color-primary-light-color:var(--color-blue-light-color);--color-primary-outline:var(--color-blue-outline);--color-primary-outline-hover:alpha(var(--color-blue-outline),.1);--color-dark-0:#c9c9c9;--color-dark-1:#b8b8b8;--color-dark-2:#828282;--color-dark-3:#696969;--color-dark-4:#424242;--color-dark-5:#3b3b3b;--color-dark-6:#2e2e2e;--color-dark-7:#242424;--color-dark-8:#1f1f1f;--color-dark-9:#141414;--color-slate-0:#f8f9fb;--color-slate-1:#f1f3f6;--color-slate-2:#e4e7ed;--color-slate-3:#dadce5;--color-slate-4:#c1c6d4;--color-slate-5:#9096b2;--color-slate-6:#4a5568;--color-slate-7:#313446;--color-slate-8:#252938;--color-slate-9:#1d1f29;--color-gray-0:#f8f9fa;--color-gray-1:#f1f3f5;--color-gray-2:#e9ecef;--color-gray-3:#dee2e6;--color-gray-4:#ced4da;--color-gray-5:#adb5bd;--color-gray-6:#868e96;--color-gray-7:#495057;--color-gray-8:#343a40;--color-gray-9:#212529;--color-red-0:#fdf4f4;--color-red-1:#f5e0e0;--color-red-2:#e8c5c5;--color-red-3:#d49999;--color-red-4:#c27373;--color-red-5:#a85a5a;--color-red-6:#8f4545;--color-red-7:#763636;--color-red-8:#5d2a2a;--color-red-9:#4a2121;--color-pink-0:#fdf6f8;--color-pink-1:#f7e4e9;--color-pink-2:#edc2d0;--color-pink-3:#dd9bb0;--color-pink-4:#c97a93;--color-pink-5:#b26179;--color-pink-6:#954d65;--color-pink-7:#7a3e52;--color-pink-8:#603140;--color-pink-9:#4d2733;--color-grape-0:#f8f0fc;--color-grape-1:#f3d9fa;--color-grape-2:#eebefa;--color-grape-3:#e599f7;--color-grape-4:#da77f2;--color-grape-5:#cc5de8;--color-grape-6:#be4bdb;--color-grape-7:#ae3ec9;--color-grape-8:#9c36b5;--color-grape-9:#862e9c;--color-violet-0:#f3f0ff;--color-violet-1:#e5dbff;--color-violet-2:#d0bfff;--color-violet-3:#b197fc;--color-violet-4:#9775fa;--color-violet-5:#845ef7;--color-violet-6:#7950f2;--color-violet-7:#7048e8;--color-violet-8:#6741d9;--color-violet-9:#5f3dc4;--color-indigo-0:#edf2ff;--color-indigo-1:#dbe4ff;--color-indigo-2:#bac8ff;--color-indigo-3:#91a7ff;--color-indigo-4:#748ffc;--color-indigo-5:#5c7cfa;--color-indigo-6:#4c6ef5;--color-indigo-7:#4263eb;--color-indigo-8:#3b5bdb;--color-indigo-9:#364fc7;--color-blue-0:#e7f5ff;--color-blue-1:#d0ebff;--color-blue-2:#a5d8ff;--color-blue-3:#74c0fc;--color-blue-4:#4dabf7;--color-blue-5:#339af0;--color-blue-6:#228be6;--color-blue-7:#1c7ed6;--color-blue-8:#1971c2;--color-blue-9:#1864ab;--color-cyan-0:#e3fafc;--color-cyan-1:#c5f6fa;--color-cyan-2:#99e9f2;--color-cyan-3:#66d9e8;--color-cyan-4:#3bc9db;--color-cyan-5:#22b8cf;--color-cyan-6:#15aabf;--color-cyan-7:#1098ad;--color-cyan-8:#0c8599;--color-cyan-9:#0b7285;--color-teal-0:#e6fcf5;--color-teal-1:#c3fae8;--color-teal-2:#96f2d7;--color-teal-3:#63e6be;--color-teal-4:#38d9a9;--color-teal-5:#20c997;--color-teal-6:#12b886;--color-teal-7:#0ca678;--color-teal-8:#099268;--color-teal-9:#087f5b;--color-green-0:#ebfbee;--color-green-1:#d3f9d8;--color-green-2:#b2f2bb;--color-green-3:#8ce99a;--color-green-4:#69db7c;--color-green-5:#51cf66;--color-green-6:#40c057;--color-green-7:#37b24d;--color-green-8:#2f9e44;--color-green-9:#2b8a3e;--color-lime-0:#f4fce3;--color-lime-1:#e9fac8;--color-lime-2:#d8f5a2;--color-lime-3:#c0eb75;--color-lime-4:#a9e34b;--color-lime-5:#94d82d;--color-lime-6:#82c91e;--color-lime-7:#74b816;--color-lime-8:#66a80f;--color-lime-9:#5c940d;--color-yellow-0:#fdfbf0;--color-yellow-1:#f9f4d6;--color-yellow-2:#f0e6a6;--color-yellow-3:#e3d372;--color-yellow-4:#d4bf47;--color-yellow-5:#c2a72b;--color-yellow-6:#a68c1a;--color-yellow-7:#8a7315;--color-yellow-8:#6e5a12;--color-yellow-9:#584610;--color-orange-0:#fdf6f0;--color-orange-1:#f7e6d3;--color-orange-2:#edd1b0;--color-orange-3:#deb887;--color-orange-4:#cd9a5b;--color-orange-5:#b8833a;--color-orange-6:#a0692f;--color-orange-7:#8b5a28;--color-orange-8:#704621;--color-orange-9:#5a3419}
1
+ :root{--color-white:#fff;--color-black:#000;--color-primary-0:var(--color-blue-0);--color-primary-1:var(--color-blue-1);--color-primary-2:var(--color-blue-2);--color-primary-3:var(--color-blue-3);--color-primary-4:var(--color-blue-4);--color-primary-5:var(--color-blue-5);--color-primary-6:var(--color-blue-6);--color-primary-7:var(--color-blue-7);--color-primary-8:var(--color-blue-8);--color-primary-9:var(--color-blue-9);--color-primary-filled:var(--color-blue-filled);--color-primary-filled-hover:var(--color-blue-filled-hover);--color-primary-light:alpha(var(--color-blue-light),.15);--color-primary-light-hover:var(--color-blue-light-hover);--color-primary-light-color:var(--color-blue-light-color);--color-primary-outline:var(--color-blue-outline);--color-primary-outline-hover:alpha(var(--color-blue-outline),.1);--color-dark-0:#c9c9c9;--color-dark-1:#b8b8b8;--color-dark-2:#828282;--color-dark-3:#696969;--color-dark-4:#424242;--color-dark-5:#3b3b3b;--color-dark-6:#2e2e2e;--color-dark-7:#242424;--color-dark-8:#1f1f1f;--color-dark-9:#141414;--color-slate-0:#f8f9fb;--color-slate-1:#f1f3f6;--color-slate-2:#e4e7ed;--color-slate-3:#dadce5;--color-slate-4:#c1c6d4;--color-slate-5:#9096b2;--color-slate-6:#4a5568;--color-slate-7:#313446;--color-slate-8:#252938;--color-slate-9:#1d1f29;--color-gray-0:#f8f9fa;--color-gray-1:#f1f3f5;--color-gray-2:#e9ecef;--color-gray-3:#dee2e6;--color-gray-4:#ced4da;--color-gray-5:#adb5bd;--color-gray-6:#868e96;--color-gray-7:#495057;--color-gray-8:#343a40;--color-gray-9:#212529;--color-red-0:#fff5f5;--color-red-1:#ffe3e3;--color-red-2:#ffc9c9;--color-red-3:#ffa8a8;--color-red-4:#ff8787;--color-red-5:#ff6b6b;--color-red-6:#fa5252;--color-red-7:#f03e3e;--color-red-8:#e03131;--color-red-9:#c92a2a;--color-pink-0:#fdf6f8;--color-pink-1:#f7e4e9;--color-pink-2:#edc2d0;--color-pink-3:#dd9bb0;--color-pink-4:#c97a93;--color-pink-5:#b26179;--color-pink-6:#954d65;--color-pink-7:#7a3e52;--color-pink-8:#603140;--color-pink-9:#4d2733;--color-grape-0:#f8f0fc;--color-grape-1:#f3d9fa;--color-grape-2:#eebefa;--color-grape-3:#e599f7;--color-grape-4:#da77f2;--color-grape-5:#cc5de8;--color-grape-6:#be4bdb;--color-grape-7:#ae3ec9;--color-grape-8:#9c36b5;--color-grape-9:#862e9c;--color-violet-0:#f3f0ff;--color-violet-1:#e5dbff;--color-violet-2:#d0bfff;--color-violet-3:#b197fc;--color-violet-4:#9775fa;--color-violet-5:#845ef7;--color-violet-6:#7950f2;--color-violet-7:#7048e8;--color-violet-8:#6741d9;--color-violet-9:#5f3dc4;--color-indigo-0:#edf2ff;--color-indigo-1:#dbe4ff;--color-indigo-2:#bac8ff;--color-indigo-3:#91a7ff;--color-indigo-4:#748ffc;--color-indigo-5:#5c7cfa;--color-indigo-6:#4c6ef5;--color-indigo-7:#4263eb;--color-indigo-8:#3b5bdb;--color-indigo-9:#364fc7;--color-blue-0:#e7f5ff;--color-blue-1:#d0ebff;--color-blue-2:#a5d8ff;--color-blue-3:#74c0fc;--color-blue-4:#4dabf7;--color-blue-5:#339af0;--color-blue-6:#228be6;--color-blue-7:#1c7ed6;--color-blue-8:#1971c2;--color-blue-9:#1864ab;--color-cyan-0:#e3fafc;--color-cyan-1:#c5f6fa;--color-cyan-2:#99e9f2;--color-cyan-3:#66d9e8;--color-cyan-4:#3bc9db;--color-cyan-5:#22b8cf;--color-cyan-6:#15aabf;--color-cyan-7:#1098ad;--color-cyan-8:#0c8599;--color-cyan-9:#0b7285;--color-teal-0:#e6fcf5;--color-teal-1:#c3fae8;--color-teal-2:#96f2d7;--color-teal-3:#63e6be;--color-teal-4:#38d9a9;--color-teal-5:#20c997;--color-teal-6:#12b886;--color-teal-7:#0ca678;--color-teal-8:#099268;--color-teal-9:#087f5b;--color-green-0:#ebfbee;--color-green-1:#d3f9d8;--color-green-2:#b2f2bb;--color-green-3:#8ce99a;--color-green-4:#69db7c;--color-green-5:#51cf66;--color-green-6:#40c057;--color-green-7:#37b24d;--color-green-8:#2f9e44;--color-green-9:#2b8a3e;--color-lime-0:#f4fce3;--color-lime-1:#e9fac8;--color-lime-2:#d8f5a2;--color-lime-3:#c0eb75;--color-lime-4:#a9e34b;--color-lime-5:#94d82d;--color-lime-6:#82c91e;--color-lime-7:#74b816;--color-lime-8:#66a80f;--color-lime-9:#5c940d;--color-yellow-0:#fff9db;--color-yellow-1:#fff3bf;--color-yellow-2:#ffec99;--color-yellow-3:#ffe066;--color-yellow-4:#ffd43b;--color-yellow-5:#fcc419;--color-yellow-6:#fab005;--color-yellow-7:#f59f00;--color-yellow-8:#f08c00;--color-yellow-9:#e67700;--color-orange-0:#fff4e6;--color-orange-1:#ffe8cc;--color-orange-2:#ffd8a8;--color-orange-3:#ffc078;--color-orange-4:#ffa94d;--color-orange-5:#ff922b;--color-orange-6:#fd7e14;--color-orange-7:#f76707;--color-orange-8:#e8590c;--color-orange-9:#d9480f}
@@ -1 +1 @@
1
- :root{@mixin light-root{--primary-color-contrast:var(--color-white);--color-bright:var(--color-black);--color-text:#000;--color-body:#fff;--color-error:var(--color-red-6);--color-placeholder:var(--color-gray-5);--color-anchor:var(--color-blue-6);--color-default:var(--color-white);--color-default-hover:var(--color-gray-0);--color-default-color:var(--color-black);--color-default-border:var(--color-gray-4);--color-dimmed:var(--color-gray-6);--color-disabled:var(--color-gray-2);--color-disabled-text:var(--color-gray-5);--color-disabled-border:var(--color-gray-3);--color-dark-color:var(--color-dark-filled);--color-dark-filled:var(--color-dark-6);--color-dark-filled-hover:var(--color-dark-7);--color-dark-light:rgba(46,46,46,.1);--color-dark-light-hover:rgba(46,46,46,.12);--color-dark-light-color:var(--color-dark-6);--color-dark-outline:var(--color-dark-6);--color-dark-outline-hover:rgba(46,46,46,.05);--color-gray-color:var(--color-gray-filled);--color-gray-filled:var(--color-gray-6);--color-gray-filled-hover:var(--color-gray-7);--color-gray-light:hsla(210,7%,56%,.1);--color-gray-light-hover:hsla(210,7%,56%,.12);--color-gray-light-color:var(--color-gray-6);--color-gray-outline:var(--color-gray-6);--color-gray-outline-hover:hsla(210,7%,56%,.05);--color-red-color:var(--color-red-filled);--color-red-filled:var(--color-red-6);--color-red-filled-hover:var(--color-red-7);--color-red-light:rgba(250,82,82,.1);--color-red-light-hover:rgba(250,82,82,.12);--color-red-light-color:var(--color-red-6);--color-red-outline:var(--color-red-6);--color-red-outline-hover:rgba(250,82,82,.05);--color-pink-color:var(--color-pink-filled);--color-pink-filled:var(--color-pink-6);--color-pink-filled-hover:var(--color-pink-7);--color-pink-light:rgba(230,73,128,.1);--color-pink-light-hover:rgba(230,73,128,.12);--color-pink-light-color:var(--color-pink-6);--color-pink-outline:var(--color-pink-6);--color-pink-outline-hover:rgba(230,73,128,.05);--color-grape-color:var(--color-grape-filled);--color-grape-filled:var(--color-grape-6);--color-grape-filled-hover:var(--color-grape-7);--color-grape-light:rgba(190,75,219,.1);--color-grape-light-hover:rgba(190,75,219,.12);--color-grape-light-color:var(--color-grape-6);--color-grape-outline:var(--color-grape-6);--color-grape-outline-hover:rgba(190,75,219,.05);--color-violet-color:var(--color-violet-filled);--color-violet-filled:var(--color-violet-6);--color-violet-filled-hover:var(--color-violet-7);--color-violet-light:rgba(121,80,242,.1);--color-violet-light-hover:rgba(121,80,242,.12);--color-violet-light-color:var(--color-violet-6);--color-violet-outline:var(--color-violet-6);--color-violet-outline-hover:rgba(121,80,242,.05);--color-indigo-color:var(--color-indigo-filled);--color-indigo-filled:var(--color-indigo-6);--color-indigo-filled-hover:var(--color-indigo-7);--color-indigo-light:rgba(76,110,245,.1);--color-indigo-light-hover:rgba(76,110,245,.12);--color-indigo-light-color:var(--color-indigo-6);--color-indigo-outline:var(--color-indigo-6);--color-indigo-outline-hover:rgba(76,110,245,.05);--color-blue-color:var(--color-blue-filled);--color-blue-filled:var(--color-blue-6);--color-blue-filled-hover:var(--color-blue-7);--color-blue-light:rgba(34,139,230,.1);--color-blue-light-hover:rgba(34,139,230,.12);--color-blue-light-color:var(--color-blue-6);--color-blue-outline:var(--color-blue-6);--color-blue-outline-hover:rgba(34,139,230,.05);--color-cyan-color:var(--color-cyan-filled);--color-cyan-filled:var(--color-cyan-6);--color-cyan-filled-hover:var(--color-cyan-7);--color-cyan-light:rgba(21,170,191,.1);--color-cyan-light-hover:rgba(21,170,191,.12);--color-cyan-light-color:var(--color-cyan-6);--color-cyan-outline:var(--color-cyan-6);--color-cyan-outline-hover:rgba(21,170,191,.05);--color-teal-color:var(--color-teal-filled);--color-teal-filled:var(--color-teal-6);--color-teal-filled-hover:var(--color-teal-7);--color-teal-light:rgba(18,184,134,.1);--color-teal-light-hover:rgba(18,184,134,.12);--color-teal-light-color:var(--color-teal-6);--color-teal-outline:var(--color-teal-6);--color-teal-outline-hover:rgba(18,184,134,.05);--color-green-color:var(--color-green-filled);--color-green-filled:var(--color-green-6);--color-green-filled-hover:var(--color-green-7);--color-green-light:rgba(64,192,87,.1);--color-green-light-hover:rgba(64,192,87,.12);--color-green-light-color:var(--color-green-6);--color-green-outline:var(--color-green-6);--color-green-outline-hover:rgba(64,192,87,.05);--color-lime-color:var(--color-lime-filled);--color-lime-filled:var(--color-lime-6);--color-lime-filled-hover:var(--color-lime-7);--color-lime-light:rgba(130,201,30,.1);--color-lime-light-hover:rgba(130,201,30,.12);--color-lime-light-color:var(--color-lime-6);--color-lime-outline:var(--color-lime-6);--color-lime-outline-hover:rgba(130,201,30,.05);--color-yellow-color:var(--color-yellow-filled);--color-yellow-filled:var(--color-yellow-6);--color-yellow-filled-hover:var(--color-yellow-7);--color-yellow-light:rgba(250,176,5,.1);--color-yellow-light-hover:rgba(250,176,5,.12);--color-yellow-light-color:var(--color-yellow-6);--color-yellow-outline:var(--color-yellow-6);--color-yellow-outline-hover:rgba(250,176,5,.05);--color-orange-color:var(--color-orange-filled);--color-orange-filled:var(--color-orange-6);--color-orange-filled-hover:var(--color-orange-7);--color-orange-light:rgba(253,126,20,.1);--color-orange-light-hover:rgba(253,126,20,.12);--color-orange-light-color:var(--color-orange-6);--color-orange-outline:var(--color-orange-6);--color-orange-outline-hover:rgba(253,126,20,.05)}}
1
+ :root{@mixin light-root{--primary-color-contrast:var(--color-white);--color-bright:var(--color-black);--color-text:#000;--color-body:#fff;--color-error:var(--color-red-6);--color-placeholder:var(--color-gray-5);--color-anchor:var(--color-blue-6);--color-default:var(--color-white);--color-default-hover:var(--color-gray-0);--color-default-color:var(--color-black);--color-default-border:var(--color-gray-4);--color-dimmed:var(--color-gray-6);--color-disabled:var(--color-gray-2);--color-disabled-text:var(--color-gray-5);--color-disabled-border:var(--color-gray-3);--color-dark-color:var(--color-dark-filled);--color-dark-filled:var(--color-dark-6);--color-dark-filled-hover:var(--color-dark-7);--color-dark-light:alpha(var(--color-dark-6),0.1);--color-dark-light-hover:alpha(var(--color-dark-6),0.12);--color-dark-light-color:var(--color-dark-6);--color-dark-outline:var(--color-dark-6);--color-dark-outline-hover:alpha(var(--color-dark-6),0.05);--color-gray-color:var(--color-gray-filled);--color-gray-filled:var(--color-gray-6);--color-gray-filled-hover:var(--color-gray-7);--color-gray-light:alpha(var(--color-gray-6),0.1);--color-gray-light-hover:alpha(var(--color-gray-6),0.12);--color-gray-light-color:var(--color-gray-6);--color-gray-outline:var(--color-gray-6);--color-gray-outline-hover:alpha(var(--color-gray-6),0.05);--color-red-color:var(--color-red-filled);--color-red-filled:var(--color-red-6);--color-red-filled-hover:var(--color-red-7);--color-red-light:alpha(var(--color-red-8),.1);--color-red-light-hover:alpha(var(--color-red-8),.12);--color-red-light-color:var(--color-red-6);--color-red-outline:var(--color-red-6);--color-red-outline-hover:alpha(var(--color-red-8),.01);--color-pink-color:var(--color-pink-filled);--color-pink-filled:var(--color-pink-6);--color-pink-filled-hover:var(--color-pink-7);--color-pink-light:alpha(var(--color-pink-6),0.1);--color-pink-light-hover:alpha(var(--color-pink-6),0.12);--color-pink-light-color:var(--color-pink-6);--color-pink-outline:var(--color-pink-6);--color-pink-outline-hover:alpha(var(--color-pink-6),0.05);--color-grape-color:var(--color-grape-filled);--color-grape-filled:var(--color-grape-6);--color-grape-filled-hover:var(--color-grape-7);--color-grape-light:alpha(var(--color-grape-6),0.1);--color-grape-light-hover:alpha(var(--color-grape-6),0.12);--color-grape-light-color:var(--color-grape-6);--color-grape-outline:var(--color-grape-6);--color-grape-outline-hover:alpha(var(--color-grape-6),0.05);--color-violet-color:var(--color-violet-filled);--color-violet-filled:var(--color-violet-6);--color-violet-filled-hover:var(--color-violet-7);--color-violet-light:alpha(var(--color-violet-6),0.1);--color-violet-light-hover:alpha(var(--color-violet-6),0.12);--color-violet-light-color:var(--color-violet-6);--color-violet-outline:var(--color-violet-6);--color-violet-outline-hover:alpha(var(--color-violet-6),0.05);--color-indigo-color:var(--color-indigo-filled);--color-indigo-filled:var(--color-indigo-6);--color-indigo-filled-hover:var(--color-indigo-7);--color-indigo-light:alpha(var(--color-indigo-6),0.1);--color-indigo-light-hover:alpha(var(--color-indigo-6),0.12);--color-indigo-light-color:var(--color-indigo-6);--color-indigo-outline:var(--color-indigo-6);--color-indigo-outline-hover:alpha(var(--color-indigo-6),0.05);--color-blue-color:var(--color-blue-filled);--color-blue-filled:var(--color-blue-6);--color-blue-filled-hover:var(--color-blue-7);--color-blue-light:alpha(var(--color-blue-6),0.1);--color-blue-light-hover:alpha(var(--color-blue-6),0.12);--color-blue-light-color:var(--color-blue-6);--color-blue-outline:var(--color-blue-6);--color-blue-outline-hover:alpha(var(--color-blue-6),0.05);--color-cyan-color:var(--color-cyan-filled);--color-cyan-filled:var(--color-cyan-6);--color-cyan-filled-hover:var(--color-cyan-7);--color-cyan-light:alpha(var(--color-cyan-6),0.1);--color-cyan-light-hover:alpha(var(--color-cyan-6),0.12);--color-cyan-light-color:var(--color-cyan-6);--color-cyan-outline:var(--color-cyan-6);--color-cyan-outline-hover:alpha(var(--color-cyan-6),0.05);--color-teal-color:var(--color-teal-filled);--color-teal-filled:var(--color-teal-6);--color-teal-filled-hover:var(--color-teal-7);--color-teal-light:alpha(var(--color-teal-6),0.1);--color-teal-light-hover:alpha(var(--color-teal-6),0.12);--color-teal-light-color:var(--color-teal-6);--color-teal-outline:var(--color-teal-6);--color-teal-outline-hover:alpha(var(--color-teal-6),0.05);--color-green-color:var(--color-green-filled);--color-green-filled:var(--color-green-6);--color-green-filled-hover:var(--color-green-7);--color-green-light:alpha(var(--color-green-6),0.1);--color-green-light-hover:alpha(var(--color-green-6),0.12);--color-green-light-color:var(--color-green-6);--color-green-outline:var(--color-green-6);--color-green-outline-hover:alpha(var(--color-green-6),0.05);--color-lime-color:var(--color-lime-filled);--color-lime-filled:var(--color-lime-6);--color-lime-filled-hover:var(--color-lime-7);--color-lime-light:alpha(var(--color-lime-6),0.1);--color-lime-light-hover:alpha(var(--color-lime-6),0.12);--color-lime-light-color:var(--color-lime-6);--color-lime-outline:var(--color-lime-6);--color-lime-outline-hover:alpha(var(--color-lime-6),0.05);--color-yellow-color:var(--color-yellow-filled);--color-yellow-filled:var(--color-yellow-6);--color-yellow-filled-hover:var(--color-yellow-7);--color-yellow-light:alpha(var(--color-yellow-6),0.1);--color-yellow-light-hover:alpha(var(--color-yellow-6),0.12);--color-yellow-light-color:var(--color-yellow-6);--color-yellow-outline:var(--color-yellow-6);--color-yellow-outline-hover:alpha(var(--color-yellow-6),0.05);--color-orange-color:var(--color-orange-filled);--color-orange-filled:var(--color-orange-6);--color-orange-filled-hover:var(--color-orange-7);--color-orange-light:alpha(var(--color-orange-6),0.1);--color-orange-light-hover:alpha(var(--color-orange-6),0.12);--color-orange-light-color:var(--color-orange-6);--color-orange-outline:var(--color-orange-6);--color-orange-outline-hover:alpha(var(--color-orange-6),0.05)}}
@@ -5,6 +5,25 @@ export interface TreeNode<T extends string = string> {
5
5
  /** Optional array of child nodes */
6
6
  children?: TreeNode<T>[];
7
7
  }
8
+ /**
9
+ * Filters tree nodes based on a predicate function.
10
+ * Returns a new tree containing only nodes that match the predicate.
11
+ * Parent nodes are kept if they have matching children.
12
+ *
13
+ * @template Node - The type of tree nodes
14
+ * @param {Node[]} tree - The tree to filter
15
+ * @param {(node: Node) => boolean} predicate - Function to test each node
16
+ * @returns {Node[]} New filtered tree
17
+ * @example
18
+ * const tree = [
19
+ * { value: 'folder', children: [{ value: 'file1' }, { value: 'file2' }] },
20
+ * { value: 'file3' }
21
+ * ]
22
+ * // Keep only folders (nodes with children)
23
+ * filterTree(tree, node => node.children && node.children.length > 0)
24
+ * // Result: [{ value: 'folder', children: [{ value: 'file1' }, { value: 'file2' }] }]
25
+ */
26
+ export declare function filterTree<Node extends TreeNode = TreeNode>(tree: Node[], predicate: (node: Node) => boolean): Node[];
8
27
  /**
9
28
  * Searches for a tree item by its value using depth-first search.
10
29
  * @template T - The type of node values
@@ -7,6 +7,21 @@ function traverse(nodes) {
7
7
  }
8
8
  return result;
9
9
  }
10
+ export function filterTree(tree, predicate) {
11
+ const result = [];
12
+ for (const node of tree) {
13
+ const filteredChildren = node.children?.length ? filterTree(node.children, predicate) : void 0;
14
+ if (predicate(node) || filteredChildren && filteredChildren.length > 0) {
15
+ const newNode = { ...node };
16
+ if (filteredChildren && filteredChildren.length > 0)
17
+ newNode.children = filteredChildren;
18
+ else
19
+ delete newNode.children;
20
+ result.push(newNode);
21
+ }
22
+ }
23
+ return result;
24
+ }
10
25
  export function findTreeItem(items, value) {
11
26
  for (const item of items) {
12
27
  if (item.value === value)
@@ -66,20 +81,5 @@ export function getTreeItemsBetween(tree, start, end) {
66
81
  }
67
82
  export function removeTreeNodes(tree, valuesToRemove) {
68
83
  const removeSet = new Set(valuesToRemove);
69
- function recurse(nodes) {
70
- const result = [];
71
- for (const node of nodes) {
72
- if (removeSet.has(node.value))
73
- continue;
74
- const newNode = { ...node };
75
- if (node.children?.length) {
76
- const filteredChildren = recurse(node.children);
77
- if (filteredChildren.length > 0)
78
- newNode.children = filteredChildren;
79
- }
80
- result.push(newNode);
81
- }
82
- return result;
83
- }
84
- return recurse(tree);
84
+ return filterTree(tree, (n) => !removeSet.has(n.value));
85
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuance-ui",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "A UI Library for Modern Web Apps, powered by Vue.",
5
5
  "repository": {
6
6
  "type": "git",