nuance-ui 0.1.28 → 0.1.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.
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^4.0.0"
6
6
  },
7
- "version": "0.1.28",
7
+ "version": "0.1.30",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
@@ -4,6 +4,7 @@ import type { BoxProps } from './box.vue.js';
4
4
  import type { LinkProps } from './link/index.js';
5
5
  import type { TextProps } from './text.vue.js';
6
6
  export interface BreadcrumbsItem extends Omit<LinkProps, 'mod'> {
7
+ active?: boolean;
7
8
  label: string;
8
9
  icon?: string;
9
10
  class?: string;
@@ -16,8 +17,6 @@ export interface BreadcrumbsProps extends BoxProps {
16
17
  separator?: string;
17
18
  /** Controls spacing between separator and breadcrumb @default `'xs'` */
18
19
  spacing?: NuanceSpacing;
19
- /** Function to determine if an item is active */
20
- activeItem?: (item: BreadcrumbsItem) => boolean;
21
20
  color?: NuanceColor;
22
21
  size?: TextProps['fz'];
23
22
  }
@@ -17,7 +17,6 @@ const {
17
17
  items: { type: null, required: false },
18
18
  separator: { type: String, required: false },
19
19
  spacing: { type: [String, Number], required: false },
20
- activeItem: { type: Function, required: false },
21
20
  color: { type: null, required: false },
22
21
  size: { type: null, required: false },
23
22
  is: { type: null, required: false },
@@ -44,13 +43,13 @@ const style = computed(() => ({
44
43
  :name='item.slot ?? "item"'
45
44
  :item='item'
46
45
  :ix='ix'
47
- :active='activeItem ? activeItem(item) : isActive'
46
+ :active='item?.active ?? isActive'
48
47
  >
49
48
  <Link
50
49
  v-bind='pickLinkProps(item).link'
51
50
  inherit
52
51
  :class='$style.item'
53
- :mod='{ active: activeItem ? activeItem(item) : isActive }'
52
+ :mod='{ active: item?.active ?? isActive }'
54
53
  >
55
54
  <Icon v-if='item?.icon' :name='item.icon' :class='$style.icon' />
56
55
  <Text is='span' inherit truncate>
@@ -4,6 +4,7 @@ import type { BoxProps } from './box.vue.js';
4
4
  import type { LinkProps } from './link/index.js';
5
5
  import type { TextProps } from './text.vue.js';
6
6
  export interface BreadcrumbsItem extends Omit<LinkProps, 'mod'> {
7
+ active?: boolean;
7
8
  label: string;
8
9
  icon?: string;
9
10
  class?: string;
@@ -16,8 +17,6 @@ export interface BreadcrumbsProps extends BoxProps {
16
17
  separator?: string;
17
18
  /** Controls spacing between separator and breadcrumb @default `'xs'` */
18
19
  spacing?: NuanceSpacing;
19
- /** Function to determine if an item is active */
20
- activeItem?: (item: BreadcrumbsItem) => boolean;
21
20
  color?: NuanceColor;
22
21
  size?: TextProps['fz'];
23
22
  }
@@ -38,7 +38,7 @@ const mod = computed(() => [
38
38
  <slot />
39
39
 
40
40
  <div :class='$style.wrapper'>
41
- <Box is='label' :class='$style.label' :for='id' :mod='{ disabled }'>
41
+ <Box is='label' v-if='label || $slots.label' :class='$style.label' :for='id' :mod='{ disabled }'>
42
42
  <slot name='label'>
43
43
  {{ label }}
44
44
  </slot>
@@ -104,6 +104,10 @@ const mod = computed(() => [
104
104
  &[data-disabled] {
105
105
  --label-cursor: not-allowed;
106
106
  }
107
+
108
+ &:empty {
109
+ display: none;
110
+ }
107
111
  }
108
112
 
109
113
  .label {
@@ -1,6 +1,11 @@
1
1
  import type { Updater } from '@tanstack/vue-table';
2
2
  import type { Ref } from 'vue';
3
- import type { TableColumn, TableData } from './model.js';
3
+ import type { TableColumn, TableData, TableProps, TableRow } from './model.js';
4
4
  export declare function processColumns<T extends TableData>(columns: TableColumn<T>[]): TableColumn<T>[];
5
5
  export declare function valueUpdater<T extends Updater<any>>(updaterOrValue: T, ref: Ref): void;
6
6
  export declare function resolveValue<T, A = undefined>(prop: T | ((arg: A) => T), arg?: A): T | undefined;
7
+ export declare function createRowHandlers<T extends TableData>(props: TableProps<T>): {
8
+ onRowSelect: (e: Event, row: TableRow<T>) => void;
9
+ onRowHover: (e: Event, row: TableRow<T> | null) => void;
10
+ onRowContextmenu: (e: Event, row: TableRow<T>) => void;
11
+ };
@@ -22,3 +22,34 @@ export function resolveValue(prop, arg) {
22
22
  return prop(arg);
23
23
  return prop;
24
24
  }
25
+ export function createRowHandlers(props) {
26
+ function onRowSelect(e, row) {
27
+ if (!props?.onSelect)
28
+ return;
29
+ const target = e.target;
30
+ const isInteractive = target.closest("button") || target.closest("a");
31
+ if (isInteractive)
32
+ return;
33
+ e.preventDefault();
34
+ e.stopPropagation();
35
+ props.onSelect(e, row);
36
+ }
37
+ function onRowHover(e, row) {
38
+ if (!props?.onHover)
39
+ return;
40
+ props.onHover(e, row);
41
+ }
42
+ function onRowContextmenu(e, row) {
43
+ if (!props?.onContextmenu)
44
+ return;
45
+ if (Array.isArray(props.onContextmenu))
46
+ props.onContextmenu.forEach((fn) => fn(e, row));
47
+ else
48
+ props.onContextmenu(e, row);
49
+ }
50
+ return {
51
+ onRowSelect,
52
+ onRowHover,
53
+ onRowContextmenu
54
+ };
55
+ }
@@ -7,15 +7,12 @@ import {
7
7
  getSortedRowModel,
8
8
  useVueTable
9
9
  } from "@tanstack/vue-table";
10
- import { useVirtualizer } from "@tanstack/vue-virtual";
11
10
  import { reactivePick, unrefElement } from "@vueuse/core";
12
11
  import { useStyleResolver } from "#imports";
13
- import defu from "defu";
14
- import { computed, ref, toRef, useTemplateRef, watch } from "vue";
12
+ import { computed, ref, useTemplateRef, watch } from "vue";
15
13
  import { getThemeColor } from "../../utils";
16
14
  import Box from "../box.vue";
17
- import TableRow from "./_ui/table-row.vue";
18
- import { processColumns, resolveValue, valueUpdater } from "./lib";
15
+ import { createRowHandlers, processColumns, resolveValue, valueUpdater } from "./lib";
19
16
  defineOptions({ inheritAttrs: false });
20
17
  const props = defineProps({
21
18
  data: { type: Array, required: false },
@@ -204,33 +201,11 @@ const rows = computed(() => table.getRowModel().rows);
204
201
  watch(() => props.data, () => {
205
202
  data.value = props.data ? [...props.data] : [];
206
203
  }, props.watchOptions);
207
- const virtualizerProps = toRef(() => defu(typeof props.virtualize === "boolean" ? {} : props.virtualize, {
208
- estimateSize: 65,
209
- overscan: 12
210
- }));
211
- const virtualizer = !!props.virtualize && useVirtualizer({
212
- ...virtualizerProps.value,
213
- get count() {
214
- return rows.value.length;
215
- },
216
- getScrollElement: () => unrefElement(rootRef),
217
- estimateSize: (index) => {
218
- const estimate = virtualizerProps.value.estimateSize;
219
- return typeof estimate === "function" ? estimate(index) : estimate;
220
- }
221
- });
222
- const renderedSize = computed(() => {
223
- if (!virtualizer)
224
- return 0;
225
- const virtualItems = virtualizer.value.getVirtualItems();
226
- if (!virtualItems?.length)
227
- return 0;
228
- return virtualItems.reduce((sum, item) => sum + item.size, 0);
229
- });
230
204
  const style = computed(() => useStyleResolver((theme) => ({
231
205
  "--table-loader-color": props.loadingColor ? getThemeColor(props.loadingColor, theme) : void 0,
232
206
  "--vertical-align": props.verticalAlign
233
207
  })));
208
+ const { onRowContextmenu, onRowHover, onRowSelect } = createRowHandlers(props);
234
209
  defineExpose({
235
210
  get $el() {
236
211
  return unrefElement(rootRef);
@@ -241,15 +216,7 @@ defineExpose({
241
216
  </script>
242
217
 
243
218
  <template>
244
- <Box
245
- ref='rootRef'
246
- :class='[$style.root, props.classes?.root]'
247
- :style='[
248
- virtualizer ? { height: `${virtualizer.getTotalSize()}px` } : void 0,
249
- style
250
- ]'
251
- :mod='{ virtualize: !!virtualizer }'
252
- >
219
+ <Box ref='rootRef' :class='[$style.root, props.classes?.root]' :style>
253
220
  <table ref='tableRef' :class='[$style.table, props.classes?.table]'>
254
221
  <caption v-if='caption || $slots.caption' :class='props.classes?.caption'>
255
222
  <slot name='caption'>
@@ -274,8 +241,15 @@ defineExpose({
274
241
  :scope="header.colSpan > 1 ? 'colgroup' : 'col'"
275
242
  :colspan='header.colSpan > 1 ? header.colSpan : void 0'
276
243
  :rowspan='header.rowSpan > 1 ? header.rowSpan : void 0'
277
- :class='[$style.th, props.classes?.th, resolveValue(header.column.columnDef.meta?.class?.th, header)]'
278
- :style='resolveValue(header.column.columnDef.meta?.style?.th, header)'
244
+ :class='[
245
+ $style.th,
246
+ props.classes?.th,
247
+ resolveValue(header.column.columnDef.meta?.class?.th, header)
248
+ ]'
249
+ :style='[
250
+ { width: header.getSize() !== 150 ? `${header.getSize()}px` : void 0 },
251
+ resolveValue(header.column.columnDef.meta?.style?.th, header)
252
+ ]'
279
253
  >
280
254
  <slot :name='`${header.id}-header`' v-bind='header.getContext()'>
281
255
  <FlexRender
@@ -294,36 +268,47 @@ defineExpose({
294
268
  <slot name='body-top' />
295
269
 
296
270
  <template v-if='rows.length'>
297
- <template v-if='virtualizer'>
298
- <template v-for='(virtualRow, index) in virtualizer.getVirtualItems()' :key='rows[virtualRow.index]?.id'>
299
- <TableRow
300
- :row='rows[virtualRow.index]'
301
- :class='[$style.tr, props.classes?.tr, resolveValue(table.options.meta?.class?.tr, virtualRow)]'
302
- :style='[
303
- {
304
- height: `${virtualRow.size}px`,
305
- transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`
306
- },
307
- resolveValue(table.options.meta?.style?.tr, virtualRow)
308
- ]'
309
- :on-select='props?.onSelect'
310
- :on-hover='props?.onHover'
311
- :on-contextmenu='props?.onContextmenu'
312
- />
313
- </template>
314
- </template>
315
-
316
- <template v-else>
317
- <TableRow
318
- v-for='row in rows'
319
- :key='row.id'
320
- :row='row'
271
+ <template v-for='row in rows' :key='row.id'>
272
+ <Box
273
+ is='tr'
274
+ :mod='{
275
+ selected: row.getIsSelected(),
276
+ expanded: row.getIsExpanded(),
277
+ selectable: !!onSelect || !!onHover || !!onContextmenu
278
+ }'
279
+ :role="onSelect ? 'button' : void 0"
280
+ :tabindex='onSelect ? 0 : void 0'
321
281
  :class='[$style.tr, props.classes?.tr, resolveValue(table.options.meta?.class?.tr, row)]'
322
282
  :style='resolveValue(table.options.meta?.style?.tr, row)'
323
- :on-select='props?.onSelect'
324
- :on-hover='props?.onHover'
325
- :on-contextmenu='props?.onContextmenu'
326
- />
283
+ @click='onRowSelect($event, row)'
284
+ @pointerenter='onRowHover($event, row)'
285
+ @pointerleave='onRowHover($event, null)'
286
+ @contextmenu='onRowContextmenu($event, row)'
287
+ >
288
+ <Box
289
+ is='td'
290
+ v-for='cell in row.getVisibleCells()'
291
+ :key='cell.id'
292
+ :mod='{ pinned: cell.column.getIsPinned() }'
293
+ :colspan='resolveValue(cell.column.columnDef.meta?.colspan?.td, cell)'
294
+ :rowspan='resolveValue(cell.column.columnDef.meta?.rowspan?.td, cell)'
295
+ :class='resolveValue(cell.column.columnDef.meta?.class?.td, cell)'
296
+ :style='[
297
+ { width: cell.column.getSize() !== 150 ? `${cell.column.getSize()}px` : void 0 },
298
+ resolveValue(cell.column.columnDef.meta?.style?.td, cell)
299
+ ]'
300
+ >
301
+ <slot :name='`${cell.column.id}-cell`' v-bind='cell.getContext()'>
302
+ <FlexRender :render='cell.column.columnDef.cell' :props='cell.getContext()' />
303
+ </slot>
304
+ </Box>
305
+ </Box>
306
+
307
+ <tr v-if='row.getIsExpanded()'>
308
+ <td :colspan='row.getAllCells().length'>
309
+ <slot name='expanded' :row='row' />
310
+ </td>
311
+ </tr>
327
312
  </template>
328
313
  </template>
329
314
 
@@ -348,7 +333,6 @@ defineExpose({
348
333
  is='tfoot'
349
334
  v-if='hasFooter'
350
335
  :class='[$style.tfoot, props.classes?.tfoot]'
351
- :style='virtualizer ? { transform: `translateY(${virtualizer.getTotalSize() - renderedSize}px)` } : void 0'
352
336
  :mod='{ sticky: props.sticky === "footer" || props.sticky === true }'
353
337
  >
354
338
  <tr :class='[$style.separator, props.classes?.separator]' />
@@ -8,6 +8,7 @@ import Loader from "../../loader/loader.vue";
8
8
  import RovingFocusItem from "../../roving-focus/roving-focus-item.vue";
9
9
  import UTransition from "../../transition/transition.vue";
10
10
  import { useTreeState } from "../lib/context";
11
+ import { filterTreeItems } from "../lib/filter-tree-items";
11
12
  import { useTreeItemHandlers } from "../lib/item-handlers";
12
13
  const {
13
14
  type = "file",
@@ -33,7 +34,8 @@ const ctx = useTreeState();
33
34
  const selected = computed(() => ctx.selected.value.includes(path));
34
35
  const expanded = computed(() => ctx.expanded.value.includes(path));
35
36
  const active = computed(() => ctx.active.value === path);
36
- const { data, pending, execute } = ctx.loadBranch(path);
37
+ const { data: state, pending, execute } = ctx.loadBranch(path);
38
+ const data = computed(() => filterTreeItems(state.value, ctx.filter));
37
39
  watch(expanded, (expanded2) => {
38
40
  if (expanded2) {
39
41
  try {
@@ -1,11 +1,12 @@
1
1
  import type { ButtonProps } from '@nui/components';
2
2
  import type { RovingFocusProps } from '../../roving-focus/roving-focus.vue.js';
3
- import type { TreeIconResolver, TreeLoader, TreeModels } from '../model.js';
3
+ import type { TreeFilter, TreeIconResolver, TreeLoader, TreeModels } from '../model.js';
4
4
  export type TreeRootProps = RovingFocusProps & {
5
5
  iconResolver?: TreeIconResolver;
6
6
  removable?: boolean;
7
7
  selectable?: boolean;
8
8
  loadBranch: TreeLoader;
9
+ filter?: TreeFilter;
9
10
  variant?: ButtonProps['variant'];
10
11
  color?: ButtonProps['color'];
11
12
  size?: ButtonProps['size'];
@@ -16,7 +16,8 @@ const {
16
16
  iconResolver = () => ({ icon: "gravity-ui:file" }),
17
17
  removable = false,
18
18
  selectable = false,
19
- loadBranch
19
+ loadBranch,
20
+ filter
20
21
  } = defineProps({
21
22
  loop: { type: Boolean, required: false },
22
23
  orientation: { type: String, required: false },
@@ -25,6 +26,7 @@ const {
25
26
  removable: { type: Boolean, required: false },
26
27
  selectable: { type: Boolean, required: false },
27
28
  loadBranch: { type: Function, required: true },
29
+ filter: { type: [String, null, Function], required: false },
28
30
  variant: { type: String, required: false },
29
31
  color: { type: null, required: false },
30
32
  size: { type: null, required: false }
@@ -48,7 +50,8 @@ useProvideTreeState({
48
50
  color,
49
51
  variant,
50
52
  selectable,
51
- loadBranch
53
+ loadBranch,
54
+ filter
52
55
  });
53
56
  if (removable) {
54
57
  useEventListener(root, "keydown", (event) => {
@@ -1,11 +1,12 @@
1
1
  import type { ButtonProps } from '@nui/components';
2
2
  import type { RovingFocusProps } from '../../roving-focus/roving-focus.vue.js';
3
- import type { TreeIconResolver, TreeLoader, TreeModels } from '../model.js';
3
+ import type { TreeFilter, TreeIconResolver, TreeLoader, TreeModels } from '../model.js';
4
4
  export type TreeRootProps = RovingFocusProps & {
5
5
  iconResolver?: TreeIconResolver;
6
6
  removable?: boolean;
7
7
  selectable?: boolean;
8
8
  loadBranch: TreeLoader;
9
+ filter?: TreeFilter;
9
10
  variant?: ButtonProps['variant'];
10
11
  color?: ButtonProps['color'];
11
12
  size?: ButtonProps['size'];
@@ -1,6 +1,6 @@
1
1
  import type { ButtonProps } from '@nui/components';
2
2
  import type { ModelRef, ShallowRef } from 'vue';
3
- import type { TreeIconResolver, TreeLoader } from '../model.js';
3
+ import type { TreeFilter, TreeIconResolver, TreeLoader } from '../model.js';
4
4
  type EventType = 'select' | 'expand';
5
5
  type SelectMode = 'single' | 'multiple' | 'range';
6
6
  export interface TreeContext {
@@ -10,6 +10,7 @@ export interface TreeContext {
10
10
  expanded: ModelRef<string[]>;
11
11
  iconResolver: TreeIconResolver;
12
12
  loadBranch: TreeLoader;
13
+ filter?: TreeFilter;
13
14
  selectable: boolean;
14
15
  variant: ButtonProps['variant'];
15
16
  color: ButtonProps['color'];
@@ -0,0 +1,2 @@
1
+ import type { TreeFilter, TreeItem } from '../model.js';
2
+ export declare function filterTreeItems(items: TreeItem[] | undefined, filter?: TreeFilter): TreeItem[] | undefined;
@@ -0,0 +1,7 @@
1
+ export function filterTreeItems(items, filter) {
2
+ if (!filter || !items)
3
+ return items;
4
+ if (typeof filter === "string")
5
+ return items.filter((i) => i.type === filter);
6
+ return items.filter(filter);
7
+ }
@@ -10,8 +10,6 @@ export function useTreeItemHandlers(path, isFolder, expanded) {
10
10
  ctx.toggle("select", path, "multiple");
11
11
  else
12
12
  ctx.toggle("select", path, "single");
13
- if (isFolder.value && !event.ctrlKey && !event.metaKey && !event.shiftKey)
14
- ctx.toggle("expand", path);
15
13
  }
16
14
  function handleKeyDown(event) {
17
15
  switch (event.key) {
@@ -38,3 +38,4 @@ export type TreeIconResolver = (type: TreeItemType, name?: string, path?: string
38
38
  icon: string;
39
39
  color?: NuanceColor;
40
40
  };
41
+ export type TreeFilter = 'directory' | null | ((item: TreeItem) => boolean);
@@ -1,12 +1,14 @@
1
1
  <script setup>
2
- import { onMounted } from "vue";
2
+ import { computed, onMounted } from "vue";
3
3
  import UTreeItem from "./_ui/tree-item.vue";
4
4
  import TreeRoot from "./_ui/tree-root.vue";
5
+ import { filterTreeItems } from "./lib/filter-tree-items";
5
6
  const {
6
7
  color,
7
8
  variant = "subtle",
8
9
  size = "compact-sm",
9
10
  loadBranch,
11
+ filter = "directory",
10
12
  ...props
11
13
  } = defineProps({
12
14
  loop: { type: Boolean, required: false },
@@ -16,6 +18,7 @@ const {
16
18
  removable: { type: Boolean, required: false },
17
19
  selectable: { type: Boolean, required: false },
18
20
  loadBranch: { type: Function, required: true },
21
+ filter: { type: [String, null, Function], required: false },
19
22
  variant: { type: String, required: false },
20
23
  color: { type: null, required: false },
21
24
  size: { type: null, required: false }
@@ -24,7 +27,8 @@ defineEmits(["delete"]);
24
27
  const active = defineModel("active", { type: [String, null], ...{ default: null } });
25
28
  const selected = defineModel("selected", { type: Array, ...{ default: [] } });
26
29
  const expanded = defineModel("expanded", { type: Array, ...{ default: [] } });
27
- const { data: root, execute } = loadBranch("/");
30
+ const { data: state, execute } = loadBranch("/");
31
+ const root = computed(() => filterTreeItems(state.value, filter));
28
32
  onMounted(execute);
29
33
  </script>
30
34
 
@@ -38,6 +42,7 @@ onMounted(execute);
38
42
  :size
39
43
  :color
40
44
  :variant
45
+ :filter
41
46
  @delete='(path) => $emit("delete", path)'
42
47
  >
43
48
  <UTreeItem
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuance-ui",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "description": "A UI Library for Modern Web Apps, powered by Vue.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,35 +0,0 @@
1
- import type { Row } from '@tanstack/vue-table';
2
- import type { TableData, TableRow } from '../model.js';
3
- export interface TableRowProps<T extends TableData> {
4
- row: Row<T>;
5
- onSelect?: (e: Event, row: TableRow<T>) => void;
6
- onHover?: (e: Event, row: TableRow<T> | null) => void;
7
- onContextmenu?: ((e: Event, row: TableRow<T>) => void) | Array<((e: Event, row: TableRow<T>) => void)>;
8
- }
9
- declare const __VLS_export: <T extends TableData>(__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
- props: __VLS_PrettifyLocal<TableRowProps<T>> & import("vue").PublicProps;
11
- expose: (exposed: {}) => void;
12
- attrs: any;
13
- slots: {
14
- [x: `${string}-cell`]: ((props: {
15
- cell: import("@tanstack/table-core").Cell<T, unknown>;
16
- column: import("@tanstack/table-core").Column<T, unknown>;
17
- getValue: import("@tanstack/table-core").Getter<unknown>;
18
- renderValue: import("@tanstack/table-core").Getter<unknown>;
19
- row: Row<T>;
20
- table: import("@tanstack/table-core").Table<T>;
21
- }) => any) | undefined;
22
- } & {
23
- expanded?: (props: {
24
- row: Row<T>;
25
- }) => any;
26
- };
27
- emit: {};
28
- }>) => import("vue").VNode & {
29
- __ctx?: Awaited<typeof __VLS_setup>;
30
- };
31
- declare const _default: typeof __VLS_export;
32
- export default _default;
33
- type __VLS_PrettifyLocal<T> = {
34
- [K in keyof T as K]: T[K];
35
- } & {};
@@ -1,74 +0,0 @@
1
- <script setup>
2
- import { FlexRender } from "@tanstack/vue-table";
3
- import Box from "../../box.vue";
4
- import { resolveValue } from "../lib";
5
- const { row, onSelect, onHover, onContextmenu } = defineProps({
6
- row: { type: Object, required: true },
7
- onSelect: { type: Function, required: false },
8
- onHover: { type: Function, required: false },
9
- onContextmenu: { type: [Function, Array], required: false }
10
- });
11
- function onRowSelect(e, row2) {
12
- if (!onSelect)
13
- return;
14
- const target = e.target;
15
- const isInteractive = target.closest("button") || target.closest("a");
16
- if (isInteractive)
17
- return;
18
- e.preventDefault();
19
- e.stopPropagation();
20
- onSelect(e, row2);
21
- }
22
- function onRowHover(e, row2) {
23
- if (!onHover)
24
- return;
25
- onHover(e, row2);
26
- }
27
- function onRowContextmenu(e, row2) {
28
- if (!onContextmenu)
29
- return;
30
- if (Array.isArray(onContextmenu))
31
- onContextmenu.forEach((fn) => fn(e, row2));
32
- else
33
- onContextmenu(e, row2);
34
- }
35
- </script>
36
-
37
- <template>
38
- <Box
39
- is='tr'
40
- v-bind='$attrs'
41
- :mod='{
42
- selected: row.getIsSelected(),
43
- expanded: row.getIsExpanded(),
44
- selectable: !!onSelect || !!onHover || !!onContextmenu
45
- }'
46
- :role="onSelect ? 'button' : void 0"
47
- :tabindex='onSelect ? 0 : void 0'
48
- @click='onRowSelect($event, row)'
49
- @pointerenter='onRowHover($event, row)'
50
- @pointerleave='onRowHover($event, null)'
51
- @contextmenu='onRowContextmenu($event, row)'
52
- >
53
- <Box
54
- is='td'
55
- v-for='cell in row.getVisibleCells()'
56
- :key='cell.id'
57
- :mod='{ pinned: cell.column.getIsPinned() }'
58
- :colspan='resolveValue(cell.column.columnDef.meta?.colspan?.td, cell)'
59
- :rowspan='resolveValue(cell.column.columnDef.meta?.rowspan?.td, cell)'
60
- :class='resolveValue(cell.column.columnDef.meta?.class?.td, cell)'
61
- :style='resolveValue(cell.column.columnDef.meta?.style?.td, cell)'
62
- >
63
- <slot :name='`${cell.column.id}-cell`' v-bind='cell.getContext()'>
64
- <FlexRender :render='cell.column.columnDef.cell' :props='cell.getContext()' />
65
- </slot>
66
- </Box>
67
- </Box>
68
-
69
- <tr v-if='row.getIsExpanded()'>
70
- <td :colspan='row.getAllCells().length'>
71
- <slot name='expanded' :row='row' />
72
- </td>
73
- </tr>
74
- </template>
@@ -1,35 +0,0 @@
1
- import type { Row } from '@tanstack/vue-table';
2
- import type { TableData, TableRow } from '../model.js';
3
- export interface TableRowProps<T extends TableData> {
4
- row: Row<T>;
5
- onSelect?: (e: Event, row: TableRow<T>) => void;
6
- onHover?: (e: Event, row: TableRow<T> | null) => void;
7
- onContextmenu?: ((e: Event, row: TableRow<T>) => void) | Array<((e: Event, row: TableRow<T>) => void)>;
8
- }
9
- declare const __VLS_export: <T extends TableData>(__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
- props: __VLS_PrettifyLocal<TableRowProps<T>> & import("vue").PublicProps;
11
- expose: (exposed: {}) => void;
12
- attrs: any;
13
- slots: {
14
- [x: `${string}-cell`]: ((props: {
15
- cell: import("@tanstack/table-core").Cell<T, unknown>;
16
- column: import("@tanstack/table-core").Column<T, unknown>;
17
- getValue: import("@tanstack/table-core").Getter<unknown>;
18
- renderValue: import("@tanstack/table-core").Getter<unknown>;
19
- row: Row<T>;
20
- table: import("@tanstack/table-core").Table<T>;
21
- }) => any) | undefined;
22
- } & {
23
- expanded?: (props: {
24
- row: Row<T>;
25
- }) => any;
26
- };
27
- emit: {};
28
- }>) => import("vue").VNode & {
29
- __ctx?: Awaited<typeof __VLS_setup>;
30
- };
31
- declare const _default: typeof __VLS_export;
32
- export default _default;
33
- type __VLS_PrettifyLocal<T> = {
34
- [K in keyof T as K]: T[K];
35
- } & {};
@@ -1,7 +0,0 @@
1
- import type { TreeItem } from '../model.js';
2
- /**
3
- * Получает все элементы дерева с expanded: true
4
- * @param items - массив элементов дерева
5
- * @returns массив value элементов с expanded: true
6
- */
7
- export declare function getExpandedItems<T extends string = string>(items: TreeItem<T>[]): T[];
@@ -1,10 +0,0 @@
1
- export function getExpandedItems(items) {
2
- const result = [];
3
- for (const item of items) {
4
- if (item.expanded === true)
5
- result.push(item.value);
6
- if (item.children && item.children.length > 0)
7
- result.push(...getExpandedItems(item.children));
8
- }
9
- return result;
10
- }