@xleddyl/443-components-vue 0.10.2 → 0.12.0

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 (72) hide show
  1. package/CATALOG.md +195 -180
  2. package/README.md +107 -23
  3. package/dist/components/data/Tag.vue +2 -0
  4. package/dist/components/data/Tag.vue.d.ts +2 -0
  5. package/dist/components/data/TagList.vue +239 -0
  6. package/dist/components/data/TagList.vue.d.ts +53 -0
  7. package/dist/components/data/index.d.ts +1 -0
  8. package/dist/components/data/index.mjs +1 -0
  9. package/dist/components/data/types.d.ts +15 -0
  10. package/dist/components/forms/Combobox.vue +33 -4
  11. package/dist/components/forms/Combobox.vue.d.ts +3 -1
  12. package/dist/components/forms/NumberInput.vue.d.ts +1 -1
  13. package/dist/components/forms/PinInput.vue.d.ts +2 -2
  14. package/dist/components/forms/types.d.ts +2 -0
  15. package/dist/components/layout/AppShell.vue +14 -2
  16. package/dist/components/layout/AppShell.vue.d.ts +3 -1
  17. package/dist/components/layout/Sidebar.vue +8 -3
  18. package/dist/components/layout/Sidebar.vue.d.ts +6 -1
  19. package/dist/components/layout/Stepper.vue +148 -0
  20. package/dist/components/layout/Stepper.vue.d.ts +420 -0
  21. package/dist/components/layout/index.d.ts +1 -0
  22. package/dist/components/layout/index.mjs +1 -0
  23. package/dist/components/layout/types.d.ts +13 -0
  24. package/dist/components/overlays/Toaster.vue +10 -0
  25. package/dist/components/overlays/Toaster.vue.d.ts +1 -1
  26. package/dist/components/templates/DashboardLayout.vue +13 -1
  27. package/dist/components/templates/DashboardLayout.vue.d.ts +7 -2
  28. package/dist/components/templates/SettingsModal.vue +95 -4
  29. package/dist/components/templates/SettingsModal.vue.d.ts +6 -1
  30. package/dist/components/templates/types.d.ts +4 -1
  31. package/dist/composables/data.d.ts +1 -0
  32. package/dist/composables/data.mjs +1 -0
  33. package/dist/composables/layout.d.ts +1 -0
  34. package/dist/composables/layout.mjs +1 -0
  35. package/dist/composables/useRouteState.d.ts +13 -0
  36. package/dist/composables/useRouteState.mjs +37 -0
  37. package/dist/composables/useSortable.d.ts +38 -0
  38. package/dist/composables/useSortable.mjs +215 -0
  39. package/dist/grid/DataGrid.vue +7 -1
  40. package/dist/grid/DataGrid.vue.d.ts +8 -1
  41. package/dist/grid/GridToolbar.vue +57 -2
  42. package/dist/grid/GridToolbar.vue.d.ts +13 -2
  43. package/dist/grid/cells/BadgeCell.vue +90 -18
  44. package/dist/grid/cells/BadgeCell.vue.d.ts +14 -14
  45. package/dist/grid/data-grid.css +57 -0
  46. package/dist/grid/spreadsheet.mjs +8 -4
  47. package/dist/grid/types.d.ts +3 -0
  48. package/dist/icons/builtin.d.ts +2 -0
  49. package/dist/icons/builtin.mjs +2 -0
  50. package/dist/internal/data/sortable.d.ts +5 -0
  51. package/dist/internal/data/sortable.mjs +23 -0
  52. package/dist/internal/layout/query.d.ts +6 -0
  53. package/dist/internal/layout/query.mjs +64 -0
  54. package/dist/internal/layout/route.d.ts +9 -2
  55. package/dist/internal/overlays/avoid.d.ts +26 -0
  56. package/dist/internal/overlays/avoid.mjs +134 -0
  57. package/dist/locale/de.mjs +24 -0
  58. package/dist/locale/en.mjs +24 -0
  59. package/dist/locale/it.mjs +24 -0
  60. package/dist/locale/types.d.ts +24 -0
  61. package/dist/nuxt/module.mjs +14 -0
  62. package/dist/nuxt/runtime/layouts/dashboard.vue +9 -1
  63. package/dist/styles/data/tag-list.css +93 -0
  64. package/dist/styles/data.css +1 -0
  65. package/dist/styles/forced-colors.css +10 -0
  66. package/dist/styles/layout/app-shell.css +25 -6
  67. package/dist/styles/layout/sidebar.css +11 -2
  68. package/dist/styles/layout/stepper.css +244 -0
  69. package/dist/styles/layout.css +1 -0
  70. package/dist/styles/overlays/toast.css +17 -12
  71. package/dist/styles/templates/settings-modal.css +5 -1
  72. package/package.json +1 -1
@@ -12,6 +12,46 @@
12
12
  :aria-label="text.search"
13
13
  />
14
14
  </div>
15
+ <span v-if="$slots.filters" class="k-data-grid-filters">
16
+ <Button
17
+ variant="outline"
18
+ tone="neutral"
19
+ size="sm"
20
+ icon="funnel"
21
+ square
22
+ :aria-label="filtersLabel"
23
+ aria-haspopup="dialog"
24
+ :aria-expanded="filtersOpen ? 'true' : 'false'"
25
+ :class="{ 'is-active': activeFilters > 0 }"
26
+ @click="filtersOpen = true"
27
+ />
28
+ <Badge
29
+ v-if="activeFilters > 0"
30
+ class="k-data-grid-filters-count"
31
+ tone="accent"
32
+ variant="solid"
33
+ size="sm"
34
+ :label="activeFilters"
35
+ aria-hidden="true"
36
+ />
37
+ </span>
38
+ <Modal v-if="$slots.filters" v-model:open="filtersOpen" :title="text.filters" size="sm">
39
+ <div class="k-data-grid-filters-body">
40
+ <slot name="filters" :close="closeFilters" :count="activeFilters" />
41
+ </div>
42
+ <template #footer="{ close }">
43
+ <Button
44
+ class="k-data-grid-filters-reset"
45
+ variant="ghost"
46
+ tone="neutral"
47
+ icon="arrow-path"
48
+ :label="text.resetFilters"
49
+ :aria-disabled="activeFilters === 0 ? 'true' : void 0"
50
+ @click="resetFilters"
51
+ />
52
+ <Button :label="text.showResults" @click="close" />
53
+ </template>
54
+ </Modal>
15
55
  <div class="k-data-grid-toolbar-actions">
16
56
  <slot />
17
57
  <DropdownMenu
@@ -47,8 +87,11 @@
47
87
  import { computed, onBeforeUnmount, ref, watch } from "vue";
48
88
  import Button from "../components/core/Button.vue";
49
89
  import Input from "../components/core/Input.vue";
90
+ import Badge from "../components/data/Badge.vue";
50
91
  import DropdownMenu from "../components/overlays/DropdownMenu.vue";
92
+ import Modal from "../components/overlays/Modal.vue";
51
93
  import { useLocale } from "../composables/useLocale";
94
+ import { formatLocaleMessage } from "../locale";
52
95
  const props = defineProps({
53
96
  api: { type: [Object, null], required: false },
54
97
  messages: { type: Object, required: false },
@@ -56,15 +99,21 @@ const props = defineProps({
56
99
  columnMenu: { type: Boolean, required: false, default: true },
57
100
  exportable: { type: Boolean, required: false, default: true },
58
101
  exportFileName: { type: String, required: false, default: "export" },
59
- debounce: { type: Number, required: false, default: 0 }
102
+ debounce: { type: Number, required: false, default: 0 },
103
+ filterCount: { type: Number, required: false, default: 0 }
60
104
  });
61
- const emit = defineEmits(["resetColumns"]);
105
+ const emit = defineEmits(["resetColumns", "filtersReset"]);
62
106
  const query = defineModel({ type: String, ...{ default: "" } });
63
107
  const { locale } = useLocale();
108
+ const filtersOpen = ref(false);
109
+ const activeFilters = computed(() => Math.max(0, Math.floor(props.filterCount)));
64
110
  const text = computed(() => ({
65
111
  ...locale.value.messages.grid,
66
112
  ...props.messages
67
113
  }));
114
+ const filtersLabel = computed(
115
+ () => formatLocaleMessage(locale.value.code, text.value.filtersActive, { count: activeFilters.value })
116
+ );
68
117
  const draft = ref(query.value);
69
118
  const columns = ref([]);
70
119
  const visibleCount = computed(() => columns.value.filter((column) => column.visible).length);
@@ -130,6 +179,12 @@ function resetColumns() {
130
179
  props.api?.resetColumnState();
131
180
  emit("resetColumns");
132
181
  }
182
+ function resetFilters() {
183
+ if (activeFilters.value > 0) emit("filtersReset");
184
+ }
185
+ function closeFilters() {
186
+ filtersOpen.value = false;
187
+ }
133
188
  function exportCsv() {
134
189
  props.api?.exportDataAsCsv({ fileName: props.exportFileName });
135
190
  }
@@ -1,7 +1,13 @@
1
1
  import type { GridMessages } from './types';
2
- declare var __VLS_8: {};
2
+ declare function closeFilters(): void;
3
+ declare var __VLS_28: {
4
+ close: typeof closeFilters;
5
+ count: number;
6
+ }, __VLS_45: {};
3
7
  type __VLS_Slots = {} & {
4
- default?: (props: typeof __VLS_8) => any;
8
+ filters?: (props: typeof __VLS_28) => any;
9
+ } & {
10
+ default?: (props: typeof __VLS_45) => any;
5
11
  };
6
12
  declare const __VLS_base: import("vue").DefineComponent<{
7
13
  api?: import("ag-grid-community").GridApi | null;
@@ -11,6 +17,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
11
17
  exportable?: boolean;
12
18
  exportFileName?: string;
13
19
  debounce?: number;
20
+ filterCount?: number;
14
21
  modelValue?: string;
15
22
  key?: PropertyKey | undefined;
16
23
  prefix?: string | undefined | undefined;
@@ -207,6 +214,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
207
214
  }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
208
215
  resetColumns: () => any;
209
216
  "update:modelValue": (value: string) => any;
217
+ filtersReset: () => any;
210
218
  }, string, import("vue").PublicProps, Readonly<{
211
219
  api?: import("ag-grid-community").GridApi | null;
212
220
  messages?: Partial<GridMessages>;
@@ -215,6 +223,7 @@ declare const __VLS_base: import("vue").DefineComponent<{
215
223
  exportable?: boolean;
216
224
  exportFileName?: string;
217
225
  debounce?: number;
226
+ filterCount?: number;
218
227
  modelValue?: string;
219
228
  key?: PropertyKey | undefined;
220
229
  prefix?: string | undefined | undefined;
@@ -411,12 +420,14 @@ declare const __VLS_base: import("vue").DefineComponent<{
411
420
  }> & Readonly<{
412
421
  onResetColumns?: (() => any) | undefined;
413
422
  "onUpdate:modelValue"?: ((value: string) => any) | undefined;
423
+ onFiltersReset?: (() => any) | undefined;
414
424
  }>, {
415
425
  debounce: number;
416
426
  searchable: boolean;
417
427
  columnMenu: boolean;
418
428
  exportable: boolean;
419
429
  exportFileName: string;
430
+ filterCount: number;
420
431
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
421
432
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
422
433
  declare const _default: typeof __VLS_export;
@@ -1,11 +1,60 @@
1
1
  <template>
2
- <template v-if="text">
3
- <Badge v-if="params.variant" :class="badgeClass" :tone :variant="params.variant" :size>{{
4
- text
5
- }}</Badge>
6
- <span v-else class="k-data-grid-badge" :class="[`k-data-grid-badge-${tone}`, badgeClass]">{{
7
- text
8
- }}</span>
2
+ <span
3
+ v-if="isList && entries.length"
4
+ class="k-data-grid-badges"
5
+ :class="{ 'is-wrap': params.wrap }"
6
+ :title="fullText"
7
+ >
8
+ <template v-for="entry in shown" :key="entry.key">
9
+ <Badge
10
+ v-if="params.variant"
11
+ :class="entry.badgeClass"
12
+ :tone="entry.tone"
13
+ :variant="params.variant"
14
+ :size
15
+ >{{ entry.text }}</Badge
16
+ >
17
+ <span
18
+ v-else
19
+ class="k-data-grid-badge"
20
+ :class="[`k-data-grid-badge-${entry.tone}`, entry.badgeClass]"
21
+ >{{ entry.text }}</span
22
+ >
23
+ </template>
24
+ <template v-if="hiddenCount > 0">
25
+ <Badge
26
+ v-if="params.variant"
27
+ class="k-data-grid-badge-more"
28
+ tone="neutral"
29
+ :variant="params.variant"
30
+ :size
31
+ aria-hidden="true"
32
+ >+{{ hiddenCount }}</Badge
33
+ >
34
+ <span
35
+ v-else
36
+ class="k-data-grid-badge k-data-grid-badge-neutral k-data-grid-badge-more"
37
+ aria-hidden="true"
38
+ >+{{ hiddenCount }}</span
39
+ >
40
+ <span class="k-visually-hidden">{{ moreText }}</span>
41
+ </template>
42
+ </span>
43
+ <template v-else-if="!isList && single">
44
+ <Badge
45
+ v-if="params.variant"
46
+ :class="single.badgeClass"
47
+ :tone="single.tone"
48
+ :variant="params.variant"
49
+ :size
50
+ >{{ single.text }}</Badge
51
+ >
52
+ <span
53
+ v-else
54
+ class="k-data-grid-badge"
55
+ :class="[`k-data-grid-badge-${single.tone}`, single.badgeClass]"
56
+ >{{ single.text }}</span
57
+ >
9
58
  </template>
10
59
  <EmptyCell v-else :context="cellContext" />
11
60
  </template>
@@ -13,22 +62,45 @@
13
62
  <script setup>
14
63
  import { computed } from "vue";
15
64
  import Badge from "../../components/data/Badge.vue";
65
+ import { formatLocaleMessage } from "../../locale";
16
66
  import EmptyCell from "./EmptyCell.vue";
17
67
  const props = defineProps({
18
68
  params: { type: Object, required: true }
19
69
  });
20
- const key = computed(() => {
21
- const raw = props.params.value;
22
- return raw === null || raw === void 0 ? "" : String(raw);
23
- });
24
- const text = computed(() => key.value ? props.params.labels?.[key.value] ?? key.value : "");
25
- const tone = computed(
26
- () => props.params.tones?.[key.value] ?? props.params.defaultTone ?? "neutral"
27
- );
70
+ const cellContext = computed(() => props.params.context);
28
71
  const size = computed(() => props.params.size ?? "sm");
29
- const badgeClass = computed(() => {
72
+ const isList = computed(() => Array.isArray(props.params.value));
73
+ function keyOf(raw) {
74
+ return raw === null || raw === void 0 ? "" : String(raw);
75
+ }
76
+ function entryFor(raw, index) {
77
+ const key = keyOf(raw);
78
+ if (!key) return null;
30
79
  const source = props.params.badgeClass;
31
- return typeof source === "function" ? source(props.params.value, props.params.data) : source;
80
+ return {
81
+ key: `${index}-${key}`,
82
+ text: props.params.labels?.[key] ?? key,
83
+ tone: props.params.tones?.[key] ?? props.params.defaultTone ?? "neutral",
84
+ badgeClass: typeof source === "function" ? source(raw, props.params.data) : source
85
+ };
86
+ }
87
+ const single = computed(() => isList.value ? null : entryFor(props.params.value, 0));
88
+ const entries = computed(() => {
89
+ if (!isList.value) return [];
90
+ return props.params.value.map((raw, index) => entryFor(raw, index)).filter((entry) => entry !== null);
32
91
  });
33
- const cellContext = computed(() => props.params.context);
92
+ const limit = computed(() => {
93
+ const max = props.params.max;
94
+ return max === void 0 || max < 1 ? entries.value.length : Math.floor(max);
95
+ });
96
+ const shown = computed(() => entries.value.slice(0, limit.value));
97
+ const hiddenCount = computed(() => entries.value.length - shown.value.length);
98
+ const fullText = computed(() => entries.value.map((entry) => entry.text).join(", "));
99
+ const moreText = computed(
100
+ () => formatLocaleMessage(
101
+ cellContext.value?.locale ?? "en",
102
+ cellContext.value?.messages?.moreValues ?? "{count} more",
103
+ { count: hiddenCount.value }
104
+ )
105
+ );
34
106
  </script>
@@ -1,13 +1,6 @@
1
1
  import type { BadgeCellParams, GridCellContext } from '../types';
2
2
  declare const __VLS_export: import("vue").DefineComponent<{
3
3
  params: import("ag-grid-community").ICellRendererParams<any, any, any> & BadgeCellParams<unknown>;
4
- label?: string | number;
5
- tone?: import("../../index.ts").Tone;
6
- variant?: import("../../index.ts").BadgeVariant;
7
- size?: import("../../index.ts").BadgeSize;
8
- dot?: boolean;
9
- pulse?: boolean;
10
- icon?: import("../../index.ts").IconName;
11
4
  innerHTML?: string | undefined | undefined;
12
5
  class?: import("vue").ClassValue;
13
6
  style?: import("vue").StyleValue;
@@ -200,6 +193,13 @@ declare const __VLS_export: import("vue").DefineComponent<{
200
193
  ref?: import("vue").VNodeRef | undefined;
201
194
  ref_for?: boolean | undefined | undefined;
202
195
  ref_key?: string | undefined | undefined;
196
+ label?: string | number;
197
+ tone?: import("../../index.ts").Tone;
198
+ variant?: import("../../index.ts").BadgeVariant;
199
+ size?: import("../../index.ts").BadgeSize;
200
+ dot?: boolean;
201
+ pulse?: boolean;
202
+ icon?: import("../../index.ts").IconName;
203
203
  onVnodeBeforeMount?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
204
204
  onVnodeMounted?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
205
205
  onVnodeBeforeUpdate?: (((vnode: import("vue").VNode, oldVNode: import("vue").VNode) => void) | ((vnode: import("vue").VNode, oldVNode: import("vue").VNode) => void)[]) | undefined;
@@ -209,13 +209,6 @@ declare const __VLS_export: import("vue").DefineComponent<{
209
209
  context?: GridCellContext;
210
210
  }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{
211
211
  params: import("ag-grid-community").ICellRendererParams<any, any, any> & BadgeCellParams<unknown>;
212
- label?: string | number;
213
- tone?: import("../../index.ts").Tone;
214
- variant?: import("../../index.ts").BadgeVariant;
215
- size?: import("../../index.ts").BadgeSize;
216
- dot?: boolean;
217
- pulse?: boolean;
218
- icon?: import("../../index.ts").IconName;
219
212
  innerHTML?: string | undefined | undefined;
220
213
  class?: import("vue").ClassValue;
221
214
  style?: import("vue").StyleValue;
@@ -408,6 +401,13 @@ declare const __VLS_export: import("vue").DefineComponent<{
408
401
  ref?: import("vue").VNodeRef | undefined;
409
402
  ref_for?: boolean | undefined | undefined;
410
403
  ref_key?: string | undefined | undefined;
404
+ label?: string | number;
405
+ tone?: import("../../index.ts").Tone;
406
+ variant?: import("../../index.ts").BadgeVariant;
407
+ size?: import("../../index.ts").BadgeSize;
408
+ dot?: boolean;
409
+ pulse?: boolean;
410
+ icon?: import("../../index.ts").IconName;
411
411
  onVnodeBeforeMount?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
412
412
  onVnodeMounted?: (((vnode: import("vue").VNode) => void) | ((vnode: import("vue").VNode) => void)[]) | undefined;
413
413
  onVnodeBeforeUpdate?: (((vnode: import("vue").VNode, oldVNode: import("vue").VNode) => void) | ((vnode: import("vue").VNode, oldVNode: import("vue").VNode) => void)[]) | undefined;
@@ -20,6 +20,39 @@
20
20
  max-width: 22rem;
21
21
  }
22
22
 
23
+ .k-data-grid-filters {
24
+ position: relative;
25
+ display: inline-flex;
26
+ flex: none;
27
+ }
28
+
29
+ .k-data-grid-filters > .k-btn.is-active {
30
+ color: var(--k-accent-text);
31
+ }
32
+
33
+ .k-data-grid-filters > .k-data-grid-filters-count {
34
+ position: absolute;
35
+ inset-block-start: -0.4375rem;
36
+ inset-inline-end: -0.4375rem;
37
+ min-width: 1.125rem;
38
+ height: 1.125rem;
39
+ padding-inline: 0.25rem;
40
+ justify-content: center;
41
+ font-size: 0.75rem;
42
+ line-height: 1;
43
+ pointer-events: none;
44
+ }
45
+
46
+ .k-data-grid-filters-body {
47
+ display: flex;
48
+ flex-direction: column;
49
+ gap: 0.875rem;
50
+ }
51
+
52
+ .k-data-grid-filters-reset {
53
+ margin-inline-end: auto;
54
+ }
55
+
23
56
  .k-data-grid-toolbar-actions {
24
57
  display: flex;
25
58
  flex-wrap: wrap;
@@ -163,6 +196,30 @@
163
196
  white-space: nowrap;
164
197
  }
165
198
 
199
+ .k-data-grid-badges {
200
+ display: flex;
201
+ flex-wrap: nowrap;
202
+ align-items: center;
203
+ gap: 0.25rem;
204
+ min-width: 0;
205
+ max-width: 100%;
206
+ overflow: hidden;
207
+ }
208
+
209
+ .k-data-grid-badges.is-wrap {
210
+ flex-wrap: wrap;
211
+ padding-block: 0.25rem;
212
+ line-height: 1.2;
213
+ }
214
+
215
+ .k-data-grid-badges > * {
216
+ flex-shrink: 0;
217
+ }
218
+
219
+ .k-data-grid-badges > .k-data-grid-badge-more {
220
+ font-variant-numeric: tabular-nums;
221
+ }
222
+
166
223
  .k-data-grid-badge-accent {
167
224
  --k-badge-tone: var(--k-accent-text);
168
225
  }
@@ -102,15 +102,19 @@ export function createGridSpreadsheet(options) {
102
102
  const inside = cell.row >= rect.top && cell.row <= rect.bottom && cell.col >= rect.left && cell.col <= rect.right;
103
103
  return inside ? cell : null;
104
104
  }
105
+ function onRangeEdge(params, edge) {
106
+ const cell = rangeCell(params);
107
+ return !!cell && !!rect && edge(cell, rect);
108
+ }
105
109
  const classRules = {
106
110
  "is-range": (params) => {
107
111
  const cell = rangeCell(params);
108
112
  return !!cell && !sameCell(cell, active);
109
113
  },
110
- "is-range-top": (params) => rangeCell(params)?.row === rect?.top,
111
- "is-range-bottom": (params) => rangeCell(params)?.row === rect?.bottom,
112
- "is-range-left": (params) => rangeCell(params)?.col === rect?.left,
113
- "is-range-right": (params) => rangeCell(params)?.col === rect?.right,
114
+ "is-range-top": (params) => onRangeEdge(params, (cell, area) => cell.row === area.top),
115
+ "is-range-bottom": (params) => onRangeEdge(params, (cell, area) => cell.row === area.bottom),
116
+ "is-range-left": (params) => onRangeEdge(params, (cell, area) => cell.col === area.left),
117
+ "is-range-right": (params) => onRangeEdge(params, (cell, area) => cell.col === area.right),
114
118
  "is-active": (params) => !!active && sameCell(cellOf(params), active),
115
119
  "is-fill-corner": (params) => {
116
120
  if (!rect) return false;
@@ -31,6 +31,7 @@ export interface GridToolbarProps {
31
31
  exportable?: boolean;
32
32
  exportFileName?: string;
33
33
  debounce?: number;
34
+ filterCount?: number;
34
35
  }
35
36
  export interface BooleanCellParams {
36
37
  trueLabel?: string;
@@ -49,6 +50,8 @@ export interface BadgeCellParams<T = unknown> {
49
50
  variant?: BadgeVariant;
50
51
  size?: BadgeSize;
51
52
  badgeClass?: string | ((value: unknown, data: T | undefined) => string | undefined);
53
+ max?: number;
54
+ wrap?: boolean;
52
55
  }
53
56
  export type ImageCellFit = 'cover' | 'contain';
54
57
  export interface ImageCellParams<T = unknown> {
@@ -7,6 +7,8 @@ export declare const builtinIcons: {
7
7
  readonly 'chevron-up': readonly ["m4.5 15.75 7.5-7.5 7.5 7.5"];
8
8
  readonly 'chevron-left': readonly ["M15.75 19.5 8.25 12l7.5-7.5"];
9
9
  readonly 'chevron-right': readonly ["m8.25 4.5 7.5 7.5-7.5 7.5"];
10
+ readonly 'sidebar-collapse': readonly ["M15.75 19.5 8.25 12l7.5-7.5"];
11
+ readonly 'sidebar-expand': readonly ["m8.25 4.5 7.5 7.5-7.5 7.5"];
10
12
  readonly 'chevron-up-down': readonly ["M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"];
11
13
  readonly 'chevron-double-left': readonly ["m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5"];
12
14
  readonly 'chevron-double-right': readonly ["m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"];
@@ -7,6 +7,8 @@ export const builtinIcons = {
7
7
  "chevron-up": ["m4.5 15.75 7.5-7.5 7.5 7.5"],
8
8
  "chevron-left": ["M15.75 19.5 8.25 12l7.5-7.5"],
9
9
  "chevron-right": ["m8.25 4.5 7.5 7.5-7.5 7.5"],
10
+ "sidebar-collapse": ["M15.75 19.5 8.25 12l7.5-7.5"],
11
+ "sidebar-expand": ["m8.25 4.5 7.5 7.5-7.5 7.5"],
10
12
  "chevron-up-down": ["M8.25 15 12 18.75 15.75 15m-7.5-6L12 5.25 15.75 9"],
11
13
  "chevron-double-left": ["m18.75 4.5-7.5 7.5 7.5 7.5m-6-15L5.25 12l7.5 7.5"],
12
14
  "chevron-double-right": ["m5.25 4.5 7.5 7.5-7.5 7.5m6-15 7.5 7.5-7.5 7.5"],
@@ -0,0 +1,5 @@
1
+ export type SortableAxis = 'horizontal' | 'vertical';
2
+ export declare const SORTABLE_ATTR = "data-k-sortable";
3
+ export declare function sortableElements(container: HTMLElement | null | undefined): HTMLElement[];
4
+ export declare function isRtl(element: Element | null | undefined): boolean;
5
+ export declare function insertionIndex(elements: HTMLElement[], x: number, y: number, axis: SortableAxis, rtl: boolean): number;
@@ -0,0 +1,23 @@
1
+ export const SORTABLE_ATTR = "data-k-sortable";
2
+ export function sortableElements(container) {
3
+ if (!container) return [];
4
+ return Array.from(container.querySelectorAll(`[${SORTABLE_ATTR}]`)).sort(
5
+ (a, b) => Number(a.getAttribute(SORTABLE_ATTR)) - Number(b.getAttribute(SORTABLE_ATTR))
6
+ );
7
+ }
8
+ export function isRtl(element) {
9
+ return element ? getComputedStyle(element).direction === "rtl" : false;
10
+ }
11
+ function isBefore(rect, x, y, axis, rtl) {
12
+ if (axis === "vertical") return rect.top + rect.height / 2 < y;
13
+ if (rect.bottom <= y) return true;
14
+ if (rect.top > y) return false;
15
+ const center = rect.left + rect.width / 2;
16
+ return rtl ? center > x : center < x;
17
+ }
18
+ export function insertionIndex(elements, x, y, axis, rtl) {
19
+ let index = 0;
20
+ for (const element of elements)
21
+ if (isBefore(element.getBoundingClientRect(), x, y, axis, rtl)) index++;
22
+ return index;
23
+ }
@@ -0,0 +1,6 @@
1
+ import type { MaybeRefOrGetter } from 'vue';
2
+ import type { RouterLike } from './route';
3
+ export type RouteHistory = 'push' | 'replace';
4
+ export declare function firstQueryValue(value: unknown): string | undefined;
5
+ export declare function useQueryValue(router: RouterLike | undefined, key: MaybeRefOrGetter<string | undefined>): import("vue").ComputedRef<string | undefined>;
6
+ export declare function writeQueryValue(router: RouterLike, key: string, value: string | undefined, history: RouteHistory): Promise<boolean>;
@@ -0,0 +1,64 @@
1
+ import { computed, toValue } from "vue";
2
+ import { isClient } from "../core/env.mjs";
3
+ const batches = /* @__PURE__ */ new WeakMap();
4
+ export function firstQueryValue(value) {
5
+ if (Array.isArray(value)) return firstQueryValue(value[0]);
6
+ return typeof value === "string" ? value : void 0;
7
+ }
8
+ export function useQueryValue(router, key) {
9
+ return computed(() => {
10
+ const name = toValue(key);
11
+ if (!router || !name) return void 0;
12
+ return firstQueryValue(router.currentRoute?.value?.query?.[name]);
13
+ });
14
+ }
15
+ function isPreviousEntry(router, location) {
16
+ if (!router.back || !router.resolve) return false;
17
+ const back = window.history.state?.back;
18
+ if (typeof back !== "string") return false;
19
+ return router.resolve(location).fullPath === back;
20
+ }
21
+ async function flush(router, batch) {
22
+ batches.delete(router);
23
+ const route = router.currentRoute?.value;
24
+ const query = { ...route?.query };
25
+ let changed = false;
26
+ for (const [key, value] of batch.changes) {
27
+ if (value === void 0) {
28
+ if (!(key in query)) continue;
29
+ delete query[key];
30
+ changed = true;
31
+ } else if (query[key] !== value) {
32
+ query[key] = value;
33
+ changed = true;
34
+ }
35
+ }
36
+ if (!changed) return true;
37
+ const location = { path: route?.path, query, hash: route?.hash };
38
+ try {
39
+ if (batch.history === "push" && isPreviousEntry(router, location)) {
40
+ router.back?.();
41
+ return true;
42
+ }
43
+ const failure = batch.history === "replace" && router.replace ? await router.replace(location) : await router.push(location);
44
+ return !failure;
45
+ } catch {
46
+ return false;
47
+ }
48
+ }
49
+ export function writeQueryValue(router, key, value, history) {
50
+ if (!isClient()) return Promise.resolve(true);
51
+ let batch = batches.get(router);
52
+ if (!batch) {
53
+ const created = {
54
+ changes: /* @__PURE__ */ new Map(),
55
+ history,
56
+ promise: Promise.resolve().then(() => flush(router, created))
57
+ };
58
+ batch = created;
59
+ batches.set(router, batch);
60
+ }
61
+ batch.changes.set(key, value === "" ? void 0 : value);
62
+ if (history === "push") batch.history = "push";
63
+ return batch.promise;
64
+ }
@@ -1,9 +1,17 @@
1
1
  import type { MaybeRefOrGetter } from 'vue';
2
- interface RouteLike {
2
+ export interface RouteLike {
3
3
  path?: string;
4
+ fullPath?: string;
5
+ hash?: string;
6
+ query?: Record<string, unknown>;
4
7
  }
5
8
  export interface RouterLike {
6
9
  push: (to: unknown) => unknown;
10
+ replace?: (to: unknown) => unknown;
11
+ back?: () => unknown;
12
+ resolve?: (to: unknown) => {
13
+ fullPath?: string;
14
+ };
7
15
  beforeEach: (guard: (to: RouteLike, from: RouteLike) => boolean | void | Promise<boolean | void>) => () => void;
8
16
  currentRoute?: {
9
17
  value?: RouteLike;
@@ -13,4 +21,3 @@ export declare function useRouterLike(): RouterLike | undefined;
13
21
  export declare function useCurrentPath(override?: MaybeRefOrGetter<string | undefined>): import("vue").ComputedRef<string | undefined>;
14
22
  export declare function targetPath(target: unknown): string | undefined;
15
23
  export declare function matchesPath(current: string, target: string, exact: boolean): boolean;
16
- export {};
@@ -0,0 +1,26 @@
1
+ import type { Ref } from 'vue';
2
+ export interface ToasterInsets {
3
+ left: number;
4
+ right: number;
5
+ top: number;
6
+ bottom: number;
7
+ }
8
+ export interface ToasterAvoidanceOptions {
9
+ outlet: () => HTMLElement | null;
10
+ toaster: Readonly<Ref<HTMLElement | null | undefined>>;
11
+ position: () => string;
12
+ }
13
+ export declare function useToasterAvoidance(options: ToasterAvoidanceOptions): {
14
+ insets: Ref<{
15
+ left: number;
16
+ right: number;
17
+ top: number;
18
+ bottom: number;
19
+ }, ToasterInsets | {
20
+ left: number;
21
+ right: number;
22
+ top: number;
23
+ bottom: number;
24
+ }>;
25
+ refresh: () => void;
26
+ };